WingtipsToLightStepLifecycleListener implements SpanLifecycleListener { @Override public void spanCompleted(Span wingtipsSpan) { if (!shouldReportCompletedSpan(wingtipsSpan)) { return; } try { String operationName = wingtipsSpan.getSpanName(); long startTimeMicros = wingtipsSpan.getSpanStartTimeEpochMicros(); long durationMicros = TimeUnit.NANOSECONDS.toMicros(wingtipsSpan.getDurationNanos()); long stopTimeMicros = startTimeMicros + durationMicros; String wtSanitizedSpanId = sanitizeIdIfNecessary(wingtipsSpan.getSpanId(), false); String wtSanitizedTraceId = sanitizeIdIfNecessary(wingtipsSpan.getTraceId(), true); String wtSanitizedParentId = sanitizeIdIfNecessary(wingtipsSpan.getParentSpanId(), false); SpanBuilder lsSpanBuilder = (SpanBuilder) ( tracer.buildSpan(operationName) .withStartTimestamp(wingtipsSpan.getSpanStartTimeEpochMicros()) .ignoreActiveSpan() .withTag("wingtips.span_id", wingtipsSpan.getSpanId()) .withTag("wingtips.trace_id", wingtipsSpan.getTraceId()) .withTag("wingtips.parent_id", String.valueOf(wingtipsSpan.getParentSpanId())) .withTag("span.type", wingtipsSpan.getSpanPurpose().name()) ); long lsSpanId = TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(wtSanitizedSpanId); long lsTraceId = TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(wtSanitizedTraceId); lsSpanBuilder.withTraceIdAndSpanId(lsTraceId, lsSpanId); if (wingtipsSpan.getParentSpanId() != null) { long lsParentId = TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(wtSanitizedParentId); SpanContext lsSpanContext = new SpanContext(lsTraceId, lsParentId); lsSpanBuilder = (SpanBuilder)(lsSpanBuilder.asChildOf(lsSpanContext)); } io.opentracing.Span lsSpan = lsSpanBuilder.start(); for (Span.TimestampedAnnotation wingtipsAnnotation : wingtipsSpan.getTimestampedAnnotations()) { lsSpan.log(wingtipsAnnotation.getTimestampEpochMicros(), wingtipsAnnotation.getValue()); } for (Map.Entry<String, String> wtTag : wingtipsSpan.getTags().entrySet()) { lsSpan.setTag(wtTag.getKey(), wtTag.getValue()); } if (!wtSanitizedSpanId.equals(wingtipsSpan.getSpanId())) { lsSpan.setTag("wingtips.span_id.invalid", true); wingtipsSpan.putTag("sanitized_span_id", wtSanitizedSpanId); } if (!wtSanitizedTraceId.equals(wingtipsSpan.getTraceId())) { lsSpan.setTag("wingtips.trace_id.invalid", true); wingtipsSpan.putTag("sanitized_trace_id", wtSanitizedTraceId); } if (wtSanitizedParentId != null && !wtSanitizedParentId.equals(wingtipsSpan.getParentSpanId())) { lsSpan.setTag("wingtips.parent_id.invalid", true); wingtipsSpan.putTag("sanitized_parent_id", wtSanitizedParentId); } lsSpan.finish(stopTimeMicros); } catch (Exception ex) { long currentBadSpanCount = spanHandlingErrorCounter.incrementAndGet(); long currentTimeMillis = System.currentTimeMillis(); long timeSinceLastLogMsgMillis = currentTimeMillis - lastSpanHandlingErrorLogTimeEpochMillis; if (timeSinceLastLogMsgMillis >= MIN_SPAN_HANDLING_ERROR_LOG_INTERVAL_MILLIS) { lastSpanHandlingErrorLogTimeEpochMillis = currentTimeMillis; lightStepToWingtipsLogger.warn( "There have been {} spans that were not LightStep compatible, or that experienced an error " + "during span handling. Latest example: " + "wingtips_span_with_error=\"{}\", conversion_or_handling_error=\"{}\"", currentBadSpanCount, wingtipsSpan.toKeyValueString(), ex.toString() ); } } } WingtipsToLightStepLifecycleListener(
        @NotNull String serviceName,
        @NotNull String accessToken,
        @NotNull String satelliteUrl,
        int satellitePort
    );  WingtipsToLightStepLifecycleListener(@NotNull JRETracer tracer); @Override void spanSampled(Span wingtipsSpan); @Override void spanStarted(Span wingtipsSpan); @Override void spanCompleted(Span wingtipsSpan);  }
@Test public void spanCompleted_does_not_propagate_unexpected_exception() { doThrow(new RuntimeException("intentional test exception")).when(jreTracerMock).buildSpan(anyString()); Span completedSpan = Span.newBuilder("fooSpan", Span.SpanPurpose.CLIENT).build(); completedSpan.close(); Throwable ex = catchThrowable(() -> listener.spanCompleted(completedSpan)); verify(jreTracerMock).buildSpan(anyString()); assertThat(ex).isNull(); }
@Test public void spanCompleted_does_nothing_if_span_is_not_sampleable() { doReturn(false).when(spanMock).isSampleable(); listener.spanCompleted(spanMock); verify(spanMock).isSampleable(); verifyNoMoreInteractions(spanMock); verifyNoInteractions(jreTracerMock, lsSpanBuilderMock); }