
includes.tracing.common-callbacks.adoc Maven / Gradle / Ivy
///////////////////////////////////////////////////////////////////////////////
Copyright (c) 2024 Oracle and/or its affiliates.
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
http://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.
///////////////////////////////////////////////////////////////////////////////
ifndef::rootdir[:rootdir: {docdir}/..]
include::{rootdir}/attributes.adoc
// tag::defs[]
:tracing-javadoc: {tracing-javadoc-base-url}/io/helidon/tracing
:tracing-api-javadoc: {tracing-javadoc}
:listener-type: SpanListener
:forbidden-exc: {listener-type}.ForbiddenOperationException
// end::defs[]
// tag::detailed[]
// tag::intro[]
== Responding to Span Lifecycle Events [[Tracing-callbacks]]
Applications and libraries can register listeners to be notified at several moments during the lifecycle of every span:
* Before a new span starts
* After a new span has started
* After a span ends
* After a span is activated (creating a new scope)
* After a scope is closed
// end::intro[]
The next sections explain how you can write and add a listener and what it can do. See the link:{tracing-api-javadoc}/{listener-type}.html[`{listener-type}`] Javadoc for more information.
=== Understanding What Listeners Do
A listener cannot affect the lifecycle of a span or scope it is notified about, but it can add tags and events and update the baggage associated with a span.
Often a listener does additional work that does not change the span or scope such as logging a message.
When Helidon invokes the listener's methods it passes proxies for the `Span.Builder`, `Span`, and `Scope` arguments. These proxies limit the access the listener has to the span builder, span, or scope, as summarized in the following table. If a listener method tries to invoke a forbidden operation, the proxy throws a link:{tracing-javadoc}/{forbidden-exc}.html[`{forbidden-exc}`] and Helidon then logs a `WARNING` message describing the invalid operation invocation.
.Summary of Permitted Operations on Proxies Passed to Listeners
|====
| Tracing type | Changes allowed
| link:{tracing-javadoc}/Span.Builder.html[`Span.Builder`] | Add tags
| link:{tracing-javadoc}/Span.html[`Span`] | Retrieve and update baggage, add events, add tags
| link:{tracing-javadoc}/Scope.html[`Scope`] | none
|====
The following tables list specifically what operations the proxies permit.
.link:{tracing-javadoc}/Span.Builder.html[`io.helidon.tracing.Span.Builder`] Operations
|====
| Method | Purpose | OK?
| `build()` | Starts the span. | -
| `end` methods | Ends the span. | -
| `get()` | Starts the span. | -
| `kind(Kind)` | Sets the "kind" of span (server, client, internal, etc.) | -
| `parent(SpanContext)` | Sets the parent of the span to be created from the builder. | -
| `start()` | Starts the span. | -
| `start(Instant)` | Starts the span. | -
| `tag` methods| Add a tag to the builder before the span is built. | ✓
| `unwrap(Class)` | Cast the builder to the specified implementation type. † | ✓
|====
† Helidon returns the unwrapped object, not a proxy for it.
.link:{tracing-javadoc}/Span.html[`io.helidon.tracing.Span`] Operations
|====
| Method | Purpose | OK?
| `activate()` | Makes the span "current", returning a `Scope`. | -
| `addEvent` methods | Associate a string (and optionally other info) with a span. | ✓
| `baggage()` | Returns the `Baggage` instance associated with the span.| ✓
| `context()` | Returns the `SpanContext` associated with the span.| ✓
| `status(Status)` | Sets the status of the span. | -
| any `tag` method| Add a tag to the span. | ✓
| `unwrap(Class)` | Cast the span to the specified implementation type. † | ✓
|====
† Helidon returns the unwrapped object, not a proxy to it.
.link:{tracing-javadoc}/Scope.html[`io.helidon.tracing.Scope`] Operations
|====
| Method | Purpose | OK?
| `close()` | Close the scope. | -
| `isClosed()`| Reports whether the scope is closed. | ✓
|====
.link:{tracing-javadoc}/SpanContext.html[`io.helidon.tracing.SpanContext`] Operations
|====
| Method | Purpose | OK?
| `asParent(Span.Builder)` | Sets this context as the parent of a new span builder. | ✓
| `baggage()` | Returns `Baggage` instance associated with the span context. | ✓
| `spanId()` | Returns the span ID. | ✓
| `traceId()` | Returns the trace ID.| ✓
|====
=== Adding a Listener
==== Explicitly Registering a Listener on a link:{tracing-javadoc}/Tracer.html[`Tracer`]
Create a `{listener-type}` instance and invoke the `Tracer#register({listener-type})` method to make the listener known to that tracer.
==== Automatically Registering a Listener on all `Tracer` Instances
Helidon also uses Java service loading to locate listeners and register them automatically on all `Tracer` objects.
Follow these steps to add a listener service provider.
1. Implement the link:{tracing-api-javadoc}/{listener-type}.html[`{listener-type}`] interface.
2. Declare your implementation as a service provider:
a. Create the file `META-INF/services/io.helidon.tracing.{listener-type}` containing a line with the fully-qualified name of your class which implements `{listener-type}`.
b. If your service has a `module-info.java` file add the following line to it:
+
[source,java,subs="attributes+"]
----
provides io.helidon.tracing.{listener-type} with ;
----
The `{listener-type}` interface declares default no-op implementations for all the methods, so your listener can implement only the methods it needs to.
Helidon invokes each listener's methods in the following order:
.Order in which Helidon Invokes Listener Methods
|====
| Method | When invoked
| `starting(Span.Builder> spanBuilder)` | Just before a span is started from its builder.
| `started(Span span)` | Just after a span has started.
| `activated(Span span, Scope scope)` | After a span has been activated, creating a new scope. A given span might never be activated; it depends on the code.
| `closed(Span span, Scope scope)` | After a scope has been closed.
| `ended(Span span)` | After a span has ended successfully.
| `ended(Span span, Throwable t)` | After a span has ended unsuccessfully.
|====
// end::detailed[]
// tag::brief[]
include::common-callbacks.adoc[tag=intro]
See the link:{tracing-api-javadoc}/{listener-type}.html[`{listener-type}`] Javadoc for more information.
// end::brief[]
© 2015 - 2025 Weber Informatics LLC | Privacy Policy