use of io.opencensus.trace.propagation.SpanContextParseException in project instrumentation-java by census-instrumentation.
the class BinaryFormatImpl method fromByteArray.
@Override
public SpanContext fromByteArray(byte[] bytes) throws SpanContextParseException {
checkNotNull(bytes, "bytes");
if (bytes.length == 0 || bytes[0] != VERSION_ID) {
throw new SpanContextParseException("Unsupported version.");
}
if (bytes.length < REQUIRED_FORMAT_LENGTH) {
throw new SpanContextParseException("Invalid input: truncated");
}
// TODO: the following logic assumes that fields are written in ID order. The spec does not say
// that. If it decides not to, this logic would need to be more like a loop
TraceId traceId;
SpanId spanId;
TraceOptions traceOptions = TraceOptions.DEFAULT;
int pos = 1;
if (bytes[pos] == TRACE_ID_FIELD_ID) {
traceId = TraceId.fromBytes(bytes, pos + ID_SIZE);
pos += ID_SIZE + TraceId.SIZE;
} else {
// TODO: update the spec to suggest that the trace ID is not actually optional
throw new SpanContextParseException("Invalid input: expected trace ID at offset " + pos);
}
if (bytes[pos] == SPAN_ID_FIELD_ID) {
spanId = SpanId.fromBytes(bytes, pos + ID_SIZE);
pos += ID_SIZE + SpanId.SIZE;
} else {
// TODO: update the spec to suggest that the span ID is not actually optional.
throw new SpanContextParseException("Invalid input: expected span ID at offset " + pos);
}
// failing.
if (bytes.length > pos && bytes[pos] == TRACE_OPTION_FIELD_ID) {
if (bytes.length < ALL_FORMAT_LENGTH) {
throw new SpanContextParseException("Invalid input: truncated");
}
traceOptions = TraceOptions.fromByte(bytes[pos + ID_SIZE]);
}
return SpanContext.create(traceId, spanId, traceOptions, TRACESTATE_DEFAULT);
}
use of io.opencensus.trace.propagation.SpanContextParseException in project instrumentation-java by census-instrumentation.
the class TraceContextFormat method extract.
@Override
public <C> /*>>> extends @NonNull Object*/
SpanContext extract(C carrier, Getter<C> getter) throws SpanContextParseException {
checkNotNull(carrier, "carrier");
checkNotNull(getter, "getter");
TraceId traceId;
SpanId spanId;
TraceOptions traceOptions;
String traceparent = getter.get(carrier, TRACEPARENT);
if (traceparent == null) {
throw new SpanContextParseException("Traceparent not present");
}
try {
// TODO(bdrutu): Do we need to verify that version is hex and that for the version
// the length is the expected one?
checkArgument(traceparent.charAt(TRACE_OPTION_OFFSET - 1) == TRACEPARENT_DELIMITER && (traceparent.length() == TRACEPARENT_HEADER_SIZE || (traceparent.length() > TRACEPARENT_HEADER_SIZE && traceparent.charAt(TRACEPARENT_HEADER_SIZE) == TRACEPARENT_DELIMITER)) && traceparent.charAt(SPAN_ID_OFFSET - 1) == TRACEPARENT_DELIMITER && traceparent.charAt(TRACE_OPTION_OFFSET - 1) == TRACEPARENT_DELIMITER, "Missing or malformed TRACEPARENT.");
traceId = TraceId.fromLowerBase16(traceparent, TRACE_ID_OFFSET);
spanId = SpanId.fromLowerBase16(traceparent, SPAN_ID_OFFSET);
traceOptions = TraceOptions.fromLowerBase16(traceparent, TRACE_OPTION_OFFSET);
} catch (IllegalArgumentException e) {
throw new SpanContextParseException("Invalid traceparent: " + traceparent, e);
}
String tracestate = getter.get(carrier, TRACESTATE);
try {
if (tracestate == null || tracestate.isEmpty()) {
return SpanContext.create(traceId, spanId, traceOptions, TRACESTATE_DEFAULT);
}
Tracestate.Builder tracestateBuilder = Tracestate.builder();
List<String> listMembers = TRACESTATE_ENTRY_DELIMITER_SPLITTER.splitToList(tracestate);
checkArgument(listMembers.size() <= TRACESTATE_MAX_MEMBERS, "Tracestate has too many elements.");
// front of the list.
for (int i = listMembers.size() - 1; i >= 0; i--) {
String listMember = listMembers.get(i);
int index = listMember.indexOf(TRACESTATE_KEY_VALUE_DELIMITER);
checkArgument(index != -1, "Invalid tracestate list-member format.");
tracestateBuilder.set(listMember.substring(0, index), listMember.substring(index + 1, listMember.length()));
}
return SpanContext.create(traceId, spanId, traceOptions, tracestateBuilder.build());
} catch (IllegalArgumentException e) {
throw new SpanContextParseException("Invalid tracestate: " + tracestate, e);
}
}
use of io.opencensus.trace.propagation.SpanContextParseException in project grpc-java by grpc.
the class CensusModulesTest method traceHeaderMalformed.
@Test
public void traceHeaderMalformed() throws Exception {
// As comparison, normal header parsing
Metadata headers = new Metadata();
headers.put(censusTracing.tracingHeader, fakeAttemptSpanContext);
// mockTracingPropagationHandler was stubbed to always return fakeServerParentSpanContext
assertSame(spyAttemptSpan.getContext(), headers.get(censusTracing.tracingHeader));
// Make BinaryPropagationHandler always throw when parsing the header
when(mockTracingPropagationHandler.fromByteArray(any(byte[].class))).thenThrow(new SpanContextParseException("Malformed header"));
headers = new Metadata();
assertNull(headers.get(censusTracing.tracingHeader));
headers.put(censusTracing.tracingHeader, fakeAttemptSpanContext);
assertSame(SpanContext.INVALID, headers.get(censusTracing.tracingHeader));
assertNotSame(spyClientSpan.getContext(), SpanContext.INVALID);
// A null Span is used as the parent in this case
censusTracing.getServerTracerFactory().newServerStreamTracer(method.getFullMethodName(), headers);
verify(tracer).spanBuilderWithRemoteParent(eq("Recv.package1.service2.method3"), ArgumentMatchers.<SpanContext>isNull());
verify(spyServerSpanBuilder).setRecordEvents(eq(true));
}
use of io.opencensus.trace.propagation.SpanContextParseException in project instrumentation-java by census-instrumentation.
the class HttpServerHandler method handleStart.
/**
* Instrument an incoming request before it is handled.
*
* <p>This method will create a span under the deserialized propagated parent context. If the
* parent context is not present, the span will be created under the current context.
*
* <p>The generated span will NOT be set as current context. User can control when to enter the
* scope of this span. Use {@link AbstractHttpHandler#getSpanFromContext} to retrieve the span.
*
* @param carrier the entity that holds the HTTP information.
* @param request the request entity.
* @return the {@link HttpRequestContext} that contains stats and trace data associated with the
* request.
* @since 0.19
*/
public HttpRequestContext handleStart(C carrier, Q request) {
checkNotNull(carrier, "carrier");
checkNotNull(request, "request");
SpanBuilder spanBuilder = null;
String spanName = getSpanName(request, extractor);
// de-serialize the context
SpanContext spanContext = null;
try {
spanContext = textFormat.extract(carrier, getter);
} catch (SpanContextParseException e) {
// TODO: Currently we cannot distinguish between context parse error and missing context.
// Logging would be annoying so we just ignore this error and do not even log a message.
}
if (spanContext == null || publicEndpoint) {
spanBuilder = tracer.spanBuilder(spanName);
} else {
spanBuilder = tracer.spanBuilderWithRemoteParent(spanName, spanContext);
}
Span span = spanBuilder.setSpanKind(Kind.SERVER).startSpan();
if (publicEndpoint && spanContext != null) {
span.addLink(Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN));
}
if (span.getOptions().contains(Options.RECORD_EVENTS)) {
addSpanRequestAttributes(span, request, extractor);
}
return getNewContext(span, tagger.getCurrentTagContext());
}
use of io.opencensus.trace.propagation.SpanContextParseException in project instrumentation-java by census-instrumentation.
the class CloudTraceFormat method extract.
@Override
public <C> /*>>> extends @NonNull Object*/
SpanContext extract(C carrier, Getter<C> getter) throws SpanContextParseException {
checkNotNull(carrier, "carrier");
checkNotNull(getter, "getter");
try {
String headerStr = getter.get(carrier, HEADER_NAME);
if (headerStr == null || headerStr.length() < MIN_HEADER_SIZE) {
throw new SpanContextParseException("Missing or too short header: " + HEADER_NAME);
}
checkArgument(headerStr.charAt(TRACE_ID_SIZE) == SPAN_ID_DELIMITER, "Invalid TRACE_ID size");
TraceId traceId = TraceId.fromLowerBase16(headerStr.subSequence(0, TRACE_ID_SIZE));
int traceOptionsPos = headerStr.indexOf(TRACE_OPTION_DELIMITER, TRACE_ID_SIZE);
CharSequence spanIdStr = headerStr.subSequence(SPAN_ID_START_POS, traceOptionsPos < 0 ? headerStr.length() : traceOptionsPos);
SpanId spanId = longToSpanId(UnsignedLongs.parseUnsignedLong(spanIdStr.toString(), 10));
TraceOptions traceOptions = OPTIONS_NOT_SAMPLED;
if (traceOptionsPos > 0) {
String traceOptionsStr = headerStr.substring(traceOptionsPos + TRACE_OPTION_DELIMITER_SIZE);
if ((UnsignedInts.parseUnsignedInt(traceOptionsStr, 10) & CLOUD_TRACE_IS_SAMPLED) != 0) {
traceOptions = OPTIONS_SAMPLED;
}
}
return SpanContext.create(traceId, spanId, traceOptions, TRACESTATE_DEFAULT);
} catch (IllegalArgumentException e) {
throw new SpanContextParseException("Invalid input", e);
}
}
Aggregations