@Test public void fromHttpServletRequest_returns_null_if_passed_null_request() { // when Span nullSpan = HttpSpanFactory.fromHttpServletRequest(null, USER_ID_HEADER_KEYS); // then //noinspection ConstantConditions assertThat(nullSpan).isNull(); }
/** * @return A {@link Span} object created from the headers if they exist (see {@link #fromHttpServletRequest(HttpServletRequest, List)} for details), or if the headers don't * have enough information then this will return a new root span with a span name based on the results of {@link #getSpanName(HttpServletRequest)} and user ID based * on the result of {@link #getUserIdFromHttpServletRequest(HttpServletRequest, List)}. Since this method is for a server receiving a request * the returned span's {@link Span#getSpanPurpose()} will be {@link SpanPurpose#SERVER}. */ public static Span fromHttpServletRequestOrCreateRootSpan(HttpServletRequest servletRequest, List<String> userIdHeaderKeys) { Span span = fromHttpServletRequest(servletRequest, userIdHeaderKeys); if (span == null) { span = Span .generateRootSpanForNewTrace(getSpanName(servletRequest), SpanPurpose.SERVER) .withUserId(getUserIdFromHttpServletRequest(servletRequest, userIdHeaderKeys)) .build(); } return span; }
@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()); }
/** * @param request The incoming request. * @return A new {@link Span} for the overall request. This inspects the incoming request's headers to determine * if it should continue an existing trace with a child span, or whether a brand new trace needs to be started. * {@link #getInitialSpanName(HttpServletRequest, HttpTagAndSpanNamingStrategy, HttpTagAndSpanNamingAdapter)} * is used to generate the initial span name. */ protected Span createNewSpanForRequest(HttpServletRequest request) { // See if there's trace info in the incoming request's headers. If so it becomes the parent trace. Tracer tracer = Tracer.getInstance(); final Span parentSpan = HttpSpanFactory.fromHttpServletRequest(request, getUserIdHeaderKeys()); Span newSpan; if (parentSpan != null) { logger.debug("Found parent Span {}", parentSpan); newSpan = tracer.startRequestWithChildSpan( parentSpan, getInitialSpanName(request, tagAndNamingStrategy, tagAndNamingAdapter) ); } else { newSpan = tracer.startRequestWithRootSpan( getInitialSpanName(request, tagAndNamingStrategy, tagAndNamingAdapter), HttpSpanFactory.getUserIdFromHttpServletRequest(request, getUserIdHeaderKeys()) ); logger.debug("Parent span not found, starting a new span {}", newSpan); } return newSpan; }
@Test public void fromHttpServletRequest_defaults_span_sampleable_value_to_true_if_request_header_and_attribute_is_null() { // given: request where the request header and attribute for TRACE_SAMPLED returns null given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(sampleTraceID); given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(null); given(request.getAttribute(TraceHeaders.TRACE_SAMPLED)).willReturn(null); // when: creating span from request Span newSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); // then: new span should be sampleable assertThat(newSpan.isSampleable()).isTrue(); }
@Test public void fromHttpServletRequest_sets_span_sampleable_to_false_if_trace_sampled_header_is_empty_but_attribute_returns_false() { // given: request where the header for TRACE_SAMPLED returns null but the attribute returns false given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(sampleTraceID); given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(" "); given(request.getAttribute(TraceHeaders.TRACE_SAMPLED)).willReturn(false); // when: creating span from request Span newSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); // then: new span should be disabled assertThat(newSpan.isSampleable()).isFalse(); }
@Test public void fromHttpServletRequest_sets_span_sampleable_to_false_if_trace_sampled_header_is_null_but_attribute_returns_false() { // given: request where the header for TRACE_SAMPLED returns null but the attribute returns false given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(sampleTraceID); given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(null); given(request.getAttribute(TraceHeaders.TRACE_SAMPLED)).willReturn(false); // when: creating span from request Span newSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); // then: new span should be disabled assertThat(newSpan.isSampleable()).isFalse(); }
@Test public void fromHttpServletRequest_returns_null_if_traceId_header_is_missing() { // given: a set of standard Span header values, *minus* trace ID given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(Boolean.FALSE.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 span = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); // then: ensure Span object returned is null assertThat(span).isNull(); }
@Test public void fromHttpServletRequest_creates_span_with_all_values_if_all_values_available_from_request_headers() { // given: a set of standard Span header values given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(sampleTraceID); given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(Boolean.FALSE.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 long beforeCallNanos = System.nanoTime(); Span goodSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); long afterCallNanos = System.nanoTime(); // then: ensure Span object gets identical values from corresponding headers assertThat(goodSpan.getTraceId()).isEqualTo(sampleTraceID); assertThat(goodSpan.isSampleable()).isFalse(); assertThat(goodSpan.getSpanId()).isEqualTo(sampleSpanID); assertThat(goodSpan.getParentSpanId()).isEqualTo(sampleParentSpanID); assertThat(goodSpan.getUserId()).isEqualTo(userId); assertThat(goodSpan.getSpanStartTimeNanos()).isBetween(beforeCallNanos, afterCallNanos); assertThat(goodSpan.isCompleted()).isFalse(); assertThat(goodSpan.getSpanPurpose()).isEqualTo(SpanPurpose.SERVER); }
@Test public void fromHttpServletRequest_pulls_from_alt_user_id_if_specified_in_header_and_primary_is_missing() { // given: a set of standard Span header values with the alt user ID header specified instead of the primary 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(ALT_USER_ID_HEADER_KEY)).willReturn(altUserId); // when: creating Span object from HTTP request long beforeCallNanos = System.nanoTime(); Span goodSpan = HttpSpanFactory.fromHttpServletRequest(request, USER_ID_HEADER_KEYS); long afterCallNanos = System.nanoTime(); // then: ensure Span object gets identical values from corresponding headers assertThat(goodSpan.getTraceId()).isEqualTo(sampleTraceID); assertThat(goodSpan.isSampleable()).isTrue(); assertThat(goodSpan.getSpanId()).isEqualTo(sampleSpanID); assertThat(goodSpan.getParentSpanId()).isEqualTo(sampleParentSpanID); assertThat(goodSpan.getUserId()).isEqualTo(altUserId); assertThat(goodSpan.getSpanStartTimeNanos()).isBetween(beforeCallNanos, afterCallNanos); assertThat(goodSpan.isCompleted()).isFalse(); assertThat(goodSpan.getSpanPurpose()).isEqualTo(SpanPurpose.SERVER); }
@Test public void fromHttpServletRequest_creates_span_with_all_values_minus_user_id_if_user_id_list_is_not_passed_in() { // given: a set of standard Span header values given(request.getHeader(TraceHeaders.TRACE_ID)).willReturn(sampleTraceID); given(request.getHeader(TraceHeaders.TRACE_SAMPLED)).willReturn(Boolean.FALSE.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 long beforeCallNanos = System.nanoTime(); Span goodSpan = HttpSpanFactory.fromHttpServletRequest(request, null); long afterCallNanos = System.nanoTime(); // then: ensure Span object gets identical values from corresponding headers assertThat(goodSpan.getTraceId()).isEqualTo(sampleTraceID); assertThat(goodSpan.isSampleable()).isFalse(); assertThat(goodSpan.getSpanId()).isEqualTo(sampleSpanID); assertThat(goodSpan.getParentSpanId()).isEqualTo(sampleParentSpanID); assertThat(goodSpan.getUserId()).isNull(); assertThat(goodSpan.getSpanStartTimeNanos()).isBetween(beforeCallNanos, afterCallNanos); assertThat(goodSpan.isCompleted()).isFalse(); assertThat(goodSpan.getSpanPurpose()).isEqualTo(SpanPurpose.SERVER); }