String escapedValue = escapeJson(annotation.getValue()); .append("\":\"").append(annotation.getTimestampEpochMicros()).append('\"');
annotationsList.add(TimestampedAnnotation.forEpochMicros(timestamp, value));
@Test public void TimestampedAnnotation_forEpochMicrosWithNanoOffset_works_as_expected() { // given long timestampMicros = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()); long nanoOffset = 4242; String value = UUID.randomUUID().toString(); long expectedMicrosOffset = TimeUnit.NANOSECONDS.toMicros(nanoOffset); assertThat(expectedMicrosOffset).isGreaterThan(0); long expectedTimestamp = timestampMicros + expectedMicrosOffset; assertThat(expectedTimestamp).isNotEqualTo(timestampMicros); // when TimestampedAnnotation result = TimestampedAnnotation.forEpochMicrosWithNanoOffset( timestampMicros, nanoOffset, value ); // then assertThat(result.getTimestampEpochMicros()).isEqualTo(expectedTimestamp); assertThat(result.getValue()).isEqualTo(value); } }
subspan.addTimestampedAnnotation(TimestampedAnnotation.forEpochMicrosWithNanoOffset( subspan.getSpanStartTimeEpochMicros(), -connectionSetupTimeNanos, subspan.addTimestampedAnnotation(TimestampedAnnotation.forEpochMicros( subspan.getSpanStartTimeEpochMicros(), proxySpanTaggingStrategy.connFinishAnnotationName()
subspan.addTimestampedAnnotation(TimestampedAnnotation.forEpochMicrosWithNanoOffset( subspan.getSpanStartTimeEpochMicros(), -connectionSetupTimeNanos, subspan.addTimestampedAnnotation(TimestampedAnnotation.forEpochMicros( subspan.getSpanStartTimeEpochMicros(), proxySpanTaggingStrategy.connFinishAnnotationName()
span, distributedTracingConfig.getServerSpanNamingAndTaggingStrategy().wireReceiveStartAnnotationName() ); Assertions.assertThat(wireReceiveStartAnnotation.getTimestampEpochMicros()) .isBetween(span.getSpanStartTimeEpochMicros(), expectedMaxWireReceiveStartTimestamp);
.map( a -> MapBuilder.builder( SpanParser.ANNOTATION_SUBOBJECT_TIMESTAMP_FIELD, String.valueOf(a.getTimestampEpochMicros()) ).put( SpanParser.ANNOTATION_SUBOBJECT_VALUE_FIELD, a.getValue() ).build()
long expectedMaxTimestamp = span.getSpanStartTimeEpochMicros() + maxPossibleOffsetMicros; assertThat(span.getTimestampedAnnotations().get(0).getTimestampEpochMicros()) .isBetween(expectedMinTimestamp, expectedMaxTimestamp);
spanBuilder.addAnnotation(wingtipsAnnotation.getTimestampEpochMicros(), wingtipsAnnotation.getValue());
span.getSpanStartTimeEpochMicros() + TimeUnit.NANOSECONDS.toMicros(nanosAfter - nanosBefore); TimestampedAnnotation wireReceiveStartAnnotation = findAnnotationInSpan(span, "wr.start"); Assertions.assertThat(wireReceiveStartAnnotation.getTimestampEpochMicros()) .isBetween(span.getSpanStartTimeEpochMicros(), expectedMaxWireReceiveStartTimestamp);
String escapedAnnotationValue = escapeJson(annotation.getValue()); builder.append(",").append(KEY_VALUE_TIMESTAMPED_ANNOTATION_PREFIX) .append(annotation.getTimestampEpochMicros()) .append("=\"").append(escapedAnnotationValue).append('\"');
spanBuilder.addAnnotation(wingtipsAnnotation.getTimestampEpochMicros(), wingtipsAnnotation.getValue());
/** * Adds a {@link TimestampedAnnotation} to this Span's {@link #getTimestampedAnnotations()} list, with the current * time in epoch microseconds as the timestamp and the given value. * * <p>NOTE: Since the span keeps track of its duration in nanoseconds, this method results in a * {@link TimestampedAnnotation} with a {@link TimestampedAnnotation#getTimestampEpochMicros()} that is more * accurate than if you created the {@link TimestampedAnnotation} directly (i.e. this method uses {@link * TimestampedAnnotation#forEpochMicrosWithNanoOffset(long, long, String)}). This method should therefore be * used anytime you want to add an annotation to a Span with a timestamp of "right now". * * @param value The desired {@link TimestampedAnnotation#getValue()} for the new annotation. */ public void addTimestampedAnnotationForCurrentTime(String value) { addTimestampedAnnotation( TimestampedAnnotation.forEpochMicrosWithNanoOffset( spanStartTimeEpochMicros, System.nanoTime() - spanStartTimeNanos, value ) ); }
/** * A convenience static factory method that lets you generate an instance of {@link TimestampedAnnotation} * with a timestamp of "right now", however unfortunately that "right now" timestamp will have a resolution of * only epoch milliseconds. This epoch millisecond resolution is the best we can do, because without more info * we don't have anything more accurate than {@link System#currentTimeMillis()}. * * <p>NOTE: {@link Span}s keep track of nanosecond duration, so {@link * Span#addTimestampedAnnotation(TimestampedAnnotation)} is able to give a more accurate timestamp than this * method by calling {@link #forEpochMicrosWithNanoOffset(long, long, String)} with the nanosecond offset. * Since {@link Span#addTimestampedAnnotation(TimestampedAnnotation)} is more accurate, you should use that * method directly on the {@link Span} rather than this method whenever possible. * * @param value The value to associate with the "right now" timestamp. * @return A new {@link TimestampedAnnotation} with a timestamp of {@link System#currentTimeMillis()} * (converted to microseconds), and the given value. */ public static TimestampedAnnotation forCurrentTime(String value) { return forEpochMillis(System.currentTimeMillis(), value); }
@UseDataProvider("escapedAndUnescapedQuotesBeforeKeyOrValueEndScenarioDataProvider") @Test public void fromJSON_properly_handles_escaped_quotes_and_unescaped_quotes_preceded_by_backslashes( EscapedAndUnescapedQuotesBeforeKeyOrValueEndScenario scenario ) { // given Span span = Span.newBuilder("someSpan", SpanPurpose.CLIENT) .withTag(scenario.unescapedKey, scenario.unescapedValue) .withTimestampedAnnotation( TimestampedAnnotation.forEpochMicros(1234, scenario.unescapedValue) ) .build(); String json = SpanParser.convertSpanToJSON(span); // when Span result = SpanParser.fromJSON(json); // then assertThat(result.getTags().get(scenario.unescapedKey)).isEqualTo(scenario.unescapedValue); assertThat(result.getTimestampedAnnotations().get(0).getValue()).isEqualTo(scenario.unescapedValue); }
/** * A convenience static factory method that lets you generate an instance of {@link TimestampedAnnotation} * with a timestamp based on the given timestamp, but offset by the given nanosecond offset value. This * method can be used to create instances of {@link TimestampedAnnotation} that have a more accurate * timestamp than simply {@link System#currentTimeMillis()} converted to microseconds. * * @param timestampEpochMicros The timestamp in epoch microseconds (not milliseconds). * @param offsetNanos The offset (in nanoseconds) to apply to the given timestamp in order to come up with * the desired final timestamp. * @param value The value to associate with the resulting timestamp. * @return A new {@link TimestampedAnnotation} with a final timestamp calculated by adding the given timestamp * and offset, and with the given value. */ public static TimestampedAnnotation forEpochMicrosWithNanoOffset( long timestampEpochMicros, long offsetNanos, String value ) { long offsetMicros = TimeUnit.NANOSECONDS.toMicros(offsetNanos); return forEpochMicros(timestampEpochMicros + offsetMicros, value); }
private void verifySpanAnnotation( Span span, String annotationName, boolean annotationShouldExist, AtomicInteger expectedNumAnnotationsCounter, AtomicLong minAnnotationTimestamp ) { TimestampedAnnotation annotation = findSpanAnnotation(span, annotationName); if (annotationShouldExist) { assertThat(annotation).isNotNull(); expectedNumAnnotationsCounter.incrementAndGet(); assertThat(annotation.getTimestampEpochMicros()).isGreaterThanOrEqualTo(minAnnotationTimestamp.get()); minAnnotationTimestamp.set(annotation.getTimestampEpochMicros()); } else { assertThat(annotation).isNull(); } }
protected void addAllAnnotationsToBuilder( zipkin.Span.Builder builder, List<TimestampedAnnotation> wingtipsAnnotations, Endpoint zipkinEndpoint ) { for (TimestampedAnnotation wingtipsAnnotation : wingtipsAnnotations) { builder.addAnnotation( Annotation.create( wingtipsAnnotation.getTimestampEpochMicros(), wingtipsAnnotation.getValue(), zipkinEndpoint ) ); } }
@Test public void TimestampedAnnotation_forCurrentTime_works_as_expected() { // given String value = UUID.randomUUID().toString(); // when long beforeMillis = System.currentTimeMillis(); TimestampedAnnotation result = TimestampedAnnotation.forCurrentTime(value); long afterMillis = System.currentTimeMillis(); // then long beforeMicros = TimeUnit.MILLISECONDS.toMicros(beforeMillis); long afterMicros = TimeUnit.MILLISECONDS.toMicros(afterMillis); assertThat(result.getTimestampEpochMicros()).isBetween(beforeMicros, afterMicros); assertThat(result.getValue()).isEqualTo(value); }
/** * A convenience static factory method that lets you generate an instance of {@link TimestampedAnnotation} * based on a timestamp in epoch milliseconds rather than microseconds. For example you could use this method * when a timestamp was recorded with {@link System#currentTimeMillis()}, and you wanted to create a * {@link TimestampedAnnotation} using that timestamp. * * @param timestampEpochMillis The timestamp in epoch milliseconds (not microseconds). * @param value The value to associate with the given timestamp. * @return A new {@link TimestampedAnnotation} with the given timestamp (converted to microseconds), and the * given value. */ public static TimestampedAnnotation forEpochMillis(long timestampEpochMillis, String value) { return forEpochMicros(TimeUnit.MILLISECONDS.toMicros(timestampEpochMillis), value); }