下面列出了怎么用io.opentracing.tag.Tags的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void testExceptionInHandler() {
Client client = ClientBuilder.newClient();
Response response = client.target(url("/exception"))
.request()
.get();
response.close();
Assert.assertEquals(500, response.getStatus());
await().until(finishedSpansSizeEquals(1));
List<MockSpan> mockSpans = mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
MockSpan mockSpan = mockSpans.get(0);
Assert.assertEquals(6, mockSpan.tags().size());
Assert.assertEquals(true, mockSpan.tags().get(Tags.ERROR.getKey()));
Assert.assertEquals(1, mockSpan.logEntries().size());
Assert.assertEquals(2, mockSpan.logEntries().get(0).fields().size());
Assert.assertNotNull(mockSpan.logEntries().get(0).fields().get("error.object"));
Assert.assertEquals("error", mockSpan.logEntries().get(0).fields().get("event"));
// TODO resteasy and CXF returns 200
// Resteasy filter https://issues.jboss.org/browse/RESTEASY-1758
// Assert.assertEquals(500, mockSpan.tags().get(Tags.HTTP_STATUS.getKey()));
}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// do not record
if ("$echo".equals(invocation.getMethodName())) {
return invoker.invoke(invocation);
}
RpcContext rpcContext = RpcContext.getContext();
// get appName
if (StringUtils.isBlank(this.appName)) {
this.appName = SofaTracerConfiguration
.getProperty(SofaTracerConfiguration.TRACER_APPNAME_KEY);
}
// get span kind by rpc request type
String spanKind = spanKind(rpcContext);
Result result;
if (spanKind.equals(Tags.SPAN_KIND_SERVER)) {
result = doServerFilter(invoker, invocation);
} else {
result = doClientFilter(rpcContext, invoker, invocation);
}
return result;
}
/**
* Method: asChildOf(SpanContext parent)
*/
@Test
public void testAsChildOfParentTestBizBaggageAndSysBaggage() {
//create
SofaTracerSpan spanParent = (SofaTracerSpan) this.sofaTracer.buildSpan("spanParent")
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER).start();
String parentTraceId = spanParent.getSofaTracerSpanContext().getTraceId();
SofaTracerSpanContext parentSpanContext = (SofaTracerSpanContext) spanParent.context();
assertTrue(parentSpanContext.getSpanId().equals(SofaTracer.ROOT_SPAN_ID));
//child
SofaTracerSpan spanChild = (SofaTracerSpan) this.sofaTracer.buildSpan("spanChild")
.asChildOf(spanParent).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).start();
String childTraceId = spanChild.getSofaTracerSpanContext().getTraceId();
String childSpanId = spanChild.getSofaTracerSpanContext().getSpanId();
String[] childArray = childSpanId.split("\\.");
assertEquals("\nroot spanId : " + parentSpanContext.getSpanId(), 2, childArray.length);
assertEquals("child spanId : " + childSpanId, SofaTracer.ROOT_SPAN_ID, childArray[0]);
assertEquals("Traceid : " + parentTraceId, parentTraceId, childTraceId);
}
public void beforeRequest(Object request, Context context) {
logger.info("before send {}", request);
// we cannot use active span because we don't know in which thread it is executed
// and we cannot therefore activate span. thread can come from common thread pool.
SpanBuilder spanBuilder =
tracer
.buildSpan(OPERATION_NAME)
.ignoreActiveSpan()
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT);
if (parentContext != null) {
spanBuilder.asChildOf(parentContext);
}
context.put("span", spanBuilder.start());
}
@Override
public void initSend(TraceableMessage message, String address) {
Span span = tracer.buildSpan(SEND_SPAN_NAME)
.withTag(Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER)
.withTag(Tags.MESSAGE_BUS_DESTINATION, address)
.withTag(Tags.COMPONENT, COMPONENT)
.start();
LazyTextMapInject carrier = new LazyTextMapInject();
tracer.inject(span.context(), Format.Builtin.TEXT_MAP, carrier);
if(carrier.getInjectMap() != null) {
message.setTracingAnnotation(ANNOTATION_KEY, carrier.getInjectMap());
} else {
message.removeTracingAnnotation(ANNOTATION_KEY);
}
message.setTracingContext(SEND_SPAN_CONTEXT_KEY, span);
}
@Test
public void testSyncWithStandardTags() throws Exception {
{
getRestTemplate().getForEntity("/sync", String.class);
Awaitility.await().until(reportedSpansSize(), IsEqual.equalTo(1));
}
List<MockSpan> mockSpans = TracingBeansConfiguration.mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
assertOnErrors(mockSpans);
MockSpan span = mockSpans.get(0);
Assert.assertEquals("sync", span.operationName());
Assert.assertEquals(5, span.tags().size());
Assert.assertEquals(Tags.SPAN_KIND_SERVER, span.tags().get(Tags.SPAN_KIND.getKey()));
Assert.assertEquals("GET", span.tags().get(Tags.HTTP_METHOD.getKey()));
Assert.assertEquals(getUrl("/sync"), span.tags().get(Tags.HTTP_URL.getKey()));
Assert.assertEquals(200, span.tags().get(Tags.HTTP_STATUS.getKey()));
Assert.assertNotNull(span.tags().get(Tags.COMPONENT.getKey()));
assertLogEvents(span.logEntries(), Arrays.asList("preHandle", "afterCompletion"));
}
/**
* common tag to XStringBuilder format
* @param xsb
* @param span
*/
protected void appendXsbCommonSlot(XStringBuilder xsb, SofaTracerSpan span) {
SofaTracerSpanContext context = span.getSofaTracerSpanContext();
Map<String, String> tagWithStr = span.getTagsWithStr();
//span end time
xsb.append(Timestamp.format(span.getEndTime()));
//appName
xsb.append(tagWithStr.get(CommonSpanTags.LOCAL_APP));
//TraceId
xsb.append(context.getTraceId());
//RpcId
xsb.append(context.getSpanId());
//span kind
xsb.append(tagWithStr.get(Tags.SPAN_KIND.getKey()));
// result code
xsb.append(tagWithStr.get(CommonSpanTags.RESULT_CODE));
// thread name
xsb.append(tagWithStr.get(CommonSpanTags.CURRENT_THREAD_NAME));
// time.cost.milliseconds
xsb.append((span.getEndTime() - span.getStartTime()) + SofaTracerConstant.MS);
}
@Advice.OnMethodEnter
public static void exit(final @ClassName String className, final @Advice.Origin String origin, @Advice.Argument(value = 0, readOnly = false, typing = Typing.DYNAMIC) Runnable arg) throws Exception {
if (!isAllowed(className, origin))
return;
final Tracer tracer = GlobalTracer.get();
if (isVerbose(className)) {
final Span span = tracer
.buildSpan("scheduleAtFixedRate")
.withTag(Tags.COMPONENT, "java-concurrent")
.start();
arg = WrapperProxy.wrap(arg, new TracedRunnable(arg, span, true));
span.finish();
}
else if (tracer.activeSpan() != null) {
arg = WrapperProxy.wrap(arg, new TracedRunnable(arg, tracer.activeSpan(), false));
}
}
/**
* TODO Some jax-rs clients does not support redirects (RestEasy, CXF). If they will support we
* make sure that span context is copied to redirected requests.
*/
@Test
public void testRedirect() {
Response response = client.target(url("/redirect"))
.request()
// disable for jersey
.property("jersey.config.client.followRedirects", false)
.get();
response.close();
assertNoActiveSpan();
List<MockSpan> mockSpans = mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
assertOnErrors(mockTracer.finishedSpans());
MockSpan mockSpan = mockSpans.get(0);
Assert.assertEquals("GET", mockSpan.operationName());
Assert.assertEquals(7, mockSpan.tags().size());
Assert.assertEquals(Tags.SPAN_KIND_CLIENT, mockSpan.tags().get(Tags.SPAN_KIND.getKey()));
Assert.assertEquals("jaxrs", mockSpan.tags().get(Tags.COMPONENT.getKey()));
Assert.assertEquals(url("/redirect"), mockSpan.tags().get(Tags.HTTP_URL.getKey()));
Assert.assertEquals("GET", mockSpan.tags().get(Tags.HTTP_METHOD.getKey()));
Assert.assertEquals(303, mockSpan.tags().get(Tags.HTTP_STATUS.getKey()));
Assert.assertEquals(getPort(), mockSpan.tags().get(Tags.PEER_PORT.getKey()));
Assert.assertEquals("localhost", mockSpan.tags().get(Tags.PEER_HOSTNAME.getKey()));
}
@Override
public void start(Future<Void> startFuture) throws Exception {
log.info("HTTP Kafka producer starting with config {}", this.config);
WebClientOptions options = new WebClientOptions()
.setDefaultHost(this.config.getHostname())
.setDefaultPort(this.config.getPort());
this.client = WebClient.create(vertx, options);
this.sendTimer = vertx.setPeriodic(this.config.getSendInterval(), t -> {
Tracer tracer = GlobalTracer.get();
Span span = tracer.buildSpan("send").withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).start();
this.send(this.config.getTopic(), span).setHandler(ar -> {
if (ar.succeeded()) {
log.info("Sent {}", ar.result());
}
span.finish();
});
});
startFuture.complete();
}
@Test
void testErrorLogging() {
Span span = apmTracer.buildSpan("someWork").start();
try (Scope scope = apmTracer.activateSpan(span)) {
throw new RuntimeException("Catch me if you can");
} catch (Exception ex) {
Tags.ERROR.set(span, true);
span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, ex, Fields.MESSAGE, ex.getMessage()));
} finally {
span.finish();
}
assertThat(reporter.getTransactions()).hasSize(1);
assertThat(reporter.getFirstTransaction().getResult()).isEqualTo("error");
assertThat(reporter.getErrors()).hasSize(1);
assertThat(reporter.getFirstError().getException()).isNotNull();
assertThat(reporter.getFirstError().getException().getMessage()).isEqualTo("Catch me if you can");
assertThat(reporter.getFirstError().getTraceContext().getParentId()).isEqualTo(reporter.getFirstTransaction().getTraceContext().getId());
}
@Test
public void testSecuredURLUnAuthorized() throws Exception {
{
getRestTemplate().getForEntity("/secured", String.class);
Awaitility.await().until(reportedSpansSize(), IsEqual.equalTo(1));
}
List<MockSpan> mockSpans = TracingBeansConfiguration.mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
assertOnErrors(mockSpans);
MockSpan span = mockSpans.get(0);
Assert.assertEquals("GET", span.operationName());
Assert.assertEquals(5, span.tags().size());
Assert.assertEquals(Tags.SPAN_KIND_SERVER, span.tags().get(Tags.SPAN_KIND.getKey()));
Assert.assertEquals("GET", span.tags().get(Tags.HTTP_METHOD.getKey()));
Assert.assertEquals(getUrl("/secured"), span.tags().get(Tags.HTTP_URL.getKey()));
Assert.assertEquals(401, span.tags().get(Tags.HTTP_STATUS.getKey()));
Assert.assertNotNull(span.tags().get(Tags.COMPONENT.getKey()));
// request does not hit any controller
assertLogEvents(span.logEntries(), Collections.<String>emptyList());
}
@Test
public void testControllerView() {
{
getRestTemplate().getForEntity("/controllerView", String.class);
Awaitility.await().until(reportedSpansSize(), IsEqual.equalTo(1));
}
List<MockSpan> mockSpans = TracingBeansConfiguration.mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
assertOnErrors(mockSpans);
MockSpan span = mockSpans.get(0);
Assert.assertEquals("GET", span.operationName());
Assert.assertEquals(5, span.tags().size());
Assert.assertEquals(Tags.SPAN_KIND_SERVER, span.tags().get(Tags.SPAN_KIND.getKey()));
Assert.assertEquals("GET", span.tags().get(Tags.HTTP_METHOD.getKey()));
Assert.assertEquals(getUrl("/controllerView"), span.tags().get(Tags.HTTP_URL.getKey()));
Assert.assertEquals(200, span.tags().get(Tags.HTTP_STATUS.getKey()));
Assert.assertNotNull(span.tags().get(Tags.COMPONENT.getKey()));
assertLogEvents(span.logEntries(), Arrays.asList("preHandle", "afterCompletion"));
}
public void afterInvoke(String error) {
SofaTraceContext sofaTraceContext = SofaTraceContextHolder.getSofaTraceContext();
SofaTracerSpan clientSpan = sofaTraceContext.pop();
if (clientSpan == null) {
return;
}
if (StringUtils.isNotBlank(error)) {
clientSpan.setTag(CommonSpanTags.RESULT_CODE, SofaTracerConstant.RESULT_CODE_SUCCESS);
} else {
clientSpan.setTag(CommonSpanTags.RESULT_CODE, SofaTracerConstant.RESULT_CODE_ERROR);
}
// log event
clientSpan.log(LogData.CLIENT_RECV_EVENT_VALUE);
// set resultCode
clientSpan.setTag(Tags.ERROR.getKey(), error);
// finish client span
clientSpan.finish();
// restore parent span
if (clientSpan.getParentSofaTracerSpan() != null) {
sofaTraceContext.push(clientSpan.getParentSofaTracerSpan());
}
}
@Test
public void testStandardTagsWithPort() {
final String path = "/foo";
final String url = wireMockRule.url(path);
{
stubFor(get(urlPathEqualTo(path))
.willReturn(ok()));
client.getForEntity(url, String.class);
}
List<MockSpan> mockSpans = mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
MockSpan mockSpan = mockSpans.get(0);
Assert.assertEquals("GET", mockSpan.operationName());
Assert.assertEquals(6, mockSpan.tags().size());
Assert.assertEquals(componentName, mockSpan.tags().get(Tags.COMPONENT.getKey()));
Assert.assertEquals(Tags.SPAN_KIND_CLIENT, mockSpan.tags().get(Tags.SPAN_KIND.getKey()));
Assert.assertEquals("GET", mockSpan.tags().get(Tags.HTTP_METHOD.getKey()));
Assert.assertEquals(url, mockSpan.tags().get(Tags.HTTP_URL.getKey()));
Assert.assertEquals(200, mockSpan.tags().get(Tags.HTTP_STATUS.getKey()));
Assert.assertEquals(wireMockRule.port(), mockSpan.tags().get(Tags.PEER_PORT.getKey()));
Assert.assertEquals(0, mockSpan.logEntries().size());
}
@Override
public void start(final String dataSourceName, final String sql, final List<Object> parameters,
final DataSourceMetaData dataSourceMetaData, final boolean isTrunkThread, final Map<String, Object> shardingExecuteDataMap) {
if (!isTrunkThread) {
activeSpan = ((ActiveSpan.Continuation) shardingExecuteDataMap.get(OpenTracingRootInvokeHook.ACTIVE_SPAN_CONTINUATION)).activate();
}
span = ShardingTracer.get().buildSpan(OPERATION_NAME)
.withTag(Tags.COMPONENT.getKey(), ShardingTags.COMPONENT_NAME)
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
.withTag(Tags.PEER_HOSTNAME.getKey(), dataSourceMetaData.getHostName())
.withTag(Tags.PEER_PORT.getKey(), dataSourceMetaData.getPort())
.withTag(Tags.DB_TYPE.getKey(), "sql")
.withTag(Tags.DB_INSTANCE.getKey(), dataSourceName)
.withTag(Tags.DB_STATEMENT.getKey(), sql)
.withTag(ShardingTags.DB_BIND_VARIABLES.getKey(), toString(parameters)).startManual();
}
@Override
protected String getOperationName(String spanKind, String httpMethod, Class<?> clazz, Method method) {
if (spanKind.equals(Tags.SPAN_KIND_SERVER)) {
StringBuilder operationName = new StringBuilder(httpMethod.toUpperCase() + ":");
Path classPath = clazz.getAnnotation(Path.class);
if (classPath == null) {
throw new IllegalArgumentException("Supplied clazz is not JAX-RS resource");
}
if (!classPath.value().startsWith("/")) {
operationName.append("/");
}
operationName.append(classPath.value());
if (!classPath.value().endsWith("/")) {
operationName.append("/");
}
Path methodPath = method.getAnnotation(Path.class);
String methodPathStr = methodPath.value();
if (methodPathStr.startsWith("/")) {
methodPathStr = methodPathStr.replaceFirst("/", "");
}
operationName.append(methodPathStr);
return operationName.toString();
}
return super.getOperationName(spanKind, httpMethod, clazz, method);
}
public void tell(final String message) {
final Span parent = tracer.scopeManager().activeSpan();
phaser.register();
executor.submit(
new Runnable() {
@Override
public void run() {
Span child = tracer
.buildSpan("received")
.addReference(References.FOLLOWS_FROM, parent.context())
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
.start();
try (Scope scope = tracer.activateSpan(child)) {
phaser.arriveAndAwaitAdvance(); // child tracer started
child.log("received " + message);
phaser.arriveAndAwaitAdvance(); // assert size
} finally {
child.finish();
}
phaser.arriveAndAwaitAdvance(); // child tracer finished
phaser.arriveAndAwaitAdvance(); // assert size
}
});
}
@Test
public void test(final MockTracer tracer) throws ExecutionException, InterruptedException {
try (final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAsyncConfiguration.class)) {
final SpringAsyncConfiguration configuration = context.getBean(SpringAsyncConfiguration.class);
final String res = configuration.async().get();
assertEquals("whatever", res);
try {
configuration.asyncException().get();
fail();
}
catch (final Exception ignore) {
}
await().atMost(15, TimeUnit.SECONDS).until(TestUtil.reportedSpansSize(tracer), equalTo(2));
final List<MockSpan> spans = tracer.finishedSpans();
assertEquals(2, spans.size());
for (final MockSpan span : spans) {
assertEquals("spring-async", span.tags().get(Tags.COMPONENT.getKey()));
}
}
}
@Test
public void testHelloRequest() throws IOException {
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(localRequestUrl("/hello")).build();
client.newCall(request).execute();
Awaitility.await().until(reportedSpansSize(), IsEqual.equalTo(1));
}
List<MockSpan> mockSpans = mockTracer.finishedSpans();
Assert.assertEquals(1, mockSpans.size());
assertOnErrors(mockSpans);
MockSpan mockSpan = mockSpans.get(0);
Assert.assertEquals("GET", mockSpan.operationName());
Assert.assertEquals(5, mockSpan.tags().size());
Assert.assertEquals(Tags.SPAN_KIND_SERVER, mockSpan.tags().get(Tags.SPAN_KIND.getKey()));
Assert.assertEquals("GET", mockSpan.tags().get(Tags.HTTP_METHOD.getKey()));
Assert.assertEquals(localRequestUrl("/hello"), mockSpan.tags().get(Tags.HTTP_URL.getKey()));
Assert.assertEquals(202, mockSpan.tags().get(Tags.HTTP_STATUS.getKey()));
Assert.assertEquals("java-web-servlet", mockSpan.tags().get(Tags.COMPONENT.getKey()));
}
@Advice.OnMethodEnter
public static void exit(final @ClassName String className, final @Advice.Origin String origin, @Advice.Argument(value = 0, readOnly = false, typing = Typing.DYNAMIC) Runnable arg) throws Exception {
if (!isAllowed(className, origin))
return;
final Tracer tracer = GlobalTracer.get();
if (isVerbose(className)) {
final Span span = tracer
.buildSpan("scheduleWithFixedDelay")
.withTag(Tags.COMPONENT, "java-concurrent")
.start();
arg = WrapperProxy.wrap(arg, new TracedRunnable(arg, span, true));
span.finish();
}
else if (tracer.activeSpan() != null) {
arg = WrapperProxy.wrap(arg, new TracedRunnable(arg, tracer.activeSpan(), false));
}
}
public static void enter(final Object thiz) {
if (LocalSpanContext.get(COMPONENT_NAME) != null) {
LocalSpanContext.get(COMPONENT_NAME).increment();
return;
}
final Tracer tracer = GlobalTracer.get();
HttpRequest request = (HttpRequest)thiz;
final Span span = tracer
.buildSpan(request.getRequestMethod())
.withTag(Tags.COMPONENT, COMPONENT_NAME)
.withTag(Tags.HTTP_METHOD, request.getRequestMethod())
.withTag(Tags.HTTP_URL, request.getUrl().toString())
.withTag(Tags.PEER_PORT, getPort(request))
.withTag(Tags.PEER_HOSTNAME, request.getUrl().getHost()).start();
final Scope scope = tracer.activateSpan(span);
tracer.inject(span.context(), Builtin.HTTP_HEADERS, new HttpHeadersInjectAdapter(request.getHeaders()));
LocalSpanContext.set(COMPONENT_NAME, span, scope);
}
@Test
public void test(final MockTracer tracer) throws IOException {
final Server server = Server.forRouter(components -> RoutingDsl.fromComponents(components)
.GET("/hello/:to")
.routeTo(request -> {
assertNotNull(tracer.activeSpan());
return ok("Hello");
})
.build());
final URL url = new URL("http://localhost:" + server.httpPort() + "/hello/world");
final HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
assertEquals(200, connection.getResponseCode());
server.stop();
assertEquals(1, tracer.finishedSpans().size());
assertEquals(PlayAgentIntercept.COMPONENT_NAME, tracer.finishedSpans().get(0).tags().get(Tags.COMPONENT.getKey()));
}
@Test
public void testMetricsReporter() {
// prepare
SpanData metricSpanData = Mockito.mock(SpanData.class);
Mockito.when(metricSpanData.getOperationName())
.thenReturn("testOp");
Mockito.when(metricSpanData.getTags())
.thenReturn(Collections.<String, Object>singletonMap(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT));
Mockito.when(metricSpanData.getDuration())
.thenReturn(500L);
// test
metricsReporter.reportSpan(metricSpanData);
// verify
MetricFamilySamples samples = testCollectorRegistry.metricFamilySamples().nextElement();
assertFalse(samples.samples.isEmpty());
}
/**
* Make sure that a span is created when an active span exists joins the active
*/
static void commandSpanJoinsActiveSpan(MockTracer tracer, Runnable command) {
final MockSpan parent = tracer.buildSpan("parent").start();
try (Scope ignored = tracer.activateSpan(parent)) {
command.run();
assertEquals(1, tracer.finishedSpans().size());
}
parent.finish();
assertEquals(2, tracer.finishedSpans().size());
Optional<MockSpan> redisSpan = tracer.finishedSpans().stream()
.filter((s) -> "java-redis".equals(s.tags().get(Tags.COMPONENT.getKey()))).findFirst();
Optional<MockSpan> parentSpan =
tracer.finishedSpans().stream().filter((s) -> "parent".equals(s.operationName()))
.findFirst();
assertTrue(redisSpan.isPresent());
assertTrue(parentSpan.isPresent());
assertEquals(redisSpan.get().context().traceId(), parentSpan.get().context().traceId());
assertEquals(redisSpan.get().parentId(), parentSpan.get().context().spanId());
}
protected void stopTraceSpan(final TraceScopeHolder<TraceScope> holder, final int responseStatus) {
if (holder == null) {
return;
}
final TraceScope traceScope = holder.getScope();
if (traceScope != null) {
Span span = traceScope.getSpan();
Scope scope = traceScope.getScope();
// If the client invocation was asynchronous , the trace span has been created
// in another thread and should be re-attached to the current one.
if (holder.isDetached()) {
scope = tracer.scopeManager().activate(span);
}
span.setTag(Tags.HTTP_STATUS.getKey(), responseStatus);
span.setTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT);
span.finish();
scope.close();
}
}
/**
* Verifies that a client invocation of the <em>set-last-known-gateway</em> operation fails
* if the device connection service cannot be reached.
*
* @param ctx The vert.x test context.
*/
@Test
public void testSetLastKnownGatewayForDeviceFailsWithSendError(final VertxTestContext ctx) {
// GIVEN a client with no credit left
when(sender.sendQueueFull()).thenReturn(true);
// WHEN setting last known gateway information
client.setLastKnownGatewayForDevice("deviceId", "gatewayId", span.context())
.onComplete(ctx.failing(t -> {
ctx.verify(() -> {
// THEN the invocation fails and the span is marked as erroneous
verify(span).setTag(eq(Tags.ERROR.getKey()), eq(Boolean.TRUE));
// and the span is finished
verify(span).finish();
});
ctx.completeNow();
}));
}
static <K, V> Span buildAndInjectSpan(ProducerRecord<K, V> record, Tracer tracer,
BiFunction<String, ProducerRecord, String> producerSpanNameProvider,
SpanContext parent, Collection<SpanDecorator> spanDecorators) {
String producerOper =
TO_PREFIX + record.topic(); // <======== It provides better readability in the UI
Tracer.SpanBuilder spanBuilder = tracer
.buildSpan(producerSpanNameProvider.apply(producerOper, record))
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER);
SpanContext spanContext = TracingKafkaUtils.extractSpanContext(record.headers(), tracer);
if (spanContext != null) {
spanBuilder.asChildOf(spanContext);
} else if (parent != null) {
spanBuilder.asChildOf(parent);
}
Span span = spanBuilder.start();
for (SpanDecorator decorator : spanDecorators) {
decorator.onSend(record, span);
}
try {
TracingKafkaUtils.inject(span.context(), record.headers(), tracer);
} catch (Exception e) {
// it can happen if headers are read only (when record is sent second time)
logger.error("failed to inject span context. sending record second time?", e);
}
return span;
}
/**
* Verifies that a client invocation of the <em>get-last-known-gateway</em> operation fails
* if the device connection service cannot be reached.
*
* @param ctx The vert.x test context.
*/
@Test
public void testGetLastKnownGatewayForDeviceFailsWithRejectedRequest(final VertxTestContext ctx) {
// GIVEN a client with no credit left
final ProtonDelivery update = mock(ProtonDelivery.class);
when(update.getRemoteState()).thenReturn(new Rejected());
when(update.remotelySettled()).thenReturn(true);
when(sender.send(any(Message.class), VertxMockSupport.anyHandler())).thenAnswer(invocation -> {
final Handler<ProtonDelivery> dispositionHandler = invocation.getArgument(1);
dispositionHandler.handle(update);
return mock(ProtonDelivery.class);
});
// WHEN getting last known gateway information
client.getLastKnownGatewayForDevice("deviceId", span.context())
.onComplete(ctx.failing(t -> {
assertThat(((ServiceInvocationException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
ctx.verify(() -> {
// THEN the invocation fails and the span is marked as erroneous
verify(span).setTag(eq(Tags.ERROR.getKey()), eq(Boolean.TRUE));
// and the span is finished
verify(span).finish();
});
ctx.completeNow();
}));
}
protected TraceScopeHolder<TraceScope> startTraceSpan(final Map<String, List<String>> requestHeaders,
URI uri, String method) {
SpanContext parent = tracer.extract(Builtin.HTTP_HEADERS,
new TextMapAdapter(
requestHeaders
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, this::getFirstValueOrEmpty))
));
Span activeSpan = null;
Scope scope = null;
if (parent == null) {
activeSpan = tracer.buildSpan(buildSpanDescription(uri.getPath(), method)).start();
scope = tracer.scopeManager().activate(activeSpan);
} else {
activeSpan = tracer.buildSpan(buildSpanDescription(uri.getPath(), method)).asChildOf(parent).start();
scope = tracer.scopeManager().activate(activeSpan);
}
// Set additional tags
activeSpan.setTag(Tags.HTTP_METHOD.getKey(), method);
activeSpan.setTag(Tags.HTTP_URL.getKey(), uri.toString());
// If the service resource is using asynchronous processing mode, the trace
// scope will be closed in another thread and as such should be detached.
Span span = null;
if (isAsyncResponse()) {
// Do not modify the current context span
span = activeSpan;
propagateContinuationSpan(span);
scope.close();
}
return new TraceScopeHolder<TraceScope>(new TraceScope(activeSpan, scope), span != null);
}