loggily 0.7.0 → 0.10.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 +46 -133
- package/dist/context.d.mts +2 -2
- package/dist/context.d.mts.map +1 -1
- package/dist/context.mjs +3 -3
- package/dist/context.mjs.map +1 -1
- package/dist/core-Byd3DY71.mjs +1324 -0
- package/dist/core-Byd3DY71.mjs.map +1 -0
- package/dist/core-DHB4KaG1.d.mts +260 -0
- package/dist/core-DHB4KaG1.d.mts.map +1 -0
- package/dist/{index-Co4jC3mx.d.mts → file-writer-BhJzFNKE.d.mts} +68 -50
- package/dist/file-writer-BhJzFNKE.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-D0omS7eF.d.mts +85 -0
- package/dist/pipeline-D0omS7eF.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 +26 -4
- package/dist/core-DAFH-huv.d.mts +0 -199
- package/dist/core-DAFH-huv.d.mts.map +0 -1
- package/dist/core-Du3sIje6.mjs +0 -900
- 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
|
@@ -1,49 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { l as SpanData } from "./core-DHB4KaG1.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/file-writer.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* File writer for loggily — Node.js/Bun only.
|
|
6
|
-
*
|
|
7
|
-
* Separated from core logger to allow tree-shaking in browser bundles.
|
|
8
|
-
* Uses dynamic import("node:fs") to avoid static dependency on Node APIs.
|
|
9
|
-
*/
|
|
10
|
-
/** Options for creating an async buffered file writer */
|
|
11
|
-
interface FileWriterOptions {
|
|
12
|
-
/** Buffer size threshold in bytes before flushing (default: 4096) */
|
|
13
|
-
bufferSize?: number;
|
|
14
|
-
/** Flush interval in milliseconds (default: 100) */
|
|
15
|
-
flushInterval?: number;
|
|
16
|
-
}
|
|
17
|
-
/** An async buffered file writer with automatic flushing */
|
|
18
|
-
interface FileWriter {
|
|
19
|
-
/** Write a line to the buffer (appends newline) */
|
|
20
|
-
write(line: string): void;
|
|
21
|
-
/** Flush the buffer immediately */
|
|
22
|
-
flush(): void;
|
|
23
|
-
/** Close the writer and flush remaining buffer */
|
|
24
|
-
close(): void;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Create an async buffered file writer for log output.
|
|
28
|
-
* Buffers writes and flushes on size threshold or interval.
|
|
29
|
-
* Registers a process.on('exit') handler to flush remaining buffer.
|
|
30
|
-
*
|
|
31
|
-
* **Node.js/Bun only** — not available in browser environments.
|
|
32
|
-
*
|
|
33
|
-
* @param filePath - Path to the log file (opened in append mode)
|
|
34
|
-
* @param options - Buffer size and flush interval configuration
|
|
35
|
-
* @returns FileWriter with write, flush, and close methods
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* const writer = createFileWriter('/tmp/app.log')
|
|
39
|
-
* const unsubscribe = addWriter((formatted) => writer.write(formatted))
|
|
40
|
-
*
|
|
41
|
-
* // On shutdown:
|
|
42
|
-
* unsubscribe()
|
|
43
|
-
* writer.close()
|
|
44
|
-
*/
|
|
45
|
-
declare function createFileWriter(filePath: string, options?: FileWriterOptions): FileWriter;
|
|
46
|
-
//#endregion
|
|
47
3
|
//#region src/tracing.d.ts
|
|
48
4
|
/** Supported ID formats */
|
|
49
5
|
type IdFormat = "simple" | "w3c";
|
|
@@ -51,9 +7,15 @@ type IdFormat = "simple" | "w3c";
|
|
|
51
7
|
* Set the ID format for new spans and traces.
|
|
52
8
|
* - "simple": sp_1, sp_2, tr_1, tr_2 (default, lightweight)
|
|
53
9
|
* - "w3c": 32-char hex trace ID, 16-char hex span ID (W3C Trace Context compatible)
|
|
10
|
+
*
|
|
11
|
+
* @deprecated Use the `TRACE_ID_FORMAT` env var or `{ idFormat: "w3c" }` in the config array instead.
|
|
54
12
|
*/
|
|
55
13
|
declare function setIdFormat(format: IdFormat): void;
|
|
56
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Get the current ID format.
|
|
16
|
+
*
|
|
17
|
+
* @deprecated Use the `TRACE_ID_FORMAT` env var or `{ idFormat: "w3c" }` in the config array instead.
|
|
18
|
+
*/
|
|
57
19
|
declare function getIdFormat(): IdFormat;
|
|
58
20
|
/** Options for traceparent header formatting */
|
|
59
21
|
interface TraceparentOptions {
|
|
@@ -77,7 +39,8 @@ interface TraceparentOptions {
|
|
|
77
39
|
*
|
|
78
40
|
* @example
|
|
79
41
|
* ```typescript
|
|
80
|
-
* const span = log.span("http-request")
|
|
42
|
+
* const span = log.span?.("http-request")
|
|
43
|
+
* if (!span) return
|
|
81
44
|
* const header = traceparent(span.spanData)
|
|
82
45
|
* // → "00-a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6-1a2b3c4d5e6f7a8b-01"
|
|
83
46
|
* fetch(url, { headers: { traceparent: header } })
|
|
@@ -88,11 +51,66 @@ declare function traceparent(spanData: SpanData, options?: TraceparentOptions):
|
|
|
88
51
|
* Set the head-based sampling rate for new traces.
|
|
89
52
|
* Applied at trace creation — all spans within a sampled trace are kept.
|
|
90
53
|
*
|
|
54
|
+
* @deprecated Use the `TRACE_SAMPLE_RATE` env var or `{ sampleRate: 0.1 }` in the config array instead.
|
|
91
55
|
* @param rate - Sampling rate from 0.0 (sample nothing) to 1.0 (sample everything, default)
|
|
92
56
|
*/
|
|
93
57
|
declare function setSampleRate(rate: number): void;
|
|
94
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Get the current sampling rate.
|
|
60
|
+
*
|
|
61
|
+
* @deprecated Use the `TRACE_SAMPLE_RATE` env var or `{ sampleRate: 0.1 }` in the config array instead.
|
|
62
|
+
*/
|
|
95
63
|
declare function getSampleRate(): number;
|
|
96
64
|
//#endregion
|
|
97
|
-
|
|
98
|
-
|
|
65
|
+
//#region src/file-writer.d.ts
|
|
66
|
+
/**
|
|
67
|
+
* File writer for loggily — Node.js/Bun only.
|
|
68
|
+
*
|
|
69
|
+
* Separated from core logger to allow tree-shaking in browser bundles.
|
|
70
|
+
* Uses dynamic import("node:fs") to avoid static dependency on Node APIs.
|
|
71
|
+
*/
|
|
72
|
+
/** Options for creating an async buffered file writer */
|
|
73
|
+
interface FileWriterOptions {
|
|
74
|
+
/** Buffer size threshold in bytes before flushing (default: 4096) */
|
|
75
|
+
bufferSize?: number;
|
|
76
|
+
/** Flush interval in milliseconds (default: 100) */
|
|
77
|
+
flushInterval?: number;
|
|
78
|
+
/** Test-only filesystem injection. Production callers should omit this. */
|
|
79
|
+
__fs?: {
|
|
80
|
+
openSync(path: string, flags: string): number;
|
|
81
|
+
writeSync(fd: number, data: string): unknown;
|
|
82
|
+
closeSync(fd: number): void;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** An async buffered file writer with automatic flushing */
|
|
86
|
+
interface FileWriter {
|
|
87
|
+
/** Write a line to the buffer (appends newline) */
|
|
88
|
+
write(line: string): void;
|
|
89
|
+
/** Flush the buffer immediately */
|
|
90
|
+
flush(): void;
|
|
91
|
+
/** Close the writer and flush remaining buffer */
|
|
92
|
+
close(): void;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create an async buffered file writer for log output.
|
|
96
|
+
* Buffers writes and flushes on size threshold or interval.
|
|
97
|
+
* Registers a process.on('exit') handler to flush remaining buffer.
|
|
98
|
+
*
|
|
99
|
+
* **Node.js/Bun only** — not available in browser environments.
|
|
100
|
+
*
|
|
101
|
+
* @param filePath - Path to the log file (opened in append mode)
|
|
102
|
+
* @param options - Buffer size and flush interval configuration
|
|
103
|
+
* @returns FileWriter with write, flush, and close methods
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* const writer = createFileWriter('/tmp/app.log')
|
|
107
|
+
* const unsubscribe = addWriter((formatted) => writer.write(formatted))
|
|
108
|
+
*
|
|
109
|
+
* // On shutdown:
|
|
110
|
+
* unsubscribe()
|
|
111
|
+
* writer.close()
|
|
112
|
+
*/
|
|
113
|
+
declare function createFileWriter(filePath: string, options?: FileWriterOptions): FileWriter;
|
|
114
|
+
//#endregion
|
|
115
|
+
export { TraceparentOptions as a, setIdFormat as c, IdFormat as i, setSampleRate as l, FileWriterOptions as n, getIdFormat as o, createFileWriter as r, getSampleRate as s, FileWriter as t, traceparent as u };
|
|
116
|
+
//# sourceMappingURL=file-writer-BhJzFNKE.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-writer-BhJzFNKE.d.mts","names":[],"sources":["../src/tracing.ts","../src/file-writer.ts"],"mappings":";;;;KAYY,QAAA;;;;;AAoBZ;;;iBATgB,WAAA,CAAY,MAAA,EAAQ,QAAA;;AAkDpC;;;;iBAzCgB,WAAA,CAAA,GAAe,QAAA;;UAyCd,kBAAA;EA+Ba;EA7B5B,OAAA;AAAA;;;;;AA6EF;;;;;;;;AC9IA;;;;;;;;;;;;iBD4FgB,WAAA,CACd,QAAA,EAAU,QAAA,EACV,OAAA,GAAU,kBAAA;;;;;AChFZ;;;iBDoHgB,aAAA,CAAc,IAAA;;;;;;iBAYd,aAAA,CAAA;;;;;;AA5IhB;;;;UCFiB,iBAAA;EDaD;ECXd,UAAA;;EAEA,aAAA;EDS0C;ECP1C,IAAA;IACE,QAAA,CAAS,IAAA,UAAc,KAAA;IACvB,SAAA,CAAU,EAAA,UAAY,IAAA;IACtB,SAAA,CAAU,EAAA;EAAA;AAAA;;UAKG,UAAA;EDmDf;ECjDA,KAAA,CAAM,IAAA;ED4EQ;EC1Ed,KAAA;;EAEA,KAAA;AAAA;;;;;;AD8GF;;;;;AAYA;;;;;;;;AC9IA;iBA0CgB,gBAAA,CACd,QAAA,UACA,OAAA,GAAS,iBAAA,GACR,UAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { A as getTraceFilter, B as startCollecting, C as disableSpans, D as getLogFormat, E as getDebugFilter, F as setLogLevel, G as writeSpan, H as withConfigMetrics, I as setOutputMode, L as setSuppressConsole, M as resetIds, N as setDebugFilter, O as getLogLevel, P as setLogFormat, R as setTraceFilter, S as createTestLogger, T as getCollectedSpans, U as withEnvDefaults, V as stopCollecting, W as withSpans, _ as addWriter, a as LoggerFactory, b as createLogger, c as PluginCtx, d as SpanRecord, f as SpanRecorder, i as Logger, j as pipe, k as getOutputMode, l as SpanData, m as WriterFn, n as LazyMessage, o as LoggerPlugin, r as LazyProps, s as OutputMode, t as ConditionalLogger, u as SpanLogger, v as baseCreateLogger, w as enableSpans, y as clearCollectedSpans, z as spansAreEnabled } from "./core-DHB4KaG1.mjs";
|
|
2
|
+
import { a as LOG_LEVEL_PRIORITY, c as LogLevel, d as SpanEvent, f as Stage, h as safeStringify, i as FileDescriptor, l as OutputLogLevel, m as buildPipeline, n as ConfigObject, o as LogEvent, p as Writable, r as Event, s as LogFormat, t as ConfigElement, u as Pipeline } from "./pipeline-D0omS7eF.mjs";
|
|
3
|
+
import { a as TraceparentOptions, c as setIdFormat, i as IdFormat, l as setSampleRate, n as FileWriterOptions, o as getIdFormat, s as getSampleRate, t as FileWriter, u as traceparent } from "./file-writer-BhJzFNKE.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/index.browser.d.ts
|
|
6
|
+
/** @throws Always — createFileWriter is not available in browser environments */
|
|
7
|
+
declare function createFileWriter(): never;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { type ConditionalLogger, type ConfigElement, type ConfigObject, type Event, type FileDescriptor, type FileWriter, type FileWriterOptions, type IdFormat, LOG_LEVEL_PRIORITY, type LazyMessage, type LazyProps, type LogEvent, type LogFormat, type LogLevel, type Logger, type LoggerFactory, type LoggerPlugin, type OutputLogLevel, type OutputMode, type Pipeline, type PluginCtx, type SpanData, type SpanEvent, type SpanLogger, type SpanRecord, type SpanRecorder, type Stage, type TraceparentOptions, type Writable, type WriterFn, addWriter, baseCreateLogger, buildPipeline, clearCollectedSpans, createFileWriter, createLogger, createTestLogger, disableSpans, enableSpans, getCollectedSpans, getDebugFilter, getIdFormat, getLogFormat, getLogLevel, getOutputMode, getSampleRate, getTraceFilter, pipe, resetIds, safeStringify, setDebugFilter, setIdFormat, setLogFormat, setLogLevel, setOutputMode, setSampleRate, setSuppressConsole, setTraceFilter, spansAreEnabled, startCollecting, stopCollecting, traceparent, withConfigMetrics, withEnvDefaults, withSpans, writeSpan };
|
|
10
|
+
//# sourceMappingURL=index.browser.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.d.mts","names":[],"sources":["../src/index.browser.ts"],"mappings":";;;;;;iBAmGgB,gBAAA,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { A as withEnvDefaults, B as setSampleRate, C as setOutputMode, D as startCollecting, E as spansAreEnabled, F as safeStringify, L as getIdFormat, M as writeSpan, N as LOG_LEVEL_PRIORITY, O as stopCollecting, P as buildPipeline, R as getSampleRate, S as setLogLevel, T as setTraceFilter, V as traceparent, _ as getTraceFilter, a as baseCreateLogger, b as setDebugFilter, d as enableSpans, f as getCollectedSpans, g as getOutputMode, h as getLogLevel, i as addWriter, j as withSpans, k as withConfigMetrics, l as createTestLogger, m as getLogFormat, o as clearCollectedSpans, p as getDebugFilter, s as createLogger, u as disableSpans, v as pipe, w as setSuppressConsole, x as setLogFormat, y as resetIds, z as setIdFormat } from "./core-Byd3DY71.mjs";
|
|
2
|
+
//#region src/index.browser.ts
|
|
3
|
+
/** @throws Always — createFileWriter is not available in browser environments */
|
|
4
|
+
function createFileWriter() {
|
|
5
|
+
throw new Error("createFileWriter is not available in browser environments. Use a writable sink in the config array instead.");
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { LOG_LEVEL_PRIORITY, addWriter, baseCreateLogger, buildPipeline, clearCollectedSpans, createFileWriter, createLogger, createTestLogger, disableSpans, enableSpans, getCollectedSpans, getDebugFilter, getIdFormat, getLogFormat, getLogLevel, getOutputMode, getSampleRate, getTraceFilter, pipe, resetIds, safeStringify, setDebugFilter, setIdFormat, setLogFormat, setLogLevel, setOutputMode, setSampleRate, setSuppressConsole, setTraceFilter, spansAreEnabled, startCollecting, stopCollecting, traceparent, withConfigMetrics, withEnvDefaults, withSpans, writeSpan };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=index.browser.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.mjs","names":[],"sources":["../src/index.browser.ts"],"sourcesContent":["/**\n * loggily v2 browser entry point.\n *\n * Re-exports the full logger API except createFileWriter (which requires node:fs).\n * Bundlers resolve this via the \"browser\" condition in package.json exports.\n */\n\nexport {\n // Core API\n createLogger,\n baseCreateLogger,\n createTestLogger,\n pipe,\n withSpans,\n withEnvDefaults,\n withConfigMetrics,\n type LoggerFactory,\n type LoggerPlugin,\n type PluginCtx,\n\n // Types\n type ConditionalLogger,\n type Logger,\n type SpanLogger,\n type SpanData,\n type LazyMessage,\n type LazyProps,\n type Event,\n type LogEvent,\n type SpanEvent,\n type Stage,\n type LogLevel,\n type OutputLogLevel,\n type LogFormat,\n type OutputMode,\n\n // Constants\n LOG_LEVEL_PRIORITY,\n\n // Utilities\n safeStringify,\n resetIds,\n\n // Span collection\n startCollecting,\n stopCollecting,\n getCollectedSpans,\n clearCollectedSpans,\n\n // Span metrics\n type SpanRecord,\n type SpanRecorder,\n\n // Deprecated v1 API (throws with migration instructions)\n setLogLevel,\n getLogLevel,\n enableSpans,\n disableSpans,\n spansAreEnabled,\n setTraceFilter,\n getTraceFilter,\n setDebugFilter,\n getDebugFilter,\n setLogFormat,\n getLogFormat,\n setSuppressConsole,\n setOutputMode,\n getOutputMode,\n addWriter,\n type WriterFn,\n writeSpan,\n} from \"./core.js\"\n\n// Tracing utilities (runtime-agnostic, work in browser)\nexport {\n setIdFormat,\n getIdFormat,\n type IdFormat,\n traceparent,\n type TraceparentOptions,\n setSampleRate,\n getSampleRate,\n} from \"./tracing.js\"\n\n// Pipeline builder for power users\nexport { buildPipeline, type Pipeline } from \"./pipeline.js\"\n\n// Re-export config types for typed pipeline construction\nexport type {\n ConfigElement,\n ConfigObject,\n FileDescriptor,\n Writable,\n} from \"./pipeline.js\"\n\n// File writer types (exported for type compatibility, but the function throws)\nexport type { FileWriterOptions, FileWriter } from \"./file-writer.js\"\n\n/** @throws Always — createFileWriter is not available in browser environments */\nexport function createFileWriter(): never {\n throw new Error(\n \"createFileWriter is not available in browser environments. Use a writable sink in the config array instead.\",\n )\n}\n"],"mappings":";;;AAmGA,SAAgB,mBAA0B;AACxC,OAAM,IAAI,MACR,8GACD"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { a as
|
|
3
|
-
|
|
1
|
+
import { A as getTraceFilter, B as startCollecting, C as disableSpans, D as getLogFormat, E as getDebugFilter, F as setLogLevel, G as writeSpan, H as withConfigMetrics, I as setOutputMode, L as setSuppressConsole, M as resetIds, N as setDebugFilter, O as getLogLevel, P as setLogFormat, R as setTraceFilter, S as createTestLogger, T as getCollectedSpans, U as withEnvDefaults, V as stopCollecting, W as withSpans, _ as addWriter, a as LoggerFactory, b as createLogger, c as PluginCtx, d as SpanRecord, f as SpanRecorder, g as _setContextHooks, h as _clearContextHooks, i as Logger, j as pipe, k as getOutputMode, l as SpanData, m as WriterFn, n as LazyMessage, o as LoggerPlugin, p as SpannedLogger, r as LazyProps, s as OutputMode, t as ConditionalLogger, u as SpanLogger, v as baseCreateLogger, w as enableSpans, x as createSpanDataProxy, y as clearCollectedSpans, z as spansAreEnabled } from "./core-DHB4KaG1.mjs";
|
|
2
|
+
import { a as LOG_LEVEL_PRIORITY, c as LogLevel, d as SpanEvent, f as Stage, g as serializeCause, h as safeStringify, i as FileDescriptor, l as OutputLogLevel, m as buildPipeline, n as ConfigObject, o as LogEvent, p as Writable, r as Event, s as LogFormat, t as ConfigElement, u as Pipeline } from "./pipeline-D0omS7eF.mjs";
|
|
3
|
+
import { a as TraceparentOptions, c as setIdFormat, i as IdFormat, l as setSampleRate, n as FileWriterOptions, o as getIdFormat, r as createFileWriter, s as getSampleRate, t as FileWriter, u as traceparent } from "./file-writer-BhJzFNKE.mjs";
|
|
4
|
+
export { type ConditionalLogger, type ConfigElement, type ConfigObject, type Event, type FileDescriptor, type FileWriter, type FileWriterOptions, type IdFormat, LOG_LEVEL_PRIORITY, type LazyMessage, type LazyProps, type LogEvent, type LogFormat, type LogLevel, type Logger, type LoggerFactory, type LoggerPlugin, type OutputLogLevel, type OutputMode, type Pipeline, type PluginCtx, type SpanData, type SpanEvent, type SpanLogger, type SpanRecord, type SpanRecorder, type SpannedLogger, type Stage, type TraceparentOptions, type Writable, type WriterFn, _clearContextHooks, _setContextHooks, addWriter, baseCreateLogger, buildPipeline, clearCollectedSpans, createFileWriter, createLogger, createSpanDataProxy, createTestLogger, disableSpans, enableSpans, getCollectedSpans, getDebugFilter, getIdFormat, getLogFormat, getLogLevel, getOutputMode, getSampleRate, getTraceFilter, pipe, resetIds, safeStringify, serializeCause, setDebugFilter, setIdFormat, setLogFormat, setLogLevel, setOutputMode, setSampleRate, setSuppressConsole, setTraceFilter, spansAreEnabled, startCollecting, stopCollecting, traceparent, withConfigMetrics, withEnvDefaults, withSpans, writeSpan };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
|
|
1
|
+
import { A as withEnvDefaults, B as setSampleRate, C as setOutputMode, D as startCollecting, E as spansAreEnabled, F as safeStringify, H as createFileWriter, I as serializeCause, L as getIdFormat, M as writeSpan, N as LOG_LEVEL_PRIORITY, O as stopCollecting, P as buildPipeline, R as getSampleRate, S as setLogLevel, T as setTraceFilter, V as traceparent, _ as getTraceFilter, a as baseCreateLogger, b as setDebugFilter, c as createSpanDataProxy, d as enableSpans, f as getCollectedSpans, g as getOutputMode, h as getLogLevel, i as addWriter, j as withSpans, k as withConfigMetrics, l as createTestLogger, m as getLogFormat, n as _setContextHooks, o as clearCollectedSpans, p as getDebugFilter, r as _setLogFileWriterFactory, s as createLogger, t as _clearContextHooks, u as disableSpans, v as pipe, w as setSuppressConsole, x as setLogFormat, y as resetIds, z as setIdFormat } from "./core-Byd3DY71.mjs";
|
|
2
|
+
//#region src/index.ts
|
|
3
|
+
_setLogFileWriterFactory(createFileWriter);
|
|
4
|
+
//#endregion
|
|
5
|
+
export { LOG_LEVEL_PRIORITY, _clearContextHooks, _setContextHooks, addWriter, baseCreateLogger, buildPipeline, clearCollectedSpans, createFileWriter, createLogger, createSpanDataProxy, createTestLogger, disableSpans, enableSpans, getCollectedSpans, getDebugFilter, getIdFormat, getLogFormat, getLogLevel, getOutputMode, getSampleRate, getTraceFilter, pipe, resetIds, safeStringify, serializeCause, setDebugFilter, setIdFormat, setLogFormat, setLogLevel, setOutputMode, setSampleRate, setSuppressConsole, setTraceFilter, spansAreEnabled, startCollecting, stopCollecting, traceparent, withConfigMetrics, withEnvDefaults, withSpans, writeSpan };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["_cfw"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * loggily v2 — Structured logging with spans\n *\n * One import. Objects configure. Arrays branch. Values write.\n */\n\nexport {\n // Core API\n createLogger,\n baseCreateLogger,\n createTestLogger,\n pipe,\n type LoggerFactory,\n type LoggerPlugin,\n type PluginCtx,\n // Plugins\n withSpans,\n withEnvDefaults,\n withConfigMetrics,\n // Types\n type ConditionalLogger,\n type Logger,\n type SpanLogger,\n type SpannedLogger,\n type SpanData,\n type LazyMessage,\n type LazyProps,\n type Event,\n type LogEvent,\n type SpanEvent,\n type Stage,\n type LogLevel,\n type OutputLogLevel,\n type LogFormat,\n type OutputMode,\n // Constants\n LOG_LEVEL_PRIORITY,\n // Utilities\n safeStringify,\n resetIds,\n // Span collection\n startCollecting,\n stopCollecting,\n getCollectedSpans,\n clearCollectedSpans,\n // Span metrics\n type SpanRecord,\n type SpanRecorder,\n // Internal (used by context.ts)\n _setContextHooks,\n _clearContextHooks,\n createSpanDataProxy,\n // Deprecated v1 API (maps to env vars for backwards compat)\n setLogLevel,\n getLogLevel,\n enableSpans,\n disableSpans,\n spansAreEnabled,\n setTraceFilter,\n getTraceFilter,\n setDebugFilter,\n getDebugFilter,\n setLogFormat,\n getLogFormat,\n setSuppressConsole,\n setOutputMode,\n getOutputMode,\n addWriter,\n type WriterFn,\n writeSpan,\n} from \"./core.js\"\n\nexport {\n createFileWriter,\n type FileWriter,\n type FileWriterOptions,\n} from \"./file-writer.js\"\n\n// Wire file writer into core for LOG_FILE env var support\nimport { createFileWriter as _cfw } from \"./file-writer.js\"\nimport { _setLogFileWriterFactory } from \"./core.js\"\n_setLogFileWriterFactory(_cfw)\n\nexport {\n setIdFormat,\n getIdFormat,\n type IdFormat,\n traceparent,\n type TraceparentOptions,\n setSampleRate,\n getSampleRate,\n} from \"./tracing.js\"\n\n// Re-export pipeline builder and utilities for power users\nexport { buildPipeline, type Pipeline, serializeCause } from \"./pipeline.js\"\n\n// Re-export config types for typed pipeline construction\nexport type {\n ConfigElement,\n ConfigObject,\n FileDescriptor,\n Writable,\n} from \"./pipeline.js\"\n"],"mappings":";;AAiFA,yBAAyBA,iBAAK"}
|
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 { J as createMetricsCollector, K as MetricsCollector, Y as withMetrics, d as SpanRecord, f as SpanRecorder, q as SpanStats } from "./core-DHB4KaG1.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(\n collector: SpanRecorder,\n): (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 = (\n span as unknown as { [Symbol.dispose]: () => void }\n )[Symbol.dispose]\n ;(span as unknown as { [Symbol.dispose]: () => void })[\n Symbol.dispose\n ] = () => {\n originalDispose.call(span)\n // After original disposal computed duration, record it\n if (span.spanData?.duration != null) {\n collector.recordSpan({\n name: span.name,\n durationMs: span.spanData.duration,\n })\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 (\n namespace?: string,\n childProps?: Record<string, unknown>,\n ): Logger => {\n const child = target.logger(namespace, childProps)\n // Re-wrap the child — withMetrics(collector) applied recursively\n return withMetrics(collector)(\n child as unknown as ConditionalLogger,\n ) 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,YACd,WACkD;AAClD,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,kBACJ,KACA,OAAO;AACP,UACA,OAAO,iBACC;AACR,sBAAgB,KAAK,KAAK;AAE1B,UAAI,KAAK,UAAU,YAAY,KAC7B,WAAU,WAAW;OACnB,MAAM,KAAK;OACX,YAAY,KAAK,SAAS;OAC3B,CAAC;;AAGN,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,SACE,WACA,eACW;IACX,MAAM,QAAQ,OAAO,OAAO,WAAW,WAAW;AAElD,WAAO,YAAY,UAAU,CAC3B,MACD;;AAGL,UAAQ,OAAuD;KAElE,CAAC"}
|
package/dist/otel.d.mts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { f as Stage } from "./pipeline-D0omS7eF.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"}
|