diff options
3 files changed, 120 insertions, 35 deletions
diff --git a/contrib/zpages/src/main/java/io/opencensus/contrib/zpages/TracezZPageHandler.java b/contrib/zpages/src/main/java/io/opencensus/contrib/zpages/TracezZPageHandler.java index 40e858e9..e8ed9b9f 100644 --- a/contrib/zpages/src/main/java/io/opencensus/contrib/zpages/TracezZPageHandler.java +++ b/contrib/zpages/src/main/java/io/opencensus/contrib/zpages/TracezZPageHandler.java @@ -29,6 +29,7 @@ import io.opencensus.trace.Annotation; import io.opencensus.trace.AttributeValue; import io.opencensus.trace.NetworkEvent; import io.opencensus.trace.NetworkEvent.Type; +import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; import io.opencensus.trace.Status.CanonicalCode; @@ -107,6 +108,10 @@ final class TracezZPageHandler extends ZPageHandler { private static final Tracer tracer = Tracing.getTracer(); // Color to use for zebra-striping. private static final String ZEBRA_STRIPE_COLOR = "#eee"; + // Color for sampled traceIds. + private static final String SAMPLED_TRACE_ID_COLOR = "blue"; + // Color for not sampled traceIds + private static final String NOT_SAMPLED_TRACE_ID_COLOR = "black"; // The header for span name. private static final String HEADER_SPAN_NAME = "zspanname"; // The header for type (running = 0, latency = 1, error = 2) to display. @@ -233,6 +238,7 @@ final class TracezZPageHandler extends ZPageHandler { if (spans != null) { emitSpans(out, formatter, spans); + emitLegend(out); } } } @@ -286,9 +292,10 @@ final class TracezZPageHandler extends ZPageHandler { * 1.0e-9) : String.format("%13s", " "); + SpanContext spanContext = span.getContext(); formatter.format( - "<b>%04d/%02d/%02d-%02d:%02d:%02d.%06d %s TraceId: %s SpanId: %s " - + "ParentSpanId: %s</b>%n", + "<b>%04d/%02d/%02d-%02d:%02d:%02d.%06d %s TraceId: <b style=\"color:%s;\">%s</b> " + + "SpanId: %s ParentSpanId: %s</b>%n", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), @@ -297,8 +304,11 @@ final class TracezZPageHandler extends ZPageHandler { calendar.get(Calendar.SECOND), microsField, elapsedSecondsStr, - BaseEncoding.base16().lowerCase().encode(span.getContext().getTraceId().getBytes()), - BaseEncoding.base16().lowerCase().encode(span.getContext().getSpanId().getBytes()), + spanContext.getTraceOptions().isSampled() + ? SAMPLED_TRACE_ID_COLOR + : NOT_SAMPLED_TRACE_ID_COLOR, + BaseEncoding.base16().lowerCase().encode(spanContext.getTraceId().getBytes()), + BaseEncoding.base16().lowerCase().encode(spanContext.getSpanId().getBytes()), BaseEncoding.base16() .lowerCase() .encode( @@ -511,6 +521,14 @@ final class TracezZPageHandler extends ZPageHandler { } } + private static void emitLegend(PrintWriter out) { + out.write("<br>\n"); + out.printf("<p><b style=\"color:%s;\">TraceId</b> means sampled request. " + + "<b style=\"color:%s;\">TraceId</b> means not sampled request.</p>%n", + SAMPLED_TRACE_ID_COLOR, + NOT_SAMPLED_TRACE_ID_COLOR); + } + private static Map<LatencyBucketBoundaries, String> buildLatencyBucketBoundariesStringMap() { Map<LatencyBucketBoundaries, String> ret = new HashMap<>(); for (LatencyBucketBoundaries latencyBucketBoundaries : LatencyBucketBoundaries.values()) { diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java index 554666bd..fc77a09a 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java @@ -51,25 +51,44 @@ public final class SampledSpanStoreImpl extends SampledSpanStore { private static final class Bucket { - private final EvictingQueue<SpanImpl> queue; - private long lastSampleNanoTime; + private final EvictingQueue<SpanImpl> sampledSpansQueue; + private final EvictingQueue<SpanImpl> notSampledSpansQueue; + private long lastSampledNanoTime; + private long lastNotSampledNanoTime; private Bucket(int numSamples) { - queue = EvictingQueue.create(numSamples); + sampledSpansQueue = EvictingQueue.create(numSamples); + notSampledSpansQueue = EvictingQueue.create(numSamples); } private void considerForSampling(SpanImpl span) { long spanEndNanoTime = span.getEndNanoTime(); - // Need to compare by doing the subtraction all the time because in case of an overflow, - // this may never sample again (at least for the next ~200 years). No real chance to - // overflow two times because that means the process runs for ~200 years. - if (spanEndNanoTime - lastSampleNanoTime > TIME_BETWEEN_SAMPLES) { - queue.add(span); - lastSampleNanoTime = spanEndNanoTime; + if (span.getContext().getTraceOptions().isSampled()) { + // Need to compare by doing the subtraction all the time because in case of an overflow, + // this may never sample again (at least for the next ~200 years). No real chance to + // overflow two times because that means the process runs for ~200 years. + if (spanEndNanoTime - lastSampledNanoTime > TIME_BETWEEN_SAMPLES) { + sampledSpansQueue.add(span); + lastSampledNanoTime = spanEndNanoTime; + } + } else { + // Need to compare by doing the subtraction all the time because in case of an overflow, + // this may never sample again (at least for the next ~200 years). No real chance to + // overflow two times because that means the process runs for ~200 years. + if (spanEndNanoTime - lastNotSampledNanoTime > TIME_BETWEEN_SAMPLES) { + notSampledSpansQueue.add(span); + lastNotSampledNanoTime = spanEndNanoTime; + } } } private void getSamples(int maxSpansToReturn, List<SpanImpl> output) { + getSamples(sampledSpansQueue, maxSpansToReturn, output); + getSamples(notSampledSpansQueue, maxSpansToReturn, output); + } + + private static void getSamples(EvictingQueue<SpanImpl> queue, int maxSpansToReturn, + List<SpanImpl> output) { for (SpanImpl span : queue) { if (output.size() >= maxSpansToReturn) { break; @@ -80,6 +99,14 @@ public final class SampledSpanStoreImpl extends SampledSpanStore { private void getSamplesFilteredByLatency( long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn, List<SpanImpl> output) { + getSamplesFilteredByLatency(sampledSpansQueue, latencyLowerNs, latencyUpperNs, + maxSpansToReturn, output); + getSamplesFilteredByLatency(notSampledSpansQueue, latencyLowerNs, latencyUpperNs, + maxSpansToReturn, output); + } + + private static void getSamplesFilteredByLatency(EvictingQueue<SpanImpl> queue, + long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn, List<SpanImpl> output) { for (SpanImpl span : queue) { if (output.size() >= maxSpansToReturn) { break; @@ -92,7 +119,7 @@ public final class SampledSpanStoreImpl extends SampledSpanStore { } private int getNumSamples() { - return queue.size(); + return sampledSpansQueue.size() + notSampledSpansQueue.size(); } } diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/export/SampledSpanStoreImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/export/SampledSpanStoreImplTest.java index 694e2e2e..87b3bdbe 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/export/SampledSpanStoreImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/export/SampledSpanStoreImplTest.java @@ -61,6 +61,11 @@ public class SampledSpanStoreImplTest { TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.builder().setIsSampled().build()); + private final SpanContext notSampledSpanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.DEFAULT); private final SpanId parentSpanId = SpanId.generateRandomId(random); private final EnumSet<Options> recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); private final TestClock testClock = TestClock.create(Timestamp.create(12345, 54321)); @@ -83,7 +88,7 @@ public class SampledSpanStoreImplTest { sampleStore.registerSpanNamesForCollection(Arrays.asList(REGISTERED_SPAN_NAME)); } - SpanImpl createSpan(String spanName) { + SpanImpl createSampledSpan(String spanName) { SpanImpl span = SpanImpl.startSpan( sampledSpanContext, @@ -98,9 +103,25 @@ public class SampledSpanStoreImplTest { return span; } + SpanImpl createNotSampledSpan(String spanName) { + SpanImpl span = + SpanImpl.startSpan( + notSampledSpanContext, + recordSpanOptions, + spanName, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + null, + testClock); + return span; + } + private void addSpanNameToAllLatencyBuckets(String spanName) { for (LatencyBucketBoundaries boundaries : LatencyBucketBoundaries.values()) { - Span span = createSpan(spanName); + Span sampledSpan = createSampledSpan(spanName); + Span notSampledSpan = createNotSampledSpan(spanName); if (boundaries.getLatencyLowerNs() < NUM_NANOS_PER_SECOND) { testClock.advanceTime(Duration.create(0, (int) boundaries.getLatencyLowerNs())); } else { @@ -109,16 +130,19 @@ public class SampledSpanStoreImplTest { boundaries.getLatencyLowerNs() / NUM_NANOS_PER_SECOND, (int) (boundaries.getLatencyLowerNs() % NUM_NANOS_PER_SECOND))); } - span.end(); + sampledSpan.end(); + notSampledSpan.end(); } } private void addSpanNameToAllErrorBuckets(String spanName) { for (CanonicalCode code : CanonicalCode.values()) { if (code != CanonicalCode.OK) { - Span span = createSpan(spanName); + Span sampledSpan = createSampledSpan(spanName); + Span notSampledSpan = createNotSampledSpan(spanName); testClock.advanceTime(Duration.create(0, 1000)); - span.end(EndSpanOptions.builder().setStatus(code.toStatus()).build()); + sampledSpan.end(EndSpanOptions.builder().setStatus(code.toStatus()).build()); + notSampledSpan.end(EndSpanOptions.builder().setStatus(code.toStatus()).build()); } } } @@ -133,7 +157,7 @@ public class SampledSpanStoreImplTest { perSpanNameSummary.get(REGISTERED_SPAN_NAME).getNumbersOfLatencySampledSpans(); assertThat(latencyBucketsSummaries.size()).isEqualTo(LatencyBucketBoundaries.values().length); for (Map.Entry<LatencyBucketBoundaries, Integer> it : latencyBucketsSummaries.entrySet()) { - assertThat(it.getValue()).isEqualTo(1); + assertThat(it.getValue()).isEqualTo(2); } } @@ -173,7 +197,7 @@ public class SampledSpanStoreImplTest { perSpanNameSummary.get(REGISTERED_SPAN_NAME).getNumbersOfErrorSampledSpans(); assertThat(errorBucketsSummaries.size()).isEqualTo(CanonicalCode.values().length - 1); for (Map.Entry<CanonicalCode, Integer> it : errorBucketsSummaries.entrySet()) { - assertThat(it.getValue()).isEqualTo(1); + assertThat(it.getValue()).isEqualTo(2); } } @@ -188,7 +212,7 @@ public class SampledSpanStoreImplTest { @Test public void getErrorSampledSpans() { - SpanImpl span = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); Collection<SpanData> samples = @@ -200,12 +224,12 @@ public class SampledSpanStoreImplTest { @Test public void getErrorSampledSpans_MaxSpansToReturn() { - SpanImpl span1 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span1.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); // Advance time to allow other spans to be sampled. testClock.advanceTime(Duration.create(5, 0)); - SpanImpl span2 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span2.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); Collection<SpanData> samples = @@ -218,10 +242,10 @@ public class SampledSpanStoreImplTest { @Test public void getErrorSampledSpans_NullCode() { - SpanImpl span1 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span1.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); - SpanImpl span2 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span2.end(EndSpanOptions.builder().setStatus(Status.UNKNOWN).build()); Collection<SpanData> samples = @@ -232,10 +256,10 @@ public class SampledSpanStoreImplTest { @Test public void getErrorSampledSpans_NullCode_MaxSpansToReturn() { - SpanImpl span1 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span1.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); - SpanImpl span2 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span2.end(EndSpanOptions.builder().setStatus(Status.UNKNOWN).build()); Collection<SpanData> samples = @@ -246,7 +270,7 @@ public class SampledSpanStoreImplTest { @Test public void getLatencySampledSpans() { - SpanImpl span = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span.end(); Collection<SpanData> samples = @@ -262,7 +286,7 @@ public class SampledSpanStoreImplTest { @Test public void getLatencySampledSpans_ExclusiveUpperBound() { - SpanImpl span = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span.end(); Collection<SpanData> samples = @@ -277,7 +301,7 @@ public class SampledSpanStoreImplTest { @Test public void getLatencySampledSpans_InclusiveLowerBound() { - SpanImpl span = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span.end(); Collection<SpanData> samples = @@ -293,12 +317,12 @@ public class SampledSpanStoreImplTest { @Test public void getLatencySampledSpans_QueryBetweenMultipleBuckets() { - SpanImpl span1 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span1.end(); // Advance time to allow other spans to be sampled. testClock.advanceTime(Duration.create(5, 0)); - SpanImpl span2 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(200))); span2.end(); Collection<SpanData> samples = @@ -313,12 +337,12 @@ public class SampledSpanStoreImplTest { @Test public void getLatencySampledSpans_MaxSpansToReturn() { - SpanImpl span1 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span1.end(); // Advance time to allow other spans to be sampled. testClock.advanceTime(Duration.create(5, 0)); - SpanImpl span2 = createSpan(REGISTERED_SPAN_NAME); + SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(200))); span2.end(); Collection<SpanData> samples = @@ -331,4 +355,20 @@ public class SampledSpanStoreImplTest { assertThat(samples.size()).isEqualTo(1); assertThat(samples.contains(span1.toSpanData())).isTrue(); } + + @Test + public void ignoreNegativeSpanLatency() { + SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); + testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(-20))); + span.end(); + Collection<SpanData> samples = + sampleStore.getLatencySampledSpans( + LatencyFilter.create( + REGISTERED_SPAN_NAME, + 0, + Long.MAX_VALUE, + 0)); + assertThat(samples.size()).isEqualTo(0); + } + } |
