diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/AsyncBatchDelivery.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/AsyncBatchDelivery.java index 5b2c5197..e973c7bc 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/AsyncBatchDelivery.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/AsyncBatchDelivery.java @@ -41,9 +41,14 @@ public class AsyncBatchDelivery implements BatchDelivery { private static final Logger LOG = StatusLogger.getLogger(); + private volatile State state = State.STOPPED; + private final BatchOperations batchOperations; private final BatchEmitter batchEmitter; + private final IndexTemplate indexTemplate; + private final ClientObjectFactory objectFactory; + public AsyncBatchDelivery(int batchSize, int deliveryInterval, ClientObjectFactory objectFactory, FailoverPolicy failoverPolicy, IndexTemplate indexTemplate) { this.batchOperations = objectFactory.createBatchOperations(); this.batchEmitter = createBatchEmitterServiceProvider() @@ -52,9 +57,8 @@ public AsyncBatchDelivery(int batchSize, int deliveryInterval, ClientObjectFacto deliveryInterval, objectFactory, failoverPolicy); - if (indexTemplate != null) { - objectFactory.execute(indexTemplate); - } + this.indexTemplate = indexTemplate; + this.objectFactory = objectFactory; } /** @@ -149,4 +153,33 @@ public Builder withIndexTemplate(IndexTemplate indexTemplate) { } + // ========== + // LIFECYCLE + // ========== + + @Override + public void start() { + if (indexTemplate != null) { + objectFactory.addOperation(() -> objectFactory.execute(indexTemplate)); + } + batchEmitter.start(); + state = State.STARTED; + } + + @Override + public void stop() { + batchEmitter.stop(); + state = State.STOPPED; + } + + @Override + public boolean isStarted() { + return state == State.STARTED; + } + + @Override + public boolean isStopped() { + return state == State.STOPPED; + } + } diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchDelivery.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchDelivery.java index ee67de93..b181c8dd 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchDelivery.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchDelivery.java @@ -26,7 +26,7 @@ * * @param type of accepted items */ -public interface BatchDelivery { +public interface BatchDelivery extends LifeCycle { String ELEMENT_TYPE = "batchDelivery"; diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchEmitter.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchEmitter.java index 4b5bbc17..afb70336 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchEmitter.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BatchEmitter.java @@ -27,7 +27,7 @@ * * @param type of accepted batch item */ -public interface BatchEmitter { +public interface BatchEmitter extends LifeCycle { /** * @param batchItem batch item to be processed diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BulkEmitter.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BulkEmitter.java index 418e1835..6fb8d572 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BulkEmitter.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/BulkEmitter.java @@ -35,6 +35,8 @@ */ public class BulkEmitter implements BatchEmitter { + private volatile State state = State.STOPPED; + private final AtomicInteger size = new AtomicInteger(); private final int maxSize; @@ -98,6 +100,30 @@ public void addListener(Function onReadyListener) { this.listener = onReadyListener; } + // ========== + // LIFECYCLE + // ========== + + @Override + public void start() { + state = State.STARTED; + } + + @Override + public void stop() { + state = State.STOPPED; + } + + @Override + public boolean isStarted() { + return state == State.STARTED; + } + + @Override + public boolean isStopped() { + return state == State.STOPPED; + } + /* * Class used as monitor to increase lock visibility in profiling tools */ diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ClientObjectFactory.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ClientObjectFactory.java index e3a33459..d9de27b4 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ClientObjectFactory.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ClientObjectFactory.java @@ -73,7 +73,17 @@ public interface ClientObjectFactory { /** * Updates target with index template * @param indexTemplate index template request + * @deprecated will be replaced by {@link #addOperation(Operation)} in future releases */ + @Deprecated void execute(IndexTemplate indexTemplate); + /** + * Allows to add operation to be executed before next batch. Exact time of the execution depends on implementation of this factory. + * + * NOTE: {@code default} added for backwards compatibility. {@code default} will be removed future releases + * @param operation operation to be executed + */ + default void addOperation(Operation operation) {} + } diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppender.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppender.java index 65321540..559a8a29 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppender.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppender.java @@ -35,6 +35,7 @@ import org.apache.logging.log4j.core.layout.AbstractLayout; import org.apache.logging.log4j.core.layout.AbstractStringLayout; + /** * Plugin class responsible for delivery of incoming {@link LogEvent}(s) to {@link BatchDelivery} implementation. *

@@ -51,8 +52,8 @@ public class ElasticsearchAppender extends AbstractAppender { public static final String PLUGIN_NAME = "Elasticsearch"; - private IndexNameFormatter indexNameFormatter; - private final ItemAppender itemAppender; + private final IndexNameFormatter indexNameFormatter; + private final ItemAppender itemAppender; protected ElasticsearchAppender(String name, Filter filter, AbstractLayout layout, boolean ignoreExceptions, BatchDelivery batchDelivery, boolean messageOnly, IndexNameFormatter indexNameFormatter) { @@ -71,6 +72,18 @@ public void append(LogEvent event) { itemAppender.append(formattedIndexName, event); } + @Override + public void start() { + itemAppender.start(); + super.start(); + } + + @Override + public void stop() { + itemAppender.stop(); + super.stop(); + } + @PluginBuilderFactory public static Builder newBuilder() { return new Builder(); diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemAppender.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemAppender.java index 592f0df0..965ea58c 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemAppender.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemAppender.java @@ -25,7 +25,7 @@ * * @param log source type */ -public interface ItemAppender { +public interface ItemAppender extends LifeCycle { void append(String formattedIndexName, T source); diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemSourceAppender.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemSourceAppender.java index cbb9e505..0129d7fb 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemSourceAppender.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/ItemSourceAppender.java @@ -29,6 +29,8 @@ */ public class ItemSourceAppender implements ItemAppender { + private volatile State state = State.STOPPED; + private final BatchDelivery batchDelivery; private final Function serializer; @@ -48,4 +50,28 @@ public final void append(String formattedIndexName, LogEvent event) { batchDelivery.add(formattedIndexName, serializer.apply(event)); } + @Override + public void start() { + batchDelivery.start(); + state = State.STARTED; + } + + @Override + public void stop() { + if (batchDelivery.isStarted()) { + batchDelivery.stop(); + } + state = State.STOPPED; + } + + @Override + public boolean isStarted() { + return state == State.STARTED; + } + + @Override + public boolean isStopped() { + return state == State.STOPPED; + } + } diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/LifeCycle.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/LifeCycle.java new file mode 100644 index 00000000..22e7f23d --- /dev/null +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/LifeCycle.java @@ -0,0 +1,17 @@ +package org.appenders.log4j2.elasticsearch; + +public interface LifeCycle { + + void start(); + + void stop(); + + boolean isStarted(); + + boolean isStopped(); + + enum State { + STARTED, STOPPED + } + +} diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/Operation.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/Operation.java new file mode 100644 index 00000000..4b3260bd --- /dev/null +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/Operation.java @@ -0,0 +1,7 @@ +package org.appenders.log4j2.elasticsearch; + +public interface Operation { + + void execute() throws Exception; + +} diff --git a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/StringAppender.java b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/StringAppender.java index 5f6648a8..573134f2 100644 --- a/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/StringAppender.java +++ b/log4j2-elasticsearch-core/src/main/java/org/appenders/log4j2/elasticsearch/StringAppender.java @@ -29,6 +29,8 @@ */ public class StringAppender implements ItemAppender { + private volatile State state = State.STOPPED; + private final BatchDelivery batchDelivery; private final Function serializer; @@ -48,4 +50,32 @@ public void append(String formattedIndexName, LogEvent logEvent) { batchDelivery.add(formattedIndexName, serializer.apply(logEvent)); } + // ========== + // LIFECYCLE + // ========== + + @Override + public void start() { + batchDelivery.start(); + state = State.STARTED; + } + + @Override + public void stop() { + if (batchDelivery.isStarted()) { + batchDelivery.stop(); + } + state = State.STOPPED; + } + + @Override + public boolean isStarted() { + return state == State.STARTED; + } + + @Override + public boolean isStopped() { + return state == State.STOPPED; + } + } diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BatchDeliveryTest.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BatchDeliveryTest.java index c33c6f4c..ea93bef1 100644 --- a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BatchDeliveryTest.java +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BatchDeliveryTest.java @@ -29,15 +29,18 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; import java.util.UUID; import static org.appenders.log4j2.elasticsearch.IndexTemplateTest.TEST_INDEX_TEMPLATE; import static org.appenders.log4j2.elasticsearch.IndexTemplateTest.TEST_PATH; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -150,20 +153,20 @@ public void deliveryAddsBatchItemToBatchEmitter() { TestHttpObjectFactory objectFactory = createTestObjectFactoryBuilder().build(); TestBatchEmitterFactory batchEmitterFactory = spy(new TestBatchEmitterFactory()); - TestAsyncBatchDelivery.mockedProvider = batchEmitterFactory; BatchEmitter emitter = batchEmitterFactory.createInstance(TEST_BATCH_SIZE, TEST_DELIVERY_INTERVAL, objectFactory, new NoopFailoverPolicy()); - AsyncBatchDelivery.Builder builder = createTestBatchDeliveryBuilder(); - TestAsyncBatchDelivery testAsyncBatchDelivery = spy(new TestAsyncBatchDelivery( + TestAsyncBatchDelivery delivery = spy(new TestAsyncBatchDelivery( TEST_BATCH_SIZE, TEST_DELIVERY_INTERVAL, objectFactory, new NoopFailoverPolicy(), - null)); - Mockito.when(builder.build()).thenReturn(testAsyncBatchDelivery); - - AsyncBatchDelivery delivery = builder.build(); + null) { + @Override + protected BatchEmitterServiceProvider createBatchEmitterServiceProvider() { + return batchEmitterFactory; + } + }); String testMessage = "test message"; @@ -178,29 +181,124 @@ public void deliveryAddsBatchItemToBatchEmitter() { } @Test - public void batchDeliveryExecutesIndexTemplateDuringStartupWhenIndexTemplatesNotNull() { + public void lifecycleStartSetsUpIndexTemplateExecutionIfIndexTemplateIsConfigured() { // given - TestBatchEmitterFactory batchEmitterFactory = spy(new TestBatchEmitterFactory()); - TestAsyncBatchDelivery.mockedProvider = batchEmitterFactory; + TestHttpObjectFactory objectFactory = spy(createTestObjectFactoryBuilder().build()); + + IndexTemplate indexTemplate = mock(IndexTemplate.class); + + BatchDelivery batchDelivery = createTestBatchDeliveryBuilder() + .withClientObjectFactory(objectFactory) + .withIndexTemplate(indexTemplate) + .build(); + + // when + batchDelivery.start(); + + // then + verify(objectFactory).addOperation(any()); + + + + } + + @Test + public void lifecycleStartDoesntSetUpIndexTemplateExecutionIfIndexTemplateIsNotConfigured() { + // given TestHttpObjectFactory objectFactory = spy(createTestObjectFactoryBuilder().build()); - IndexTemplate testIndexTemplate = spy(new IndexTemplate(TEST_INDEX_TEMPLATE, TEST_PATH)); - new TestAsyncBatchDelivery( + BatchDelivery batchDelivery = createTestBatchDeliveryBuilder() + .withClientObjectFactory(objectFactory) + .withIndexTemplate(null) + .build(); + + // when + batchDelivery.start(); + + // then + verify(objectFactory, never()).addOperation(any()); + + } + + @Test + public void lifecycleStartStartsBatchEmitter() { + + // given + BatchEmitter batchEmitter = mock(BatchEmitter.class); + + BatchEmitterServiceProvider batchEmitterFactory = new TestBatchEmitterFactory() { + @Override + public BatchEmitter createInstance(int batchSize, int deliveryInterval, ClientObjectFactory clientObjectFactory, FailoverPolicy failoverPolicy) { + return batchEmitter; + } + }; + + TestAsyncBatchDelivery batchDelivery = spy(new TestAsyncBatchDelivery( TEST_BATCH_SIZE, TEST_DELIVERY_INTERVAL, - objectFactory, + createTestObjectFactoryBuilder().build(), new NoopFailoverPolicy(), - testIndexTemplate); + null) { + @Override + protected BatchEmitterServiceProvider createBatchEmitterServiceProvider() { + return batchEmitterFactory; + } + }); + + // when + batchDelivery.start(); + + // then + verify(batchEmitter).start(); + + } + + @Test + public void lifecycleStart() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + // when + lifeCycle.start(); + + // then + assertFalse(lifeCycle.isStopped()); + assertTrue(lifeCycle.isStarted()); + + } + + @Test + public void lifecycleStop() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + lifeCycle.start(); + assertTrue(lifeCycle.isStarted()); + + // when + lifeCycle.stop(); // then - Mockito.verify(objectFactory, times(1)).execute(eq(testIndexTemplate)); + assertFalse(lifeCycle.isStarted()); + assertTrue(lifeCycle.isStopped()); + + } + + private LifeCycle createLifeCycleTestObject() { + return createTestBatchDeliveryBuilder().build(); } - private static class TestAsyncBatchDelivery extends AsyncBatchDelivery { + static class TestAsyncBatchDelivery extends AsyncBatchDelivery { - public static BatchEmitterServiceProvider mockedProvider; + private BatchEmitterServiceProvider mockedProvider; public TestAsyncBatchDelivery(int batchSize, int deliveryInterval, ClientObjectFactory objectFactory, FailoverPolicy failoverPolicy, IndexTemplate indexTemplate) { super(batchSize, deliveryInterval, objectFactory, failoverPolicy, indexTemplate); diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BulkEmitterTest.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BulkEmitterTest.java index ac1fc723..1f97762d 100644 --- a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BulkEmitterTest.java +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/BulkEmitterTest.java @@ -33,6 +33,8 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Function; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -134,6 +136,47 @@ public void addToBatchBuilderSynchronizedBlock() { } + @Test + public void lifecycleStart() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + // when + lifeCycle.start(); + + // then + assertFalse(lifeCycle.isStopped()); + assertTrue(lifeCycle.isStarted()); + + } + + @Test + public void lifecycleStop() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + lifeCycle.start(); + assertTrue(lifeCycle.isStarted()); + + // when + lifeCycle.stop(); + + // then + assertFalse(lifeCycle.isStarted()); + assertTrue(lifeCycle.isStopped()); + + } + + private BulkEmitter createLifeCycleTestObject() { + return createTestBulkEmitter(TEST_BATCH_SIZE, LARGE_TEST_INTERVAL, new TestBatchOperations()); + } + public static BulkEmitter createTestBulkEmitter(int batchSize, int interval, BatchOperations batchOperations) { return spy(new BulkEmitter(batchSize, interval, batchOperations)); } diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ClientObjectFactoryTest.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ClientObjectFactoryTest.java new file mode 100644 index 00000000..23f5a269 --- /dev/null +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ClientObjectFactoryTest.java @@ -0,0 +1,52 @@ +package org.appenders.log4j2.elasticsearch; + +import org.junit.Test; + +import java.util.Collection; +import java.util.function.Function; + +public class ClientObjectFactoryTest { + + @Test + public void addOperationHasDefaultImpl() { + + // given + ClientObjectFactory factory = new ClientObjectFactory() { + + @Override + public Collection getServerList() { + return null; + } + + @Override + public Object createClient() { + return null; + } + + @Override + public Function createBatchListener(FailoverPolicy failoverPolicy) { + return null; + } + + @Override + public Function createFailureHandler(FailoverPolicy failover) { + return null; + } + + @Override + public BatchOperations createBatchOperations() { + return null; + } + + @Override + public void execute(IndexTemplate indexTemplate) { + + } + }; + + // when + factory.addOperation(() -> {}); + + } + +} diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppenderTest.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppenderTest.java index 1380dfa8..d0391605 100644 --- a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppenderTest.java +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ElasticsearchAppenderTest.java @@ -23,6 +23,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LifeCycle; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.ConfigurationException; import org.apache.logging.log4j.core.filter.ThresholdFilter; @@ -37,12 +38,15 @@ import org.powermock.api.mockito.PowerMockito; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.internal.verification.VerificationModeFactory.times; @@ -52,8 +56,6 @@ public class ElasticsearchAppenderTest { private static final String TEST_APPENDER_NAME = "testAppender"; - private static ItemAppenderFactory mockItemAppenderFactory; - @Test public void builderReturnsNonNullObject() { @@ -114,15 +116,7 @@ public void appenderDelegatesToItemAppender() { when(itemAppenderFactory.createInstance(anyBoolean(), any(AbstractLayout.class), any(BatchDelivery.class))) .thenReturn(itemAppender); - ElasticsearchAppender appender = new TestElasticsearchAppender( - "testAppender", - null, - JsonLayout.newBuilder().build(), - false, - mock(BatchDelivery.class), - false, - mock(IndexNameFormatter.class) - ); + ElasticsearchAppender appender = createTestElasticsearchAppender(itemAppenderFactory); LogEvent logEvent = mock(LogEvent.class); @@ -134,6 +128,27 @@ public void appenderDelegatesToItemAppender() { } + private TestElasticsearchAppender createTestElasticsearchAppender() { + return createTestElasticsearchAppender(mockedItemAppenderFactory()); + } + + private TestElasticsearchAppender createTestElasticsearchAppender(ItemAppenderFactory mockItemAppenderFactory) { + return new TestElasticsearchAppender( + "testAppender", + null, + JsonLayout.newBuilder().build(), + false, + mock(BatchDelivery.class), + false, + mock(IndexNameFormatter.class) + ) { + @Override + protected ItemAppenderFactory createItemAppenderFactory() { + return mockItemAppenderFactory; + } + }; + } + @Test public void appenderUsesProvidedLayoutWhenMessageOnlyIsSetToFalse() { @@ -181,6 +196,94 @@ public void appenderUsesProvidedIndexNameFormatter() { verify(batchDelivery, times(1)).add(eq("formattedIndexName"), any(ItemSource.class)); } + @Test + public void lifecycleStart() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertFalse(lifeCycle.isStarted()); + + // when + lifeCycle.start(); + + // then + assertFalse(lifeCycle.isStopped()); + assertTrue(lifeCycle.isStarted()); + + } + + @Test + public void lifecycleStop() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertFalse(lifeCycle.isStarted()); + + lifeCycle.start(); + assertTrue(lifeCycle.isStarted()); + + // when + lifeCycle.stop(); + + // then + assertFalse(lifeCycle.isStarted()); + assertTrue(lifeCycle.isStopped()); + + } + + @Test + public void lifecycleStartStartsItemAppender() { + + // given + ItemSourceAppender mockItemAppender = mock(ItemSourceAppender.class); + + ItemAppenderFactory itemAppenderFactory = new ItemAppenderFactory() { + @Override + public ItemSourceAppender createInstance(boolean messageOnly, AbstractLayout layout, BatchDelivery batchDelivery) { + return mockItemAppender; + } + }; + + TestElasticsearchAppender appender = createTestElasticsearchAppender(itemAppenderFactory); + + // when + appender.start(); + + // then + verify(mockItemAppender).start(); + + + } + + @Test + public void lifecycleStopStopsItemAppender() { + + // given + ItemSourceAppender mockItemAppender = mock(ItemSourceAppender.class); + + ItemAppenderFactory itemAppenderFactory = new ItemAppenderFactory() { + @Override + public ItemSourceAppender createInstance(boolean messageOnly, AbstractLayout layout, BatchDelivery batchDelivery) { + return mockItemAppender; + } + }; + + TestElasticsearchAppender appender = createTestElasticsearchAppender(itemAppenderFactory); + + // when + appender.stop(); + + // then + verify(mockItemAppender).stop(); + + } + + private LifeCycle createLifeCycleTestObject() { + return createTestElasticsearchAppenderBuilder().build(); + } + private LogEvent createTestLogEvent() { return DefaultLogEventFactory.getInstance().createEvent("testLogger", null, @@ -220,10 +323,7 @@ protected ItemAppenderFactory createItemAppenderFactory() { } private static ItemAppenderFactory mockedItemAppenderFactory() { - if (mockItemAppenderFactory == null) { - mockItemAppenderFactory = mock(ItemAppenderFactory.class); - } - return mockItemAppenderFactory; + return mock(ItemAppenderFactory.class); } } diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ItemSourceAppenderTest.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ItemSourceAppenderTest.java new file mode 100644 index 00000000..aba15f15 --- /dev/null +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/ItemSourceAppenderTest.java @@ -0,0 +1,106 @@ +package org.appenders.log4j2.elasticsearch; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class ItemSourceAppenderTest { + + @Test + public void lifecycleStart() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + // when + lifeCycle.start(); + + // then + assertFalse(lifeCycle.isStopped()); + assertTrue(lifeCycle.isStarted()); + + } + + @Test + public void lifecycleStop() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + lifeCycle.start(); + assertTrue(lifeCycle.isStarted()); + + // when + lifeCycle.stop(); + + // then + assertFalse(lifeCycle.isStarted()); + assertTrue(lifeCycle.isStopped()); + + } + + @Test + public void lifecycleStartStartsBatchDelivery() { + + // given + BatchDelivery batchDelivery = mock(BatchDelivery.class); + ItemAppender itemAppender = new ItemSourceAppender(batchDelivery, logEvent -> null); + + // when + itemAppender.start(); + + // then + verify(batchDelivery).start(); + + } + + @Test + public void lifecycleStopStopsBatchDeliveryIfStarted() { + + // given + BatchDelivery batchDelivery = mock(BatchDelivery.class); + when(batchDelivery.isStarted()).thenReturn(true); + + ItemAppender itemAppender = new ItemSourceAppender(batchDelivery, logEvent -> null); + + // when + itemAppender.stop(); + + // then + verify(batchDelivery).stop(); + + } + + @Test + public void lifecycleStopDoesntStopBatchDeliveryIfNotStarted() { + + // given + BatchDelivery batchDelivery = mock(BatchDelivery.class); + when(batchDelivery.isStarted()).thenReturn(false); + + ItemAppender itemAppender = new ItemSourceAppender(batchDelivery, logEvent -> null); + + // when + itemAppender.stop(); + + // then + verify(batchDelivery, never()).stop(); + + } + + private LifeCycle createLifeCycleTestObject() { + BatchDelivery batchDelivery = mock(BatchDelivery.class); + when(batchDelivery.isStarted()).thenReturn(false); + return new ItemSourceAppender(batchDelivery, logEvent -> null); + } + +} diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/StringAppenderTest.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/StringAppenderTest.java new file mode 100644 index 00000000..add3b53b --- /dev/null +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/StringAppenderTest.java @@ -0,0 +1,107 @@ +package org.appenders.log4j2.elasticsearch; + + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class StringAppenderTest { + + + @Test + public void lifecycleStart() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + // when + lifeCycle.start(); + + // then + assertFalse(lifeCycle.isStopped()); + assertTrue(lifeCycle.isStarted()); + + } + + @Test + public void lifecycleStop() { + + // given + LifeCycle lifeCycle = createLifeCycleTestObject(); + + assertTrue(lifeCycle.isStopped()); + + lifeCycle.start(); + assertTrue(lifeCycle.isStarted()); + + // when + lifeCycle.stop(); + + // then + assertFalse(lifeCycle.isStarted()); + assertTrue(lifeCycle.isStopped()); + + } + + @Test + public void lifecycleStartStartsBatchDelivery() { + + // given + BatchDelivery batchDelivery = mock(BatchDelivery.class); + ItemAppender itemAppender = new StringAppender(batchDelivery, logEvent -> null); + + // when + itemAppender.start(); + + // then + verify(batchDelivery).start(); + + } + + @Test + public void lifecycleStopStopsBatchDeliveryIfStarted() { + + // given + BatchDelivery batchDelivery = mock(BatchDelivery.class); + when(batchDelivery.isStarted()).thenReturn(true); + + ItemAppender itemAppender = new StringAppender(batchDelivery, logEvent -> null); + + // when + itemAppender.stop(); + + // then + verify(batchDelivery).stop(); + + } + + @Test + public void lifecycleStopDoesntStopBatchDeliveryIfNotStarted() { + + // given + BatchDelivery batchDelivery = mock(BatchDelivery.class); + when(batchDelivery.isStarted()).thenReturn(false); + + ItemAppender itemAppender = new StringAppender(batchDelivery, logEvent -> null); + + // when + itemAppender.stop(); + + // then + verify(batchDelivery, never()).stop(); + + } + + private LifeCycle createLifeCycleTestObject() { + BatchDelivery batchDelivery = mock(BatchDelivery.class); + return new StringAppender(batchDelivery, logEvent -> null); + } + +} diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestBatchEmitterFactory.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestBatchEmitterFactory.java index b373c7c0..028bc42f 100644 --- a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestBatchEmitterFactory.java +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestBatchEmitterFactory.java @@ -27,7 +27,7 @@ public class TestBatchEmitterFactory extends BatchEmitterServiceProvider implements BatchEmitterFactory { - private BulkEmitter spiedEmitter; + private BatchEmitter spiedEmitter; @Override public boolean accepts(Class clientObjectFactoryClass) { diff --git a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestHttpObjectFactory.java b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestHttpObjectFactory.java index 98fb601f..feecc459 100644 --- a/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestHttpObjectFactory.java +++ b/log4j2-elasticsearch-core/src/test/java/org/appenders/log4j2/elasticsearch/TestHttpObjectFactory.java @@ -93,6 +93,14 @@ public BatchOperations createBatchOperations() { public void execute(IndexTemplate indexTemplate) { } + @Override + public void addOperation(Operation operation) { + try { + operation.execute(); + } catch (Exception e) { + } + } + protected TestResultHandler createResultHandler(BulkEmitterTest.TestBatch bulk, Function failureHandler) { return new TestResultHandler() { };