Class LoggingSpanFactory

java.lang.Object
org.axonframework.messaging.tracing.LoggingSpanFactory
All Implemented Interfaces:
DescribableComponent, SpanFactory

public final class LoggingSpanFactory extends Object implements SpanFactory
A 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 Details

  • Method Details

    • createDispatchSpan

      public Span createDispatchSpan(String operationName, Message message, @Nullable ProcessingContext context)
      Description copied from interface: SpanFactory
      Creates a Span for an outbound (dispatch / producer) operation on the given Message. The parent is the active span on context (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 in message's metadata, then the implementation's optional ambient fallback, then a new root). The context, when non-null, is also forwarded to every SpanAttributesProvider the implementation was constructed with.
      Specified by:
      createDispatchSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      message - the message the operation acts on
      context - the active processing context, or null when 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: SpanFactory
      Creates a Span for an inbound (handler / consumer) operation on the given Message. The parent is the tracing context propagated in message's metadata (cross-thread / cross-process); when none is present, the active span on context; when neither is present, the implementation's optional ambient fallback applies before a new root (see the class-level parent-resolution notes).
      Specified by:
      createHandlerSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      message - the message being handled
      context - the active processing context, or null when 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: SpanFactory
      Creates a Span for an inbound (handler / consumer) operation that runs inside an independently traced processing context. The parent is the active span on context; the tracing context propagated in message'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 context over 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 from message and attach it as a link; when no link can be extracted, the span is still created and this method never throws.

      Specified by:
      createContextParentHandlerSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      message - the message being handled -- its metadata supplies the link target
      context - the processing context supplying the structural parent, or null when 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: SpanFactory
      Creates a Span for an inbound (handler / consumer) operation on the given Message, with an additional link to linkedMessage'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 from linkedMessage'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 in SpanFactory.createHandlerSpan(String, Message, ProcessingContext).
      Specified by:
      createLinkedHandlerSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      message - the message being handled
      linkedMessage - the message whose span context is linked to
      context - the active processing context, or null when none is available
      Returns:
      the created span (not yet started)
    • createInternalSpan

      public Span createInternalSpan(String operationName, @Nullable ProcessingContext context)
      Description copied from interface: SpanFactory
      Creates a Span for an internal operation that is not directly tied to a Message. The parent is the active span on context (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 via Span.addAttribute(String, String).
      Specified by:
      createInternalSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      context - the active processing context, or null when none is available
      Returns:
      the created span (not yet started)
    • createRootSpan

      public Span createRootSpan(String operationName, @Nullable ProcessingContext context)
      Description copied from interface: SpanFactory
      Creates a Span that 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. When context is 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 context carries 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:
      createRootSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      context - the processing context the root should become the active span of (and link back to), or null
      Returns:
      the created root span (not yet started)
    • createDisconnectedHandlerSpan

      public Span createDisconnectedHandlerSpan(String operationName, Message message, @Nullable ProcessingContext context)
      Description copied from interface: SpanFactory
      Creates a Span for 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 in message'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:
      createDisconnectedHandlerSpan in interface SpanFactory
      Parameters:
      operationName - the span name
      message - the message being handled -- its metadata supplies the link target
      context - the active processing context, or null when none is available
      Returns:
      the created span (not yet started)
    • describeTo

      public void describeTo(ComponentDescriptor descriptor)
      Description copied from interface: DescribableComponent
      Describe the properties of this DescribableComponent with the given descriptor.

      Components should call the appropriate describeProperty methods 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 DescribableComponent implementation 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 the describeTo method, 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:
      describeTo in interface DescribableComponent
      Parameters:
      descriptor - The component descriptor to describe this DescribableComponentn its properties in.