/** * Helper method for adding tracing-related request attributes to the given request based on the given span. * * @param span The span for the overall request. * @param request The request object to add tracing-related request attributes to. */ protected void addTracingInfoToRequestAttributes(Span span, HttpServletRequest request) { request.setAttribute(TraceHeaders.TRACE_SAMPLED, span.isSampleable()); request.setAttribute(TraceHeaders.TRACE_ID, span.getTraceId()); request.setAttribute(TraceHeaders.SPAN_ID, span.getSpanId()); request.setAttribute(TraceHeaders.PARENT_SPAN_ID, span.getParentSpanId()); request.setAttribute(TraceHeaders.SPAN_NAME, span.getSpanName()); request.setAttribute(Span.class.getName(), span); }
public EndpointSpanInfoDto(HttpServletRequest request, Span endpoint_execution_span, List<String> userIdHeaderKeys) { this.parent_span_info = new SpanInfoDto( request.getHeader(TraceHeaders.TRACE_ID), request.getHeader(TraceHeaders.SPAN_ID), request.getHeader(TraceHeaders.PARENT_SPAN_ID), request.getHeader(TraceHeaders.TRACE_SAMPLED), HttpSpanFactory.getUserIdFromHttpServletRequest(request, userIdHeaderKeys) ); this.endpoint_execution_span_info = new SpanInfoDto( endpoint_execution_span.getTraceId(), endpoint_execution_span.getSpanId(), endpoint_execution_span.getParentSpanId(), String.valueOf(endpoint_execution_span.isSampleable()), endpoint_execution_span.getUserId() ); }
public EndpointSpanInfoDto(HttpServletRequest request, Span endpoint_execution_span, List<String> userIdHeaderKeys) { this.parent_span_info = new SpanInfoDto( request.getHeader(TraceHeaders.TRACE_ID), request.getHeader(TraceHeaders.SPAN_ID), request.getHeader(TraceHeaders.PARENT_SPAN_ID), request.getHeader(TraceHeaders.TRACE_SAMPLED), HttpSpanFactory.getUserIdFromHttpServletRequest(request, userIdHeaderKeys) ); this.endpoint_execution_span_info = new SpanInfoDto( endpoint_execution_span.getTraceId(), endpoint_execution_span.getSpanId(), endpoint_execution_span.getParentSpanId(), String.valueOf(endpoint_execution_span.isSampleable()), endpoint_execution_span.getUserId() ); }
@Test public void fromHttpServletRequest_generates_new_spanId_if_missing_from_headers() { // given: a request with a trace ID but no span ID in the headers String traceId = UUID.randomUUID().toString(); given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(traceId); // when: we use it to create span objects Span firstSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); Span secondSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); // then: ensure each call generates a span with the same trace ID but new span ID assertThat(firstSpan.getTraceId()).isEqualTo(traceId); assertThat(secondSpan.getTraceId()).isEqualTo(traceId); assertThat(firstSpan.getSpanId()).isNotEmpty(); assertThat(secondSpan.getSpanId()).isNotEmpty(); assertThat(firstSpan.getSpanId()).isNotEqualTo(secondSpan.getSpanId()); }
@Test public void doFilterInternal_should_set_request_attributes_to_new_span_info() throws ServletException, IOException { // given: filter RequestTracingFilter filter = getBasicFilter(); // when: doFilterInternal is called filter.doFilterInternal(requestMock, responseMock, spanCapturingFilterChain); // then: request attributes should be set with the new span's info assertThat(spanCapturingFilterChain.capturedSpan).isNotNull(); Span newSpan = spanCapturingFilterChain.capturedSpan; verify(requestMock).setAttribute(TraceHeaders.TRACE_SAMPLED, newSpan.isSampleable()); verify(requestMock).setAttribute(TraceHeaders.TRACE_ID, newSpan.getTraceId()); verify(requestMock).setAttribute(TraceHeaders.SPAN_ID, newSpan.getSpanId()); verify(requestMock).setAttribute(TraceHeaders.PARENT_SPAN_ID, newSpan.getParentSpanId()); verify(requestMock).setAttribute(TraceHeaders.SPAN_NAME, newSpan.getSpanName()); verify(requestMock).setAttribute(Span.class.getName(), newSpan); }
@Test public void fromRequestWithHeaders_generates_valid_span_with_minimum_of_trace_id() { // given String traceId = UUID.randomUUID().toString(); given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(traceId); // when Span result = HttpRequestTracingUtils.fromRequestWithHeaders(request, USER_ID_HEADER_KEYS); // then assertThat(result).isNotNull(); assertThat(result.getTraceId()).isEqualTo(traceId); assertThat(result.getSpanId()).isNotEmpty(); }
@Test public void fromRequestWithHeaders_gets_fresh_span_ids_even_with_same_trace_id() { // given: a request with a trace ID String traceId = UUID.randomUUID().toString(); given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(traceId); // when: we use it to create multiple spans Span firstSpan = HttpRequestTracingUtils.fromRequestWithHeaders(request, USER_ID_HEADER_KEYS); Span secondSpan = HttpRequestTracingUtils.fromRequestWithHeaders(request, USER_ID_HEADER_KEYS); // then: each span gets its own unique span ID assertThat(firstSpan.getTraceId()).isEqualTo(traceId); assertThat(secondSpan.getTraceId()).isEqualTo(traceId); assertThat(firstSpan.getSpanId()).isNotEmpty(); assertThat(secondSpan.getSpanId()).isNotEmpty(); assertThat(firstSpan.getSpanId()).isNotEqualTo(secondSpan.getTraceId()); }
private SpanInfoDto spanInfoDtoFromSpan(Span span) { return new SpanInfoDto( span.getTraceId(), span.getSpanId(), span.getParentSpanId(), String.valueOf(span.isSampleable()), span.getUserId() ); }
private SpanInfoDto spanInfoDtoFromSpan(Span span) { return new SpanInfoDto( span.getTraceId(), span.getSpanId(), span.getParentSpanId(), String.valueOf(span.isSampleable()), span.getUserId() ); }
@Test public void equals_returns_false_and_hashCode_different_if_spanId_is_different() { // given Span fullSpan1 = createFilledOutSpan(true); Span fullSpan2 = createFilledOutSpan(true); Whitebox.setInternalState(fullSpan2, "spanId", fullSpan1.getSpanId() + "_nope"); // expect assertThat(fullSpan1.equals(fullSpan2)).isFalse(); assertThat(fullSpan1.hashCode()).isNotEqualTo(fullSpan2.hashCode()); }
@Test public void fromRequestWithHeaders_generates_span_from_headers_in_request() { // given: a set of standard span header values given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(sampleTraceID); given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(Boolean.TRUE.toString()); given(request.getHeader(TraceHeaders.SPAN_ID)).willReturn(sampleSpanID); given(request.getHeader(TraceHeaders.PARENT_SPAN_ID)).willReturn(sampleParentSpanID); given(request.getHeader(USER_ID_HEADER_KEY)).willReturn(userId); // when: creating span object from HTTP request Span goodSpan = HttpRequestTracingUtils.fromRequestWithHeaders(request, USER_ID_HEADER_KEYS); // then: ensure span object gets identical values from corresponding headers, and the span purpose is set to SERVER assertThat(goodSpan.getTraceId()).isEqualTo(sampleTraceID); assertThat(goodSpan.isSampleable()).isTrue(); assertThat(goodSpan.getSpanId()).isEqualTo(sampleSpanID); assertThat(goodSpan.getParentSpanId()).isEqualTo(sampleParentSpanID); assertThat(goodSpan.getUserId()).isEqualTo(userId); assertThat(goodSpan.getSpanPurpose()).isEqualTo(SpanPurpose.SERVER); }
private void verifyExpectedTracingHeadersReceivedDownstream( ExtractableResponse response, Span expectedSpan ) { verifyExpectedTracingHeadersReceivedDownstream( response, expectedSpan.getTraceId(), expectedSpan.getSpanId(), expectedSpan.getParentSpanId(), convertSampleableBooleanToExpectedB3Value(expectedSpan.isSampleable()) ); }
@Override public zipkin.Span convertWingtipsSpanToZipkinSpan(Span wingtipsSpan, Endpoint zipkinEndpoint, String localComponentNamespace) { String traceId = wingtipsSpan.getTraceId(); long startEpochMicros = wingtipsSpan.getSpanStartTimeEpochMicros(); long durationMicros = TimeUnit.NANOSECONDS.toMicros(wingtipsSpan.getDurationNanos()); zipkin.Span.Builder builder = createNewZipkinSpanBuilderWithSpanPurposeAnnotations(wingtipsSpan, startEpochMicros, durationMicros, zipkinEndpoint, localComponentNamespace) .id(nullSafeLong(wingtipsSpan.getSpanId())) .name(wingtipsSpan.getSpanName()) .parentId(nullSafeLong(wingtipsSpan.getParentSpanId())) .timestamp(startEpochMicros) .traceIdHigh(traceId.length() == 32 ? nullSafeLong(traceId, 0) : 0) .traceId(nullSafeLong(traceId)) .duration(durationMicros); addAllTagsToBuilderAsBinaryAnnotations(builder, wingtipsSpan.getTags(), zipkinEndpoint); addAllAnnotationsToBuilder(builder, wingtipsSpan.getTimestampedAnnotations(), zipkinEndpoint); return builder.build(); }
@Override public zipkin.Span convertWingtipsSpanToZipkinSpan(Span wingtipsSpan, Endpoint zipkinEndpoint, String localComponentNamespace) { String traceId = wingtipsSpan.getTraceId(); long startEpochMicros = wingtipsSpan.getSpanStartTimeEpochMicros(); long durationMicros = TimeUnit.NANOSECONDS.toMicros(wingtipsSpan.getDurationNanos()); zipkin.Span.Builder builder = createNewZipkinSpanBuilderWithSpanPurposeAnnotations(wingtipsSpan, startEpochMicros, durationMicros, zipkinEndpoint, localComponentNamespace) .id(nullSafeLong(wingtipsSpan.getSpanId())) .name(wingtipsSpan.getSpanName()) .parentId(nullSafeLong(wingtipsSpan.getParentSpanId())) .timestamp(startEpochMicros) .traceIdHigh(traceId.length() == 32 ? nullSafeLong(traceId, 0) : 0) .traceId(nullSafeLong(traceId)) .duration(durationMicros); addAllTagsToBuilderAsBinaryAnnotations(builder, wingtipsSpan.getTags(), zipkinEndpoint); addAllAnnotationsToBuilder(builder, wingtipsSpan.getTimestampedAnnotations(), zipkinEndpoint); return builder.build(); }
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders() { Span span = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT).build(); Map<String, String> headers = MapBuilder .builder(TraceHeaders.TRACE_ID, span.getTraceId()) .put(TraceHeaders.SPAN_ID, span.getSpanId()) .put(TraceHeaders.SPAN_NAME, span.getSpanName()) .put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable())) .build(); return Pair.of(span, headers); }
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders() { Span span = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT).build(); Map<String, String> headers = MapBuilder .builder(TraceHeaders.TRACE_ID, span.getTraceId()) .put(TraceHeaders.SPAN_ID, span.getSpanId()) .put(TraceHeaders.SPAN_NAME, span.getSpanName()) .put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable())) .build(); return Pair.of(span, headers); }
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders(boolean includeUserId) { Span.Builder spanBuilder = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT); if (includeUserId) { spanBuilder.withUserId("user-" + UUID.randomUUID().toString()); } Span span = spanBuilder.build(); MapBuilder<String, String> headersBuilder = MapBuilder .builder(TraceHeaders.TRACE_ID, span.getTraceId()) .put(TraceHeaders.SPAN_ID, span.getSpanId()) .put(TraceHeaders.SPAN_NAME, span.getSpanName()) .put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable())); if (span.getUserId() != null) { headersBuilder.put(USER_ID_HEADER_KEY, span.getUserId()); } return Pair.of(span, headersBuilder.build()); }
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders(boolean includeUserId) { Span.Builder spanBuilder = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT); if (includeUserId) { spanBuilder.withUserId("user-" + UUID.randomUUID().toString()); } Span span = spanBuilder.build(); MapBuilder<String, String> headersBuilder = MapBuilder .builder(TraceHeaders.TRACE_ID, span.getTraceId()) .put(TraceHeaders.SPAN_ID, span.getSpanId()) .put(TraceHeaders.SPAN_NAME, span.getSpanName()) .put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable())); if (span.getUserId() != null) { headersBuilder.put(USER_ID_HEADER_KEY, span.getUserId()); } return Pair.of(span, headersBuilder.build()); }
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders() { Span span = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT).build(); Map<String, String> headers = MapBuilder .builder(TraceHeaders.TRACE_ID, span.getTraceId()) .put(TraceHeaders.SPAN_ID, span.getSpanId()) .put(TraceHeaders.SPAN_NAME, span.getSpanName()) .put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable())) .build(); return Pair.of(span, headers); }
private Pair<Span, Map<String, String>> generateUpstreamSpanHeaders() { Span span = Span.newBuilder("upstreamSpan", Span.SpanPurpose.CLIENT).build(); Map<String, String> headers = MapBuilder .builder(TraceHeaders.TRACE_ID, span.getTraceId()) .put(TraceHeaders.SPAN_ID, span.getSpanId()) .put(TraceHeaders.SPAN_NAME, span.getSpanName()) .put(TraceHeaders.TRACE_SAMPLED, String.valueOf(span.isSampleable())) .build(); return Pair.of(span, headers); }