SpanParser { 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('\"'); if (span.isCompleted()) { builder.append(",").append(DURATION_NANOS_FIELD).append("=\"").append(span.getDurationNanos()).append('\"'); } 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('\"'); } 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(); } protected  SpanParser(); static String convertSpanToJSON(Span span); static Span fromJSON(String json); static String convertSpanToKeyValueFormat(Span span); static Span fromKeyValueString(String keyValueStr); static String escapeJson(String orig); static String unescapeJson(String escaped); static final String TRACE_ID_FIELD; static final String PARENT_SPAN_ID_FIELD; static final String SPAN_ID_FIELD; static final String SPAN_NAME_FIELD; static final String SAMPLEABLE_FIELD; static final String USER_ID_FIELD; static final String SPAN_PURPOSE_FIELD; static final String START_TIME_EPOCH_MICROS_FIELD; static final String DURATION_NANOS_FIELD; static final String TAGS_FIELD; static final String ANNOTATIONS_LIST_FIELD; static final String ANNOTATION_SUBOBJECT_TIMESTAMP_FIELD; static final String ANNOTATION_SUBOBJECT_VALUE_FIELD; static final String KEY_VALUE_TAG_PREFIX; static final String KEY_VALUE_TIMESTAMPED_ANNOTATION_PREFIX; }
@UseDataProvider("tagAndAnnotationScenarioDataProvider") @Test public void convertSpanToKeyValueFormat_should_function_properly_when_there_are_no_null_values( TagAndAnnotationScenario scenario ) { Span validSpan = createFilledOutSpan(true, scenario.tags, scenario.annotations); assertThat(validSpan.getTraceId()).isNotEmpty(); assertThat(validSpan.getUserId()).isNotEmpty(); assertThat(validSpan.getParentSpanId()).isNotEmpty(); assertThat(validSpan.getSpanName()).isNotEmpty(); assertThat(validSpan.getSpanId()).isNotEmpty(); assertThat(validSpan.getDurationNanos()).isNotNull(); assertThat(validSpan.isCompleted()).isTrue(); assertThat(validSpan.getSpanPurpose()).isNotNull(); assertThat(validSpan.getTags()).isEqualTo(scenario.tags); assertThat(validSpan.getTimestampedAnnotations()).isEqualTo(scenario.annotations); String keyValueStr = SpanParser.convertSpanToKeyValueFormat(validSpan); Map<String, Object> deserializedValues = deserializeKeyValueSpanString(keyValueStr); verifySpanEqualsDeserializedValues(validSpan, deserializedValues); }
@Test public void convertSpanToKeyValueFormat_should_function_properly_when_there_are_null_values() { Span validSpan = Span.generateRootSpanForNewTrace(spanName, null).build(); assertThat(validSpan.getParentSpanId()).isNull(); assertThat(validSpan.getUserId()).isNull(); assertThat(validSpan.getDurationNanos()).isNull(); String keyValueStr = SpanParser.convertSpanToKeyValueFormat(validSpan); Map<String, Object> deserializedValues = deserializeKeyValueSpanString(keyValueStr); verifySpanEqualsDeserializedValues(validSpan, deserializedValues); }
@Test public void convertSpanToKeyValueFormat_should_function_properly_for_non_completed_spans() { Span validSpan = Span.generateRootSpanForNewTrace(spanName, spanPurpose).build(); assertThat(validSpan.isCompleted()).isFalse(); String keyValueStr = SpanParser.convertSpanToKeyValueFormat(validSpan); Map<String, Object> deserializedValues = deserializeKeyValueSpanString(keyValueStr); verifySpanEqualsDeserializedValues(validSpan, deserializedValues); }
@Test public void convertSpanToKeyValueFormat_should_function_properly_for_completed_spans() { Span validSpan = Span.generateRootSpanForNewTrace(spanName, spanPurpose).build(); completeSpan(validSpan); assertThat(validSpan.isCompleted()).isTrue(); String keyValueStr = SpanParser.convertSpanToKeyValueFormat(validSpan); Map<String, Object> deserializedValues = deserializeKeyValueSpanString(keyValueStr); verifySpanEqualsDeserializedValues(validSpan, deserializedValues); }