package org.stagemonitor.tracing.mdc;
import org.slf4j.MDC;
import org.stagemonitor.core.CorePlugin;
import org.stagemonitor.core.MeasurementSession;
import org.stagemonitor.core.Stagemonitor;
import org.stagemonitor.tracing.B3HeaderFormat;
import org.stagemonitor.tracing.TracingPlugin;
import org.stagemonitor.tracing.wrapper.SpanWrapper;
import org.stagemonitor.tracing.wrapper.StatelessSpanEventListener;
/**
* This class adds the {@link MDC} properties requestId, application, host and instance.
* <p/>
* If you are using logback or log4j, you can append this to your pattern to append the properties to each log entry:
* <code>trace:[%X{traceId}] span:[%X{spanId}] A:[%X{application}] H:[%X{host}] I:[%X{instance}]</code>
*/
public class MDCSpanEventListener extends StatelessSpanEventListener {
private final CorePlugin corePlugin;
private final TracingPlugin tracingPlugin;
public MDCSpanEventListener(CorePlugin corePlugin, TracingPlugin tracingPlugin) {
this.corePlugin = corePlugin;
this.tracingPlugin = tracingPlugin;
}
@Override
public void onStart(SpanWrapper spanWrapper) {
if (corePlugin.isStagemonitorActive()) {
final MeasurementSession measurementSession = corePlugin.getMeasurementSession();
if (measurementSession != null) {
addToMdcIfNotNull("application", measurementSession.getApplicationName());
addToMdcIfNotNull("host", measurementSession.getHostName());
addToMdcIfNotNull("instance", measurementSession.getInstanceName());
}
// don't store the context in MDC if stagemonitor is not active
// so that thread pools that get created on startup don't inherit the ids
if (Stagemonitor.isStarted()) {
tracingPlugin.getTracer().inject(spanWrapper.context(), B3HeaderFormat.INSTANCE, new B3HeaderFormat.B3InjectAdapter() {
@Override
public void setParentId(String value) {
addToMdcIfNotNull("parentId", value);
}
@Override
public void setSpanId(String value) {
addToMdcIfNotNull("spanId", value);
}
@Override
public void setTraceId(String value) {
addToMdcIfNotNull("traceId", value);
}
});
}
}
}
@Override
public void onFinish(SpanWrapper spanWrapper, String operationName, long durationNanos) {
// the other keys are not span-scoped hence not removed here
MDC.remove("traceId");
MDC.remove("spanId");
MDC.remove("parentId");
}
private void addToMdcIfNotNull(String key, String value) {
if (value != null) {
MDC.put(key, value);
}
}
}