Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/main/java/net/logstash/logback/LifeCycleManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.logstash.logback;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import ch.qos.logback.core.spi.LifeCycle;

/**
* Manages the lifecycle of subcomponents.
*
* <p>Specifically:</p>
*
* <ul>
* <li>Only starts a subcomponent if the subcomponent is not already started.</li>
* <li>Only stops a subcomponent if this lifecycle manager started the subcomponent.</li>
* </ul>
*/
public class LifeCycleManager {

private final Set<LifeCycle> started = Collections.newSetFromMap(new ConcurrentHashMap<>());

/**
* Starts the given lifecycle component if and only if it is not already started.
*
* @param lifeCycle the component to start
* @return true if this method execution started the component
*/
public boolean start(LifeCycle lifeCycle) {
if (lifeCycle.isStarted()) {
return false;
}
lifeCycle.start();
started.add(lifeCycle);
return true;
}

/**
* Stops the given lifecycle component if and only if it is currently started,
* AND was started by this lifecycle manager via {@link #start(LifeCycle)}.
*
* @param lifeCycle the component to stop
* @return true if this method execution stopped the component
*/
public boolean stop(LifeCycle lifeCycle) {
if (!lifeCycle.isStarted()) {
return false;
}
if (!started.remove(lifeCycle)) {
return false;
}
lifeCycle.stop();
return true;
}

/**
* Stops all of the lifecycle components that were started by {@link #start(LifeCycle)}
* and are currently started.
*
* @return the lifecycle components that this method execution stopped
*/
public Set<LifeCycle> stopAll() {
Set<LifeCycle> stopped = new HashSet<>();

for (Iterator<LifeCycle> iterator = started.iterator(); iterator.hasNext();) {
LifeCycle lifeCycle = iterator.next();
if (lifeCycle.isStarted()) {
lifeCycle.stop();
stopped.add(lifeCycle);
}
iterator.remove();
}
return Collections.unmodifiableSet(stopped);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import net.logstash.logback.LifeCycleManager;
import net.logstash.logback.appender.destination.DelegateDestinationConnectionStrategy;
import net.logstash.logback.appender.destination.DestinationConnectionStrategy;
import net.logstash.logback.appender.destination.DestinationParser;
Expand Down Expand Up @@ -359,6 +360,11 @@ private class TcpSendingEventHandler implements EventHandler<LogEvent<Event>>, L
*/
private Future<?> readerFuture;

/**
* Manages the lifecycle of subcomponents
*/
private final LifeCycleManager lifecycleManager = new LifeCycleManager();

/**
* When run, if the {@link AbstractLogstashTcpSocketAppender#keepAliveDuration}
* has elapsed since the last event was sent,
Expand Down Expand Up @@ -631,6 +637,7 @@ private boolean hasKeepAliveDurationElapsed(long lastSentNanoTime, long currentN
public void onStart() {
this.destinationAttemptStartTimes = new long[destinations.size()];
openSocket();
lifecycleManager.start(encoder);
scheduleKeepAlive(System.nanoTime());
scheduleWriteTimeout();
}
Expand All @@ -639,7 +646,7 @@ public void onStart() {
public void onShutdown() {
unscheduleWriteTimeout();
unscheduleKeepAlive();
closeEncoder();
lifecycleManager.stop(encoder);
closeSocket();
}

Expand Down Expand Up @@ -788,10 +795,6 @@ private synchronized void closeSocket() {
}
}

private void closeEncoder() {
encoder.stop();
}

private synchronized void scheduleKeepAlive(long basedOnNanoTime) {
if (isKeepAliveEnabled() && !Thread.currentThread().isInterrupted()) {
if (keepAliveRunnable == null) {
Expand Down Expand Up @@ -967,10 +970,6 @@ public synchronized void start() {
if (errorCount == 0) {

encoder.setContext(getContext());
if (!encoder.isStarted()) {
encoder.start();
}

/*
* Increase the core size to handle the reader thread
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import ch.qos.logback.core.net.SyslogAppenderBase;
import ch.qos.logback.core.net.SyslogOutputStream;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import net.logstash.logback.LifeCycleManager;
import net.logstash.logback.appender.listener.AppenderListener;

/**
Expand All @@ -40,6 +41,11 @@ public class AbstractLogstashUdpSocketAppender<Event extends DeferredProcessingA

private SyslogOutputStream syslogOutputStream;

/**
* Manages the lifecycle of subcomponents
*/
private final LifeCycleManager lifecycleManager = new LifeCycleManager();

public AbstractLogstashUdpSocketAppender() {
setFacility("NEWS"); // NOTE: this value is never used
}
Expand All @@ -53,15 +59,15 @@ public void start() {

super.start();
if (isStarted()) {
getLayout().start();
lifecycleManager.start(getLayout());
fireAppenderStarted();
}
}

@Override
public void stop() {
super.stop();
getLayout().stop();
lifecycleManager.stop(getLayout());
fireAppenderStopped();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import ch.qos.logback.core.status.OnConsoleStatusListener;
import ch.qos.logback.core.status.Status;
import net.logstash.logback.LifeCycleManager;
import net.logstash.logback.appender.listener.AppenderListener;
import ch.qos.logback.access.spi.IAccessEvent;
import ch.qos.logback.classic.AsyncAppender;
Expand Down Expand Up @@ -248,6 +249,11 @@ public abstract class AsyncDisruptorAppender<Event extends DeferredProcessingAwa
*/
protected final List<Listener> listeners = new ArrayList<>();

/**
* Manages the lifecycle of subcomponents
*/
private final LifeCycleManager lifecycleManager = new LifeCycleManager();

/**
* Event wrapper object used for each element of the {@link RingBuffer}.
*/
Expand Down Expand Up @@ -369,7 +375,7 @@ public void start() {
statusListener.setLevelValue(Status.WARN);
statusListener.setDelegate(new OnConsoleStatusListener());
statusListener.setContext(getContext());
statusListener.start();
lifecycleManager.start(statusListener);
getStatusManager().add(statusListener);
}

Expand Down Expand Up @@ -439,6 +445,8 @@ public void stop() {
} catch (InterruptedException e) {
addWarn("Some queued events have not been logged due to requested shutdown", e);
}

lifecycleManager.stopAll();
fireAppenderStopped();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import ch.qos.logback.core.spi.AppenderAttachable;
import ch.qos.logback.core.spi.AppenderAttachableImpl;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import net.logstash.logback.LifeCycleManager;
import net.logstash.logback.appender.listener.AppenderListener;

/**
Expand All @@ -52,7 +53,12 @@ public abstract class DelegatingAsyncDisruptorAppender<Event extends DeferredPro
* The delegate appenders.
*/
private final AppenderAttachableImpl<Event> appenders = new AppenderAttachableImpl<Event>();


/**
* Manages the lifecycle of subcomponents
*/
private final LifeCycleManager lifecycleManager = new LifeCycleManager();

private class DelegatingEventHandler implements EventHandler<LogEvent<Event>> {
/**
* Whether exceptions should be reported with a error status or not.
Expand Down Expand Up @@ -142,18 +148,14 @@ private void startDelegateAppenders() {
if (appender.getContext() == null) {
appender.setContext(getContext());
}
if (!appender.isStarted()) {
appender.start();
}
lifecycleManager.start(appender);
}
}

private void stopDelegateAppenders() {
for (Iterator<Appender<Event>> appenderIter = appenders.iteratorForAppenders(); appenderIter.hasNext();) {
Appender<Event> appender = appenderIter.next();
if (appender.isStarted()) {
appender.stop();
}
lifecycleManager.stop(appender);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ch.qos.logback.access.spi.IAccessEvent;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import net.logstash.logback.LifeCycleManager;

/**
* A {@link JsonProvider} that nests other providers within a subobject.
Expand All @@ -35,21 +36,26 @@ public abstract class AbstractNestedJsonProvider<Event extends DeferredProcessin
* The providers that are used to populate the output nested JSON object.
*/
private JsonProviders<Event> jsonProviders = new JsonProviders<Event>();


/**
* Manages the lifecycle of subcomponents
*/
private final LifeCycleManager lifecycleManager = new LifeCycleManager();

public AbstractNestedJsonProvider() {
setFieldName(FIELD_NESTED);
}

@Override
public void start() {
super.start();
getProviders().start();
lifecycleManager.start(getProviders());
}

@Override
public void stop() {
super.stop();
getProviders().stop();
lifecycleManager.stop(getProviders());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.lang.ref.SoftReference;
import java.util.ServiceConfigurationError;

import net.logstash.logback.LifeCycleManager;
import net.logstash.logback.decorate.JsonFactoryDecorator;
import net.logstash.logback.decorate.JsonGeneratorDecorator;
import net.logstash.logback.decorate.NullJsonFactoryDecorator;
Expand Down Expand Up @@ -86,6 +87,11 @@ protected SoftReference<BufferRecycler> initialValue() {
*/
private JsonProviders<Event> jsonProviders = new JsonProviders<Event>();

/**
* Manages the lifecycle of subcomponents
*/
private final LifeCycleManager lifecycleManager = new LifeCycleManager();

private JsonEncoding encoding = JsonEncoding.UTF8;

private boolean findAndRegisterJacksonModules = true;
Expand All @@ -104,13 +110,13 @@ public void start() {
jsonFactory = createJsonFactory();
jsonProviders.setContext(context);
jsonProviders.setJsonFactory(jsonFactory);
jsonProviders.start();
lifecycleManager.start(jsonProviders);
started = true;
}

@Override
public void stop() {
jsonProviders.stop();
lifecycleManager.stop(jsonProviders);
started = false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,8 @@ public void setCustomFieldsNode(JsonNode customFields) {
@Override
public void setJsonFactory(JsonFactory jsonFactory) {
this.jsonFactory = jsonFactory;
if (isStarted()) {
initializeCustomFields();
}
}
}
Loading