/** * Sets the span variables on the MDC context. */ protected static void configureMDC(Span span) { MDC.put(TRACE_ID_MDC_KEY, span.getTraceId()); MDC.put(SPAN_JSON_MDC_KEY, span.toJSON()); }
/** * 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); }
@Test public void doFilterInternal_should_set_trace_id_in_response_header() throws ServletException, IOException { // given: filter RequestTracingFilter filter = getBasicFilter(); // when: doFilterInternal is called filter.doFilterInternal(requestMock, responseMock, spanCapturingFilterChain); // then: response header should be set with the span's trace ID assertThat(spanCapturingFilterChain.capturedSpan).isNotNull(); verify(responseMock).setHeader(TraceHeaders.TRACE_ID, spanCapturingFilterChain.capturedSpan.getTraceId()); }
@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()); }
@Test public void fromRequestWithHeaders_sets_user_id_to_null_if_passed_null_or_empty_userIdHeaderKeys_list() { // given String traceId = UUID.randomUUID().toString(); given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(traceId); List<List<String>> badLists = Arrays.asList(null, Collections.<String>emptyList()); for (List<String> badList : badLists) { // when Span result = HttpRequestTracingUtils.fromRequestWithHeaders(request, badList); // expect assertThat(result.getTraceId()).isEqualTo(traceId); assertThat(result.getUserId()).isNull(); } }
@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 registerWithThread_should_do_nothing_if_copy_of_same_stack_is_passed_in() { // given Tracer tracer = Tracer.getInstance(); tracer.startRequestWithRootSpan("foo"); Span subspan = tracer.startSubSpan("bar", SpanPurpose.LOCAL_ONLY); assertThat(MDC.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId()); assertThat(MDC.get(Tracer.SPAN_JSON_MDC_KEY)).isEqualTo(subspan.toJSON()); // when Deque<Span> spanStack = getSpanStackThreadLocal().get(); tracer.registerWithThread(new LinkedList<>(spanStack)); // then assertThat(getSpanStackThreadLocal().get()).isEqualTo(spanStack); assertThat(MDC.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId()); assertThat(MDC.get(Tracer.SPAN_JSON_MDC_KEY)).isEqualTo(subspan.toJSON()); }
@Test public void registerWithThread_should_do_nothing_if_same_stack_is_passed_in() { // given Tracer tracer = Tracer.getInstance(); tracer.startRequestWithRootSpan("foo"); Span subspan = tracer.startSubSpan("bar", SpanPurpose.LOCAL_ONLY); assertThat(MDC.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId()); assertThat(MDC.get(Tracer.SPAN_JSON_MDC_KEY)).isEqualTo(subspan.toJSON()); // when Deque<Span> spanStack = getSpanStackThreadLocal().get(); tracer.registerWithThread(spanStack); // then assertThat(getSpanStackThreadLocal().get()).isEqualTo(spanStack); assertThat(MDC.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId()); assertThat(MDC.get(Tracer.SPAN_JSON_MDC_KEY)).isEqualTo(subspan.toJSON()); }
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_traceId_is_different() { // given Span fullSpan1 = createFilledOutSpan(true); Span fullSpan2 = createFilledOutSpan(true); Whitebox.setInternalState(fullSpan2, "traceId", fullSpan1.getTraceId() + "_nope"); // expect assertThat(fullSpan1.equals(fullSpan2)).isFalse(); assertThat(fullSpan1.hashCode()).isNotEqualTo(fullSpan2.hashCode()); }
@Test public void registerWithThread_should_reset_everything_if_passed_null() { // given Tracer tracer = Tracer.getInstance(); tracer.startRequestWithRootSpan("foo"); Span subspan = tracer.startSubSpan("bar", SpanPurpose.LOCAL_ONLY); assertThat(MDC.get(Tracer.TRACE_ID_MDC_KEY)).isEqualTo(subspan.getTraceId()); assertThat(MDC.get(Tracer.SPAN_JSON_MDC_KEY)).isEqualTo(subspan.toJSON()); // when tracer.registerWithThread(null); // then assertThat(getSpanStackThreadLocal().get()).isNull(); assertThat(MDC.get(Tracer.TRACE_ID_MDC_KEY)).isNull(); assertThat(MDC.get(Tracer.SPAN_JSON_MDC_KEY)).isNull(); }
@Test @UseDataProvider("nullAndEmptyStrings") public void fromRequestWithHeaders_sets_user_id_to_null_if_request_returns_null_or_empty_for_user_id(String nullOrEmptyUserId) { // given String traceId = UUID.randomUUID().toString(); given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(traceId); given(request.getHeader(USER_ID_HEADER_KEY)).willReturn(nullOrEmptyUserId); given(request.getAttribute(USER_ID_HEADER_KEY)).willReturn(nullOrEmptyUserId); // when Span result = HttpRequestTracingUtils.fromRequestWithHeaders(request, USER_ID_HEADER_KEYS); // expect assertThat(result.getTraceId()).isEqualTo(traceId); assertThat(result.getUserId()).isNull(); }
private void verifyExpectedTracingHeadersReceivedDownstream( ExtractableResponse response, Span expectedSpan ) { verifyExpectedTracingHeadersReceivedDownstream( response, expectedSpan.getTraceId(), expectedSpan.getSpanId(), expectedSpan.getParentSpanId(), convertSampleableBooleanToExpectedB3Value(expectedSpan.isSampleable()) ); }
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); }
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); }