Loading CHANGES.md +2 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ To be released. null` (was `{ name: string; values: Record<string, string> } | null`). - Added `RouterRouteResult` interface. - Fedify now supports OpenTelemetry for tracing. - Fedify now supports OpenTelemetry for tracing. [[#170]] - Added `CreateFederationOptions.tracerProvider` option. Loading @@ -75,6 +75,7 @@ To be released. [SvelteKit]: https://kit.svelte.dev/ [#162]: https://github.com/dahlia/fedify/issues/162 [#170]: https://github.com/dahlia/fedify/issues/170 [#171]: https://github.com/dahlia/fedify/issues/171 [#173]: https://github.com/dahlia/fedify/issues/173 [#183]: https://github.com/dahlia/fedify/pull/183 Loading docs/manual/opentelemetry.md +1 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ spans: | Operation | Description | |----------------------|-----------------------------------| | `Federation.fetch()` | Serves the incoming HTTP request. | | `handleWebFinger()` | Handles the WebFinger request. | More operations will be instrumented in the future releases. Loading src/federation/middleware.ts +5 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import { SpanKind, SpanStatusCode, trace, Tracer, type TracerProvider, } from "@opentelemetry/api"; import { Loading Loading @@ -1906,7 +1907,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { } let response: Response; try { response = await this.#fetch(request, { ...options, span }); response = await this.#fetch(request, { ...options, span, tracer }); } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR, Loading Loading @@ -1957,7 +1958,8 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { onUnauthorized, contextData, span, }: FederationFetchOptions<TContextData> & { span: Span }, tracer, }: FederationFetchOptions<TContextData> & { span: Span; tracer: Tracer }, ): Promise<Response> { onNotFound ??= notFound; onNotAcceptable ??= notAcceptable; Loading @@ -1975,6 +1977,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { actorDispatcher: this.actorCallbacks?.dispatcher, actorHandleMapper: this.actorCallbacks?.handleMapper, onNotFound, tracer, }); case "nodeInfoJrd": return await handleNodeInfoJrd(request, context); Loading src/webfinger/handler.ts +44 −0 Original line number Diff line number Diff line import { getLogger } from "@logtape/logtape"; import type { Span, Tracer } from "@opentelemetry/api"; import { SpanKind, SpanStatusCode } from "@opentelemetry/api"; import { toASCII } from "node:punycode"; import type { ActorDispatcher, Loading Loading @@ -34,6 +36,16 @@ export interface WebFingerHandlerParameters<TContextData> { * The function to call when the actor is not found. */ onNotFound(request: Request): Response | Promise<Response>; /** * The OpenTelemetry tracer. */ tracer?: Tracer; /** * The span for the request. */ span?: Span; } /** Loading @@ -44,12 +56,43 @@ export interface WebFingerHandlerParameters<TContextData> { * @returns The response to the request. */ export async function handleWebFinger<TContextData>( request: Request, options: WebFingerHandlerParameters<TContextData>, ): Promise<Response> { if (options.tracer == null) { return await handleWebFingerInternal(request, options); } return await options.tracer.startActiveSpan( "WebFinger", { kind: SpanKind.SERVER }, async (span) => { try { const response = await handleWebFingerInternal(request, options); span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR, }); return response; } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR, message: String(error), }); throw error; } finally { span.end(); } }, ); } async function handleWebFingerInternal<TContextData>( request: Request, { context, actorDispatcher, actorHandleMapper, onNotFound, span, }: WebFingerHandlerParameters<TContextData>, ): Promise<Response> { if (actorDispatcher == null) return await onNotFound(request); Loading @@ -57,6 +100,7 @@ export async function handleWebFinger<TContextData>( if (resource == null) { return new Response("Missing resource parameter.", { status: 400 }); } span?.setAttribute("webfinger.resource", resource); let resourceUrl: URL; try { resourceUrl = new URL(resource); Loading Loading
CHANGES.md +2 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ To be released. null` (was `{ name: string; values: Record<string, string> } | null`). - Added `RouterRouteResult` interface. - Fedify now supports OpenTelemetry for tracing. - Fedify now supports OpenTelemetry for tracing. [[#170]] - Added `CreateFederationOptions.tracerProvider` option. Loading @@ -75,6 +75,7 @@ To be released. [SvelteKit]: https://kit.svelte.dev/ [#162]: https://github.com/dahlia/fedify/issues/162 [#170]: https://github.com/dahlia/fedify/issues/170 [#171]: https://github.com/dahlia/fedify/issues/171 [#173]: https://github.com/dahlia/fedify/issues/173 [#183]: https://github.com/dahlia/fedify/pull/183 Loading
docs/manual/opentelemetry.md +1 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ spans: | Operation | Description | |----------------------|-----------------------------------| | `Federation.fetch()` | Serves the incoming HTTP request. | | `handleWebFinger()` | Handles the WebFinger request. | More operations will be instrumented in the future releases. Loading
src/federation/middleware.ts +5 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import { SpanKind, SpanStatusCode, trace, Tracer, type TracerProvider, } from "@opentelemetry/api"; import { Loading Loading @@ -1906,7 +1907,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { } let response: Response; try { response = await this.#fetch(request, { ...options, span }); response = await this.#fetch(request, { ...options, span, tracer }); } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR, Loading Loading @@ -1957,7 +1958,8 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { onUnauthorized, contextData, span, }: FederationFetchOptions<TContextData> & { span: Span }, tracer, }: FederationFetchOptions<TContextData> & { span: Span; tracer: Tracer }, ): Promise<Response> { onNotFound ??= notFound; onNotAcceptable ??= notAcceptable; Loading @@ -1975,6 +1977,7 @@ export class FederationImpl<TContextData> implements Federation<TContextData> { actorDispatcher: this.actorCallbacks?.dispatcher, actorHandleMapper: this.actorCallbacks?.handleMapper, onNotFound, tracer, }); case "nodeInfoJrd": return await handleNodeInfoJrd(request, context); Loading
src/webfinger/handler.ts +44 −0 Original line number Diff line number Diff line import { getLogger } from "@logtape/logtape"; import type { Span, Tracer } from "@opentelemetry/api"; import { SpanKind, SpanStatusCode } from "@opentelemetry/api"; import { toASCII } from "node:punycode"; import type { ActorDispatcher, Loading Loading @@ -34,6 +36,16 @@ export interface WebFingerHandlerParameters<TContextData> { * The function to call when the actor is not found. */ onNotFound(request: Request): Response | Promise<Response>; /** * The OpenTelemetry tracer. */ tracer?: Tracer; /** * The span for the request. */ span?: Span; } /** Loading @@ -44,12 +56,43 @@ export interface WebFingerHandlerParameters<TContextData> { * @returns The response to the request. */ export async function handleWebFinger<TContextData>( request: Request, options: WebFingerHandlerParameters<TContextData>, ): Promise<Response> { if (options.tracer == null) { return await handleWebFingerInternal(request, options); } return await options.tracer.startActiveSpan( "WebFinger", { kind: SpanKind.SERVER }, async (span) => { try { const response = await handleWebFingerInternal(request, options); span.setStatus({ code: response.ok ? SpanStatusCode.UNSET : SpanStatusCode.ERROR, }); return response; } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR, message: String(error), }); throw error; } finally { span.end(); } }, ); } async function handleWebFingerInternal<TContextData>( request: Request, { context, actorDispatcher, actorHandleMapper, onNotFound, span, }: WebFingerHandlerParameters<TContextData>, ): Promise<Response> { if (actorDispatcher == null) return await onNotFound(request); Loading @@ -57,6 +100,7 @@ export async function handleWebFinger<TContextData>( if (resource == null) { return new Response("Missing resource parameter.", { status: 400 }); } span?.setAttribute("webfinger.resource", resource); let resourceUrl: URL; try { resourceUrl = new URL(resource); Loading