Class LoggingSpanFactory
- All Implemented Interfaces:
DescribableComponent,SpanFactory
SpanFactory that logs span lifecycle events through SLF4J, for development and debugging when no APM
backend is available. Span start and end are logged at INFO, each line prefixed with a generated span
identifier and the operation name in the form [spanId][operationName]. Added attributes are logged at
DEBUG behind the same prefix.
When a span relates to a Message, the message's type and identifier are logged too. When the span is created while another message is being handled -- i.e. the supplied
ProcessingContext carries a current message -- the in-flight
message's type and identifier are appended as well, so a dispatch / internal span can be correlated with the handler
it originated from.
This factory performs no context propagation: Span.propagateContext(Message) returns the message unchanged.
Use it as a standalone local development aid. Exporting spans to tracing backends is configured through Micrometer
Tracing and its exporters.
- Since:
- 4.6.0
- Author:
- Mateusz Nowak, Mitchell Herrijgers
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final LoggingSpanFactoryThe singletonLoggingSpanFactoryinstance. -
Method Summary
Modifier and TypeMethodDescriptioncreateContextParentHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context) Creates aSpanfor an inbound (handler / consumer) operation that runs inside an independently traced processing context.createDisconnectedHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context) Creates aSpanfor an inbound (handler / consumer) operation that should start a new trace (root) yet remain navigable to the producing trace through a span link.createDispatchSpan(String operationName, Message message, @Nullable ProcessingContext context) createHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context) createInternalSpan(String operationName, @Nullable ProcessingContext context) createLinkedHandlerSpan(String operationName, Message message, Message linkedMessage, @Nullable ProcessingContext context) createRootSpan(String operationName, @Nullable ProcessingContext context) Creates aSpanthat always starts a new trace (a root), ignoring any active span when resolving its own parent.voiddescribeTo(ComponentDescriptor descriptor) Describe the properties ofthis DescribableComponentwith the givendescriptor.
-
Field Details
-
INSTANCE
The singletonLoggingSpanFactoryinstance.
-
-
Method Details
-
createDispatchSpan
public Span createDispatchSpan(String operationName, Message message, @Nullable ProcessingContext context) Description copied from interface:SpanFactoryCreates aSpanfor an outbound (dispatch / producer) operation on the givenMessage. The parent is the active span oncontext(when present), so a message dispatched from within another traced operation nests under it; otherwise resolution continues per the class-level parent-resolution notes (the context propagated inmessage's metadata, then the implementation's optional ambient fallback, then a new root). Thecontext, when non-null, is also forwarded to everySpanAttributesProviderthe implementation was constructed with.- Specified by:
createDispatchSpanin interfaceSpanFactory- Parameters:
operationName- the span namemessage- the message the operation acts oncontext- the active processing context, ornullwhen none is available- Returns:
- the created span (not yet started)
-
createHandlerSpan
public Span createHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context) Description copied from interface:SpanFactoryCreates aSpanfor an inbound (handler / consumer) operation on the givenMessage. The parent is the tracing context propagated inmessage's metadata (cross-thread / cross-process); when none is present, the active span oncontext; when neither is present, the implementation's optional ambient fallback applies before a new root (see the class-level parent-resolution notes).- Specified by:
createHandlerSpanin interfaceSpanFactory- Parameters:
operationName- the span namemessage- the message being handledcontext- the active processing context, ornullwhen none is available- Returns:
- the created span (not yet started)
-
createContextParentHandlerSpan
public Span createContextParentHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context) Description copied from interface:SpanFactoryCreates aSpanfor an inbound (handler / consumer) operation that runs inside an independently traced processing context. The parent is the active span oncontext; the tracing context propagated inmessage's metadata is attached as a span link instead of replacing that parent. This keeps an enclosing operation, such as a streaming-event-processor batch, as the structural parent while preserving navigation to the producer that created the handled message.Implementations MUST prefer the active span on
contextover the propagated message context. When no active context span is available, the implementation's optional ambient fallback applies before a new root. Implementations MUST independently extract the propagated context frommessageand attach it as a link; when no link can be extracted, the span is still created and this method never throws.- Specified by:
createContextParentHandlerSpanin interfaceSpanFactory- Parameters:
operationName- the span namemessage- the message being handled -- its metadata supplies the link targetcontext- the processing context supplying the structural parent, ornullwhen unavailable- Returns:
- the created span (not yet started)
-
createLinkedHandlerSpan
public Span createLinkedHandlerSpan(String operationName, Message message, Message linkedMessage, @Nullable ProcessingContext context) Description copied from interface:SpanFactoryCreates aSpanfor an inbound (handler / consumer) operation on the givenMessage, with an additional link tolinkedMessage's span context. The link expresses a relationship between traces without changing the span's parent; tracing backends typically render it as navigation between the linked traces. Implementations MUST extract the propagated context fromlinkedMessage's metadata and attach it as a span link; when no link can be extracted the span is still created without the link, and this method never throws. Parent resolution is as inSpanFactory.createHandlerSpan(String, Message, ProcessingContext).- Specified by:
createLinkedHandlerSpanin interfaceSpanFactory- Parameters:
operationName- the span namemessage- the message being handledlinkedMessage- the message whose span context is linked tocontext- the active processing context, ornullwhen none is available- Returns:
- the created span (not yet started)
-
createInternalSpan
Description copied from interface:SpanFactoryCreates aSpanfor an internal operation that is not directly tied to aMessage. The parent is the active span oncontext(when present), so the internal span nests under the operation that opened it (for example a handler span); otherwise the implementation's optional ambient fallback applies before a new root (see the class-level parent-resolution notes). Non-message attributes are attached by the calling decorator viaSpan.addAttribute(String, String).- Specified by:
createInternalSpanin interfaceSpanFactory- Parameters:
operationName- the span namecontext- the active processing context, ornullwhen none is available- Returns:
- the created span (not yet started)
-
createRootSpan
Description copied from interface:SpanFactoryCreates aSpanthat always starts a new trace (a root), ignoring any active span when resolving its own parent. Use this for operations that legitimately begin their own trace and must not attach to a stale or unrelated active span -- for example an event-processing batch boundary or an out-of-band snapshot operation running on a pooled thread. Whencontextis non-null, starting the span still records it as that context's active span, so spans created next with that context nest under this root.When
contextcarries an active span, implementations MUST attach that span as a span link (not as a parent), preserving the relationship to the operation that triggered it without creating a parent-of relationship to that operation.- Specified by:
createRootSpanin interfaceSpanFactory- Parameters:
operationName- the span namecontext- the processing context the root should become the active span of (and link back to), ornull- Returns:
- the created root span (not yet started)
-
createDisconnectedHandlerSpan
public Span createDisconnectedHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context) Description copied from interface:SpanFactoryCreates aSpanfor an inbound (handler / consumer) operation that should start a new trace (root) yet remain navigable to the producing trace through a span link. The link target is the tracing context propagated inmessage's metadata.This is the "distributed-in-different-trace" handling mode. Use it when joining the publisher's trace would either flood it (long-running consumers, batch processors) or cross trust / lifecycle boundaries, while keeping the consumer's new trace navigable back to the producer through the link.
Implementations MUST start a new trace (no parent-of relationship to the producer), extract the producer's context from
message's metadata and attach it as a span link. When no link can be extracted (e.g. no tracing context on the message), the span is still created without a link and this method never throws.- Specified by:
createDisconnectedHandlerSpanin interfaceSpanFactory- Parameters:
operationName- the span namemessage- the message being handled -- its metadata supplies the link targetcontext- the active processing context, ornullwhen none is available- Returns:
- the created span (not yet started)
-
describeTo
Description copied from interface:DescribableComponentDescribe the properties ofthis DescribableComponentwith the givendescriptor.Components should call the appropriate
describePropertymethods on the descriptor to register their properties. The descriptor is responsible for determining how these properties are formatted and structured in the final output.Best Practices: As a general rule, all relevant fields of a
DescribableComponentimplementation should be described in this method. However, developers have discretion to include only the fields that make sense in the context. Not every field may be meaningful for description purposes, especially internal implementation details. Furthermore, components might want to expose different information based on their current state. The final decision on what properties to include lies with the person implementing thedescribeTomethod, who should focus on providing information that is useful for understanding the component's configuration and state.Example implementation:
public void describeTo(ComponentDescriptor descriptor) { descriptor.describeProperty("name", this.name); descriptor.describeProperty("enabled", this.enabled); descriptor.describeProperty("configuration", this.configuration); // A nested component descriptor.describeProperty("handlers", this.eventHandlers); // A collection }- Specified by:
describeToin interfaceDescribableComponent- Parameters:
descriptor- The component descriptor to describethis DescribableComponentn its properties in.
-