Automatic tag table generation
Without this change we don't even really know how many tags are created and what are their values. With this change we want this information to be automatically rendered.
This commit is contained in:
@@ -9,10 +9,11 @@
|
||||
|spring.sleuth.baggage.local-fields | |
|
||||
|spring.sleuth.baggage.remote-fields | | List of fields that are referenced the same in-process as it is on the wire. For example, the field "x-vcap-request-id" would be set as-is including the prefix.
|
||||
|spring.sleuth.baggage.tag-fields | |
|
||||
|spring.sleuth.batch.enabled | `true` | Enable Spring Batch instrumentation.
|
||||
|spring.sleuth.circuitbreaker.enabled | `true` | Enable Spring Cloud CircuitBreaker instrumentation.
|
||||
|spring.sleuth.config.server.enabled | `true` | Enable Spring Cloud Config Server instrumentation.
|
||||
|spring.sleuth.deployer.enabled | `true` | Enable Spring Cloud Deployer instrumentation.
|
||||
|spring.sleuth.deployer.status-poll-delay | `1000` | Default poll delay to retrieve the deployed application status.
|
||||
|spring.sleuth.deployer.status-poll-delay | `500` | Default poll delay to retrieve the deployed application status.
|
||||
|spring.sleuth.enabled | `true` |
|
||||
|spring.sleuth.feign.enabled | `true` | Enable span information propagation when using Feign.
|
||||
|spring.sleuth.feign.processor.enabled | `true` | Enable post processor that wraps Feign Context in its tracing representations.
|
||||
@@ -22,6 +23,8 @@
|
||||
|spring.sleuth.integration.enabled | `true` | Enable Spring Integration instrumentation.
|
||||
|spring.sleuth.integration.patterns | `[!hystrixStreamOutput*, *, !channel*]` | An array of patterns against which channel names will be matched. @see org.springframework.integration.config.GlobalChannelInterceptor#patterns() Defaults to any channel name not matching the Hystrix Stream and functional Stream channel names.
|
||||
|spring.sleuth.integration.websockets.enabled | `true` | Enable tracing for WebSockets.
|
||||
|spring.sleuth.kafka.enabled | `true` | Enable instrumenting of Apache Kafka clients.
|
||||
|spring.sleuth.messaging.aspect.enabled | `false` | Should {@link MessageMapping} wrapping be enabled.
|
||||
|spring.sleuth.messaging.enabled | `false` | Should messaging be turned on.
|
||||
|spring.sleuth.messaging.jms.enabled | `true` | Enable tracing of JMS.
|
||||
|spring.sleuth.messaging.jms.remote-service-name | `jms` | JMS remote service name.
|
||||
@@ -35,12 +38,14 @@
|
||||
|spring.sleuth.opentracing.enabled | `true` | Enables OpenTracing support.
|
||||
|spring.sleuth.propagation.type | | Tracing context propagation types.
|
||||
|spring.sleuth.quartz.enabled | `true` | Enable tracing for Quartz.
|
||||
|spring.sleuth.r2dbc.enabled | `true` | Enable R2dbc instrumentation.
|
||||
|spring.sleuth.reactor.decorate-on-each | `true` | When true decorates on each operator, will be less performing, but logging will always contain the tracing entries in each operator. When false decorates on last operator, will be more performing, but logging might not always contain the tracing entries. @deprecated use explicit value via {@link SleuthReactorProperties#instrumentationType}
|
||||
|spring.sleuth.reactor.enabled | `true` | When true enables instrumentation for reactor.
|
||||
|spring.sleuth.reactor.instrumentation-type | |
|
||||
|spring.sleuth.redis.enabled | `true` | Enable span information propagation when using Redis.
|
||||
|spring.sleuth.redis.remote-service-name | `redis` | Service name for the remote Redis endpoint.
|
||||
|spring.sleuth.rpc.enabled | `true` | Enable tracing of RPC.
|
||||
|spring.sleuth.rsocket.enabled | `true` | When true enables instrumentation for rsocket.
|
||||
|spring.sleuth.rxjava.schedulers.hook.enabled | `true` | Enable support for RxJava via RxJavaSchedulersHook.
|
||||
|spring.sleuth.rxjava.schedulers.ignoredthreads | `[HystrixMetricPoller, ^RxComputation.*$]` | Thread names for which spans will not be sampled.
|
||||
|spring.sleuth.sampler.probability | | Probability of requests that should be sampled. E.g. 1.0 - 100% requests should be sampled. The precision is whole-numbers only (i.e. there's no support for 0.1% of the traces).
|
||||
@@ -55,6 +60,7 @@
|
||||
|spring.sleuth.task.enabled | `true` | Enable Spring Cloud Task instrumentation.
|
||||
|spring.sleuth.trace-id128 | `false` | When true, generate 128-bit trace IDs instead of 64-bit ones.
|
||||
|spring.sleuth.tracer.mode | | Set which tracer implementation should be picked.
|
||||
|spring.sleuth.tx.enabled | `true` | Enable Spring TX instrumentation.
|
||||
|spring.sleuth.web.additional-skip-pattern | | Additional pattern for URLs that should be skipped in tracing. This will be appended to the {@link SleuthWebProperties#skipPattern}.
|
||||
|spring.sleuth.web.client.enabled | `true` | Enable interceptor injecting into {@link org.springframework.web.client.RestTemplate}.
|
||||
|spring.sleuth.web.client.skip-pattern | | Pattern for URLs that should be skipped in client side tracing.
|
||||
|
||||
407
docs/src/main/asciidoc/_spans.adoc
Normal file
407
docs/src/main/asciidoc/_spans.adoc
Normal file
@@ -0,0 +1,407 @@
|
||||
=== Annotation New Or Continue Span
|
||||
|
||||
> Span that wraps a @NewSpan or @ContinueSpan annotations.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.annotation.SleuthAnnotationSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|class|Class name where a method got annotated with a Sleuth annotation.
|
||||
|method|Method name that got annotated with Sleuth annotation.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s.after|Annotated after executing a method annotated with @ContinueSpan or @NewSpan. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|%s.afterFailure|Annotated after throwing an exception from a method annotated with @ContinueSpan or @NewSpan. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|%s.before|Annotated before executing a method annotated with @ContinueSpan or @NewSpan. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|===
|
||||
|
||||
=== Async Annotation Span
|
||||
|
||||
> Span that wraps a @Async annotation. Either continues an existing one or creates a new one if there was no present one.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.async.SleuthAsyncSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|class|Class name where a method got annotated with @Async.
|
||||
|method|Method name that got annotated with @Async.
|
||||
|===
|
||||
|
||||
=== Async Callable Span
|
||||
|
||||
> Span created whenever a Callable needs to be instrumented.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.async.SleuthAsyncSpan`
|
||||
|
||||
=== Async Runnable Span
|
||||
|
||||
> Span created whenever a Runnable needs to be instrumented.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.async.SleuthAsyncSpan`
|
||||
|
||||
=== Batch Job Span
|
||||
|
||||
> Span created around a Job execution.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.batch.SleuthBatchSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|batch.job.executionId|ID of the Spring Batch execution.
|
||||
|batch.job.instanceId|ID of the Spring Batch job instance.
|
||||
|batch.job.name|Name of the Spring Batch job.
|
||||
|===
|
||||
|
||||
=== Batch Step Span
|
||||
|
||||
> Span created around a Job execution.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.batch.SleuthBatchSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|batch.job.executionId|ID of the Spring Batch execution.
|
||||
|batch.step.executionId|ID of the Spring Batch execution.
|
||||
|batch.step.name|Name of the Spring Batch job.
|
||||
|batch.step.type|Type of the Spring Batch job.
|
||||
|===
|
||||
|
||||
=== Circuit Breaker Function Span
|
||||
|
||||
> Span created when we wrap a Function passed to the CircuitBreaker. as fallback.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.circuitbreaker.SleuthCircuitBreakerSpan`
|
||||
|
||||
=== Circuit Breaker Supplier Span
|
||||
|
||||
> Span created when we wrap a Supplier passed to the CircuitBreaker.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.circuitbreaker.SleuthCircuitBreakerSpan`
|
||||
|
||||
=== Config Span
|
||||
|
||||
> Span created around an EnvironmentRepository.
|
||||
|
||||
**Span name** `find`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.config.SleuthConfigSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|config.environment.class|Implementation of the EnvironmentRepository.
|
||||
|config.environment.method|Method executed on the EnvironmentRepository.
|
||||
|===
|
||||
|
||||
=== Deployer Deploy Span
|
||||
|
||||
> Span created upon deploying of an application.
|
||||
|
||||
**Span name** `deploy`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.deployer.SleuthDeployerSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|deployer.app.group|Group of the deployed application.
|
||||
|deployer.app.id|ID of the deployed application.
|
||||
|deployer.app.name|Name of the deployed application.
|
||||
|deployer.platform.cf.org|CloudFoundry org.
|
||||
|deployer.platform.cf.space|CloudFoundry space.
|
||||
|deployer.platform.cf.url|CloudFoundry API URL.
|
||||
|deployer.platform.k8s.namespace|Kubernetes namespace.
|
||||
|deployer.platform.k8s.url|Kubernetes API URL.
|
||||
|deployer.platform.name|Name of the platform to which apps are being deployed.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|When deployer changes the state of the deployed application. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|deployer.start|When deployer started deploying the application.
|
||||
|===
|
||||
|
||||
=== Deployer Get Log Span
|
||||
|
||||
> Span created upon asking for logs of deployed applications.
|
||||
|
||||
**Span name** `getLog`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.deployer.SleuthDeployerSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|deployer.app.group|Group of the deployed application.
|
||||
|deployer.app.id|ID of the deployed application.
|
||||
|deployer.app.name|Name of the deployed application.
|
||||
|deployer.platform.cf.org|CloudFoundry org.
|
||||
|deployer.platform.cf.space|CloudFoundry space.
|
||||
|deployer.platform.cf.url|CloudFoundry API URL.
|
||||
|deployer.platform.k8s.namespace|Kubernetes namespace.
|
||||
|deployer.platform.k8s.url|Kubernetes API URL.
|
||||
|deployer.platform.name|Name of the platform to which apps are being deployed.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|When deployer changes the state of the deployed application. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|deployer.start|When deployer started deploying the application.
|
||||
|===
|
||||
|
||||
=== Deployer Scale Span
|
||||
|
||||
> Span created upon asking for logs of deployed applications.
|
||||
|
||||
**Span name** `scale`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.deployer.SleuthDeployerSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|deployer.app.group|Group of the deployed application.
|
||||
|deployer.app.id|ID of the deployed application.
|
||||
|deployer.app.name|Name of the deployed application.
|
||||
|deployer.platform.cf.org|CloudFoundry org.
|
||||
|deployer.platform.cf.space|CloudFoundry space.
|
||||
|deployer.platform.cf.url|CloudFoundry API URL.
|
||||
|deployer.platform.k8s.namespace|Kubernetes namespace.
|
||||
|deployer.platform.k8s.url|Kubernetes API URL.
|
||||
|deployer.platform.name|Name of the platform to which apps are being deployed.
|
||||
|deployer.scale.count|Scale count.
|
||||
|deployer.scale.deploymentId|Scale command deployment id.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|When deployer changes the state of the deployed application. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|deployer.start|When deployer started deploying the application.
|
||||
|===
|
||||
|
||||
=== Deployer Statuses Span
|
||||
|
||||
> Span created upon asking for statuses of deployed applications.
|
||||
|
||||
**Span name** `statuses`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.deployer.SleuthDeployerSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|deployer.app.group|Group of the deployed application.
|
||||
|deployer.app.id|ID of the deployed application.
|
||||
|deployer.app.name|Name of the deployed application.
|
||||
|deployer.platform.cf.org|CloudFoundry org.
|
||||
|deployer.platform.cf.space|CloudFoundry space.
|
||||
|deployer.platform.cf.url|CloudFoundry API URL.
|
||||
|deployer.platform.k8s.namespace|Kubernetes namespace.
|
||||
|deployer.platform.k8s.url|Kubernetes API URL.
|
||||
|deployer.platform.name|Name of the platform to which apps are being deployed.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|When deployer changes the state of the deployed application. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|deployer.start|When deployer started deploying the application.
|
||||
|===
|
||||
|
||||
=== Deployer Status Span
|
||||
|
||||
> Span created upon asking for a status of a deployed application.
|
||||
|
||||
**Span name** `status`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.deployer.SleuthDeployerSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|deployer.app.group|Group of the deployed application.
|
||||
|deployer.app.id|ID of the deployed application.
|
||||
|deployer.app.name|Name of the deployed application.
|
||||
|deployer.platform.cf.org|CloudFoundry org.
|
||||
|deployer.platform.cf.space|CloudFoundry space.
|
||||
|deployer.platform.cf.url|CloudFoundry API URL.
|
||||
|deployer.platform.k8s.namespace|Kubernetes namespace.
|
||||
|deployer.platform.k8s.url|Kubernetes API URL.
|
||||
|deployer.platform.name|Name of the platform to which apps are being deployed.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|When deployer changes the state of the deployed application. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|deployer.start|When deployer started deploying the application.
|
||||
|===
|
||||
|
||||
=== Deployer Undeploy Span
|
||||
|
||||
> Span created upon undeploying of an application.
|
||||
|
||||
**Span name** `undeploy`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.deployer.SleuthDeployerSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|deployer.app.group|Group of the deployed application.
|
||||
|deployer.app.id|ID of the deployed application.
|
||||
|deployer.app.name|Name of the deployed application.
|
||||
|deployer.platform.cf.org|CloudFoundry org.
|
||||
|deployer.platform.cf.space|CloudFoundry space.
|
||||
|deployer.platform.cf.url|CloudFoundry API URL.
|
||||
|deployer.platform.k8s.namespace|Kubernetes namespace.
|
||||
|deployer.platform.k8s.url|Kubernetes API URL.
|
||||
|deployer.platform.name|Name of the platform to which apps are being deployed.
|
||||
|===
|
||||
|
||||
.Event Values
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|When deployer changes the state of the deployed application. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|deployer.start|When deployer started deploying the application.
|
||||
|===
|
||||
|
||||
=== Messaging Span
|
||||
|
||||
> Span created when message is sent or received.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.messaging.SleuthMessagingSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|%s|User provided keys via customization options. (since the name contains `%s` the final value will be resolved at runtime)
|
||||
|channel|Name of the Spring Integration channel.
|
||||
|===
|
||||
|
||||
=== Mvc Handler Interceptor Span
|
||||
|
||||
> Span around a HandlerInterceptor. Will continue the current span and tag it
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.web.mvc.SleuthMvcSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|mvc.controller.class|Class name where a method got annotated with @Scheduled.
|
||||
|mvc.controller.method|Method name that got annotated with @Scheduled.
|
||||
|===
|
||||
|
||||
=== Quartz Trigger Span
|
||||
|
||||
> Span created when trigger is fired and then completed.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.quartz.SleuthQuartzSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|quartz.trigger|Name of the trigger.
|
||||
|===
|
||||
|
||||
=== Rsocket Responder Span
|
||||
|
||||
> Span created on the RSocket responder side.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.rsocket.SleuthRSocketSpan`
|
||||
|
||||
=== Rx Java Trace Action Span
|
||||
|
||||
> Span that wraps a Rx Java .
|
||||
|
||||
**Span name** `rxjava`.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.rxjava.SleuthRxJavaSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|thread|Name of the thread.
|
||||
|===
|
||||
|
||||
=== Scheduled Annotation Span
|
||||
|
||||
> Span that wraps a annotated method. Either creates a new span or continues an existing one.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.scheduling.SleuthSchedulingSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|class|Class name where a method got annotated with @Scheduled.
|
||||
|method|Method name that got annotated with @Scheduled.
|
||||
|===
|
||||
|
||||
=== Task Execution Listener Span
|
||||
|
||||
> Span created within the lifecycle of a task.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.task.SleuthTaskSpan`
|
||||
|
||||
=== Task Runner Span
|
||||
|
||||
> Span created when a task runner is executed.
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.task.SleuthTaskSpan`
|
||||
|
||||
=== Web Filter Span
|
||||
|
||||
> Span around a WebFilter. Will continue the current span or create a new one and tag it
|
||||
|
||||
**Span name** `%s` - since it contains `%s`, the name is dynamic and will be resolved at runtime.
|
||||
|
||||
Fully qualified name of the enclosing class `org.springframework.cloud.sleuth.instrument.web.SleuthWebSpan`
|
||||
|
||||
.Tag Keys
|
||||
|===
|
||||
|Name | Description
|
||||
|http.status_code|Response status code.
|
||||
|mvc.controller.class|Name of the class that is processing the request.
|
||||
|mvc.controller.method|Name of the method that is processing the request.
|
||||
|===
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
:numbered!:
|
||||
|
||||
[[appendix]]
|
||||
[[sleuth-spans]]
|
||||
== Spring Cloud Sleuth Spans
|
||||
|
||||
Below you can find a list of all the spans that are created by Spring Cloud Sleuth.
|
||||
|
||||
include::_spans.adoc[]
|
||||
|
||||
[[common-application-properties]]
|
||||
== Common application properties
|
||||
|
||||
|
||||
@@ -480,6 +480,11 @@ That Logback configuration file:
|
||||
NOTE: If you use a custom `logback-spring.xml`, you must pass the `spring.application.name` in the `bootstrap` rather than the `application` property file.
|
||||
Otherwise, your custom logback file does not properly read the property.
|
||||
|
||||
[[features-self-documenting-spans]]
|
||||
== Self Documenting Spans
|
||||
|
||||
A declarative format of representing span configuration was introduced via the `DocumentedSpan` abstraction. By analyzing Sleuth's source code an appendix with all span characteristics is created (including allowed tag keys and event names). You can check the <<appendix.adoc#sleuth-spans, Sleuth Spans appendix>> for more information.
|
||||
|
||||
[[features-whats-next]]
|
||||
== What to Read Next
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitor;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DocsFromSources {
|
||||
|
||||
private final File projectRoot;
|
||||
|
||||
private final Pattern inclusionPattern;
|
||||
|
||||
private final File outputDir;
|
||||
|
||||
public DocsFromSources(File projectRoot, Pattern inclusionPattern, File outputDir) {
|
||||
this.projectRoot = projectRoot;
|
||||
this.inclusionPattern = inclusionPattern;
|
||||
this.outputDir = outputDir;
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
String projectRoot = args[0];
|
||||
String inclusionPattern = args[1];
|
||||
inclusionPattern = inclusionPattern.replace("/", File.separator);
|
||||
String output = args[2];
|
||||
new DocsFromSources(new File(projectRoot), Pattern.compile(inclusionPattern), new File(output)).generate();
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
Path path = this.projectRoot.toPath();
|
||||
System.out.println("Inclusion pattern is [" + this.inclusionPattern + "]");
|
||||
Collection<SpanEntry> spanEntries = new TreeSet<>();
|
||||
FileVisitor<Path> fv = new SpanSearchingFileVisitor(this.inclusionPattern, spanEntries);
|
||||
try {
|
||||
Files.walkFileTree(path, fv);
|
||||
Path output = new File(this.outputDir, "_spans.adoc").toPath();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
System.out.println("======================================");
|
||||
System.out.println("Summary of sources analysis");
|
||||
System.out.println("Found [" + spanEntries.size() + "] spans");
|
||||
System.out.println(
|
||||
"Found [" + spanEntries.stream().flatMap(e -> e.tagKeys.stream()).distinct().count() + "] tags");
|
||||
System.out.println(
|
||||
"Found [" + spanEntries.stream().flatMap(e -> e.events.stream()).distinct().count() + "] events");
|
||||
spanEntries.forEach(spanEntry -> stringBuilder.append(spanEntry.toString()).append("\n\n"));
|
||||
Files.write(output, stringBuilder.toString().getBytes());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
class KeyValueEntry implements Comparable<KeyValueEntry> {
|
||||
|
||||
final String name;
|
||||
|
||||
final String description;
|
||||
|
||||
KeyValueEntry(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
KeyValueEntry tag = (KeyValueEntry) o;
|
||||
return Objects.equals(name, tag.name) && Objects.equals(description, tag.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(KeyValueEntry o) {
|
||||
return name.compareTo(o.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "|" + name + "|" + description();
|
||||
}
|
||||
|
||||
private String description() {
|
||||
String suffix = "";
|
||||
if (this.name.contains("%s")) {
|
||||
suffix = " (since the name contains `%s` the final value will be resolved at runtime)";
|
||||
}
|
||||
return description + suffix;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class SpanEntry implements Comparable<SpanEntry> {
|
||||
|
||||
final String name;
|
||||
|
||||
final String enclosingClass;
|
||||
|
||||
final String enumName;
|
||||
|
||||
final String description;
|
||||
|
||||
final Collection<KeyValueEntry> tagKeys;
|
||||
|
||||
final Collection<KeyValueEntry> events;
|
||||
|
||||
SpanEntry(String name, String enclosingClass, String enumName, String description,
|
||||
Collection<KeyValueEntry> tagKeys, Collection<KeyValueEntry> events) {
|
||||
Assert.isTrue(StringUtils.hasText(name), "Span name must not be empty");
|
||||
Assert.isTrue(StringUtils.hasText(description), "Span description must not be empty");
|
||||
this.name = name;
|
||||
this.enclosingClass = enclosingClass;
|
||||
this.enumName = enumName;
|
||||
this.description = description;
|
||||
this.tagKeys = tagKeys;
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SpanEntry spanEntry = (SpanEntry) o;
|
||||
return Objects.equals(name, spanEntry.name) && Objects.equals(enclosingClass, spanEntry.enclosingClass)
|
||||
&& Objects.equals(enumName, spanEntry.enumName) && Objects.equals(description, spanEntry.description)
|
||||
&& Objects.equals(tagKeys, spanEntry.tagKeys) && Objects.equals(events, spanEntry.events);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, enclosingClass, enumName, description, tagKeys, events);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(SpanEntry o) {
|
||||
return enumName.compareTo(o.enumName);
|
||||
}
|
||||
|
||||
@Override
|
||||
//@formatter:off
|
||||
public String toString() {
|
||||
StringBuilder text = new StringBuilder()
|
||||
.append("=== ").append(Arrays.stream(enumName.replace("_", " ").split(" ")).map(s -> StringUtils.capitalize(s.toLowerCase(Locale.ROOT))).collect(Collectors.joining(" ")))
|
||||
.append("\n\n> ").append(description).append("\n\n")
|
||||
.append("**Span name** `").append(name).append("`");
|
||||
if (name.contains("%s")) {
|
||||
text.append(" - since it contains `%s`, the name is dynamic and will be resolved at runtime.");
|
||||
}
|
||||
else {
|
||||
text.append(".");
|
||||
}
|
||||
text.append("\n\n").append("Fully qualified name of the enclosing class `").append(this.enclosingClass).append("`");
|
||||
if (!tagKeys.isEmpty()) {
|
||||
text.append("\n\n.Tag Keys\n|===\n|Name | Description\n").append(this.tagKeys.stream().map(KeyValueEntry::toString).collect(Collectors.joining("\n")))
|
||||
.append("\n|===");
|
||||
}
|
||||
if (!events.isEmpty()) {
|
||||
text.append("\n\n.Event Values\n|===\n|Name | Description\n").append(this.events.stream().map(KeyValueEntry::toString).collect(Collectors.joining("\n")))
|
||||
.append("\n|===");
|
||||
}
|
||||
return text.toString();
|
||||
}
|
||||
//@formatter:on
|
||||
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jboss.forge.roaster.Roaster;
|
||||
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.Expression;
|
||||
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.MethodInvocation;
|
||||
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.ReturnStatement;
|
||||
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.jboss.forge.roaster.model.JavaType;
|
||||
import org.jboss.forge.roaster.model.JavaUnit;
|
||||
import org.jboss.forge.roaster.model.impl.JavaEnumImpl;
|
||||
import org.jboss.forge.roaster.model.source.EnumConstantSource;
|
||||
import org.jboss.forge.roaster.model.source.JavaSource;
|
||||
import org.jboss.forge.roaster.model.source.MemberSource;
|
||||
|
||||
import org.springframework.cloud.sleuth.docs.DocumentedSpan;
|
||||
import org.springframework.cloud.sleuth.docs.EventValue;
|
||||
import org.springframework.cloud.sleuth.docs.TagKey;
|
||||
|
||||
class SpanSearchingFileVisitor extends SimpleFileVisitor<Path> {
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
private final Collection<SpanEntry> spanEntries;
|
||||
|
||||
SpanSearchingFileVisitor(Pattern pattern, Collection<SpanEntry> spanEntries) {
|
||||
this.pattern = pattern;
|
||||
this.spanEntries = spanEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
if (!pattern.matcher(file.toString()).matches()) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
else if (!file.toString().endsWith(".java")) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
try (InputStream stream = Files.newInputStream(file)) {
|
||||
JavaUnit unit = Roaster.parseUnit(stream);
|
||||
JavaType myClass = unit.getGoverningType();
|
||||
if (!(myClass instanceof JavaEnumImpl)) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
JavaEnumImpl myEnum = (JavaEnumImpl) myClass;
|
||||
if (!myEnum.getInterfaces().contains(DocumentedSpan.class.getCanonicalName())) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
System.out.println("Checking [" + myEnum.getName() + "]");
|
||||
if (myEnum.getEnumConstants().size() == 0) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
for (EnumConstantSource enumConstant : myEnum.getEnumConstants()) {
|
||||
SpanEntry entry = parseSpan(enumConstant, myEnum);
|
||||
if (entry != null) {
|
||||
spanEntries.add(entry);
|
||||
System.out.println(
|
||||
"Found [" + entry.tagKeys.size() + "] tags and [" + entry.events.size() + "] events");
|
||||
}
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
private SpanEntry parseSpan(EnumConstantSource enumConstant, JavaEnumImpl myEnum) {
|
||||
List<MemberSource<EnumConstantSource.Body, ?>> members = enumConstant.getBody().getMembers();
|
||||
if (members.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String name = "";
|
||||
String description = enumConstant.getJavaDoc().getText();
|
||||
Collection<KeyValueEntry> tags = new TreeSet<>();
|
||||
Collection<KeyValueEntry> events = new TreeSet<>();
|
||||
for (MemberSource<EnumConstantSource.Body, ?> member : members) {
|
||||
Object internal = member.getInternal();
|
||||
if (!(internal instanceof MethodDeclaration)) {
|
||||
return null;
|
||||
}
|
||||
MethodDeclaration methodDeclaration = (MethodDeclaration) internal;
|
||||
String methodName = methodDeclaration.getName().getIdentifier();
|
||||
if ("getName".equals(methodName)) {
|
||||
name = readStringReturnValue(methodDeclaration);
|
||||
}
|
||||
else if ("getTagKeys".equals(methodName)) {
|
||||
tags.addAll(keyValueEntries(myEnum, methodDeclaration, TagKey.class));
|
||||
}
|
||||
else if ("getEvents".equals(methodName)) {
|
||||
events.addAll(keyValueEntries(myEnum, methodDeclaration, EventValue.class));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new SpanEntry(name, myEnum.getCanonicalName(), enumConstant.getName(), description, tags, events);
|
||||
}
|
||||
|
||||
private Collection<KeyValueEntry> keyValueEntries(JavaEnumImpl myEnum, MethodDeclaration methodDeclaration,
|
||||
Class requiredClass) {
|
||||
Collection<String> enumNames = readClassValue(methodDeclaration);
|
||||
Collection<KeyValueEntry> keyValues = new TreeSet<>();
|
||||
enumNames.forEach(enumName -> {
|
||||
List<JavaSource<?>> nestedTypes = myEnum.getNestedTypes();
|
||||
JavaSource<?> nestedSource = nestedTypes.stream()
|
||||
.filter(javaSource -> javaSource.getName().equals(enumName)).findFirst().orElseThrow(
|
||||
() -> new IllegalStateException("There's no nested type with name [" + enumName + "]"));
|
||||
updateKeyValuesFromEnum(myEnum, nestedSource, requiredClass, keyValues);
|
||||
});
|
||||
return keyValues;
|
||||
}
|
||||
|
||||
private void updateKeyValuesFromEnum(JavaEnumImpl parentEnum, JavaSource<?> source, Class requiredClass,
|
||||
Collection<KeyValueEntry> keyValues) {
|
||||
if (!(source instanceof JavaEnumImpl)) {
|
||||
return;
|
||||
}
|
||||
JavaEnumImpl myEnum = (JavaEnumImpl) source;
|
||||
if (!myEnum.getInterfaces().contains(requiredClass.getCanonicalName())) {
|
||||
return;
|
||||
}
|
||||
System.out.println("Checking [" + parentEnum.getName() + "." + myEnum.getName() + "]");
|
||||
if (myEnum.getEnumConstants().size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (EnumConstantSource enumConstant : myEnum.getEnumConstants()) {
|
||||
String keyValue = enumKeyValue(enumConstant);
|
||||
keyValues.add(new KeyValueEntry(keyValue, enumConstant.getJavaDoc().getText()));
|
||||
}
|
||||
}
|
||||
|
||||
private String enumKeyValue(EnumConstantSource enumConstant) {
|
||||
List<MemberSource<EnumConstantSource.Body, ?>> members = enumConstant.getBody().getMembers();
|
||||
if (members.isEmpty()) {
|
||||
System.err.println("No method declarations in the enum.");
|
||||
return "";
|
||||
}
|
||||
Object internal = members.get(0).getInternal();
|
||||
if (!(internal instanceof MethodDeclaration)) {
|
||||
System.err.println("Can't read the member [" + internal.getClass() + "] as a method declaration.");
|
||||
return "";
|
||||
}
|
||||
MethodDeclaration methodDeclaration = (MethodDeclaration) internal;
|
||||
if (methodDeclaration.getBody().statements().isEmpty()) {
|
||||
System.err.println("Body was empty. Continuing...");
|
||||
return "";
|
||||
}
|
||||
return stringFromReturnMethodDeclaration(methodDeclaration);
|
||||
}
|
||||
|
||||
private String stringFromReturnMethodDeclaration(MethodDeclaration methodDeclaration) {
|
||||
Object statement = methodDeclaration.getBody().statements().get(0);
|
||||
if (!(statement instanceof ReturnStatement)) {
|
||||
System.err.println("Statement [" + statement.getClass() + "] is not a return statement.");
|
||||
return "";
|
||||
}
|
||||
ReturnStatement returnStatement = (ReturnStatement) statement;
|
||||
Expression expression = returnStatement.getExpression();
|
||||
if (!(expression instanceof StringLiteral)) {
|
||||
System.err.println("Statement [" + statement.getClass() + "] is not a string literal statement.");
|
||||
return "";
|
||||
}
|
||||
return ((StringLiteral) expression).getLiteralValue();
|
||||
}
|
||||
|
||||
private String readStringReturnValue(MethodDeclaration methodDeclaration) {
|
||||
return stringFromReturnMethodDeclaration(methodDeclaration);
|
||||
}
|
||||
|
||||
private Collection<String> readClassValue(MethodDeclaration methodDeclaration) {
|
||||
Object statement = methodDeclaration.getBody().statements().get(0);
|
||||
if (!(statement instanceof ReturnStatement)) {
|
||||
System.err.println("Statement [" + statement.getClass() + "] is not a return statement.");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
ReturnStatement returnStatement = (ReturnStatement) statement;
|
||||
Expression expression = returnStatement.getExpression();
|
||||
if (!(expression instanceof MethodInvocation)) {
|
||||
System.err.println("Statement [" + statement.getClass() + "] is not a method invocation.");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
MethodInvocation methodInvocation = (MethodInvocation) expression;
|
||||
if ("merge".equals(methodInvocation.getName().getIdentifier())) {
|
||||
// TODO: There must be a better way to do this...
|
||||
// TagKey.merge(TestSpanTags.values(),AsyncSpanTags.values())
|
||||
String invocationString = methodInvocation.toString();
|
||||
Matcher matcher = Pattern.compile("([a-zA-Z]+.values)").matcher(invocationString);
|
||||
Collection<String> classNames = new TreeSet<>();
|
||||
while (matcher.find()) {
|
||||
String className = matcher.group(1).split("\\.")[0];
|
||||
classNames.add(className);
|
||||
}
|
||||
return classNames;
|
||||
}
|
||||
else if (!methodInvocation.toString().endsWith(".values()")) {
|
||||
throw new IllegalStateException("You have to use the static .values() method on the enum that implements "
|
||||
+ TagKey.class + " or " + EventValue.class
|
||||
+ " interface or use [TagKey.merge(...)] method to merge multiple values from tags");
|
||||
}
|
||||
// will return Tags
|
||||
return Collections.singletonList(methodInvocation.getExpression().toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.assertj.core.api.BDDAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DocsFromSourcesTests {
|
||||
|
||||
@Test
|
||||
void should_build_a_table_out_of_enum_tag_key() throws IOException {
|
||||
File root = new File(".");
|
||||
File output = new File(root, "target");
|
||||
|
||||
new DocsFromSources(root, Pattern.compile(".*"), output).generate();
|
||||
|
||||
BDDAssertions.then(new String(Files.readAllBytes(new File(output, "_spans.adoc").toPath())))
|
||||
.contains("=== Async Annotation Span").contains("> Span that wraps a")
|
||||
.contains("**Span name** `%s` - since").contains("Fully qualified name of")
|
||||
.contains("|class|Class name where a method got annotated with @Async.")
|
||||
.contains("=== Annotation New Or Continue Span")
|
||||
.contains("|%s.before|Annotated before executing a method annotated with @ContinueSpan or @NewSpan.")
|
||||
.contains("=== Test Span").contains("**Span name** `fixed`.").contains("|foooooo|Test foo");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import org.springframework.cloud.sleuth.docs.DocumentedSpan;
|
||||
import org.springframework.cloud.sleuth.docs.EventValue;
|
||||
import org.springframework.cloud.sleuth.docs.TagKey;
|
||||
|
||||
enum SleuthAnnotationSpan implements DocumentedSpan {
|
||||
|
||||
/**
|
||||
* Span that wraps a @NewSpan or @ContinueSpan annotations.
|
||||
*/
|
||||
ANNOTATION_NEW_OR_CONTINUE_SPAN {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "%s";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagKey[] getTagKeys() {
|
||||
return Tags.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventValue[] getEvents() {
|
||||
return Events.values();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Tags related to Sleuth annotations.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 3.0.3
|
||||
*/
|
||||
enum Tags implements TagKey {
|
||||
|
||||
/**
|
||||
* Class name where a method got annotated with a Sleuth annotation.
|
||||
*/
|
||||
CLASS {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "class";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method name that got annotated with Sleuth annotation.
|
||||
*/
|
||||
METHOD {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "method";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum Events implements EventValue {
|
||||
|
||||
/**
|
||||
* Annotated before executing a method annotated with @ContinueSpan or @NewSpan.
|
||||
*/
|
||||
BEFORE {
|
||||
@Override
|
||||
public String getValue() {
|
||||
return "%s.before";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Annotated after executing a method annotated with @ContinueSpan or @NewSpan.
|
||||
*/
|
||||
AFTER {
|
||||
@Override
|
||||
public String getValue() {
|
||||
return "%s.after";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Annotated after throwing an exception from a method annotated
|
||||
* with @ContinueSpan or @NewSpan.
|
||||
*/
|
||||
AFTER_FAILURE {
|
||||
@Override
|
||||
public String getValue() {
|
||||
return "%.afterFailure";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.documentation;
|
||||
|
||||
import org.springframework.cloud.sleuth.docs.DocumentedSpan;
|
||||
import org.springframework.cloud.sleuth.docs.TagKey;
|
||||
|
||||
enum SleuthAsyncSpan implements DocumentedSpan {
|
||||
|
||||
/**
|
||||
* Span that wraps a @Async annotation. Either continues an existing one or creates a
|
||||
* new one if there was no present one.
|
||||
*/
|
||||
ASYNC_ANNOTATION_SPAN {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "%s";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagKey[] getTagKeys() {
|
||||
return AsyncSpanTags.values();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Test span.
|
||||
*/
|
||||
TEST_SPAN {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "fixed";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagKey[] getTagKeys() {
|
||||
return TagKey.merge(TestSpanTags.values(), AsyncSpanTags.values());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
enum AsyncSpanTags implements TagKey {
|
||||
|
||||
/**
|
||||
* Class name where a method got annotated with @Async.
|
||||
*/
|
||||
CLASS {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "class";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method name that got annotated with @Async.
|
||||
*/
|
||||
METHOD {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "method";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum TestSpanTags implements TagKey {
|
||||
|
||||
/**
|
||||
* Test foo
|
||||
*/
|
||||
FOO {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "foooooo";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user