package org.stagemonitor.tracing.reporter;
import org.stagemonitor.tracing.B3HeaderFormat;
import org.stagemonitor.tracing.SpanContextInformation;
import org.stagemonitor.tracing.TracingPlugin;
import org.stagemonitor.tracing.wrapper.SpanEventListener;
import org.stagemonitor.tracing.wrapper.SpanEventListenerFactory;
import org.stagemonitor.tracing.wrapper.SpanWrapper;
import org.stagemonitor.util.StringUtils;
import java.util.concurrent.TimeUnit;
import io.opentracing.tag.Tags;
public class ReadbackSpanEventListener implements SpanEventListener {
private static final double MILLISECOND_IN_NANOS = TimeUnit.MILLISECONDS.toNanos(1);
private final ReportingSpanEventListener reportingSpanEventListener;
private final TracingPlugin tracingPlugin;
private ReadbackSpan readbackSpan = new ReadbackSpan();
public ReadbackSpanEventListener(ReportingSpanEventListener reportingSpanEventListener, TracingPlugin tracingPlugin) {
this.reportingSpanEventListener = reportingSpanEventListener;
this.tracingPlugin = tracingPlugin;
}
public static class Factory implements SpanEventListenerFactory {
private final ReportingSpanEventListener reportingSpanEventListener;
private final TracingPlugin tracingPlugin;
public Factory(ReportingSpanEventListener reportingSpanEventListener, TracingPlugin tracingPlugin) {
this.reportingSpanEventListener = reportingSpanEventListener;
this.tracingPlugin = tracingPlugin;
}
@Override
public SpanEventListener create() {
return new ReadbackSpanEventListener(reportingSpanEventListener, tracingPlugin);
}
}
@Override
public void onStart(SpanWrapper spanWrapper) {
if (!isAnyReporterActive(spanWrapper)) {
readbackSpan = null;
}
if (readbackSpan != null) {
tracingPlugin.getTracer().inject(spanWrapper.context(), B3HeaderFormat.INSTANCE, new B3HeaderFormat.B3InjectAdapter() {
@Override
public void setParentId(String value) {
readbackSpan.setParentId(value);
}
@Override
public void setSpanId(String value) {
readbackSpan.setId(value);
}
@Override
public void setTraceId(String value) {
readbackSpan.setTraceId(value);
}
});
}
}
@Override
public String onSetTag(String key, String value) {
if (readbackSpan != null) {
readbackSpan.setTag(key, value);
}
return value;
}
@Override
public boolean onSetTag(String key, boolean value) {
if (readbackSpan != null) {
readbackSpan.setTag(key, value);
}
return value;
}
@Override
public Number onSetTag(String key, Number value) {
if (isNotSampled(key, value)) {
readbackSpan = null;
} else if (readbackSpan != null) {
readbackSpan.setTag(key, value);
}
return value;
}
@Override
public void onFinish(SpanWrapper spanWrapper, String operationName, long durationNanos) {
if (readbackSpan != null) {
readbackSpan.setName(operationName);
readbackSpan.setDuration(durationNanos / MILLISECOND_IN_NANOS);
final String timestamp = StringUtils.timestampAsIsoString(spanWrapper.getStartTimestampMillis());
readbackSpan.setTimestamp(timestamp);
SpanContextInformation.forSpan(spanWrapper).setReadbackSpan(readbackSpan);
}
}
private boolean isNotSampled(String key, Number value) {
return Tags.SAMPLING_PRIORITY.getKey().equals(key) && value.shortValue() <= 0;
}
private boolean isAnyReporterActive(SpanWrapper spanWrapper) {
return reportingSpanEventListener.isAnyReporterActive(SpanContextInformation.forSpan(spanWrapper));
}
}