
com.wavefront.opentracing.WavefrontTracer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wavefront-opentracing-sdk-java Show documentation
Show all versions of wavefront-opentracing-sdk-java Show documentation
Implements OpenTracing API for collecting and sending tracing data to Wavefront from Java applications.
The newest version!
package com.wavefront.opentracing;
import com.wavefront.internal.SpanDerivedMetricsUtils;
import com.wavefront.internal.reporter.WavefrontInternalReporter;
import com.wavefront.internal_reporter_java.io.dropwizard.metrics5.MetricName;
import com.wavefront.opentracing.propagation.Propagator;
import com.wavefront.opentracing.propagation.PropagatorRegistry;
import com.wavefront.opentracing.reporting.CompositeReporter;
import com.wavefront.opentracing.reporting.Reporter;
import com.wavefront.opentracing.reporting.WavefrontSpanReporter;
import com.wavefront.sdk.appagent.jvm.reporter.WavefrontJvmReporter;
import com.wavefront.sdk.common.Pair;
import com.wavefront.sdk.common.Utils;
import com.wavefront.sdk.common.application.ApplicationTags;
import com.wavefront.sdk.common.application.HeartbeaterService;
import com.wavefront.sdk.entities.tracing.sampling.Sampler;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import io.opentracing.Scope;
import io.opentracing.ScopeManager;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import io.opentracing.util.ThreadLocalScopeManager;
import static com.wavefront.sdk.common.Constants.APPLICATION_TAG_KEY;
import static com.wavefront.sdk.common.Constants.CLUSTER_TAG_KEY;
import static com.wavefront.sdk.common.Constants.NULL_TAG_VAL;
import static com.wavefront.sdk.common.Constants.SDK_METRIC_PREFIX;
import static com.wavefront.sdk.common.Constants.SERVICE_TAG_KEY;
import static com.wavefront.sdk.common.Constants.SHARD_TAG_KEY;
import static io.opentracing.tag.Tags.SPAN_KIND;
/**
* The Wavefront OpenTracing tracer for sending distributed traces to Wavefront.
*
* @author Vikram Raman ([email protected])
*/
public class WavefrontTracer implements Tracer, Closeable {
private static final Logger logger = Logger.getLogger(WavefrontTracer.class.getName());
private final ScopeManager scopeManager;
private final PropagatorRegistry registry;
private final Reporter reporter;
private final List> tags;
private final List samplers;
@Nullable
private final WavefrontSpanReporter wfSpanReporter;
@Nullable
private final WavefrontInternalReporter wfInternalReporter;
@Nullable
private final WavefrontInternalReporter wfDerivedReporter;
@Nullable
private final HeartbeaterService heartbeaterService;
@Nullable
private final WavefrontJvmReporter wfJvmReporter;
private final Supplier reportFrequencyMillis;
private final ApplicationTags applicationTags;
private final Set redMetricsCustomTagKeys;
private final boolean addCustomTagsToHeartbeatMetric;
private final boolean useSpanId128Bit;
private final static Pattern WHITESPACE = Pattern.compile("[\\s]+");
private final static String WAVEFRONT_GENERATED_COMPONENT = "wavefront-generated";
private final static String OPENTRACING_COMPONENT = "opentracing";
private final static String JAVA_COMPONENT = "java";
private WavefrontTracer(Builder builder) {
scopeManager = builder.scopeManager;
this.registry = builder.registry;
this.reporter = builder.reporter;
this.tags = builder.tags;
this.samplers = builder.samplers;
this.applicationTags = builder.applicationTags;
this.reportFrequencyMillis = builder.reportingFrequencyMillis;
this.redMetricsCustomTagKeys = builder.redMetricsCustomTagKeys;
this.addCustomTagsToHeartbeatMetric = builder.addCustomTagsToHeartbeatMetric;
this.useSpanId128Bit = builder.useSpanId128Bit;
/**
* Tracing spans will be converted to metrics and histograms and will be reported to Wavefront
* only if you use the WavefrontSpanReporter
*/
wfSpanReporter = getWavefrontSpanReporter(reporter);
if (wfSpanReporter != null) {
Tuple tuple = instantiateWavefrontStatsReporter(wfSpanReporter, builder.applicationTags,
builder.includeJvmMetrics);
wfInternalReporter = tuple.wfInternalReporter;
wfDerivedReporter = tuple.wfDerivedReporter;
wfJvmReporter = tuple.wfJvmReporter;
heartbeaterService = tuple.heartbeaterService;
wfSpanReporter.setMetricsReporter(wfInternalReporter);
} else {
wfInternalReporter = null;
wfDerivedReporter = null;
wfJvmReporter = null;
heartbeaterService = null;
}
}
@Nullable
private WavefrontSpanReporter getWavefrontSpanReporter(Reporter reporter) {
if (reporter instanceof WavefrontSpanReporter) {
return (WavefrontSpanReporter) reporter;
}
if (reporter instanceof CompositeReporter) {
CompositeReporter compositeReporter = (CompositeReporter) reporter;
for (Reporter item : compositeReporter.getReporters()) {
if (item instanceof WavefrontSpanReporter) {
return (WavefrontSpanReporter) item;
}
}
}
// default
return null;
}
private class Tuple {
WavefrontInternalReporter wfInternalReporter;
WavefrontInternalReporter wfDerivedReporter;
@Nullable
WavefrontJvmReporter wfJvmReporter;
HeartbeaterService heartbeaterService;
Tuple(WavefrontInternalReporter wfInternalReporter,
WavefrontInternalReporter wfDerivedReporter,
WavefrontJvmReporter wfJvmReporter,
HeartbeaterService heartbeaterService) {
this.wfInternalReporter = wfInternalReporter;
this.wfDerivedReporter = wfDerivedReporter;
this.wfJvmReporter = wfJvmReporter;
this.heartbeaterService = heartbeaterService;
}
}
private Tuple instantiateWavefrontStatsReporter(
WavefrontSpanReporter wfSpanReporter, ApplicationTags applicationTags,
boolean includeJvmMetrics) {
Map pointTags = new HashMap<>(applicationTags.toPointTags());
WavefrontInternalReporter wfInternalReporter = new WavefrontInternalReporter.Builder().
prefixedWith(SDK_METRIC_PREFIX + ".opentracing").withSource(wfSpanReporter.getSource()).
withReporterPointTags(pointTags).
build(wfSpanReporter.getWavefrontSender());
// Start the internal metrics reporter
wfInternalReporter.start(1, TimeUnit.MINUTES);
double sdkVersion = Utils.getSemVerGauge("wavefront-opentracing-sdk-java");
wfInternalReporter.newGauge(new MetricName("version", Collections.emptyMap()),
() -> (() -> sdkVersion));
WavefrontInternalReporter wfDerivedReporter = new WavefrontInternalReporter.Builder().
prefixedWith("tracing.derived").withSource(wfSpanReporter.getSource()).
withReporterPointTags(pointTags).reportMinuteDistribution().
build(wfSpanReporter.getWavefrontSender());
// Start the derived metrics reporter
wfDerivedReporter.start(reportFrequencyMillis.get(), TimeUnit.MILLISECONDS);
WavefrontJvmReporter wfJvmReporter = null;
if (includeJvmMetrics) {
wfJvmReporter = new WavefrontJvmReporter.Builder(applicationTags).
withSource(wfSpanReporter.getSource()).build(wfSpanReporter.getWavefrontSender());
// Start the JVM reporter
wfJvmReporter.start();
}
HeartbeaterService heartbeaterService = new HeartbeaterService(
wfSpanReporter.getWavefrontSender(), applicationTags,
Arrays.asList(WAVEFRONT_GENERATED_COMPONENT, OPENTRACING_COMPONENT, JAVA_COMPONENT),
wfSpanReporter.getSource());
return new Tuple(wfInternalReporter, wfDerivedReporter, wfJvmReporter, heartbeaterService);
}
@Nullable
WavefrontInternalReporter getWfInternalReporter() {
return wfInternalReporter;
}
@Override
public ScopeManager scopeManager() {
return scopeManager;
}
@Override
public Span activeSpan() {
return scopeManager.activeSpan();
}
@Override
public Scope activateSpan(Span span) {
return this.scopeManager.activate(span);
}
@Override
public SpanBuilder buildSpan(String operationName) {
return new WavefrontSpanBuilder(operationName, this);
}
@Override
public void inject(SpanContext spanContext, Format format, T carrier) {
Propagator propagator = registry.get(format);
if (propagator == null) {
throw new IllegalArgumentException("invalid format: " + format.toString());
}
propagator.inject((WavefrontSpanContext) spanContext, carrier);
}
@Override
public SpanContext extract(Format format, T carrier) {
Propagator propagator = registry.get(format);
if (propagator == null) {
throw new IllegalArgumentException("invalid format: " + format.toString());
}
return propagator.extract(carrier);
}
boolean sample(String operationName, long traceId, long duration) {
return sample(operationName, traceId, duration, true);
}
boolean sample(String operationName, long traceId, long duration, boolean defaultValue) {
if (samplers == null || samplers.isEmpty()) {
return defaultValue;
}
boolean earlySampling = (duration == 0);
for (Sampler sampler : samplers) {
boolean doSample = earlySampling == sampler.isEarly();
if (doSample && sampler.sample(operationName, traceId, duration)) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(sampler.getClass().getSimpleName() + "=" + true +
" op=" + operationName);
}
return true;
}
if (logger.isLoggable(Level.FINER)) {
logger.finer(sampler.getClass().getSimpleName() + "=" + false +
" op=" + operationName);
}
}
return false;
}
void reportWavefrontGeneratedData(WavefrontSpan span) {
if (wfSpanReporter == null || wfDerivedReporter == null) {
// WavefrontSpanReporter not set, so no tracing spans will be reported as metrics/histograms.
return;
}
Pair
© 2015 - 2025 Weber Informatics LLC | Privacy Policy