Skip to content

Commit 1eec926

Browse files
committed
Instrument lookupWebFinger()
1 parent 9303085 commit 1eec926

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ To be released.
6262
- Fedify now supports OpenTelemetry for tracing. [[#170]]
6363

6464
- Added `CreateFederationOptions.tracerProvider` option.
65+
- Added `LookupWebFingerOptions.tracerProvider` option.
6566

6667
- Added `@fedify/fedify/x/sveltekit` module for integrating with [SvelteKit]
6768
hook. [[#171], [#183] by Jiyu Park]

docs/manual/opentelemetry.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,11 @@ Instrumented spans
115115
Fedify automatically instruments the following operations with OpenTelemetry
116116
spans:
117117

118-
| Operation | Description |
119-
|----------------------|-----------------------------------|
120-
| `Federation.fetch()` | Serves the incoming HTTP request. |
121-
| `handleWebFinger()` | Handles the WebFinger request. |
118+
| Operation | Span type | Description |
119+
|----------------------|-----------|-----------------------------------|
120+
| `Federation.fetch()` | Server | Serves the incoming HTTP request. |
121+
| `lookupWebFinger()` | Client | Looks up the WebFinger resource. |
122+
| `handleWebFinger()` | Server | Handles the WebFinger request. |
122123

123124
More operations will be instrumented in the future releases.
124125

@@ -146,5 +147,6 @@ for ActivityPub:
146147
| `activitypub.inboxes` | int | The number of inboxes the activity is sent to. | `12` |
147148
| `activitypub.shared_inbox` | boolean | Whether the activity is sent to the shared inbox. | `true` |
148149
| `webfinger.resource` | string | The queried resource URI. | `"acct:[email protected]"` |
150+
| `webfinger.resource.scheme` | string | The scheme of the queried resource URI. | `"acct"` |
149151

150152
[OpenTelemetry Semantic Conventions]: https://opentelemetry.io/docs/specs/semconv/

src/webfinger/handler.ts

+4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ async function handleWebFingerInternal<TContextData>(
110110
}
111111
throw e;
112112
}
113+
span?.setAttribute(
114+
"webfinger.resource.scheme",
115+
resourceUrl.protocol.replace(/:$/, ""),
116+
);
113117
if (actorDispatcher == null) {
114118
logger.error("Actor dispatcher is not set.");
115119
return await onNotFound(request);

src/webfinger/lookup.ts

+54
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { getLogger } from "@logtape/logtape";
2+
import {
3+
SpanKind,
4+
SpanStatusCode,
5+
type TracerProvider,
6+
} from "@opentelemetry/api";
7+
import metadata from "../deno.json" with { type: "json" };
28
import {
39
getUserAgent,
410
type GetUserAgentOptions,
@@ -19,6 +25,12 @@ export interface LookupWebFingerOptions {
1925
* the `User-Agent` header value.
2026
*/
2127
userAgent?: GetUserAgentOptions | string;
28+
29+
/**
30+
* The OpenTelemetry tracer provider.
31+
* @since 1.3.0
32+
*/
33+
tracerProvider?: TracerProvider;
2234
}
2335

2436
/**
@@ -31,6 +43,48 @@ export interface LookupWebFingerOptions {
3143
export async function lookupWebFinger(
3244
resource: URL | string,
3345
options: LookupWebFingerOptions = {},
46+
): Promise<ResourceDescriptor | null> {
47+
if (options.tracerProvider == null) {
48+
return await lookupWebFingerInternal(resource, options);
49+
}
50+
const tracer = options.tracerProvider.getTracer(
51+
metadata.name,
52+
metadata.version,
53+
);
54+
return await tracer.startActiveSpan(
55+
"WebFinger",
56+
{
57+
kind: SpanKind.CLIENT,
58+
attributes: {
59+
"webfinger.resource": resource.toString(),
60+
"webfinger.resource.scheme": typeof resource === "string"
61+
? resource.replace(/:.*$/, "")
62+
: resource.protocol.replace(/:$/, ""),
63+
},
64+
},
65+
async (span) => {
66+
try {
67+
const result = await lookupWebFingerInternal(resource, options);
68+
span.setStatus({
69+
code: result === null ? SpanStatusCode.ERROR : SpanStatusCode.OK,
70+
});
71+
return result;
72+
} catch (error) {
73+
span.setStatus({
74+
code: SpanStatusCode.ERROR,
75+
message: String(error),
76+
});
77+
throw error;
78+
} finally {
79+
span.end();
80+
}
81+
},
82+
);
83+
}
84+
85+
async function lookupWebFingerInternal(
86+
resource: URL | string,
87+
options: LookupWebFingerOptions = {},
3488
): Promise<ResourceDescriptor | null> {
3589
if (typeof resource === "string") resource = new URL(resource);
3690
let protocol = "https:";

0 commit comments

Comments
 (0)