Java Code Examples for com.nike.wingtips.Span#getTimestampedAnnotations()

The following examples show how to use com.nike.wingtips.Span#getTimestampedAnnotations() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SpanParser.java    From wingtips with Apache License 2.0 5 votes vote down vote up
/**
 * Calculates and returns the key/value representation of this span instance. Keys are not surrounded by quotes,
 * but values are. Both keys and values are escaped via {@link #escapeJson(String)}, with keys further being
 * escaped to replace equals '=' and spaces ' ' with their escaped-unicode equivalents. Tag keys will be prefixed
 * with {@link #KEY_VALUE_TAG_PREFIX}. Timestamped annotations will be prefixed with {@link
 * #KEY_VALUE_TIMESTAMPED_ANNOTATION_PREFIX}.
 *
 * <p>NOTE: You should call {@link Span#toKeyValueString()} directly instead of this method, as that {@link
 * Span#toKeyValueString()} instance method caches the result. This can have significant performance impact in some
 * scenarios.
 */
public static String convertSpanToKeyValueFormat(Span span) {
    StringBuilder builder = new StringBuilder();

    builder.append(TRACE_ID_FIELD).append("=\"").append(escapeJson(span.getTraceId())).append('\"');
    builder.append(",").append(PARENT_SPAN_ID_FIELD).append("=\"").append(escapeJson(span.getParentSpanId())).append('\"');
    builder.append(",").append(SPAN_ID_FIELD).append("=\"").append(escapeJson(span.getSpanId())).append('\"');
    builder.append(",").append(SPAN_NAME_FIELD).append("=\"").append(escapeJson(span.getSpanName())).append('\"');
    builder.append(",").append(SAMPLEABLE_FIELD).append("=\"").append(span.isSampleable()).append('\"');
    builder.append(",").append(USER_ID_FIELD).append("=\"").append(escapeJson(span.getUserId())).append('\"');
    builder.append(",").append(SPAN_PURPOSE_FIELD).append("=\"").append(span.getSpanPurpose().name()).append('\"');
    builder.append(",").append(START_TIME_EPOCH_MICROS_FIELD).append("=\"").append(span.getSpanStartTimeEpochMicros()).append('\"');

    // Only output duration if the span is completed.
    if (span.isCompleted()) {
        builder.append(",").append(DURATION_NANOS_FIELD).append("=\"").append(span.getDurationNanos()).append('\"');
    }

    // Output tags if we have any.
    for (Map.Entry<String, String> tagEntry : span.getTags().entrySet()) {
        String sanitizedTagKey = escapeTagKeyForKeyValueFormatSerialization(tagEntry.getKey());

        String escapedTagValue = escapeJson(tagEntry.getValue());
        builder.append(",").append(KEY_VALUE_TAG_PREFIX).append(sanitizedTagKey)
               .append("=\"").append(escapedTagValue).append('\"');
    }

    // Output timestamped annotations if we have any.
    for (TimestampedAnnotation annotation : span.getTimestampedAnnotations()) {
        String escapedAnnotationValue = escapeJson(annotation.getValue());
        builder.append(",").append(KEY_VALUE_TIMESTAMPED_ANNOTATION_PREFIX)
               .append(annotation.getTimestampEpochMicros())
               .append("=\"").append(escapedAnnotationValue).append('\"');
    }

    return builder.toString();
}
 
Example 2
Source File: WingtipsToLightStepLifecycleListener.java    From wingtips with Apache License 2.0 4 votes vote down vote up
@Override
public void spanCompleted(Span wingtipsSpan) {
    try {
        String operationName = wingtipsSpan.getSpanName();
        long startTimeMicros = wingtipsSpan.getSpanStartTimeEpochMicros();

        // Given we should only be in this method on span completion, we are not going to wrap this conversion in a
        // try/catch. duration should be set on the Wingtips span.
        long durationMicros = TimeUnit.NANOSECONDS.toMicros(wingtipsSpan.getDurationNanos());
        long stopTimeMicros = startTimeMicros + durationMicros;

        // Sanitize the wingtips trace/span/parent IDs if necessary. This guarantees we can convert them to
        //      longs as required by LightStep.
        String wtSanitizedSpanId = sanitizeIdIfNecessary(wingtipsSpan.getSpanId(), false);
        String wtSanitizedTraceId = sanitizeIdIfNecessary(wingtipsSpan.getTraceId(), true);
        String wtSanitizedParentId = sanitizeIdIfNecessary(wingtipsSpan.getParentSpanId(), false);

        // Handle the common SpanBuilder settings.
        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())
        );

        // Force the LightStep span to have a Trace ID and Span ID matching the Wingtips span.
        //      NOTE: LightStep requires Ids to be longs, so we convert the sanitized wingtips trace/span IDs.
        long lsSpanId = TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(wtSanitizedSpanId);
        long lsTraceId = TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(wtSanitizedTraceId);
        lsSpanBuilder.withTraceIdAndSpanId(lsTraceId, lsSpanId);

        // Handle the parent ID / parent context SpanBuilder settings.
        if (wingtipsSpan.getParentSpanId() != null) {
            long lsParentId = TraceAndSpanIdGenerator.unsignedLowerHexStringToLong(wtSanitizedParentId);

            SpanContext lsSpanContext = new SpanContext(lsTraceId, lsParentId);

            lsSpanBuilder = (SpanBuilder)(lsSpanBuilder.asChildOf(lsSpanContext));
        }

        // Start the OT span and set logs and tags from the wingtips span.
        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());
        }

        // Add some custom boolean tags if any of the IDs had to be sanitized. The raw unsanitized ID will be
        //      available via the wingtips.*_id tags.
        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);
        }

        // on finish, the tracer library initialized on the creation of this listener will cache and transport the span
        // data to the LightStep Satellite.
        lsSpan.finish(stopTimeMicros);
    } catch (Exception ex) {
        long currentBadSpanCount = spanHandlingErrorCounter.incrementAndGet();
        // Adopted from WingtipsToZipkinLifecycleListener from Wingtips-Zipkin2 plugin.
        // Only log once every MIN_SPAN_HANDLING_ERROR_LOG_INTERVAL_MILLIS time interval to prevent log spam from a
        // malicious (or broken) caller.
        long currentTimeMillis = System.currentTimeMillis();
        long timeSinceLastLogMsgMillis = currentTimeMillis - lastSpanHandlingErrorLogTimeEpochMillis;

        if (timeSinceLastLogMsgMillis >= MIN_SPAN_HANDLING_ERROR_LOG_INTERVAL_MILLIS) {
            // We're not synchronizing the read and write to lastSpanHandlingErrorLogTimeEpochMillis, and that's ok.
            // If we get a few extra log messages due to a race condition it's not the end of the world - we're
            // still satisfying the goal of not allowing a malicious caller to endlessly spam the logs.
            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()
            );
        }
    }
}
 
Example 3
Source File: WingtipsToZipkinSpanConverterDefaultImpl.java    From wingtips with Apache License 2.0 4 votes vote down vote up
@Override
public zipkin2.Span convertWingtipsSpanToZipkinSpan(Span wingtipsSpan, Endpoint zipkinEndpoint) {
    long durationMicros = TimeUnit.NANOSECONDS.toMicros(wingtipsSpan.getDurationNanos());

    String spanId = sanitizeIdIfNecessary(wingtipsSpan.getSpanId(), false);
    String traceId = sanitizeIdIfNecessary(wingtipsSpan.getTraceId(), true);
    String parentId = sanitizeIdIfNecessary(wingtipsSpan.getParentSpanId(), false);

    final zipkin2.Span.Builder spanBuilder = zipkin2.Span
        .newBuilder()
        .id(spanId)
        .name(wingtipsSpan.getSpanName())
        .parentId(parentId)
        .traceId(traceId)
        .timestamp(wingtipsSpan.getSpanStartTimeEpochMicros())
        .duration(durationMicros)
        .localEndpoint(zipkinEndpoint)
        .kind(determineZipkinKind(wingtipsSpan));
    
    // Iterate over existing wingtips tags and add them to the zipkin builder.
    for (Map.Entry<String, String> tagEntry : wingtipsSpan.getTags().entrySet()) {
        spanBuilder.putTag(tagEntry.getKey(), tagEntry.getValue());
    }
        
    if (!spanId.equals(wingtipsSpan.getSpanId())) {
        spanBuilder.putTag("invalid.span_id", wingtipsSpan.getSpanId());
        wingtipsSpan.putTag("sanitized_span_id", spanId);
    }
    if (!traceId.equals(wingtipsSpan.getTraceId())) {
        spanBuilder.putTag("invalid.trace_id", wingtipsSpan.getTraceId());
        wingtipsSpan.putTag("sanitized_trace_id", traceId);
    }
    if (parentId != null && !parentId.equals(wingtipsSpan.getParentSpanId())) {
        spanBuilder.putTag("invalid.parent_id", wingtipsSpan.getParentSpanId());
        wingtipsSpan.putTag("sanitized_parent_id", parentId);
    }

    // Iterate over existing wingtips annotations and add them to the zipkin builder.
    for (TimestampedAnnotation wingtipsAnnotation : wingtipsSpan.getTimestampedAnnotations()) {
        spanBuilder.addAnnotation(wingtipsAnnotation.getTimestampEpochMicros(), wingtipsAnnotation.getValue());
    }
    
    return spanBuilder.build();
}