loggily 0.7.0 → 0.8.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/README.md +145 -54
- package/dist/context.mjs +1 -1
- package/dist/{core-Du3sIje6.mjs → core-B3pox577.mjs} +521 -347
- package/dist/core-B3pox577.mjs.map +1 -0
- package/dist/core-Dm2PQUoS.d.mts +191 -0
- package/dist/core-Dm2PQUoS.d.mts.map +1 -0
- package/dist/{index-Co4jC3mx.d.mts → file-writer-DtaY8Njt.d.mts} +60 -49
- package/dist/file-writer-DtaY8Njt.d.mts.map +1 -0
- package/dist/index.browser.d.mts +10 -0
- package/dist/index.browser.d.mts.map +1 -0
- package/dist/index.browser.mjs +10 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +7 -2
- package/dist/index.mjs.map +1 -0
- package/dist/metrics.d.mts +2 -48
- package/dist/metrics.mjs +13 -43
- package/dist/metrics.mjs.map +1 -1
- package/dist/otel.d.mts +63 -0
- package/dist/otel.d.mts.map +1 -0
- package/dist/otel.mjs +82 -0
- package/dist/otel.mjs.map +1 -0
- package/dist/pipeline-Cl9-wCmt.d.mts +73 -0
- package/dist/pipeline-Cl9-wCmt.d.mts.map +1 -0
- package/dist/worker.d.mts +64 -94
- package/dist/worker.d.mts.map +1 -1
- package/dist/worker.mjs +107 -281
- package/dist/worker.mjs.map +1 -1
- package/package.json +22 -3
- package/dist/core-DAFH-huv.d.mts +0 -199
- package/dist/core-DAFH-huv.d.mts.map +0 -1
- package/dist/core-Du3sIje6.mjs.map +0 -1
- package/dist/index-Co4jC3mx.d.mts.map +0 -1
- package/dist/metrics.d.mts.map +0 -1
package/dist/metrics.d.mts
CHANGED
|
@@ -1,48 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
//#region src/metrics.d.ts
|
|
4
|
-
interface SpanStats {
|
|
5
|
-
count: number;
|
|
6
|
-
min: number;
|
|
7
|
-
max: number;
|
|
8
|
-
mean: number;
|
|
9
|
-
p50: number;
|
|
10
|
-
p95: number;
|
|
11
|
-
p99: number;
|
|
12
|
-
total: number;
|
|
13
|
-
}
|
|
14
|
-
interface MetricsCollector extends SpanRecorder {
|
|
15
|
-
/** Get stats for a specific span namespace */
|
|
16
|
-
stats(name: string): SpanStats | undefined;
|
|
17
|
-
/** Get stats for all recorded namespaces */
|
|
18
|
-
all(): Map<string, SpanStats>;
|
|
19
|
-
/** Format a human-readable summary */
|
|
20
|
-
summary(): string;
|
|
21
|
-
/** Reset all collected data */
|
|
22
|
-
reset(): void;
|
|
23
|
-
}
|
|
24
|
-
declare function createMetricsCollector(maxEntries?: number): MetricsCollector;
|
|
25
|
-
/** Get aggregated span stats (from ambient collector). */
|
|
26
|
-
declare function spanStats(): Map<string, SpanStats>;
|
|
27
|
-
/** Get the ambient collector's formatted summary. */
|
|
28
|
-
declare function spanSummary(): string;
|
|
29
|
-
/** Reset the ambient collector. */
|
|
30
|
-
declare function resetSpanStats(): void;
|
|
31
|
-
/**
|
|
32
|
-
* Compose a logger with a metrics collector.
|
|
33
|
-
* Returns a curried wrapper: `withMetrics(collector?)(logger)`
|
|
34
|
-
*
|
|
35
|
-
* - No arg: uses the built-in ambient collector
|
|
36
|
-
* - Custom collector: records to your collector
|
|
37
|
-
* - Stackable: `withMetrics(a)(withMetrics(b)(logger))` fans out to both
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```typescript
|
|
41
|
-
* const log = withMetrics()(createLogger("myapp"))
|
|
42
|
-
* const log = withMetrics(myCollector)(createLogger("myapp"))
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
declare function withMetrics(collector?: SpanRecorder): (logger: ConditionalLogger) => ConditionalLogger;
|
|
46
|
-
//#endregion
|
|
47
|
-
export { MetricsCollector, type SpanRecord, type SpanRecorder, SpanStats, createMetricsCollector, resetSpanStats, spanStats, spanSummary, withMetrics };
|
|
48
|
-
//# sourceMappingURL=metrics.d.mts.map
|
|
1
|
+
import { G as SpanStats, K as createMetricsCollector, W as MetricsCollector, d as SpanRecord, f as SpanRecorder, q as withMetrics } from "./core-Dm2PQUoS.mjs";
|
|
2
|
+
export { MetricsCollector, SpanRecord, SpanRecorder, SpanStats, createMetricsCollector, withMetrics };
|
package/dist/metrics.mjs
CHANGED
|
@@ -1,23 +1,4 @@
|
|
|
1
|
-
import { r as _setAmbientRecorder } from "./core-Du3sIje6.mjs";
|
|
2
1
|
//#region src/metrics.ts
|
|
3
|
-
/**
|
|
4
|
-
* Metrics collection for loggily spans.
|
|
5
|
-
*
|
|
6
|
-
* Two modes:
|
|
7
|
-
* - **Ambient**: import this module → spans auto-record when TRACE is active
|
|
8
|
-
* - **Explicit**: `withMetrics(collector?)(logger)` for custom collection
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { spanStats } from "loggily/metrics"
|
|
13
|
-
* // TRACE=myapp bun run app
|
|
14
|
-
* // → on exit: spanStats() returns aggregated p50/p95/p99
|
|
15
|
-
*
|
|
16
|
-
* // Custom collector:
|
|
17
|
-
* import { withMetrics, createMetricsCollector } from "loggily/metrics"
|
|
18
|
-
* const log = withMetrics()(createLogger("myapp"))
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
2
|
function percentile(sorted, p) {
|
|
22
3
|
if (sorted.length === 0) return 0;
|
|
23
4
|
return sorted[Math.min(Math.floor(sorted.length * p), sorted.length - 1)];
|
|
@@ -68,38 +49,23 @@ function createMetricsCollector(maxEntries = 1e3) {
|
|
|
68
49
|
}
|
|
69
50
|
};
|
|
70
51
|
}
|
|
71
|
-
const _ambient = createMetricsCollector();
|
|
72
|
-
_setAmbientRecorder(_ambient);
|
|
73
|
-
/** Get aggregated span stats (from ambient collector). */
|
|
74
|
-
function spanStats() {
|
|
75
|
-
return _ambient.all();
|
|
76
|
-
}
|
|
77
|
-
/** Get the ambient collector's formatted summary. */
|
|
78
|
-
function spanSummary() {
|
|
79
|
-
return _ambient.summary();
|
|
80
|
-
}
|
|
81
|
-
/** Reset the ambient collector. */
|
|
82
|
-
function resetSpanStats() {
|
|
83
|
-
_ambient.reset();
|
|
84
|
-
}
|
|
85
52
|
/**
|
|
86
53
|
* Compose a logger with a metrics collector.
|
|
87
|
-
* Returns a curried wrapper: `withMetrics(collector
|
|
54
|
+
* Returns a curried wrapper: `withMetrics(collector)(logger)`
|
|
88
55
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* - Stackable: `withMetrics(a)(withMetrics(b)(logger))` fans out to both
|
|
56
|
+
* Records span duration to the provided collector on span disposal.
|
|
57
|
+
* Stackable: `withMetrics(a)(withMetrics(b)(logger))` fans out to both.
|
|
92
58
|
*
|
|
93
59
|
* @example
|
|
94
60
|
* ```typescript
|
|
95
|
-
* const
|
|
96
|
-
* const log = withMetrics(
|
|
61
|
+
* const collector = createMetricsCollector()
|
|
62
|
+
* const log = withMetrics(collector)(createLogger("myapp"))
|
|
97
63
|
* ```
|
|
98
64
|
*/
|
|
99
65
|
function withMetrics(collector) {
|
|
100
|
-
const recorder = collector ?? _ambient;
|
|
101
66
|
return (logger) => {
|
|
102
67
|
return new Proxy(logger, { get(target, prop) {
|
|
68
|
+
if (prop === "metrics") return collector;
|
|
103
69
|
if (prop === "span") {
|
|
104
70
|
const originalSpan = target.span;
|
|
105
71
|
if (!originalSpan) return void 0;
|
|
@@ -108,7 +74,7 @@ function withMetrics(collector) {
|
|
|
108
74
|
const originalDispose = span[Symbol.dispose];
|
|
109
75
|
span[Symbol.dispose] = () => {
|
|
110
76
|
originalDispose.call(span);
|
|
111
|
-
if (span.spanData?.duration != null)
|
|
77
|
+
if (span.spanData?.duration != null) collector.recordSpan({
|
|
112
78
|
name: span.name,
|
|
113
79
|
durationMs: span.spanData.duration
|
|
114
80
|
});
|
|
@@ -116,15 +82,19 @@ function withMetrics(collector) {
|
|
|
116
82
|
return span;
|
|
117
83
|
};
|
|
118
84
|
}
|
|
85
|
+
if (prop === "child") return (namespaceOrContext, childProps) => {
|
|
86
|
+
const child = target.child(namespaceOrContext, childProps);
|
|
87
|
+
return withMetrics(collector)(child);
|
|
88
|
+
};
|
|
119
89
|
if (prop === "logger") return (namespace, childProps) => {
|
|
120
90
|
const child = target.logger(namespace, childProps);
|
|
121
|
-
return withMetrics(
|
|
91
|
+
return withMetrics(collector)(child);
|
|
122
92
|
};
|
|
123
93
|
return target[prop];
|
|
124
94
|
} });
|
|
125
95
|
};
|
|
126
96
|
}
|
|
127
97
|
//#endregion
|
|
128
|
-
export { createMetricsCollector,
|
|
98
|
+
export { createMetricsCollector, withMetrics };
|
|
129
99
|
|
|
130
100
|
//# sourceMappingURL=metrics.mjs.map
|
package/dist/metrics.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.mjs","names":[],"sources":["../src/metrics.ts"],"sourcesContent":["/**\n * Metrics collection for loggily spans.\n *\n *
|
|
1
|
+
{"version":3,"file":"metrics.mjs","names":[],"sources":["../src/metrics.ts"],"sourcesContent":["/**\n * Metrics collection for loggily spans.\n *\n * Explicit only: `withMetrics(collector)(logger)` for custom collection.\n *\n * @example\n * ```typescript\n * import { withMetrics, createMetricsCollector } from \"loggily/metrics\"\n * const collector = createMetricsCollector()\n * const log = withMetrics(collector)(createLogger(\"myapp\"))\n * ```\n */\n\nimport {\n type SpanRecorder,\n type SpanRecord,\n type ConditionalLogger,\n type Logger,\n type LazyProps,\n type SpanLogger,\n} from \"./core.js\"\n\nexport type { SpanRecorder, SpanRecord }\n\n// ============ Stats ============\n\nexport interface SpanStats {\n count: number\n min: number\n max: number\n mean: number\n p50: number\n p95: number\n p99: number\n total: number\n}\n\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0\n const idx = Math.min(Math.floor(sorted.length * p), sorted.length - 1)\n return sorted[idx]!\n}\n\nfunction computeStats(durations: number[]): SpanStats {\n const sorted = [...durations].sort((a, b) => a - b)\n const total = sorted.reduce((sum, d) => sum + d, 0)\n return {\n count: sorted.length,\n min: sorted[0] ?? 0,\n max: sorted[sorted.length - 1] ?? 0,\n mean: sorted.length > 0 ? total / sorted.length : 0,\n p50: percentile(sorted, 0.5),\n p95: percentile(sorted, 0.95),\n p99: percentile(sorted, 0.99),\n total,\n }\n}\n\n// ============ Collector ============\n\nexport interface MetricsCollector extends SpanRecorder {\n /** Get stats for a specific span namespace */\n stats(name: string): SpanStats | undefined\n /** Get stats for all recorded namespaces */\n all(): Map<string, SpanStats>\n /** Format a human-readable summary */\n summary(): string\n /** Reset all collected data */\n reset(): void\n}\n\nexport function createMetricsCollector(maxEntries = 1000): MetricsCollector {\n const store = new Map<string, number[]>()\n\n return {\n recordSpan(data: SpanRecord): void {\n let arr = store.get(data.name)\n if (!arr) {\n arr = []\n store.set(data.name, arr)\n }\n arr.push(data.durationMs)\n // Bound memory: keep last N entries per namespace\n if (arr.length > maxEntries) arr.shift()\n },\n\n stats(name: string): SpanStats | undefined {\n const arr = store.get(name)\n if (!arr || arr.length === 0) return undefined\n return computeStats(arr)\n },\n\n all(): Map<string, SpanStats> {\n const result = new Map<string, SpanStats>()\n for (const [name, durations] of store) {\n if (durations.length > 0) result.set(name, computeStats(durations))\n }\n return result\n },\n\n summary(): string {\n const entries = [...this.all().entries()]\n if (entries.length === 0) return \"(no span data)\"\n const lines = entries.map(\n ([name, s]) =>\n `${name}: ${s.count} spans, mean=${s.mean.toFixed(1)}ms, p50=${s.p50.toFixed(1)}ms, p95=${s.p95.toFixed(1)}ms, p99=${s.p99.toFixed(1)}ms`,\n )\n return lines.join(\"\\n\")\n },\n\n reset(): void {\n store.clear()\n },\n }\n}\n\n// ============ withMetrics ============\n\n/**\n * Compose a logger with a metrics collector.\n * Returns a curried wrapper: `withMetrics(collector)(logger)`\n *\n * Records span duration to the provided collector on span disposal.\n * Stackable: `withMetrics(a)(withMetrics(b)(logger))` fans out to both.\n *\n * @example\n * ```typescript\n * const collector = createMetricsCollector()\n * const log = withMetrics(collector)(createLogger(\"myapp\"))\n * ```\n */\nexport function withMetrics(collector: SpanRecorder): (logger: ConditionalLogger) => ConditionalLogger {\n return (logger: ConditionalLogger): ConditionalLogger => {\n // Wrap the logger's span method to intercept disposal\n return new Proxy(logger, {\n get(target, prop: string | symbol) {\n if (prop === \"metrics\") {\n return collector\n }\n if (prop === \"span\") {\n const originalSpan = target.span\n if (!originalSpan) return undefined // TRACE off — preserve ?. behavior\n return (namespace?: string, props?: LazyProps): SpanLogger => {\n const span = originalSpan.call(target, namespace, props)\n // Wrap disposal to record to our collector\n const originalDispose = (span as unknown as { [Symbol.dispose]: () => void })[Symbol.dispose]\n ;(span as unknown as { [Symbol.dispose]: () => void })[Symbol.dispose] = () => {\n originalDispose.call(span)\n // After original disposal computed duration, record it\n if (span.spanData?.duration != null) {\n collector.recordSpan({ name: span.name, durationMs: span.spanData.duration })\n }\n }\n return span\n }\n }\n if (prop === \"child\") {\n return (\n namespaceOrContext?: string | Record<string, unknown>,\n childProps?: Record<string, unknown>,\n ): ConditionalLogger => {\n const child = target.child(namespaceOrContext as string, childProps)\n return withMetrics(collector)(child)\n }\n }\n if (prop === \"logger\") {\n // Child loggers inherit the metrics wrapper\n return (namespace?: string, childProps?: Record<string, unknown>): Logger => {\n const child = target.logger(namespace, childProps)\n // Re-wrap the child — withMetrics(collector) applied recursively\n return withMetrics(collector)(child as unknown as ConditionalLogger) as unknown as Logger\n }\n }\n return (target as unknown as Record<string | symbol, unknown>)[prop]\n },\n })\n }\n}\n"],"mappings":";AAqCA,SAAS,WAAW,QAAkB,GAAmB;AACvD,KAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAO,OADK,KAAK,IAAI,KAAK,MAAM,OAAO,SAAS,EAAE,EAAE,OAAO,SAAS,EAAE;;AAIxE,SAAS,aAAa,WAAgC;CACpD,MAAM,SAAS,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;CACnD,MAAM,QAAQ,OAAO,QAAQ,KAAK,MAAM,MAAM,GAAG,EAAE;AACnD,QAAO;EACL,OAAO,OAAO;EACd,KAAK,OAAO,MAAM;EAClB,KAAK,OAAO,OAAO,SAAS,MAAM;EAClC,MAAM,OAAO,SAAS,IAAI,QAAQ,OAAO,SAAS;EAClD,KAAK,WAAW,QAAQ,GAAI;EAC5B,KAAK,WAAW,QAAQ,IAAK;EAC7B,KAAK,WAAW,QAAQ,IAAK;EAC7B;EACD;;AAgBH,SAAgB,uBAAuB,aAAa,KAAwB;CAC1E,MAAM,wBAAQ,IAAI,KAAuB;AAEzC,QAAO;EACL,WAAW,MAAwB;GACjC,IAAI,MAAM,MAAM,IAAI,KAAK,KAAK;AAC9B,OAAI,CAAC,KAAK;AACR,UAAM,EAAE;AACR,UAAM,IAAI,KAAK,MAAM,IAAI;;AAE3B,OAAI,KAAK,KAAK,WAAW;AAEzB,OAAI,IAAI,SAAS,WAAY,KAAI,OAAO;;EAG1C,MAAM,MAAqC;GACzC,MAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,OAAI,CAAC,OAAO,IAAI,WAAW,EAAG,QAAO,KAAA;AACrC,UAAO,aAAa,IAAI;;EAG1B,MAA8B;GAC5B,MAAM,yBAAS,IAAI,KAAwB;AAC3C,QAAK,MAAM,CAAC,MAAM,cAAc,MAC9B,KAAI,UAAU,SAAS,EAAG,QAAO,IAAI,MAAM,aAAa,UAAU,CAAC;AAErE,UAAO;;EAGT,UAAkB;GAChB,MAAM,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;AACzC,OAAI,QAAQ,WAAW,EAAG,QAAO;AAKjC,UAJc,QAAQ,KACnB,CAAC,MAAM,OACN,GAAG,KAAK,IAAI,EAAE,MAAM,eAAe,EAAE,KAAK,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,QAAQ,EAAE,CAAC,IACzI,CACY,KAAK,KAAK;;EAGzB,QAAc;AACZ,SAAM,OAAO;;EAEhB;;;;;;;;;;;;;;;AAkBH,SAAgB,YAAY,WAA2E;AACrG,SAAQ,WAAiD;AAEvD,SAAO,IAAI,MAAM,QAAQ,EACvB,IAAI,QAAQ,MAAuB;AACjC,OAAI,SAAS,UACX,QAAO;AAET,OAAI,SAAS,QAAQ;IACnB,MAAM,eAAe,OAAO;AAC5B,QAAI,CAAC,aAAc,QAAO,KAAA;AAC1B,YAAQ,WAAoB,UAAkC;KAC5D,MAAM,OAAO,aAAa,KAAK,QAAQ,WAAW,MAAM;KAExD,MAAM,kBAAmB,KAAqD,OAAO;AACnF,UAAqD,OAAO,iBAAiB;AAC7E,sBAAgB,KAAK,KAAK;AAE1B,UAAI,KAAK,UAAU,YAAY,KAC7B,WAAU,WAAW;OAAE,MAAM,KAAK;OAAM,YAAY,KAAK,SAAS;OAAU,CAAC;;AAGjF,YAAO;;;AAGX,OAAI,SAAS,QACX,SACE,oBACA,eACsB;IACtB,MAAM,QAAQ,OAAO,MAAM,oBAA8B,WAAW;AACpE,WAAO,YAAY,UAAU,CAAC,MAAM;;AAGxC,OAAI,SAAS,SAEX,SAAQ,WAAoB,eAAiD;IAC3E,MAAM,QAAQ,OAAO,OAAO,WAAW,WAAW;AAElD,WAAO,YAAY,UAAU,CAAC,MAAsC;;AAGxE,UAAQ,OAAuD;KAElE,CAAC"}
|
package/dist/otel.d.mts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { f as Stage } from "./pipeline-Cl9-wCmt.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/otel.d.ts
|
|
4
|
+
interface OtelApi {
|
|
5
|
+
logs?: {
|
|
6
|
+
getLoggerProvider(): {
|
|
7
|
+
getLogger(name: string): {
|
|
8
|
+
emit(record: {
|
|
9
|
+
severityNumber: number;
|
|
10
|
+
severityText: string;
|
|
11
|
+
body: string;
|
|
12
|
+
attributes: Record<string, unknown>;
|
|
13
|
+
timestamp: number[];
|
|
14
|
+
}): void;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
trace?: {
|
|
19
|
+
getTracerProvider(): {
|
|
20
|
+
getTracer(name: string): {
|
|
21
|
+
startSpan(name: string, options?: {
|
|
22
|
+
startTime: number[];
|
|
23
|
+
attributes: Record<string, unknown>;
|
|
24
|
+
}): {
|
|
25
|
+
end(endTime?: number[]): void;
|
|
26
|
+
setAttribute(key: string, value: unknown): void;
|
|
27
|
+
setStatus(status: {
|
|
28
|
+
code: number;
|
|
29
|
+
message?: string;
|
|
30
|
+
}): void;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
interface OtelBridgeOptions {
|
|
37
|
+
/** The @opentelemetry/api module. Pass the import to avoid require() in ESM. */
|
|
38
|
+
api?: OtelApi;
|
|
39
|
+
/** Logger name for OTLP LogRecords (default: "loggily") */
|
|
40
|
+
loggerName?: string;
|
|
41
|
+
/** Tracer name for OTLP Spans (default: "loggily") */
|
|
42
|
+
tracerName?: string;
|
|
43
|
+
/** Whether to forward log events (default: true) */
|
|
44
|
+
logs?: boolean;
|
|
45
|
+
/** Whether to forward span events (default: true) */
|
|
46
|
+
spans?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a Stage that forwards loggily events to OpenTelemetry.
|
|
50
|
+
*
|
|
51
|
+
* Pass the @opentelemetry/api module via options.api:
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* import * as otelApi from "@opentelemetry/api"
|
|
55
|
+
* const log = createLogger("myapp", [toOtel({ api: otelApi }), console])
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* Events pass through unchanged (the stage is transparent).
|
|
59
|
+
*/
|
|
60
|
+
declare function toOtel(options?: OtelBridgeOptions): Stage;
|
|
61
|
+
//#endregion
|
|
62
|
+
export { OtelBridgeOptions, toOtel };
|
|
63
|
+
//# sourceMappingURL=otel.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.d.mts","names":[],"sources":["../src/otel.ts"],"mappings":";;;UAeU,OAAA;EACR,IAAA;IACE,iBAAA;MACE,SAAA,CAAU,IAAA;QACR,IAAA,CAAK,MAAA;UACH,cAAA;UACA,YAAA;UACA,IAAA;UACA,UAAA,EAAY,MAAA;UACZ,SAAA;QAAA;MAAA;IAAA;EAAA;EAKR,KAAA;IACE,iBAAA;MACE,SAAA,CAAU,IAAA;QACR,SAAA,CACE,IAAA,UACA,OAAA;UACE,SAAA;UACA,UAAA,EAAY,MAAA;QAAA;UAGd,GAAA,CAAI,OAAA;UACJ,YAAA,CAAa,GAAA,UAAa,KAAA;UAC1B,SAAA,CAAU,MAAA;YAAU,IAAA;YAAc,OAAA;UAAA;QAAA;MAAA;IAAA;EAAA;AAAA;AAAA,UAqB3B,iBAAA;EAET;EAAN,GAAA,GAAM,OAAA;EAIN;EAFA,UAAA;EAMA;EAJA,UAAA;EAIK;EAFL,IAAA;EAiBoB;EAfpB,KAAA;AAAA;;;;;;;;;;;;;iBAec,MAAA,CAAO,OAAA,GAAS,iBAAA,GAAyB,KAAA"}
|
package/dist/otel.mjs
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//#region src/otel.ts
|
|
2
|
+
const SEVERITY_MAP = {
|
|
3
|
+
trace: {
|
|
4
|
+
number: 1,
|
|
5
|
+
text: "TRACE"
|
|
6
|
+
},
|
|
7
|
+
debug: {
|
|
8
|
+
number: 5,
|
|
9
|
+
text: "DEBUG"
|
|
10
|
+
},
|
|
11
|
+
info: {
|
|
12
|
+
number: 9,
|
|
13
|
+
text: "INFO"
|
|
14
|
+
},
|
|
15
|
+
warn: {
|
|
16
|
+
number: 13,
|
|
17
|
+
text: "WARN"
|
|
18
|
+
},
|
|
19
|
+
error: {
|
|
20
|
+
number: 17,
|
|
21
|
+
text: "ERROR"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function msToHrTime(ms) {
|
|
25
|
+
return [Math.floor(ms / 1e3), ms % 1e3 * 1e6];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a Stage that forwards loggily events to OpenTelemetry.
|
|
29
|
+
*
|
|
30
|
+
* Pass the @opentelemetry/api module via options.api:
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* import * as otelApi from "@opentelemetry/api"
|
|
34
|
+
* const log = createLogger("myapp", [toOtel({ api: otelApi }), console])
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* Events pass through unchanged (the stage is transparent).
|
|
38
|
+
*/
|
|
39
|
+
function toOtel(options = {}) {
|
|
40
|
+
const { api: otelApi = null, loggerName = "loggily", tracerName = "loggily", logs: forwardLogs = true, spans: forwardSpans = true } = options;
|
|
41
|
+
function forwardLog(event) {
|
|
42
|
+
const logsApi = otelApi?.logs;
|
|
43
|
+
if (!logsApi) return;
|
|
44
|
+
const severity = SEVERITY_MAP[event.level] ?? SEVERITY_MAP.info;
|
|
45
|
+
logsApi.getLoggerProvider().getLogger(loggerName).emit({
|
|
46
|
+
severityNumber: severity.number,
|
|
47
|
+
severityText: severity.text,
|
|
48
|
+
body: event.message,
|
|
49
|
+
attributes: {
|
|
50
|
+
"loggily.namespace": event.namespace,
|
|
51
|
+
...event.props
|
|
52
|
+
},
|
|
53
|
+
timestamp: msToHrTime(event.time)
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function forwardSpan(event) {
|
|
57
|
+
const traceApi = otelApi?.trace;
|
|
58
|
+
if (!traceApi) return;
|
|
59
|
+
const tracer = traceApi.getTracerProvider().getTracer(tracerName);
|
|
60
|
+
const startTime = msToHrTime(event.time - event.duration);
|
|
61
|
+
const span = tracer.startSpan(event.name, {
|
|
62
|
+
startTime,
|
|
63
|
+
attributes: {
|
|
64
|
+
"loggily.namespace": event.namespace,
|
|
65
|
+
"loggily.span_id": event.spanId,
|
|
66
|
+
"loggily.trace_id": event.traceId,
|
|
67
|
+
...event.props
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (event.parentId) span.setAttribute("loggily.parent_id", event.parentId);
|
|
71
|
+
span.end(msToHrTime(event.time));
|
|
72
|
+
}
|
|
73
|
+
return (event) => {
|
|
74
|
+
if (forwardLogs && event.kind === "log") forwardLog(event);
|
|
75
|
+
if (forwardSpans && event.kind === "span") forwardSpan(event);
|
|
76
|
+
return event;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { toOtel };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=otel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.mjs","names":[],"sources":["../src/otel.ts"],"sourcesContent":["/**\n * loggily/otel — OpenTelemetry bridge\n *\n * Maps loggily LogEvent/SpanEvent to OpenTelemetry SDK calls.\n * Requires @opentelemetry/api as a peer dependency.\n *\n * Usage:\n * import * as otelApi from \"@opentelemetry/api\"\n * import { toOtel } from \"loggily/otel\"\n * const log = createLogger(\"myapp\", [toOtel({ api: otelApi }), console])\n */\n\nimport type { Event, LogEvent, SpanEvent, Stage } from \"./pipeline.js\"\n\n// OpenTelemetry API types (peer dep — imported at runtime)\ninterface OtelApi {\n logs?: {\n getLoggerProvider(): {\n getLogger(name: string): {\n emit(record: {\n severityNumber: number\n severityText: string\n body: string\n attributes: Record<string, unknown>\n timestamp: number[]\n }): void\n }\n }\n }\n trace?: {\n getTracerProvider(): {\n getTracer(name: string): {\n startSpan(\n name: string,\n options?: {\n startTime: number[]\n attributes: Record<string, unknown>\n },\n ): {\n end(endTime?: number[]): void\n setAttribute(key: string, value: unknown): void\n setStatus(status: { code: number; message?: string }): void\n }\n }\n }\n }\n}\n\nconst SEVERITY_MAP: Record<string, { number: number; text: string }> = {\n trace: { number: 1, text: \"TRACE\" },\n debug: { number: 5, text: \"DEBUG\" },\n info: { number: 9, text: \"INFO\" },\n warn: { number: 13, text: \"WARN\" },\n error: { number: 17, text: \"ERROR\" },\n}\n\nfunction msToHrTime(ms: number): [number, number] {\n const seconds = Math.floor(ms / 1000)\n const nanos = (ms % 1000) * 1_000_000\n return [seconds, nanos]\n}\n\nexport interface OtelBridgeOptions {\n /** The @opentelemetry/api module. Pass the import to avoid require() in ESM. */\n api?: OtelApi\n /** Logger name for OTLP LogRecords (default: \"loggily\") */\n loggerName?: string\n /** Tracer name for OTLP Spans (default: \"loggily\") */\n tracerName?: string\n /** Whether to forward log events (default: true) */\n logs?: boolean\n /** Whether to forward span events (default: true) */\n spans?: boolean\n}\n\n/**\n * Create a Stage that forwards loggily events to OpenTelemetry.\n *\n * Pass the @opentelemetry/api module via options.api:\n *\n * ```ts\n * import * as otelApi from \"@opentelemetry/api\"\n * const log = createLogger(\"myapp\", [toOtel({ api: otelApi }), console])\n * ```\n *\n * Events pass through unchanged (the stage is transparent).\n */\nexport function toOtel(options: OtelBridgeOptions = {}): Stage {\n const {\n api: otelApi = null,\n loggerName = \"loggily\",\n tracerName = \"loggily\",\n logs: forwardLogs = true,\n spans: forwardSpans = true,\n } = options\n\n function forwardLog(event: LogEvent): void {\n const logsApi = otelApi?.logs\n if (!logsApi) return\n\n const severity = SEVERITY_MAP[event.level] ?? SEVERITY_MAP.info!\n const logger = logsApi.getLoggerProvider().getLogger(loggerName)\n logger.emit({\n severityNumber: severity.number,\n severityText: severity.text,\n body: event.message,\n attributes: {\n \"loggily.namespace\": event.namespace,\n ...event.props,\n },\n timestamp: msToHrTime(event.time),\n })\n }\n\n function forwardSpan(event: SpanEvent): void {\n const traceApi = otelApi?.trace\n if (!traceApi) return\n\n const tracer = traceApi.getTracerProvider().getTracer(tracerName)\n const startTime = msToHrTime(event.time - event.duration)\n const span = tracer.startSpan(event.name, {\n startTime,\n attributes: {\n \"loggily.namespace\": event.namespace,\n \"loggily.span_id\": event.spanId,\n \"loggily.trace_id\": event.traceId,\n ...event.props,\n },\n })\n if (event.parentId) {\n span.setAttribute(\"loggily.parent_id\", event.parentId)\n }\n span.end(msToHrTime(event.time))\n }\n\n return (event: Event): Event => {\n if (forwardLogs && event.kind === \"log\") forwardLog(event)\n if (forwardSpans && event.kind === \"span\") forwardSpan(event)\n return event // transparent — pass through\n }\n}\n"],"mappings":";AAgDA,MAAM,eAAiE;CACrE,OAAO;EAAE,QAAQ;EAAG,MAAM;EAAS;CACnC,OAAO;EAAE,QAAQ;EAAG,MAAM;EAAS;CACnC,MAAM;EAAE,QAAQ;EAAG,MAAM;EAAQ;CACjC,MAAM;EAAE,QAAQ;EAAI,MAAM;EAAQ;CAClC,OAAO;EAAE,QAAQ;EAAI,MAAM;EAAS;CACrC;AAED,SAAS,WAAW,IAA8B;AAGhD,QAAO,CAFS,KAAK,MAAM,KAAK,IAAK,EACtB,KAAK,MAAQ,IACL;;;;;;;;;;;;;;AA4BzB,SAAgB,OAAO,UAA6B,EAAE,EAAS;CAC7D,MAAM,EACJ,KAAK,UAAU,MACf,aAAa,WACb,aAAa,WACb,MAAM,cAAc,MACpB,OAAO,eAAe,SACpB;CAEJ,SAAS,WAAW,OAAuB;EACzC,MAAM,UAAU,SAAS;AACzB,MAAI,CAAC,QAAS;EAEd,MAAM,WAAW,aAAa,MAAM,UAAU,aAAa;AAC5C,UAAQ,mBAAmB,CAAC,UAAU,WAAW,CACzD,KAAK;GACV,gBAAgB,SAAS;GACzB,cAAc,SAAS;GACvB,MAAM,MAAM;GACZ,YAAY;IACV,qBAAqB,MAAM;IAC3B,GAAG,MAAM;IACV;GACD,WAAW,WAAW,MAAM,KAAK;GAClC,CAAC;;CAGJ,SAAS,YAAY,OAAwB;EAC3C,MAAM,WAAW,SAAS;AAC1B,MAAI,CAAC,SAAU;EAEf,MAAM,SAAS,SAAS,mBAAmB,CAAC,UAAU,WAAW;EACjE,MAAM,YAAY,WAAW,MAAM,OAAO,MAAM,SAAS;EACzD,MAAM,OAAO,OAAO,UAAU,MAAM,MAAM;GACxC;GACA,YAAY;IACV,qBAAqB,MAAM;IAC3B,mBAAmB,MAAM;IACzB,oBAAoB,MAAM;IAC1B,GAAG,MAAM;IACV;GACF,CAAC;AACF,MAAI,MAAM,SACR,MAAK,aAAa,qBAAqB,MAAM,SAAS;AAExD,OAAK,IAAI,WAAW,MAAM,KAAK,CAAC;;AAGlC,SAAQ,UAAwB;AAC9B,MAAI,eAAe,MAAM,SAAS,MAAO,YAAW,MAAM;AAC1D,MAAI,gBAAgB,MAAM,SAAS,OAAQ,aAAY,MAAM;AAC7D,SAAO"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
//#region src/pipeline.d.ts
|
|
2
|
+
type OutputLogLevel = "trace" | "debug" | "info" | "warn" | "error";
|
|
3
|
+
type LogLevel = OutputLogLevel | "silent";
|
|
4
|
+
type LogFormat = "console" | "json";
|
|
5
|
+
type LogEvent = {
|
|
6
|
+
kind: "log";
|
|
7
|
+
time: number;
|
|
8
|
+
namespace: string;
|
|
9
|
+
level: OutputLogLevel;
|
|
10
|
+
message: string;
|
|
11
|
+
props?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
type SpanEvent = {
|
|
14
|
+
kind: "span";
|
|
15
|
+
time: number;
|
|
16
|
+
namespace: string;
|
|
17
|
+
name: string;
|
|
18
|
+
duration: number;
|
|
19
|
+
props?: Record<string, unknown>;
|
|
20
|
+
spanId: string;
|
|
21
|
+
traceId: string;
|
|
22
|
+
parentId: string | null;
|
|
23
|
+
};
|
|
24
|
+
type Event = LogEvent | SpanEvent;
|
|
25
|
+
type Stage = (event: Event) => Event | null | void;
|
|
26
|
+
declare const LOG_LEVEL_PRIORITY: Record<LogLevel, number>;
|
|
27
|
+
/** Serialize Error.cause chains up to a max depth */
|
|
28
|
+
declare function serializeCause(cause: unknown, maxDepth?: number): unknown;
|
|
29
|
+
declare function safeStringify(value: unknown): string;
|
|
30
|
+
type NsFilter = (namespace: string) => boolean;
|
|
31
|
+
interface Pipeline {
|
|
32
|
+
dispatch: (event: Event) => void;
|
|
33
|
+
level: LogLevel;
|
|
34
|
+
dispose: () => void;
|
|
35
|
+
}
|
|
36
|
+
/** A writable sink — any object with a write method. Receives raw Event objects by default. */
|
|
37
|
+
interface Writable {
|
|
38
|
+
write: (data: any) => any;
|
|
39
|
+
/** Set to false to receive formatted strings instead of raw Event objects (default: true) */
|
|
40
|
+
objectMode?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Config keys that set scope for subsequent siblings */
|
|
43
|
+
interface ConfigObject {
|
|
44
|
+
level?: LogLevel;
|
|
45
|
+
ns?: string | string[];
|
|
46
|
+
format?: LogFormat;
|
|
47
|
+
spans?: boolean;
|
|
48
|
+
/** Enable per-logger metrics collection. Creates a MetricsCollector accessible via `log.metrics`. */
|
|
49
|
+
metrics?: boolean;
|
|
50
|
+
/** ID format for trace/span IDs: "simple" (default) or "w3c" (W3C Trace Context) */
|
|
51
|
+
idFormat?: "simple" | "w3c";
|
|
52
|
+
/** Head-based sampling rate for new traces: 0.0 (none) to 1.0 (all, default) */
|
|
53
|
+
sampleRate?: number;
|
|
54
|
+
}
|
|
55
|
+
/** File output descriptor */
|
|
56
|
+
interface FileDescriptor extends ConfigObject {
|
|
57
|
+
file: string;
|
|
58
|
+
}
|
|
59
|
+
/** OTEL output descriptor (Phase 4) */
|
|
60
|
+
interface OtelDescriptor extends ConfigObject {
|
|
61
|
+
otel: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
/** A single element in a createLogger config array */
|
|
64
|
+
type ConfigElement = ConfigObject | FileDescriptor | OtelDescriptor | Console | "console" | "stderr" | Stage | Writable | ConfigElement[];
|
|
65
|
+
interface ScopeConfig {
|
|
66
|
+
level: LogLevel;
|
|
67
|
+
ns: NsFilter | null;
|
|
68
|
+
format: LogFormat;
|
|
69
|
+
}
|
|
70
|
+
declare function buildPipeline(elements: ConfigElement[], parentConfig?: Partial<ScopeConfig>): Pipeline;
|
|
71
|
+
//#endregion
|
|
72
|
+
export { LOG_LEVEL_PRIORITY as a, LogLevel as c, SpanEvent as d, Stage as f, serializeCause as g, safeStringify as h, FileDescriptor as i, OutputLogLevel as l, buildPipeline as m, ConfigObject as n, LogEvent as o, Writable as p, Event as r, LogFormat as s, ConfigElement as t, Pipeline as u };
|
|
73
|
+
//# sourceMappingURL=pipeline-Cl9-wCmt.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-Cl9-wCmt.d.mts","names":[],"sources":["../src/pipeline.ts"],"mappings":";KAOY,cAAA;AAAA,KACA,QAAA,GAAW,cAAA;AAAA,KACX,SAAA;AAAA,KAEA,QAAA;EACV,IAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,EAAO,cAAA;EACP,OAAA;EACA,KAAA,GAAQ,MAAA;AAAA;AAAA,KAGE,SAAA;EACV,IAAA;EACA,IAAA;EACA,SAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,GAAQ,MAAA;EACR,MAAA;EACA,OAAA;EACA,QAAA;AAAA;AAAA,KAGU,KAAA,GAAQ,QAAA,GAAW,SAAA;AAAA,KACnB,KAAA,IAAS,KAAA,EAAO,KAAA,KAAU,KAAA;AAAA,cAIzB,kBAAA,EAAoB,MAAA,CAAO,QAAA;;iBA4BxB,cAAA,CAAe,KAAA,WAAgB,QAAA;AAAA,iBAkB/B,aAAA,CAAc,KAAA;AAAA,KAoFlB,QAAA,IAAY,SAAA;AAAA,UA2GP,QAAA;EACf,QAAA,GAAW,KAAA,EAAO,KAAA;EAClB,KAAA,EAAO,QAAA;EACP,OAAA;AAAA;;UAqCe,QAAA;EAEf,KAAA,GAAQ,IAAA;EA5R8B;EA8RtC,UAAA;AAAA;;UAIe,YAAA;EACf,KAAA,GAAQ,QAAA;EACR,EAAA;EACA,MAAA,GAAS,SAAA;EACT,KAAA;EArSyC;EAuSzC,OAAA;EA5RD;EA8RC,QAAA;EArS+B;EAuS/B,UAAA;AAAA;;UAIe,cAAA,SAAuB,YAAA;EACtC,IAAA;AAAA;AA9PF;AAAA,UAkQiB,cAAA,SAAuB,YAAA;EACtC,IAAA,EAAM,MAAA;AAAA;;KAII,aAAA,GACR,YAAA,GACA,cAAA,GACA,cAAA,GACA,OAAA,0BAGA,KAAA,GACA,QAAA,GACA,aAAA;AAAA,UAIM,WAAA;EACR,KAAA,EAAO,QAAA;EACP,EAAA,EAAI,QAAA;EACJ,MAAA,EAAQ,SAAA;AAAA;AAAA,iBAGM,aAAA,CAAc,QAAA,EAAU,aAAA,IAAiB,YAAA,GAAe,OAAA,CAAQ,WAAA,IAAe,QAAA"}
|
package/dist/worker.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as ConditionalLogger } from "./core-Dm2PQUoS.mjs";
|
|
2
|
+
import { d as SpanEvent, f as Stage, o as LogEvent, r as Event } from "./pipeline-Cl9-wCmt.mjs";
|
|
2
3
|
|
|
3
4
|
//#region src/worker.d.ts
|
|
4
5
|
/** Message sent from worker to main thread for console output */
|
|
@@ -9,59 +10,29 @@ interface WorkerConsoleMessage {
|
|
|
9
10
|
args: unknown[];
|
|
10
11
|
timestamp: number;
|
|
11
12
|
}
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
data?: Record<string, unknown>;
|
|
19
|
-
timestamp: number;
|
|
20
|
-
}
|
|
21
|
-
/** Message sent from worker to main thread for span events */
|
|
22
|
-
interface WorkerSpanMessage {
|
|
23
|
-
type: "span";
|
|
24
|
-
event: "start" | "end";
|
|
25
|
-
namespace: string;
|
|
26
|
-
spanId: string;
|
|
27
|
-
traceId: string;
|
|
28
|
-
parentId: string | null;
|
|
29
|
-
startTime: number;
|
|
30
|
-
endTime?: number;
|
|
31
|
-
duration?: number;
|
|
32
|
-
props: Record<string, unknown>;
|
|
33
|
-
spanData: Record<string, unknown>;
|
|
34
|
-
timestamp: number;
|
|
35
|
-
}
|
|
36
|
-
/** Union type for all worker messages */
|
|
37
|
-
type WorkerMessage = WorkerConsoleMessage | WorkerLogMessage | WorkerSpanMessage;
|
|
13
|
+
/** Type guard for LogEvent (structured log from worker) */
|
|
14
|
+
declare function isWorkerLogEvent(msg: unknown): msg is LogEvent;
|
|
15
|
+
/** Type guard for SpanEvent (span from worker) */
|
|
16
|
+
declare function isWorkerSpanEvent(msg: unknown): msg is SpanEvent;
|
|
17
|
+
/** Type guard for any pipeline Event (log or span) */
|
|
18
|
+
declare function isWorkerEvent(msg: unknown): msg is Event;
|
|
38
19
|
/** Type guard for WorkerConsoleMessage */
|
|
39
20
|
declare function isWorkerConsoleMessage(msg: unknown): msg is WorkerConsoleMessage;
|
|
40
|
-
/** Type guard for
|
|
41
|
-
declare function
|
|
42
|
-
/** Type guard for WorkerSpanMessage */
|
|
43
|
-
declare function isWorkerSpanMessage(msg: unknown): msg is WorkerSpanMessage;
|
|
44
|
-
/** Type guard for any worker message */
|
|
45
|
-
declare function isWorkerMessage(msg: unknown): msg is WorkerMessage;
|
|
21
|
+
/** Type guard for any worker message (console or pipeline event) */
|
|
22
|
+
declare function isWorkerMessage(msg: unknown): msg is WorkerConsoleMessage | Event;
|
|
46
23
|
type PostMessageFn = (message: WorkerConsoleMessage) => void;
|
|
47
24
|
/**
|
|
48
|
-
* Forward console.* calls from worker to main thread.
|
|
49
|
-
*
|
|
50
|
-
* Monkey-patches console methods to send messages via postMessage.
|
|
51
|
-
* Call this at the start of your worker script.
|
|
25
|
+
* Forward console.* calls from worker to main thread via postMessage.
|
|
52
26
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
27
|
+
* Monkey-patches console methods. postMessage uses structuredClone,
|
|
28
|
+
* which handles most values natively. If cloning fails (functions,
|
|
29
|
+
* symbols), falls back to original console.
|
|
55
30
|
*
|
|
56
31
|
* @example
|
|
57
32
|
* ```typescript
|
|
58
|
-
* // At top of worker file:
|
|
59
33
|
* import { forwardConsole } from "loggily/worker"
|
|
60
34
|
* forwardConsole(postMessage, "km:worker:parse")
|
|
61
|
-
*
|
|
62
|
-
* // Now all console.* calls are forwarded:
|
|
63
35
|
* console.log("processing", { file: "test.md" })
|
|
64
|
-
* console.error(new Error("failed"))
|
|
65
36
|
* ```
|
|
66
37
|
*/
|
|
67
38
|
declare function forwardConsole(postMessage: PostMessageFn, namespace?: string): void;
|
|
@@ -70,25 +41,24 @@ declare function forwardConsole(postMessage: PostMessageFn, namespace?: string):
|
|
|
70
41
|
* Call this if you need to disable console forwarding.
|
|
71
42
|
*/
|
|
72
43
|
declare function restoreConsole(): void;
|
|
73
|
-
type PostMessageAnyFn = (message: WorkerMessage) => void;
|
|
74
|
-
/** Reset worker ID counters (for testing) */
|
|
75
|
-
declare function resetWorkerIds(): void;
|
|
76
|
-
interface WorkerLoggerOptions {
|
|
77
|
-
/** Parent span ID for nested spans */
|
|
78
|
-
parentSpanId?: string | null;
|
|
79
|
-
/** Trace ID for distributed tracing */
|
|
80
|
-
traceId?: string | null;
|
|
81
|
-
}
|
|
82
44
|
/**
|
|
83
|
-
* Create a
|
|
45
|
+
* Create a pipeline stage that forwards events via postMessage.
|
|
46
|
+
*
|
|
47
|
+
* Events are plain JSON objects that survive structuredClone natively.
|
|
48
|
+
* The stage consumes events (returns null) so nothing is output locally.
|
|
49
|
+
* The main thread uses handleWorkerEvents() or createWorkerLogHandler()
|
|
50
|
+
* to dispatch them through a local logger pipeline.
|
|
51
|
+
*/
|
|
52
|
+
declare function workerTransportStage(postMessage: (msg: unknown) => void): Stage;
|
|
53
|
+
/**
|
|
54
|
+
* Create a logger for use in a worker thread.
|
|
84
55
|
*
|
|
85
|
-
* All log
|
|
86
|
-
* The main thread should use createWorkerLogHandler to process these messages.
|
|
56
|
+
* All log and span events are forwarded to the main thread via postMessage.
|
|
57
|
+
* The main thread should use createWorkerLogHandler() to process these messages.
|
|
87
58
|
*
|
|
88
59
|
* @param postMessage - The worker's postMessage function
|
|
89
60
|
* @param namespace - Logger namespace (e.g., "km:worker:parse")
|
|
90
61
|
* @param props - Optional initial props
|
|
91
|
-
* @param options - Optional configuration
|
|
92
62
|
*
|
|
93
63
|
* @example
|
|
94
64
|
* ```typescript
|
|
@@ -96,22 +66,53 @@ interface WorkerLoggerOptions {
|
|
|
96
66
|
*
|
|
97
67
|
* const log = createWorkerLogger(postMessage, "km:worker:parse")
|
|
98
68
|
*
|
|
99
|
-
* log.info("starting parse", { file: "test.md" })
|
|
69
|
+
* log.info?.("starting parse", { file: "test.md" })
|
|
100
70
|
*
|
|
101
71
|
* {
|
|
102
|
-
* using span = log.span("process")
|
|
103
|
-
* span.info("processing...")
|
|
104
|
-
* span.spanData.
|
|
72
|
+
* using span = log.span?.("process")
|
|
73
|
+
* span.info?.("processing...")
|
|
74
|
+
* span.spanData.count = 100
|
|
105
75
|
* }
|
|
106
76
|
* // Span end event automatically sent to main thread
|
|
107
77
|
* ```
|
|
108
78
|
*/
|
|
109
|
-
declare function createWorkerLogger(postMessage:
|
|
79
|
+
declare function createWorkerLogger(postMessage: (msg: unknown) => void, namespace: string, props?: Record<string, unknown>): ConditionalLogger;
|
|
80
|
+
/**
|
|
81
|
+
* Create a handler that dispatches worker events to a target logger.
|
|
82
|
+
*
|
|
83
|
+
* Use this when you have a specific logger to dispatch through.
|
|
84
|
+
*
|
|
85
|
+
* @param target - Logger or object with dispatch method
|
|
86
|
+
* @returns Handler function to call with worker messages
|
|
87
|
+
*/
|
|
88
|
+
declare function handleWorkerEvents(target: ConditionalLogger | {
|
|
89
|
+
dispatch(event: Event): void;
|
|
90
|
+
}): (msg: unknown) => void;
|
|
91
|
+
/**
|
|
92
|
+
* Create a zero-config handler for worker logger messages.
|
|
93
|
+
*
|
|
94
|
+
* Automatically creates loggers per-namespace. For console messages,
|
|
95
|
+
* formats args and dispatches through a logger.
|
|
96
|
+
*
|
|
97
|
+
* @returns Handler function to call with any worker message
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* import { createWorkerLogHandler } from "loggily/worker"
|
|
102
|
+
*
|
|
103
|
+
* const handleLog = createWorkerLogHandler()
|
|
104
|
+
* worker.onmessage = (e) => handleLog(e.data)
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function createWorkerLogHandler(): (message: unknown) => void;
|
|
110
108
|
interface WorkerConsoleHandlerOptions {
|
|
111
109
|
/** Default namespace if message doesn't include one */
|
|
112
110
|
defaultNamespace?: string;
|
|
113
111
|
/** Custom logger to use (defaults to creating one with the namespace) */
|
|
114
|
-
logger?:
|
|
112
|
+
logger?: {
|
|
113
|
+
name: string;
|
|
114
|
+
dispatch(event: Event): void;
|
|
115
|
+
};
|
|
115
116
|
}
|
|
116
117
|
/**
|
|
117
118
|
* Create a handler for worker console messages.
|
|
@@ -132,42 +133,11 @@ interface WorkerConsoleHandlerOptions {
|
|
|
132
133
|
* worker.onmessage = (e) => {
|
|
133
134
|
* if (e.data.type === "console") {
|
|
134
135
|
* handleConsole(e.data)
|
|
135
|
-
* } else {
|
|
136
|
-
* // Handle other message types
|
|
137
136
|
* }
|
|
138
137
|
* }
|
|
139
138
|
* ```
|
|
140
139
|
*/
|
|
141
140
|
declare function createWorkerConsoleHandler(options?: WorkerConsoleHandlerOptions): (message: WorkerConsoleMessage) => void;
|
|
142
|
-
interface WorkerLogHandlerOptions {
|
|
143
|
-
/** @deprecated Span output is now controlled by TRACE env var */
|
|
144
|
-
enableSpans?: boolean;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Create a handler for worker logger messages (logs and spans).
|
|
148
|
-
*
|
|
149
|
-
* Use this on the main thread to receive and output messages from workers
|
|
150
|
-
* that use createWorkerLogger.
|
|
151
|
-
*
|
|
152
|
-
* @param options - Handler options
|
|
153
|
-
* @returns Handler function to call with worker messages
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* ```typescript
|
|
157
|
-
* import { createWorkerLogHandler, isWorkerMessage } from "loggily/worker"
|
|
158
|
-
*
|
|
159
|
-
* const handleLog = createWorkerLogHandler()
|
|
160
|
-
*
|
|
161
|
-
* worker.onmessage = (e) => {
|
|
162
|
-
* if (isWorkerMessage(e.data)) {
|
|
163
|
-
* handleLog(e.data)
|
|
164
|
-
* } else {
|
|
165
|
-
* // Handle other message types
|
|
166
|
-
* }
|
|
167
|
-
* }
|
|
168
|
-
* ```
|
|
169
|
-
*/
|
|
170
|
-
declare function createWorkerLogHandler(options?: WorkerLogHandlerOptions): (message: WorkerMessage) => void;
|
|
171
141
|
//#endregion
|
|
172
|
-
export { WorkerConsoleHandlerOptions, WorkerConsoleMessage,
|
|
142
|
+
export { WorkerConsoleHandlerOptions, WorkerConsoleMessage, createWorkerConsoleHandler, createWorkerLogHandler, createWorkerLogger, forwardConsole, handleWorkerEvents, isWorkerConsoleMessage, isWorkerEvent, isWorkerLogEvent, isWorkerMessage, isWorkerSpanEvent, restoreConsole, workerTransportStage };
|
|
173
143
|
//# sourceMappingURL=worker.d.mts.map
|