Skip to content

OpenTelemetry

This API is available since Fedify 1.3.0.

OpenTelemetry is a standardized set of APIs, libraries, agents, and instrumentation to provide observability to your applications. Fedify supports OpenTelemetry for tracing. This document explains how to use OpenTelemetry with Fedify.

Setting up OpenTelemetry

To trace your Fedify application with OpenTelemetry, you need to set up the OpenTelemetry SDK. First of all, you need to install the OpenTelemetry SDK and the tracer exporter you want to use. For example, if you want to use the trace exporter for OTLP (http/protobuf), you should install the following packages:

sh
deno add npm:@opentelemetry/sdk-node npm:@opentelemetry/exporter-trace-otlp-proto
sh
npm add @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-proto
sh
bun add @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-proto

Then you can set up the OpenTelemetry SDK in your Fedify application. Here is an example code snippet to set up the OpenTelemetry SDK with the OTLP trace exporter:

typescript
import { 
NodeSDK
} from "@opentelemetry/sdk-node";
import {
OTLPTraceExporter
} from "@opentelemetry/exporter-trace-otlp-proto";
const
sdk
= new
NodeSDK
({
serviceName
: "my-fedify-app",
traceExporter
: new
OTLPTraceExporter
({
url
: "http://localhost:4317",
headers
: { "x-some-header": "some-value" }
}), });
sdk
.
start
();

CAUTION

The above code which sets up the OpenTelemetry SDK needs to be executed before the Fedify server starts. Otherwise, the tracing may not work as expected.

Explicit TracerProvider configuration

The createFederation() function accepts the tracerProvider option to explicitly configure the TracerProvider for the OpenTelemetry SDK. Note that if it's omitted, Fedify will use the global default TracerProvider provided by the OpenTelemetry SDK.

For example, if you want to use Sentry as the trace exporter, you can set up the Sentry SDK and pass the TracerProvider provided by the Sentry SDK to the createFederation() function:

typescript
import { 
createFederation
} from "@fedify/fedify";
import {
getClient
} from "@sentry/node";
const
federation
=
createFederation
<void>({
// Omitted for brevity; see the related section for details.
tracerProvider
:
getClient
()?.traceProvider,
});

CAUTION

The Sentry SDK's OpenTelemetry integration is available since @sentry/node 8.0.0, and it's not available yet in @sentry/deno or @sentry/bun as of November 2024.

For more information about the Sentry SDK's OpenTelemetry integration, please refer to the OpenTelemetry Support section in the Sentry SDK docs.

Instrumented spans

Fedify automatically instruments the following operations with OpenTelemetry spans:

Span nameSpan kindDescription
{method} {template}ServerServes the incoming HTTP request.
activitypub.dispatch_actorServerDispatches the ActivityPub actor.
activitypub.dispatch_actor_key_pairsServerDispatches the ActivityPub actor key pairs.
activitypub.dispatch_collection {collection}ServerDispatches the ActivityPub collection.
activitypub.dispatch_collection_page {collection}ServerDispatches the ActivityPub collection page.
activitypub.dispatch_inbox_listener {type}InternalDispatches the ActivityPub inbox listener.
activitypub.dispatch_objectServerDispatches the Activity Streams object.
activitypub.fetch_keyClientFetches the public keys for the actor.
activitypub.get_actor_handleClientResolves the actor handle.
activitypub.inboxConsumerDequeues the ActivityPub activity to receive.
activitypub.inboxInternalManually routes the ActivityPub activity.
activitypub.inboxProducerEnqueues the ActivityPub activity to receive.
activitypub.inboxServerReceives the ActivityPub activity.
activitypub.lookup_objectClientLooks up the Activity Streams object.
activitypub.outboxClientSends the ActivityPub activity.
activitypub.outboxConsumerDequeues the ActivityPub activity to send.
activitypub.outboxProducerEnqueues the ActivityPub activity to send.
activitypub.parse_objectInternalParses the Activity Streams object.
activitypub.send_activityClientSends the ActivityPub activity.
http_signatures.signInternalSigns the HTTP request.
http_signatures.verifyInternalVerifies the HTTP request signature.
ld_signatures.signInternalMakes the Linked Data signature.
ld_signatures.verifyInternalVerifies the Linked Data signature.
object_integrity_proofs.signInternalMakes the object integrity proof.
object_integrity_proofs.verifyInternalVerifies the object integrity proof.
webfinger.handleServerHandles the WebFinger request.
webfinger.lookupClientLooks up the WebFinger resource.

More operations will be instrumented in the future releases.

Semantic attributes for ActivityPub

The OpenTelemetry Semantic Conventions currently do not have a specification for ActivityPub as of November 2024. However, Fedify provides a set of semantic attributes for ActivityPub. The following table shows the semantic attributes for ActivityPub:

AttributeTypeDescriptionExample
activitypub.activity.idstringThe URI of the activity object."https://example.com/activity/1"
activitypub.activity.typestring[]The qualified URI(s) of the activity type(s).["https://www.w3.org/ns/activitystreams#Create"]
activitypub.activity.tostring[]The URI(s) of the recipient collections/actors of the activity.["https://example.com/1/followers/2"]
activitypub.activity.ccstring[]The URI(s) of the carbon-copied recipient collections/actors of the activity.["https://www.w3.org/ns/activitystreams#Public"]
activitypub.activity.btostring[]The URI(s) of the blind recipient collections/actors of the activity.["https://example.com/1/followers/2"]
activitypub.activity.bccstring[]The URI(s) of the blind carbon-copied recipient collections/actors of the activity.["https://www.w3.org/ns/activitystreams#Public"]
activitypub.activity.retriesintThe ordinal number of activity resending attempt (if and only if it's retried).3
activitypub.actor.idstringThe URI of the actor object."https://example.com/actor/1"
activitypub.actor.key.cachedbooleanWhether the actor's public keys are cached.true
activitypub.actor.typestring[]The qualified URI(s) of the actor type(s).["https://www.w3.org/ns/activitystreams#Person"]
activitypub.collection.idstringThe URI of the collection object."https://example.com/collection/1"
activitypub.collection.typestring[]The qualified URI(s) of the collection type(s).["https://www.w3.org/ns/activitystreams#OrderedCollection"]
activitypub.collection.total_itemsintThe total number of items in the collection.42
activitypub.object.idstringThe URI of the object or the object enclosed by the activity."https://example.com/object/1"
activitypub.object.typestring[]The qualified URI(s) of the object type(s).["https://www.w3.org/ns/activitystreams#Note"]
activitypub.object.in_reply_tostring[]The URI(s) of the original object to which the object reply.["https://example.com/object/1"]
activitypub.inboxesintThe number of inboxes the activity is sent to.12
activitypub.shared_inboxbooleanWhether the activity is sent to the shared inbox.true
fedify.actor.identifierstringThe identifier of the actor."1"
fedify.inbox.recipientstringThe identifier of the inbox recipient."1"
fedify.object.typestringThe URI of the object type."https://www.w3.org/ns/activitystreams#Note"
fedify.object.values.{parameter}string[]The argument values of the object dispatcher.["1", "2"]
fedify.collection.cursorstringThe cursor of the collection."eyJpZCI6IjEiLCJ0eXBlIjoiT3JkZXJlZENvbGxlY3Rpb24ifQ=="
fedify.collection.itemsnumberThe number of items in the collection page. It can be less than the total items.10
http_signatures.signaturestringThe signature of the HTTP request in hexadecimal."73a74c990beabe6e59cc68f9c6db7811b59cbb22fd12dcffb3565b651540efe9"
http_signatures.algorithmstringThe algorithm of the HTTP request signature."rsa-sha256"
http_signatures.key_idstringThe public key ID of the HTTP request signature."https://example.com/actor/1#main-key"
http_signatures.digest.{algorithm}stringThe digest of the HTTP request body in hexadecimal. The {algorithm} is the digest algorithm (e.g., sha, sha-256)."d41d8cd98f00b204e9800998ecf8427e"
ld_signatures.key_idstringThe public key ID of the Linked Data signature."https://example.com/actor/1#main-key"
ld_signatures.signaturestringThe signature of the Linked Data in hexadecimal."73a74c990beabe6e59cc68f9c6db7811b59cbb22fd12dcffb3565b651540efe9"
ld_signatures.typestringThe algorithm of the Linked Data signature."RsaSignature2017"
object_integrity_proofs.cryptosuitestringThe cryptographic suite of the object integrity proof."eddsa-jcs-2022"
object_integrity_proofs.key_idstringThe public key ID of the object integrity proof."https://example.com/actor/1#main-key"
object_integrity_proofs.signaturestringThe integrity proof of the object in hexadecimal."73a74c990beabe6e59cc68f9c6db7811b59cbb22fd12dcffb3565b651540efe9"
webfinger.resourcestringThe queried resource URI."acct:fedify@hollo.social"
webfinger.resource.schemestringThe scheme of the queried resource URI."acct"