@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.
- package/esm/index.mjs +2986 -0
- package/esm/package.json +86 -0
- package/index.d.ts +11 -0
- package/logging/index.d.ts +9 -0
- package/logging/log-sink.interface.d.ts +81 -0
- package/logging/redaction.d.ts +17 -0
- package/logging/sink.factory.d.ts +15 -0
- package/logging/sinks/callback.sink.d.ts +12 -0
- package/logging/sinks/console.sink.d.ts +16 -0
- package/logging/sinks/index.d.ts +7 -0
- package/logging/sinks/otlp.sink.d.ts +67 -0
- package/logging/sinks/pino.sink.d.ts +13 -0
- package/logging/sinks/stdout.sink.d.ts +17 -0
- package/logging/sinks/winston.sink.d.ts +13 -0
- package/logging/structured-log-transport.d.ts +52 -0
- package/logging/structured-log.types.d.ts +71 -0
- package/otel/context-propagator.d.ts +17 -0
- package/otel/index.d.ts +8 -0
- package/otel/otel.setup.d.ts +32 -0
- package/otel/otel.tokens.d.ts +7 -0
- package/otel/otel.types.d.ts +151 -0
- package/otel/spans/auth.span.d.ts +27 -0
- package/otel/spans/fetch.span.d.ts +28 -0
- package/otel/spans/hook.span.d.ts +33 -0
- package/otel/spans/http-server.span.d.ts +29 -0
- package/otel/spans/index.d.ts +23 -0
- package/otel/spans/pretty-span-exporter.d.ts +19 -0
- package/otel/spans/prompt.span.d.ts +19 -0
- package/otel/spans/resource.span.d.ts +21 -0
- package/otel/spans/rpc.span.d.ts +33 -0
- package/otel/spans/span.utils.d.ts +38 -0
- package/otel/spans/startup.span.d.ts +28 -0
- package/otel/spans/tool.span.d.ts +25 -0
- package/otel/spans/transport.span.d.ts +30 -0
- package/otel/trace-context-bridge.d.ts +41 -0
- package/package.json +1 -1
- package/plugin/index.d.ts +3 -0
- package/plugin/observability.hooks.d.ts +92 -0
- package/plugin/observability.plugin.d.ts +141 -0
- package/plugin/observability.plugin.types.d.ts +38 -0
- package/request-log/index.d.ts +3 -0
- package/request-log/request-log.collector.d.ts +97 -0
- package/request-log/request-log.tokens.d.ts +7 -0
- package/request-log/request-log.types.d.ts +82 -0
- package/telemetry/index.d.ts +3 -0
- package/telemetry/telemetry.accessor.d.ts +151 -0
- package/telemetry/telemetry.context-extension.d.ts +35 -0
- package/telemetry/telemetry.tokens.d.ts +7 -0
- package/testing/index.d.ts +76 -0
package/esm/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@frontmcp/observability",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenTelemetry instrumentation, structured JSON logging, and request log objects for FrontMCP",
|
|
5
|
+
"author": "AgentFront <info@agentfront.dev>",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"opentelemetry",
|
|
9
|
+
"otel",
|
|
10
|
+
"observability",
|
|
11
|
+
"tracing",
|
|
12
|
+
"structured-logging",
|
|
13
|
+
"json-logging",
|
|
14
|
+
"request-log",
|
|
15
|
+
"mcp",
|
|
16
|
+
"frontmcp",
|
|
17
|
+
"typescript"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/agentfront/frontmcp.git",
|
|
22
|
+
"directory": "libs/observability"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/agentfront/frontmcp/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/agentfront/frontmcp/blob/main/libs/observability/README.md",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "../index.js",
|
|
30
|
+
"module": "./index.mjs",
|
|
31
|
+
"types": "../index.d.ts",
|
|
32
|
+
"sideEffects": false,
|
|
33
|
+
"exports": {
|
|
34
|
+
"./package.json": "../package.json",
|
|
35
|
+
".": {
|
|
36
|
+
"require": {
|
|
37
|
+
"types": "../index.d.ts",
|
|
38
|
+
"default": "../index.js"
|
|
39
|
+
},
|
|
40
|
+
"import": {
|
|
41
|
+
"types": "../index.d.ts",
|
|
42
|
+
"default": "./index.mjs"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"./esm": null
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=24.0.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@opentelemetry/api": "^1.9.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"@frontmcp/sdk": "^1.0.0-beta.13",
|
|
55
|
+
"@frontmcp/utils": "^1.0.0-beta.13",
|
|
56
|
+
"@opentelemetry/sdk-trace-base": "^1.25.0",
|
|
57
|
+
"@opentelemetry/sdk-node": "^0.52.0",
|
|
58
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.52.0",
|
|
59
|
+
"winston": "^3.0.0",
|
|
60
|
+
"pino": "^8.0.0 || ^9.0.0",
|
|
61
|
+
"zod": "^4.0.0"
|
|
62
|
+
},
|
|
63
|
+
"peerDependenciesMeta": {
|
|
64
|
+
"@opentelemetry/sdk-trace-base": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"@opentelemetry/sdk-node": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@opentelemetry/exporter-trace-otlp-http": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"winston": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"pino": {
|
|
77
|
+
"optional": true
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"devDependencies": {
|
|
81
|
+
"@types/node": "^24.0.0",
|
|
82
|
+
"typescript": "^5.0.0",
|
|
83
|
+
"zod": "^4.0.0",
|
|
84
|
+
"@opentelemetry/sdk-trace-base": "^1.25.0"
|
|
85
|
+
}
|
|
86
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { ObservabilityPlugin, sessionTracingId, reportStartup } from './plugin';
|
|
2
|
+
export type { ObservabilityPluginOptions, ObservabilityPluginOptionsInput, ObservabilityLoggingOptions, } from './plugin';
|
|
3
|
+
export { McpAttributes, FrontMcpAttributes, HttpAttributes, RpcAttributes, EnduserAttributes, OTEL_TRACER, OTEL_CONFIG, frontmcpToOTelSpanContext, otelToFrontmcpContext, createOTelContextFromTrace, FrontMcpPropagator, setupOTel, startSpan, endSpanOk, endSpanError, withSpan, startHttpServerSpan, setHttpResponseStatus, startRpcSpan, startToolSpan, startResourceSpan, startPromptSpan, recordHookEvent, startHookSpan, startFetchSpan, setFetchResponseStatus, startTransportSpan, setTransportRequestType, startAuthSpan, setAuthMode, setAuthResult, emitStartupReport, PrettySpanExporter, } from './otel';
|
|
4
|
+
export type { TracingOptions, OTelSetupOptions, TraceContextLike, StartSpanOptions, HttpServerSpanOptions, RpcSpanOptions, ToolSpanOptions, ResourceSpanOptions, PromptSpanOptions, HookSpanOptions, FetchSpanOptions, TransportSpanOptions, AuthSpanOptions, StartupTelemetryData, } from './otel';
|
|
5
|
+
export { StructuredLogTransport, LOG_LEVEL_TO_OTEL_SEVERITY, StdoutSink, ConsoleSink, WinstonSink, PinoSink, CallbackSink, OtlpSink, createSink, createSinks, redactFields, } from './logging';
|
|
6
|
+
export type { StructuredLogEntry, StructuredLogError, StructuredLogTransportOptions, LogSink, SinkConfig, StdoutSinkConfig, ConsoleSinkConfig, WinstonSinkConfig, PinoSinkConfig, CallbackSinkConfig, OtlpSinkConfig, OtlpSinkOptions, WinstonLike, PinoLike, ContextAccessor, ContextSnapshot, } from './logging';
|
|
7
|
+
export { TelemetryAccessor, TelemetrySpan, TELEMETRY_ACCESSOR } from './telemetry';
|
|
8
|
+
export { createTestTracer, getFinishedSpans, assertSpanExists, assertSpanAttribute, findSpan, findSpansByAttribute, } from './testing';
|
|
9
|
+
export type { TestTracer } from './testing';
|
|
10
|
+
export { RequestLogCollector, REQUEST_LOG_COLLECTOR } from './request-log';
|
|
11
|
+
export type { RequestLog, RequestLogEntry, RequestLogCollectorOptions } from './request-log';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { StructuredLogEntry, StructuredLogError, StructuredLogTransportOptions } from './structured-log.types';
|
|
2
|
+
export { LOG_LEVEL_TO_OTEL_SEVERITY } from './structured-log.types';
|
|
3
|
+
export type { LogSink, SinkConfig, StdoutSinkConfig, ConsoleSinkConfig, WinstonSinkConfig, PinoSinkConfig, CallbackSinkConfig, OtlpSinkConfig, WinstonLike, PinoLike, } from './log-sink.interface';
|
|
4
|
+
export { StructuredLogTransport } from './structured-log-transport';
|
|
5
|
+
export type { ContextAccessor, ContextSnapshot } from './structured-log-transport';
|
|
6
|
+
export { StdoutSink, ConsoleSink, WinstonSink, PinoSink, CallbackSink, OtlpSink } from './sinks';
|
|
7
|
+
export type { OtlpSinkOptions } from './sinks';
|
|
8
|
+
export { createSink, createSinks } from './sink.factory';
|
|
9
|
+
export { redactFields } from './redaction';
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { StructuredLogEntry } from './structured-log.types';
|
|
2
|
+
/**
|
|
3
|
+
* LogSink — pluggable output adapter for structured log entries.
|
|
4
|
+
*
|
|
5
|
+
* Implementations determine where and how log objects are written:
|
|
6
|
+
* - StdoutSink: NDJSON to process.stdout (12-factor)
|
|
7
|
+
* - ConsoleSink: console.log/warn/error (browser-safe)
|
|
8
|
+
* - WinstonSink: forward to winston logger instance
|
|
9
|
+
* - PinoSink: forward to pino logger instance
|
|
10
|
+
* - CallbackSink: user-provided callback function
|
|
11
|
+
*/
|
|
12
|
+
export interface LogSink {
|
|
13
|
+
/** Write a structured log entry to the output */
|
|
14
|
+
write(entry: StructuredLogEntry): void;
|
|
15
|
+
/** Optional: flush buffered entries */
|
|
16
|
+
flush?(): Promise<void>;
|
|
17
|
+
/** Optional: cleanup resources */
|
|
18
|
+
close?(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sink configuration — discriminated union for built-in sink types.
|
|
22
|
+
*/
|
|
23
|
+
export type SinkConfig = StdoutSinkConfig | ConsoleSinkConfig | WinstonSinkConfig | PinoSinkConfig | CallbackSinkConfig | OtlpSinkConfig;
|
|
24
|
+
export interface StdoutSinkConfig {
|
|
25
|
+
type: 'stdout';
|
|
26
|
+
/** Writable stream override (default: process.stdout) */
|
|
27
|
+
stream?: NodeJS.WritableStream;
|
|
28
|
+
/** Pretty-print JSON (default: false) */
|
|
29
|
+
pretty?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface ConsoleSinkConfig {
|
|
32
|
+
type: 'console';
|
|
33
|
+
}
|
|
34
|
+
export interface WinstonSinkConfig {
|
|
35
|
+
type: 'winston';
|
|
36
|
+
/** Winston logger instance */
|
|
37
|
+
logger: WinstonLike;
|
|
38
|
+
}
|
|
39
|
+
export interface PinoSinkConfig {
|
|
40
|
+
type: 'pino';
|
|
41
|
+
/** Pino logger instance */
|
|
42
|
+
logger: PinoLike;
|
|
43
|
+
}
|
|
44
|
+
export interface CallbackSinkConfig {
|
|
45
|
+
type: 'callback';
|
|
46
|
+
/** User-provided callback */
|
|
47
|
+
fn: (entry: StructuredLogEntry) => void;
|
|
48
|
+
}
|
|
49
|
+
export interface OtlpSinkConfig {
|
|
50
|
+
type: 'otlp';
|
|
51
|
+
/** OTLP endpoint (e.g., 'http://localhost:4318'). Path '/v1/logs' is appended. */
|
|
52
|
+
endpoint?: string;
|
|
53
|
+
/** Custom headers (for auth tokens, API keys) */
|
|
54
|
+
headers?: Record<string, string>;
|
|
55
|
+
/** Max batch size before auto-flush (default: 100) */
|
|
56
|
+
batchSize?: number;
|
|
57
|
+
/** Flush interval in ms (default: 5000) */
|
|
58
|
+
flushIntervalMs?: number;
|
|
59
|
+
/** Service name for resource identification */
|
|
60
|
+
serviceName?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Minimal winston-compatible logger interface.
|
|
64
|
+
* Avoids hard dependency on winston types.
|
|
65
|
+
*/
|
|
66
|
+
export interface WinstonLike {
|
|
67
|
+
debug(message: string, meta?: Record<string, unknown>): void;
|
|
68
|
+
info(message: string, meta?: Record<string, unknown>): void;
|
|
69
|
+
warn(message: string, meta?: Record<string, unknown>): void;
|
|
70
|
+
error(message: string, meta?: Record<string, unknown>): void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Minimal pino-compatible logger interface.
|
|
74
|
+
* Avoids hard dependency on pino types.
|
|
75
|
+
*/
|
|
76
|
+
export interface PinoLike {
|
|
77
|
+
debug(obj: Record<string, unknown>, msg?: string): void;
|
|
78
|
+
info(obj: Record<string, unknown>, msg?: string): void;
|
|
79
|
+
warn(obj: Record<string, unknown>, msg?: string): void;
|
|
80
|
+
error(obj: Record<string, unknown>, msg?: string): void;
|
|
81
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field redaction utilities for structured log entries.
|
|
3
|
+
*
|
|
4
|
+
* Traverses objects and replaces values of sensitive fields with '[REDACTED]'.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Redact sensitive fields from an object.
|
|
8
|
+
*
|
|
9
|
+
* Performs a shallow clone with redacted values — does not mutate the input.
|
|
10
|
+
* Field matching is case-insensitive.
|
|
11
|
+
*
|
|
12
|
+
* @param obj - Object to redact fields from
|
|
13
|
+
* @param fields - Field names to redact (case-insensitive)
|
|
14
|
+
* @param maxDepth - Maximum recursion depth (default: 5)
|
|
15
|
+
* @returns New object with sensitive fields replaced by '[REDACTED]'
|
|
16
|
+
*/
|
|
17
|
+
export declare function redactFields(obj: Record<string, unknown>, fields: string[], maxDepth?: number): Record<string, unknown>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LogSink, SinkConfig } from './log-sink.interface';
|
|
2
|
+
/**
|
|
3
|
+
* Create a LogSink from a SinkConfig.
|
|
4
|
+
*
|
|
5
|
+
* Winston and Pino sinks are instantiated inline to avoid
|
|
6
|
+
* bundling their types when not used.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createSink(config: SinkConfig): LogSink;
|
|
9
|
+
/**
|
|
10
|
+
* Create an array of LogSink instances from an array of SinkConfig.
|
|
11
|
+
*
|
|
12
|
+
* If no configs are provided, defaults to StdoutSink in Node.js
|
|
13
|
+
* or ConsoleSink in browser environments.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createSinks(configs?: SinkConfig[]): LogSink[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LogSink } from '../log-sink.interface';
|
|
2
|
+
import type { StructuredLogEntry } from '../structured-log.types';
|
|
3
|
+
/**
|
|
4
|
+
* CallbackSink — forwards structured log entries to a user-provided function.
|
|
5
|
+
*
|
|
6
|
+
* Useful for custom integrations, testing, or forwarding to queues/streams.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CallbackSink implements LogSink {
|
|
9
|
+
private readonly fn;
|
|
10
|
+
constructor(fn: (entry: StructuredLogEntry) => void);
|
|
11
|
+
write(entry: StructuredLogEntry): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LogSink } from '../log-sink.interface';
|
|
2
|
+
import type { StructuredLogEntry } from '../structured-log.types';
|
|
3
|
+
/**
|
|
4
|
+
* ConsoleSink — writes structured log entries to the console.
|
|
5
|
+
*
|
|
6
|
+
* Simple one-liner format with trace context. Use this sink when you want
|
|
7
|
+
* telemetry data in the console (e.g., browser, or when the SDK console
|
|
8
|
+
* logger is disabled).
|
|
9
|
+
*
|
|
10
|
+
* For typical development, you don't need this sink — the SDK's built-in
|
|
11
|
+
* console logger handles dev output. The telemetry pipeline runs separately
|
|
12
|
+
* via StructuredLogTransport and its configured sinks (stdout, otlp, callback).
|
|
13
|
+
*/
|
|
14
|
+
export declare class ConsoleSink implements LogSink {
|
|
15
|
+
write(entry: StructuredLogEntry): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { StdoutSink } from './stdout.sink';
|
|
2
|
+
export { ConsoleSink } from './console.sink';
|
|
3
|
+
export { WinstonSink } from './winston.sink';
|
|
4
|
+
export { PinoSink } from './pino.sink';
|
|
5
|
+
export { CallbackSink } from './callback.sink';
|
|
6
|
+
export { OtlpSink } from './otlp.sink';
|
|
7
|
+
export type { OtlpSinkOptions } from './otlp.sink';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OtlpSink — exports structured log entries via OTLP HTTP to any
|
|
3
|
+
* OTel-compatible backend (Coralogix, Datadog, Logz.io, Grafana, etc.).
|
|
4
|
+
*
|
|
5
|
+
* Posts to `{endpoint}/v1/logs` using the OTel Logs data model.
|
|
6
|
+
* Batches entries and flushes periodically or on demand.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Coralogix
|
|
11
|
+
* { type: 'otlp', endpoint: 'https://ingress.coralogix.com:443',
|
|
12
|
+
* headers: { Authorization: 'Bearer CX_API_KEY' } }
|
|
13
|
+
*
|
|
14
|
+
* // Datadog
|
|
15
|
+
* { type: 'otlp', endpoint: 'https://http-intake.logs.datadoghq.com',
|
|
16
|
+
* headers: { 'DD-API-KEY': 'YOUR_KEY' } }
|
|
17
|
+
*
|
|
18
|
+
* // Logz.io
|
|
19
|
+
* { type: 'otlp', endpoint: 'https://otlp-listener.logz.io:8071',
|
|
20
|
+
* headers: { Authorization: 'Bearer SHIPPING_TOKEN' } }
|
|
21
|
+
*
|
|
22
|
+
* // Local OTLP collector
|
|
23
|
+
* { type: 'otlp', endpoint: 'http://localhost:4318' }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import type { LogSink } from '../log-sink.interface';
|
|
27
|
+
import type { StructuredLogEntry } from '../structured-log.types';
|
|
28
|
+
export interface OtlpSinkOptions {
|
|
29
|
+
/** OTLP endpoint (e.g., 'http://localhost:4318'). Path '/v1/logs' is appended. */
|
|
30
|
+
endpoint: string;
|
|
31
|
+
/** Custom headers (for auth tokens, API keys) */
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
/** Max batch size before auto-flush (default: 100) */
|
|
34
|
+
batchSize?: number;
|
|
35
|
+
/** Max queue capacity — oldest entries are dropped when exceeded (default: 5000) */
|
|
36
|
+
maxQueueSize?: number;
|
|
37
|
+
/** Flush interval in ms (default: 5000) */
|
|
38
|
+
flushIntervalMs?: number;
|
|
39
|
+
/** Service name for resource identification */
|
|
40
|
+
serviceName?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* OtlpSink — batches structured log entries and exports via OTLP HTTP.
|
|
44
|
+
*/
|
|
45
|
+
export declare class OtlpSink implements LogSink {
|
|
46
|
+
private batch;
|
|
47
|
+
private readonly endpoint;
|
|
48
|
+
private readonly headers;
|
|
49
|
+
private readonly batchSize;
|
|
50
|
+
private readonly maxQueueSize;
|
|
51
|
+
private readonly serviceName;
|
|
52
|
+
private flushTimer?;
|
|
53
|
+
constructor(options: OtlpSinkOptions);
|
|
54
|
+
write(entry: StructuredLogEntry): void;
|
|
55
|
+
flush(): Promise<void>;
|
|
56
|
+
private requeue;
|
|
57
|
+
private enforceCapacity;
|
|
58
|
+
close(): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Build OTLP Logs JSON payload per the OTel spec.
|
|
61
|
+
*
|
|
62
|
+
* @see https://opentelemetry.io/docs/specs/otlp/#otlphttp-request
|
|
63
|
+
* @see https://opentelemetry.io/docs/specs/otel/logs/data-model/
|
|
64
|
+
*/
|
|
65
|
+
private buildOtlpPayload;
|
|
66
|
+
private entryToLogRecord;
|
|
67
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LogSink, PinoLike } from '../log-sink.interface';
|
|
2
|
+
import type { StructuredLogEntry } from '../structured-log.types';
|
|
3
|
+
/**
|
|
4
|
+
* PinoSink — forwards structured log entries to a pino logger.
|
|
5
|
+
*
|
|
6
|
+
* Pino uses the signature `logger.info(obj, msg)` where the object
|
|
7
|
+
* comes first, so we pass the entry fields as the merge object.
|
|
8
|
+
*/
|
|
9
|
+
export declare class PinoSink implements LogSink {
|
|
10
|
+
private readonly logger;
|
|
11
|
+
constructor(logger: PinoLike);
|
|
12
|
+
write(entry: StructuredLogEntry): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LogSink } from '../log-sink.interface';
|
|
2
|
+
import type { StructuredLogEntry } from '../structured-log.types';
|
|
3
|
+
/**
|
|
4
|
+
* StdoutSink — writes NDJSON (newline-delimited JSON) to process.stdout.
|
|
5
|
+
*
|
|
6
|
+
* 12-factor compliant: logs are written as a stream of events to stdout,
|
|
7
|
+
* ready for collection by Docker, K8s, CloudWatch, or any log aggregator.
|
|
8
|
+
*/
|
|
9
|
+
export declare class StdoutSink implements LogSink {
|
|
10
|
+
private readonly stream;
|
|
11
|
+
private readonly pretty;
|
|
12
|
+
constructor(options?: {
|
|
13
|
+
stream?: NodeJS.WritableStream;
|
|
14
|
+
pretty?: boolean;
|
|
15
|
+
});
|
|
16
|
+
write(entry: StructuredLogEntry): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LogSink, WinstonLike } from '../log-sink.interface';
|
|
2
|
+
import type { StructuredLogEntry } from '../structured-log.types';
|
|
3
|
+
/**
|
|
4
|
+
* WinstonSink — forwards structured log entries to a winston logger.
|
|
5
|
+
*
|
|
6
|
+
* Maps FrontMCP log levels to winston levels and passes the full
|
|
7
|
+
* entry object as metadata so winston formatters can access all fields.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WinstonSink implements LogSink {
|
|
10
|
+
private readonly logger;
|
|
11
|
+
constructor(logger: WinstonLike);
|
|
12
|
+
write(entry: StructuredLogEntry): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { LogTransportInterface, LogRecord } from '@frontmcp/sdk';
|
|
2
|
+
import type { LogSink } from './log-sink.interface';
|
|
3
|
+
import type { StructuredLogEntry, StructuredLogTransportOptions } from './structured-log.types';
|
|
4
|
+
/**
|
|
5
|
+
* Context accessor function type.
|
|
6
|
+
*
|
|
7
|
+
* The transport calls this to get the current FrontMcpContext
|
|
8
|
+
* from AsyncLocalStorage. Returns undefined when outside a request.
|
|
9
|
+
*/
|
|
10
|
+
export interface ContextAccessor {
|
|
11
|
+
(): ContextSnapshot | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Minimal context snapshot — avoids importing the full FrontMcpContext type.
|
|
15
|
+
* Extracted by the plugin from FrontMcpContextStorage.getStore().
|
|
16
|
+
*/
|
|
17
|
+
export interface ContextSnapshot {
|
|
18
|
+
requestId: string;
|
|
19
|
+
traceContext: {
|
|
20
|
+
traceId: string;
|
|
21
|
+
parentId: string;
|
|
22
|
+
traceFlags: number;
|
|
23
|
+
};
|
|
24
|
+
sessionIdHash: string;
|
|
25
|
+
scopeId: string;
|
|
26
|
+
flowName?: string;
|
|
27
|
+
elapsed: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* StructuredLogTransport — bridges SDK logger → structured log objects → sinks.
|
|
31
|
+
*
|
|
32
|
+
* This is a LogTransportInterface implementation that:
|
|
33
|
+
* 1. Receives LogRecord from the SDK logger
|
|
34
|
+
* 2. Reads FrontMcpContext (if available) for trace correlation
|
|
35
|
+
* 3. Builds a StructuredLogEntry object
|
|
36
|
+
* 4. Applies field redaction
|
|
37
|
+
* 5. Forwards to all registered LogSink instances
|
|
38
|
+
*/
|
|
39
|
+
export declare class StructuredLogTransport extends LogTransportInterface {
|
|
40
|
+
private readonly sinks;
|
|
41
|
+
private readonly redactFieldNames;
|
|
42
|
+
private readonly includeStacks;
|
|
43
|
+
private readonly staticFields;
|
|
44
|
+
private readonly getContext;
|
|
45
|
+
/** Optional listener for request log collection */
|
|
46
|
+
onEntry?: (entry: StructuredLogEntry) => void;
|
|
47
|
+
constructor(sinks: LogSink[], options?: StructuredLogTransportOptions, contextAccessor?: ContextAccessor);
|
|
48
|
+
log(rec: LogRecord): void;
|
|
49
|
+
private buildEntry;
|
|
50
|
+
private processArgs;
|
|
51
|
+
private buildError;
|
|
52
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured log entry — the core log object.
|
|
3
|
+
*
|
|
4
|
+
* Every log entry produced by StructuredLogTransport is a plain
|
|
5
|
+
* StructuredLogEntry object. Output adapters (sinks) serialize
|
|
6
|
+
* it for their target (NDJSON → stdout, winston → winston transport, etc.).
|
|
7
|
+
*/
|
|
8
|
+
export interface StructuredLogEntry {
|
|
9
|
+
/** ISO 8601 timestamp (e.g., "2026-03-31T14:22:05.123Z") */
|
|
10
|
+
timestamp: string;
|
|
11
|
+
/** Log level name */
|
|
12
|
+
level: 'debug' | 'verbose' | 'info' | 'warn' | 'error';
|
|
13
|
+
/** OTel severity number (1–24) for log correlation */
|
|
14
|
+
severity_number: number;
|
|
15
|
+
/** Log message */
|
|
16
|
+
message: string;
|
|
17
|
+
/** W3C trace ID (32 hex chars) — from FrontMcpContext */
|
|
18
|
+
trace_id?: string;
|
|
19
|
+
/** OTel span ID (16 hex chars) — from FrontMcpContext.traceContext.parentId */
|
|
20
|
+
span_id?: string;
|
|
21
|
+
/** W3C trace flags */
|
|
22
|
+
trace_flags?: number;
|
|
23
|
+
/** Unique request identifier — from FrontMcpContext */
|
|
24
|
+
request_id?: string;
|
|
25
|
+
/** SHA-256 truncated session ID (12 chars) — from FrontMcpContext */
|
|
26
|
+
session_id_hash?: string;
|
|
27
|
+
/** Scope identifier — from FrontMcpContext */
|
|
28
|
+
scope_id?: string;
|
|
29
|
+
/** Current flow name — from FrontMcpContext */
|
|
30
|
+
flow_name?: string;
|
|
31
|
+
/** Logger child prefix chain */
|
|
32
|
+
prefix?: string;
|
|
33
|
+
/** Error details (populated when level = error and args contain an Error) */
|
|
34
|
+
error?: StructuredLogError;
|
|
35
|
+
/** Elapsed time since request start in milliseconds */
|
|
36
|
+
elapsed_ms?: number;
|
|
37
|
+
/** Structured attributes extracted from log args */
|
|
38
|
+
attributes?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Structured error information.
|
|
42
|
+
*/
|
|
43
|
+
export interface StructuredLogError {
|
|
44
|
+
/** Error class name */
|
|
45
|
+
type: string;
|
|
46
|
+
/** Error message */
|
|
47
|
+
message: string;
|
|
48
|
+
/** MCP error code (if applicable) */
|
|
49
|
+
code?: string;
|
|
50
|
+
/** Unique error tracking ID (from McpError.errorId) */
|
|
51
|
+
error_id?: string;
|
|
52
|
+
/** Stack trace (only included when includeStacks is true) */
|
|
53
|
+
stack?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Options for StructuredLogTransport.
|
|
57
|
+
*/
|
|
58
|
+
export interface StructuredLogTransportOptions {
|
|
59
|
+
/** Field names to redact from attributes */
|
|
60
|
+
redactFields?: string[];
|
|
61
|
+
/** Whether to include stack traces in error entries (default: true) */
|
|
62
|
+
includeStacks?: boolean;
|
|
63
|
+
/** Static fields to include in every log entry */
|
|
64
|
+
staticFields?: Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* OTel severity numbers mapped from FrontMCP LogLevel.
|
|
68
|
+
*
|
|
69
|
+
* @see https://opentelemetry.io/docs/specs/otel/logs/data-model/#severity-fields
|
|
70
|
+
*/
|
|
71
|
+
export declare const LOG_LEVEL_TO_OTEL_SEVERITY: Record<string, number>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTel Context Propagator — integrates FrontMCP's W3C trace context
|
|
3
|
+
* parsing with OpenTelemetry's context propagation.
|
|
4
|
+
*
|
|
5
|
+
* This propagator uses the existing FrontMCP trace context parser
|
|
6
|
+
* to extract and inject W3C traceparent headers.
|
|
7
|
+
*/
|
|
8
|
+
import { type Context, type TextMapGetter, type TextMapSetter, type TextMapPropagator } from '@opentelemetry/api';
|
|
9
|
+
/**
|
|
10
|
+
* FrontMcpPropagator — OTel TextMapPropagator that reads/writes
|
|
11
|
+
* the W3C traceparent header using the same format as the SDK.
|
|
12
|
+
*/
|
|
13
|
+
export declare class FrontMcpPropagator implements TextMapPropagator {
|
|
14
|
+
inject(context: Context, carrier: unknown, setter: TextMapSetter): void;
|
|
15
|
+
extract(context: Context, carrier: unknown, getter: TextMapGetter): Context;
|
|
16
|
+
fields(): string[];
|
|
17
|
+
}
|
package/otel/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { McpAttributes, FrontMcpAttributes, HttpAttributes, RpcAttributes, EnduserAttributes } from './otel.types';
|
|
2
|
+
export type { TracingOptions, OTelSetupOptions } from './otel.types';
|
|
3
|
+
export { OTEL_TRACER, OTEL_CONFIG } from './otel.tokens';
|
|
4
|
+
export { frontmcpToOTelSpanContext, otelToFrontmcpContext, createOTelContextFromTrace } from './trace-context-bridge';
|
|
5
|
+
export type { TraceContextLike } from './trace-context-bridge';
|
|
6
|
+
export { FrontMcpPropagator } from './context-propagator';
|
|
7
|
+
export { setupOTel } from './otel.setup';
|
|
8
|
+
export * from './spans';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setupOTel() — convenience function for configuring the OpenTelemetry SDK.
|
|
3
|
+
*
|
|
4
|
+
* This is a thin wrapper around @opentelemetry/sdk-node's NodeSDK.
|
|
5
|
+
* Users can also configure OTel themselves — the ObservabilityPlugin
|
|
6
|
+
* only needs @opentelemetry/api to read the global tracer.
|
|
7
|
+
*
|
|
8
|
+
* All SDK packages are peer dependencies and lazy-loaded.
|
|
9
|
+
*/
|
|
10
|
+
import type { OTelSetupOptions } from './otel.types';
|
|
11
|
+
/**
|
|
12
|
+
* Initialize the OpenTelemetry SDK with common defaults.
|
|
13
|
+
*
|
|
14
|
+
* This function lazy-loads @opentelemetry/sdk-node and exporter packages
|
|
15
|
+
* to avoid bundling them unless explicitly called.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Setup options (serviceName, exporter, endpoint)
|
|
18
|
+
* @returns Shutdown function to gracefully stop the SDK
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const shutdown = setupOTel({
|
|
23
|
+
* serviceName: 'my-mcp-server',
|
|
24
|
+
* exporter: 'otlp',
|
|
25
|
+
* endpoint: 'http://localhost:4318',
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // On process exit:
|
|
29
|
+
* await shutdown();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function setupOTel(options?: OTelSetupOptions): () => Promise<void>;
|