@frontmcp/observability 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/esm/index.mjs +2986 -0
  2. package/esm/package.json +86 -0
  3. package/index.d.ts +11 -0
  4. package/logging/index.d.ts +9 -0
  5. package/logging/log-sink.interface.d.ts +81 -0
  6. package/logging/redaction.d.ts +17 -0
  7. package/logging/sink.factory.d.ts +15 -0
  8. package/logging/sinks/callback.sink.d.ts +12 -0
  9. package/logging/sinks/console.sink.d.ts +16 -0
  10. package/logging/sinks/index.d.ts +7 -0
  11. package/logging/sinks/otlp.sink.d.ts +67 -0
  12. package/logging/sinks/pino.sink.d.ts +13 -0
  13. package/logging/sinks/stdout.sink.d.ts +17 -0
  14. package/logging/sinks/winston.sink.d.ts +13 -0
  15. package/logging/structured-log-transport.d.ts +52 -0
  16. package/logging/structured-log.types.d.ts +71 -0
  17. package/otel/context-propagator.d.ts +17 -0
  18. package/otel/index.d.ts +8 -0
  19. package/otel/otel.setup.d.ts +32 -0
  20. package/otel/otel.tokens.d.ts +7 -0
  21. package/otel/otel.types.d.ts +151 -0
  22. package/otel/spans/auth.span.d.ts +27 -0
  23. package/otel/spans/fetch.span.d.ts +28 -0
  24. package/otel/spans/hook.span.d.ts +33 -0
  25. package/otel/spans/http-server.span.d.ts +29 -0
  26. package/otel/spans/index.d.ts +23 -0
  27. package/otel/spans/pretty-span-exporter.d.ts +19 -0
  28. package/otel/spans/prompt.span.d.ts +19 -0
  29. package/otel/spans/resource.span.d.ts +21 -0
  30. package/otel/spans/rpc.span.d.ts +33 -0
  31. package/otel/spans/span.utils.d.ts +38 -0
  32. package/otel/spans/startup.span.d.ts +28 -0
  33. package/otel/spans/tool.span.d.ts +25 -0
  34. package/otel/spans/transport.span.d.ts +30 -0
  35. package/otel/trace-context-bridge.d.ts +41 -0
  36. package/package.json +1 -1
  37. package/plugin/index.d.ts +3 -0
  38. package/plugin/observability.hooks.d.ts +92 -0
  39. package/plugin/observability.plugin.d.ts +141 -0
  40. package/plugin/observability.plugin.types.d.ts +38 -0
  41. package/request-log/index.d.ts +3 -0
  42. package/request-log/request-log.collector.d.ts +97 -0
  43. package/request-log/request-log.tokens.d.ts +7 -0
  44. package/request-log/request-log.types.d.ts +82 -0
  45. package/telemetry/index.d.ts +3 -0
  46. package/telemetry/telemetry.accessor.d.ts +151 -0
  47. package/telemetry/telemetry.context-extension.d.ts +35 -0
  48. package/telemetry/telemetry.tokens.d.ts +7 -0
  49. package/testing/index.d.ts +76 -0
@@ -0,0 +1,151 @@
1
+ /**
2
+ * OpenTelemetry semantic attributes for FrontMCP.
3
+ *
4
+ * Three attribute namespaces:
5
+ * - `mcp.*` — MCP protocol-level attributes (interoperable with other MCP implementations)
6
+ * - `frontmcp.*` — FrontMCP-specific attributes (vendor namespace per OTel conventions)
7
+ * - Standard OTel — `http.*`, `rpc.*`, `url.*`, `enduser.*`, `server.*`
8
+ */
9
+ export declare const McpAttributes: {
10
+ /** MCP protocol method name (e.g., "tools/call", "resources/read") */
11
+ readonly METHOD_NAME: "mcp.method.name";
12
+ /** MCP session identifier (hashed for privacy) */
13
+ readonly SESSION_ID: "mcp.session.id";
14
+ /** MCP resource URI */
15
+ readonly RESOURCE_URI: "mcp.resource.uri";
16
+ /** MCP component type: "tool" | "resource" | "prompt" | "resource_template" */
17
+ readonly COMPONENT_TYPE: "mcp.component.type";
18
+ /** MCP component key (e.g., "tool:get_weather", "resource:config://db") */
19
+ readonly COMPONENT_KEY: "mcp.component.key";
20
+ };
21
+ export declare const FrontMcpAttributes: {
22
+ /** Scope identifier */
23
+ readonly SCOPE_ID: "frontmcp.scope.id";
24
+ /** Server/scope name */
25
+ readonly SERVER_NAME: "frontmcp.server.name";
26
+ /** Tool name being executed */
27
+ readonly TOOL_NAME: "frontmcp.tool.name";
28
+ /** Tool owner class name */
29
+ readonly TOOL_OWNER: "frontmcp.tool.owner";
30
+ /** Resource URI being read */
31
+ readonly RESOURCE_URI: "frontmcp.resource.uri";
32
+ /** Resource name */
33
+ readonly RESOURCE_NAME: "frontmcp.resource.name";
34
+ /** Prompt name being invoked */
35
+ readonly PROMPT_NAME: "frontmcp.prompt.name";
36
+ /** Flow name (e.g., "tools:call-tool") */
37
+ readonly FLOW_NAME: "frontmcp.flow.name";
38
+ /** Flow stage (e.g., "willExecute") */
39
+ readonly FLOW_STAGE: "frontmcp.flow.stage";
40
+ /** Hook stage (e.g., "willValidateInput") */
41
+ readonly HOOK_STAGE: "frontmcp.hook.stage";
42
+ /** Hook owner identifier */
43
+ readonly HOOK_OWNER: "frontmcp.hook.owner";
44
+ /** Hashed session ID (for trace correlation, not the real session ID) */
45
+ readonly SESSION_ID_HASH: "frontmcp.session.id_hash";
46
+ /** Authentication type */
47
+ readonly AUTH_TYPE: "frontmcp.auth.type";
48
+ /** Request identifier */
49
+ readonly REQUEST_ID: "frontmcp.request.id";
50
+ /** Provider type (e.g., "local", "adapter", "remote") */
51
+ readonly PROVIDER_TYPE: "frontmcp.provider.type";
52
+ /** Delegation — original name before namespacing */
53
+ readonly DELEGATE_ORIGINAL_NAME: "frontmcp.delegate.original_name";
54
+ /** Transport type: "legacy-sse" | "streamable-http" | "stateless-http" */
55
+ readonly TRANSPORT_TYPE: "frontmcp.transport.type";
56
+ /** Transport request type: "initialize" | "message" | "elicitResult" | "sseListener" | "extApps" */
57
+ readonly TRANSPORT_REQUEST_TYPE: "frontmcp.transport.request_type";
58
+ /** Session protocol */
59
+ readonly SESSION_PROTOCOL: "frontmcp.session.protocol";
60
+ /** Whether a new session was created */
61
+ readonly SESSION_CREATED: "frontmcp.session.created";
62
+ /** Auth mode: "public" | "transparent" | "orchestrated" */
63
+ readonly AUTH_MODE: "frontmcp.auth.mode";
64
+ /** Auth result: "authorized" | "unauthorized" | "anonymous" */
65
+ readonly AUTH_RESULT: "frontmcp.auth.result";
66
+ /** OAuth grant type: "authorization_code" | "refresh_token" | "anonymous" */
67
+ readonly OAUTH_GRANT_TYPE: "frontmcp.oauth.grant_type";
68
+ /** Elicitation request ID */
69
+ readonly ELICITATION_ID: "frontmcp.elicitation.id";
70
+ /** Agent name */
71
+ readonly AGENT_NAME: "frontmcp.agent.name";
72
+ /** Agent execution loop iterations */
73
+ readonly AGENT_ITERATIONS: "frontmcp.agent.iterations";
74
+ /** Agent execution duration in ms */
75
+ readonly AGENT_EXECUTION_DURATION_MS: "frontmcp.agent.execution_duration_ms";
76
+ /** Total tools registered at startup */
77
+ readonly STARTUP_TOOLS_COUNT: "frontmcp.startup.tools_count";
78
+ /** Total resources registered at startup */
79
+ readonly STARTUP_RESOURCES_COUNT: "frontmcp.startup.resources_count";
80
+ /** Total prompts registered at startup */
81
+ readonly STARTUP_PROMPTS_COUNT: "frontmcp.startup.prompts_count";
82
+ /** Total plugins loaded at startup */
83
+ readonly STARTUP_PLUGINS_COUNT: "frontmcp.startup.plugins_count";
84
+ /** Startup initialization duration in ms */
85
+ readonly STARTUP_DURATION_MS: "frontmcp.startup.duration_ms";
86
+ };
87
+ export declare const HttpAttributes: {
88
+ readonly METHOD: "http.request.method";
89
+ readonly STATUS_CODE: "http.response.status_code";
90
+ readonly URL_PATH: "url.path";
91
+ readonly URL_FULL: "url.full";
92
+ readonly URL_SCHEME: "url.scheme";
93
+ readonly SERVER_ADDRESS: "server.address";
94
+ readonly SERVER_PORT: "server.port";
95
+ };
96
+ export declare const RpcAttributes: {
97
+ /** RPC system — "mcp" for MCP protocol */
98
+ readonly SYSTEM: "rpc.system";
99
+ /** RPC service name */
100
+ readonly SERVICE: "rpc.service";
101
+ /** RPC method */
102
+ readonly METHOD: "rpc.method";
103
+ /** JSON-RPC version */
104
+ readonly JSONRPC_VERSION: "rpc.jsonrpc.version";
105
+ /** JSON-RPC request ID */
106
+ readonly JSONRPC_REQUEST_ID: "rpc.jsonrpc.request_id";
107
+ };
108
+ export declare const EnduserAttributes: {
109
+ /** Client/user ID from auth token */
110
+ readonly ID: "enduser.id";
111
+ /** OAuth scopes (space-separated) */
112
+ readonly SCOPE: "enduser.scope";
113
+ };
114
+ /**
115
+ * OTel tracing configuration options.
116
+ */
117
+ export interface TracingOptions {
118
+ /** Instrument HTTP request spans (default: true) */
119
+ httpSpans?: boolean;
120
+ /** Instrument tool/resource/prompt execution spans (default: true) */
121
+ executionSpans?: boolean;
122
+ /** Instrument individual hook spans — verbose (default: false) */
123
+ hookSpans?: boolean;
124
+ /** Instrument outbound fetch() calls (default: true) */
125
+ fetchSpans?: boolean;
126
+ /** Record flow stages as span events (default: true) */
127
+ flowStageEvents?: boolean;
128
+ /** Instrument transport flows — SSE, streamable-http, stateless-http (default: true) */
129
+ transportSpans?: boolean;
130
+ /** Instrument auth verify/session verify flows (default: true) */
131
+ authSpans?: boolean;
132
+ /** Instrument OAuth flows — token, authorize, callback, register (default: true) */
133
+ oauthSpans?: boolean;
134
+ /** Instrument elicitation request/result flows (default: true) */
135
+ elicitationSpans?: boolean;
136
+ /** Emit startup telemetry report on first request (default: true) */
137
+ startupReport?: boolean;
138
+ }
139
+ /**
140
+ * OTel setup configuration for the convenience setupOTel() function.
141
+ */
142
+ export interface OTelSetupOptions {
143
+ /** Service name for the OTel resource (default: 'frontmcp-server') */
144
+ serviceName?: string;
145
+ /** Exporter type */
146
+ exporter?: 'otlp' | 'console';
147
+ /** OTLP endpoint URL (default: 'http://localhost:4318') */
148
+ endpoint?: string;
149
+ /** Service version */
150
+ serviceVersion?: string;
151
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Auth Span — authentication and session verification instrumentation.
3
+ */
4
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
5
+ export interface AuthSpanOptions {
6
+ /** Auth flow name (e.g., "auth:verify", "session:verify") */
7
+ flowName: string;
8
+ /** Parent OTel context */
9
+ parentContext?: Context;
10
+ }
11
+ /**
12
+ * Start an auth span.
13
+ *
14
+ * Span name: "auth {flowName}"
15
+ */
16
+ export declare function startAuthSpan(tracer: Tracer, options: AuthSpanOptions): {
17
+ span: Span;
18
+ context: Context;
19
+ };
20
+ /**
21
+ * Set auth mode on the span.
22
+ */
23
+ export declare function setAuthMode(span: Span, mode: string): void;
24
+ /**
25
+ * Set auth result on the span.
26
+ */
27
+ export declare function setAuthResult(span: Span, result: string): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Fetch Span — outbound HTTP client instrumentation.
3
+ *
4
+ * Wraps fetch() calls made via FrontMcpContext.fetch() to create
5
+ * client HTTP spans following OTel HTTP semantic conventions.
6
+ */
7
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
8
+ export interface FetchSpanOptions {
9
+ /** HTTP method */
10
+ method: string;
11
+ /** Full URL */
12
+ url: string;
13
+ /** Parent OTel context */
14
+ parentContext?: Context;
15
+ }
16
+ /**
17
+ * Start an outbound HTTP client span.
18
+ *
19
+ * Span name follows OTel convention: "{method}"
20
+ */
21
+ export declare function startFetchSpan(tracer: Tracer, options: FetchSpanOptions): {
22
+ span: Span;
23
+ context: Context;
24
+ };
25
+ /**
26
+ * Set the response status on a fetch span.
27
+ */
28
+ export declare function setFetchResponseStatus(span: Span, statusCode: number): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Hook Span — FrontMCP hook execution instrumentation.
3
+ *
4
+ * By default, hook executions are recorded as span events (not child spans)
5
+ * to keep trace depth manageable. When hookSpans is enabled, each hook
6
+ * gets its own child span.
7
+ */
8
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
9
+ export interface HookSpanOptions {
10
+ /** Hook stage name (e.g., "willExecute") */
11
+ stage: string;
12
+ /** Hook owner identifier */
13
+ owner?: string;
14
+ /** Flow name (e.g., "tools:call-tool") */
15
+ flowName?: string;
16
+ /** Parent OTel context */
17
+ parentContext?: Context;
18
+ }
19
+ /**
20
+ * Record a hook execution as a span event on the parent span.
21
+ *
22
+ * This is the default behavior — lightweight, no trace depth increase.
23
+ */
24
+ export declare function recordHookEvent(parentSpan: Span, stage: string, owner?: string): void;
25
+ /**
26
+ * Start a dedicated hook span (verbose mode).
27
+ *
28
+ * Only used when hookSpans is enabled in the tracing options.
29
+ */
30
+ export declare function startHookSpan(tracer: Tracer, options: HookSpanOptions): {
31
+ span: Span;
32
+ context: Context;
33
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * HTTP Server Span — follows OTel HTTP semantic conventions.
3
+ *
4
+ * @see https://opentelemetry.io/docs/specs/semconv/http/http-spans/
5
+ */
6
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
7
+ export interface HttpServerSpanOptions {
8
+ method: string;
9
+ path: string;
10
+ scheme?: string;
11
+ serverAddress?: string;
12
+ serverPort?: number;
13
+ scopeId?: string;
14
+ requestId?: string;
15
+ parentContext?: Context;
16
+ }
17
+ /**
18
+ * Start an HTTP server span.
19
+ *
20
+ * Span name follows OTel convention: "{method} {path}"
21
+ */
22
+ export declare function startHttpServerSpan(tracer: Tracer, options: HttpServerSpanOptions): {
23
+ span: Span;
24
+ context: Context;
25
+ };
26
+ /**
27
+ * Set the HTTP response status code on a server span.
28
+ */
29
+ export declare function setHttpResponseStatus(span: Span, statusCode: number): void;
@@ -0,0 +1,23 @@
1
+ export { startSpan, endSpanOk, endSpanError, withSpan } from './span.utils';
2
+ export type { StartSpanOptions } from './span.utils';
3
+ export { startHttpServerSpan, setHttpResponseStatus } from './http-server.span';
4
+ export type { HttpServerSpanOptions } from './http-server.span';
5
+ export { startRpcSpan } from './rpc.span';
6
+ export type { RpcSpanOptions } from './rpc.span';
7
+ export { startToolSpan } from './tool.span';
8
+ export type { ToolSpanOptions } from './tool.span';
9
+ export { startResourceSpan } from './resource.span';
10
+ export type { ResourceSpanOptions } from './resource.span';
11
+ export { startPromptSpan } from './prompt.span';
12
+ export type { PromptSpanOptions } from './prompt.span';
13
+ export { recordHookEvent, startHookSpan } from './hook.span';
14
+ export type { HookSpanOptions } from './hook.span';
15
+ export { startFetchSpan, setFetchResponseStatus } from './fetch.span';
16
+ export type { FetchSpanOptions } from './fetch.span';
17
+ export { startTransportSpan, setTransportRequestType } from './transport.span';
18
+ export type { TransportSpanOptions } from './transport.span';
19
+ export { startAuthSpan, setAuthMode, setAuthResult } from './auth.span';
20
+ export type { AuthSpanOptions } from './auth.span';
21
+ export { emitStartupReport } from './startup.span';
22
+ export { PrettySpanExporter } from './pretty-span-exporter';
23
+ export type { StartupTelemetryData } from './startup.span';
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PrettySpanExporter — human-readable span output for development.
3
+ *
4
+ * Instead of dumping raw JSON (like ConsoleSpanExporter), formats spans
5
+ * as compact, colored one-liners with key attributes and timing.
6
+ *
7
+ * Example output:
8
+ * ↳ SPAN tools/call [36008509] 8ms rpc.system=mcp mcp.session.id=5bfdd288
9
+ * ↳ SPAN tool get_weather [36008509] 5ms mcp.component.type=tool enduser.id=client-42
10
+ */
11
+ import type { SpanExporter, ReadableSpan } from '@opentelemetry/sdk-trace-base';
12
+ import type { ExportResult } from '@opentelemetry/core';
13
+ export declare class PrettySpanExporter implements SpanExporter {
14
+ private useAnsi;
15
+ constructor();
16
+ export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
17
+ shutdown(): Promise<void>;
18
+ private format;
19
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Prompt Span — FrontMCP prompt invocation instrumentation.
3
+ */
4
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
5
+ export interface PromptSpanOptions {
6
+ /** Prompt name */
7
+ name: string;
8
+ /** Parent OTel context */
9
+ parentContext?: Context;
10
+ }
11
+ /**
12
+ * Start a prompt invocation span.
13
+ *
14
+ * Span name: "prompt {name}"
15
+ */
16
+ export declare function startPromptSpan(tracer: Tracer, options: PromptSpanOptions): {
17
+ span: Span;
18
+ context: Context;
19
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Resource Read Span — FrontMCP resource read instrumentation.
3
+ */
4
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
5
+ export interface ResourceSpanOptions {
6
+ /** Resource URI */
7
+ uri: string;
8
+ /** Resource name */
9
+ name?: string;
10
+ /** Parent OTel context */
11
+ parentContext?: Context;
12
+ }
13
+ /**
14
+ * Start a resource read span.
15
+ *
16
+ * Span name: "resource {uri}"
17
+ */
18
+ export declare function startResourceSpan(tracer: Tracer, options: ResourceSpanOptions): {
19
+ span: Span;
20
+ context: Context;
21
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * RPC Span — follows OTel RPC semantic conventions for MCP.
3
+ *
4
+ * MCP is treated as its own RPC system (`rpc.system = "mcp"`)
5
+ * rather than generic JSON-RPC, following the FastMCP convention
6
+ * for better filtering in trace backends.
7
+ *
8
+ * @see https://opentelemetry.io/docs/specs/semconv/rpc/rpc-spans/
9
+ */
10
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
11
+ export interface RpcSpanOptions {
12
+ /** MCP method (e.g., "tools/call", "resources/read") */
13
+ method: string;
14
+ /** JSON-RPC request ID */
15
+ requestId?: string | number;
16
+ /** Scope ID */
17
+ scopeId?: string;
18
+ /** Server/service name */
19
+ serviceName?: string;
20
+ /** Hashed session ID for trace correlation */
21
+ sessionIdHash?: string;
22
+ /** Parent OTel context */
23
+ parentContext?: Context;
24
+ }
25
+ /**
26
+ * Start an RPC span for an MCP method invocation.
27
+ *
28
+ * Span name follows OTel convention: "{rpc.method}"
29
+ */
30
+ export declare function startRpcSpan(tracer: Tracer, options: RpcSpanOptions): {
31
+ span: Span;
32
+ context: Context;
33
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Span utility helpers for creating and managing OTel spans.
3
+ */
4
+ import { type Tracer, type Span, type Context, SpanKind } from '@opentelemetry/api';
5
+ /**
6
+ * Options for starting a span.
7
+ */
8
+ export interface StartSpanOptions {
9
+ /** Span name (follows OTel naming conventions) */
10
+ name: string;
11
+ /** Span kind (default: INTERNAL) */
12
+ kind?: SpanKind;
13
+ /** Span attributes */
14
+ attributes?: Record<string, string | number | boolean>;
15
+ /** Parent OTel context (default: current active context) */
16
+ parentContext?: Context;
17
+ }
18
+ /**
19
+ * Start a new span using the provided tracer.
20
+ *
21
+ * @returns The new span and the context with the span set as active.
22
+ */
23
+ export declare function startSpan(tracer: Tracer, options: StartSpanOptions): {
24
+ span: Span;
25
+ context: Context;
26
+ };
27
+ /**
28
+ * End a span with success status.
29
+ */
30
+ export declare function endSpanOk(span: Span): void;
31
+ /**
32
+ * End a span with error status.
33
+ */
34
+ export declare function endSpanError(span: Span, error: Error | string): void;
35
+ /**
36
+ * Run a function within a span, automatically handling success/error.
37
+ */
38
+ export declare function withSpan<T>(tracer: Tracer, options: StartSpanOptions, fn: (span: Span) => Promise<T>): Promise<T>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Startup Report Span — emits server initialization telemetry.
3
+ *
4
+ * Created as a standalone span after scope initialization completes.
5
+ * Records counts of registered components and initialization duration.
6
+ */
7
+ import { type Tracer } from '@opentelemetry/api';
8
+ export interface StartupTelemetryData {
9
+ /** Total tools registered */
10
+ toolsCount: number;
11
+ /** Total resources registered */
12
+ resourcesCount: number;
13
+ /** Total prompts registered */
14
+ promptsCount: number;
15
+ /** Total plugins loaded */
16
+ pluginsCount: number;
17
+ /** Initialization duration in ms */
18
+ durationMs: number;
19
+ /** Scope/server name */
20
+ scopeId?: string;
21
+ }
22
+ /**
23
+ * Emit a startup telemetry report as a standalone span.
24
+ *
25
+ * Creates and immediately ends a span with all startup metrics
26
+ * as attributes. Call this after scope.initialize() completes.
27
+ */
28
+ export declare function emitStartupReport(tracer: Tracer, data: StartupTelemetryData): void;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Tool Execution Span — FrontMCP tool invocation instrumentation.
3
+ */
4
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
5
+ export interface ToolSpanOptions {
6
+ /** Tool name */
7
+ name: string;
8
+ /** Tool owner class name */
9
+ owner?: string;
10
+ /** Enduser ID (from auth token, e.g., client ID) */
11
+ enduserId?: string;
12
+ /** Enduser scopes (space-separated OAuth scopes) */
13
+ enduserScope?: string;
14
+ /** Parent OTel context */
15
+ parentContext?: Context;
16
+ }
17
+ /**
18
+ * Start a tool execution span.
19
+ *
20
+ * Span name: "tool {name}"
21
+ */
22
+ export declare function startToolSpan(tracer: Tracer, options: ToolSpanOptions): {
23
+ span: Span;
24
+ context: Context;
25
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Transport Span — SSE, Streamable HTTP, Stateless HTTP instrumentation.
3
+ *
4
+ * Created for each transport-level flow that handles session creation,
5
+ * protocol routing, and message dispatch.
6
+ */
7
+ import { type Tracer, type Span, type Context } from '@opentelemetry/api';
8
+ export interface TransportSpanOptions {
9
+ /** Transport type: "legacy-sse" | "streamable-http" | "stateless-http" */
10
+ type: string;
11
+ /** Session tracing ID (hashed) */
12
+ sessionIdHash?: string;
13
+ /** Whether a new session was created */
14
+ sessionCreated?: boolean;
15
+ /** Parent OTel context */
16
+ parentContext?: Context;
17
+ }
18
+ /**
19
+ * Start a transport span.
20
+ *
21
+ * Span name: "transport {type}"
22
+ */
23
+ export declare function startTransportSpan(tracer: Tracer, options: TransportSpanOptions): {
24
+ span: Span;
25
+ context: Context;
26
+ };
27
+ /**
28
+ * Set the request type on a transport span.
29
+ */
30
+ export declare function setTransportRequestType(span: Span, requestType: string): void;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * TraceContext Bridge — maps between FrontMCP's TraceContext
3
+ * and OpenTelemetry's SpanContext.
4
+ *
5
+ * FrontMCP already has W3C Trace Context support in the SDK.
6
+ * This bridge allows OTel spans to be created as children of
7
+ * the existing trace, preserving the trace ID across the boundary.
8
+ */
9
+ import { type SpanContext, type Context as OTelContext } from '@opentelemetry/api';
10
+ /**
11
+ * Minimal TraceContext interface — matches the SDK's TraceContext type
12
+ * without importing it directly.
13
+ */
14
+ export interface TraceContextLike {
15
+ traceId: string;
16
+ parentId: string;
17
+ traceFlags: number;
18
+ raw: string;
19
+ }
20
+ /**
21
+ * Convert a FrontMCP TraceContext to an OTel SpanContext.
22
+ *
23
+ * Maps:
24
+ * - traceId → traceId (32 hex chars)
25
+ * - parentId → spanId (16 hex chars)
26
+ * - traceFlags → traceFlags
27
+ *
28
+ * The resulting SpanContext is marked as remote (isRemote: true)
29
+ * since it originated from an incoming request.
30
+ */
31
+ export declare function frontmcpToOTelSpanContext(tc: TraceContextLike): SpanContext;
32
+ /**
33
+ * Convert an OTel SpanContext back to a FrontMCP TraceContext.
34
+ */
35
+ export declare function otelToFrontmcpContext(sc: SpanContext): TraceContextLike;
36
+ /**
37
+ * Create an OTel Context with the FrontMCP TraceContext as the
38
+ * active remote parent span. All child spans created within
39
+ * this context will share the same traceId.
40
+ */
41
+ export declare function createOTelContextFromTrace(tc: TraceContextLike): OTelContext;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/observability",
3
- "version": "0.0.1",
3
+ "version": "1.0.0",
4
4
  "description": "OpenTelemetry instrumentation, structured JSON logging, and request log objects for FrontMCP",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,3 @@
1
+ export { default as ObservabilityPlugin } from './observability.plugin';
2
+ export type { ObservabilityPluginOptions, ObservabilityPluginOptionsInput, ObservabilityLoggingOptions, } from './observability.plugin.types';
3
+ export { sessionTracingId, SPAN_KEY, SPAN_CTX_KEY, EXEC_SPAN_KEY, ACTIVE_SPAN_KEY, ACTIVE_OTEL_CTX_KEY, reportStartup, } from './observability.hooks';
@@ -0,0 +1,92 @@
1
+ /**
2
+ * ObservabilityHooks — comprehensive auto-instrumentation for FrontMCP.
3
+ *
4
+ * Provides full-depth visibility across the ENTIRE FrontMCP system:
5
+ * - HTTP request flow (every stage: traceRequest → auth → route → transport → finalize)
6
+ * - Tool/Resource/Prompt/Agent execution (every flow stage as span events)
7
+ * - Auth flows (verify, session, OAuth token/authorize/callback)
8
+ * - Skill flows (search, load, HTTP endpoints)
9
+ * - Elicitation flows (request, result)
10
+ * - External fetch calls
11
+ * - Session lifecycle
12
+ * - Plugin initialization
13
+ *
14
+ * Architecture:
15
+ * - Single trace ID per request (from FrontMcpContext.traceContext)
16
+ * - Session tracing ID = truncated SHA-256 hash (not the real session ID)
17
+ * - Root span per flow type (HTTP, RPC, execution)
18
+ * - Every flow stage recorded as a timed span event
19
+ * - Error status propagated to parent spans
20
+ */
21
+ import type { TracingOptions } from '../otel/otel.types';
22
+ import { type StartupTelemetryData } from '../otel/spans/startup.span';
23
+ /** Root span for the current flow (HTTP server span or RPC span) */
24
+ export declare const SPAN_KEY: unique symbol;
25
+ /** OTel context containing the root span (for child span parenting) */
26
+ export declare const SPAN_CTX_KEY: unique symbol;
27
+ /** Execution span (tool/resource/prompt/agent child span) */
28
+ export declare const EXEC_SPAN_KEY: unique symbol;
29
+ /** Active telemetry span — stored on FrontMcpContext.set() so TelemetryAccessor can read it */
30
+ export declare const ACTIVE_SPAN_KEY: unique symbol;
31
+ /** Active OTel context for child span parenting from TelemetryAccessor */
32
+ export declare const ACTIVE_OTEL_CTX_KEY: unique symbol;
33
+ /** Timestamp of the last recorded stage event */
34
+ export declare const STAGE_TS_KEY: unique symbol;
35
+ /**
36
+ * Generate a privacy-safe session tracing ID.
37
+ * 16-char truncated SHA-256 — sufficient for trace correlation,
38
+ * not reversible to the original session ID.
39
+ */
40
+ export declare function sessionTracingId(sessionId: string): string;
41
+ /** Minimal interface for flow context objects passed to hooks. */
42
+ export interface FlowContextLike {
43
+ get?(key: symbol): unknown;
44
+ state?: Record<symbol | string, any>;
45
+ }
46
+ export declare function onHttpWillTrace(options: TracingOptions, flowCtx: any): void;
47
+ export declare function onHttpWillAcquireQuota(flowCtx: any): void;
48
+ export declare function onHttpDidAcquireQuota(flowCtx: any): void;
49
+ export declare function onHttpWillCheckAuth(flowCtx: any): void;
50
+ export declare function onHttpDidCheckAuth(flowCtx: any): void;
51
+ export declare function onHttpWillRoute(flowCtx: any): void;
52
+ export declare function onHttpDidRoute(flowCtx: any): void;
53
+ export declare function onHttpDidFinalize(flowCtx: any): void;
54
+ export declare function onToolWillParse(options: TracingOptions, flowCtx: any): void;
55
+ export declare function onToolWillFindTool(flowCtx: any): void;
56
+ export declare function onToolWillCheckAuth(flowCtx: any): void;
57
+ export declare function onToolWillCreateContext(flowCtx: any): void;
58
+ export declare function onToolWillValidateInput(flowCtx: any): void;
59
+ export declare function onToolWillExecute(options: TracingOptions, flowCtx: any): void;
60
+ export declare function onToolDidExecute(options: TracingOptions, flowCtx: any): void;
61
+ export declare function onToolWillValidateOutput(flowCtx: any): void;
62
+ export declare function onToolWillApplyUI(flowCtx: any): void;
63
+ export declare function onToolDidFinalize(flowCtx: any): void;
64
+ export declare function onResourceWillParse(options: TracingOptions, flowCtx: any): void;
65
+ export declare function onResourceWillFind(flowCtx: any): void;
66
+ export declare function onResourceWillExecute(options: TracingOptions, flowCtx: any): void;
67
+ export declare function onResourceDidExecute(flowCtx: any): void;
68
+ export declare function onResourceDidFinalize(flowCtx: any): void;
69
+ export declare function onPromptWillParse(options: TracingOptions, flowCtx: any): void;
70
+ export declare function onPromptWillFind(flowCtx: any): void;
71
+ export declare function onPromptWillExecute(options: TracingOptions, flowCtx: any): void;
72
+ export declare function onPromptDidExecute(flowCtx: any): void;
73
+ export declare function onPromptDidFinalize(flowCtx: any): void;
74
+ export declare function onAgentWillParse(options: TracingOptions, flowCtx: any): void;
75
+ export declare function onAgentWillFind(flowCtx: any): void;
76
+ export declare function onAgentWillExecute(options: TracingOptions, flowCtx: any): void;
77
+ export declare function onAgentDidExecute(flowCtx: any): void;
78
+ export declare function onAgentDidFinalize(flowCtx: any): void;
79
+ export declare function onGenericFlowWillStart(flowName: string, options: TracingOptions, flowCtx: any): void;
80
+ export declare function onGenericFlowStage(stageName: string, flowCtx: any): void;
81
+ export declare function onGenericFlowDidFinalize(flowCtx: any): void;
82
+ export declare function onTransportWillStart(transportType: string, options: TracingOptions, flowCtx: any): void;
83
+ export declare function onTransportDidRoute(flowCtx: any): void;
84
+ export declare function onTransportStage(stageName: string, flowCtx: any): void;
85
+ export declare function onTransportDidFinalize(flowCtx: any): void;
86
+ export declare function onAuthWillStart(flowName: string, options: TracingOptions, flowCtx: any): void;
87
+ export declare function onAuthDidDetermineMode(flowCtx: any): void;
88
+ export declare function onAuthStage(stageName: string, flowCtx: any): void;
89
+ export declare function onAuthDidFinalize(flowCtx: any): void;
90
+ export declare function wrapContextFetch(options: TracingOptions, flowCtx: any): void;
91
+ export declare function onAgentDidExecuteEnrich(flowCtx: any): void;
92
+ export declare function reportStartup(data: StartupTelemetryData): void;