@unhingged/logit 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +132 -2
- package/dist/chunk-3FU7DTQE.cjs +2117 -0
- package/dist/chunk-3FU7DTQE.cjs.map +1 -0
- package/dist/chunk-7J27DQIR.js +72 -0
- package/dist/chunk-7J27DQIR.js.map +1 -0
- package/dist/chunk-GW7WQELF.js +2117 -0
- package/dist/chunk-GW7WQELF.js.map +1 -0
- package/dist/chunk-SKS54NHB.cjs +72 -0
- package/dist/chunk-SKS54NHB.cjs.map +1 -0
- package/dist/express.cjs +195 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +39 -0
- package/dist/express.d.ts +39 -0
- package/dist/express.js +195 -0
- package/dist/express.js.map +1 -0
- package/dist/index.cjs +143 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +877 -0
- package/dist/index.d.ts +877 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/next.cjs +212 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +55 -0
- package/dist/next.d.ts +55 -0
- package/dist/next.js +212 -0
- package/dist/next.js.map +1 -0
- package/dist/node.cjs +341 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +58 -0
- package/dist/node.d.ts +58 -0
- package/dist/node.js +341 -0
- package/dist/node.js.map +1 -0
- package/dist/otel.cjs +304 -0
- package/dist/otel.cjs.map +1 -0
- package/dist/otel.d.cts +103 -0
- package/dist/otel.d.ts +103 -0
- package/dist/otel.js +304 -0
- package/dist/otel.js.map +1 -0
- package/dist/request-7cW3twuF.d.ts +34 -0
- package/dist/request-DrVrbDze.d.cts +34 -0
- package/package.json +89 -4
package/dist/otel.cjs
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
var _chunk3FU7DTQEcjs = require('./chunk-3FU7DTQE.cjs');
|
|
72
|
+
|
|
73
|
+
// src/otel.ts
|
|
74
|
+
var OTEL_SEVERITY = {
|
|
75
|
+
verbose: { number: 1, text: "TRACE" },
|
|
76
|
+
debug: { number: 5, text: "DEBUG" },
|
|
77
|
+
info: { number: 9, text: "INFO" },
|
|
78
|
+
warn: { number: 13, text: "WARN" },
|
|
79
|
+
error: { number: 17, text: "ERROR" },
|
|
80
|
+
fatal: { number: 21, text: "FATAL" }
|
|
81
|
+
};
|
|
82
|
+
function toAnyValue(value) {
|
|
83
|
+
if (value === null || value === void 0) return { stringValue: "" };
|
|
84
|
+
switch (typeof value) {
|
|
85
|
+
case "string":
|
|
86
|
+
return { stringValue: value };
|
|
87
|
+
case "number":
|
|
88
|
+
return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
|
|
89
|
+
case "boolean":
|
|
90
|
+
return { boolValue: value };
|
|
91
|
+
case "bigint":
|
|
92
|
+
return { intValue: value.toString() };
|
|
93
|
+
default:
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (value instanceof Date) return { stringValue: value.toISOString() };
|
|
97
|
+
if (Array.isArray(value)) return { arrayValue: { values: value.map(toAnyValue) } };
|
|
98
|
+
if (typeof value === "object") return { kvlistValue: { values: toKeyValues(value) } };
|
|
99
|
+
return { stringValue: String(value) };
|
|
100
|
+
}
|
|
101
|
+
function toKeyValues(record) {
|
|
102
|
+
return Object.keys(record).map((key) => ({ key, value: toAnyValue(record[key]) }));
|
|
103
|
+
}
|
|
104
|
+
function encodeOtlpLogs(events, options = {}) {
|
|
105
|
+
const templateAttribute = options.templateAttribute === void 0 ? "message_template.text" : options.templateAttribute;
|
|
106
|
+
return {
|
|
107
|
+
resourceLogs: [
|
|
108
|
+
{
|
|
109
|
+
resource: { attributes: toKeyValues({ ...options.resource }) },
|
|
110
|
+
scopeLogs: [
|
|
111
|
+
{
|
|
112
|
+
scope: _nullishCoalesce(options.scope, () => ( { name: "@unhingged/logit" })),
|
|
113
|
+
logRecords: events.map((event) => {
|
|
114
|
+
const attributes = [];
|
|
115
|
+
if (templateAttribute) attributes.push({ key: templateAttribute, value: { stringValue: event.messageTemplate } });
|
|
116
|
+
for (const key of Object.keys(event.properties)) attributes.push({ key, value: toAnyValue(event.properties[key]) });
|
|
117
|
+
if (event.error) {
|
|
118
|
+
attributes.push({ key: "exception.type", value: { stringValue: event.error.name } });
|
|
119
|
+
attributes.push({ key: "exception.message", value: { stringValue: event.error.message } });
|
|
120
|
+
attributes.push({ key: "exception.stacktrace", value: { stringValue: _chunk3FU7DTQEcjs.formatError.call(void 0, event.error) } });
|
|
121
|
+
}
|
|
122
|
+
const severity = OTEL_SEVERITY[event.level];
|
|
123
|
+
const nanos = `${event.timestamp.getTime()}000000`;
|
|
124
|
+
return {
|
|
125
|
+
timeUnixNano: nanos,
|
|
126
|
+
observedTimeUnixNano: nanos,
|
|
127
|
+
severityNumber: severity.number,
|
|
128
|
+
severityText: severity.text,
|
|
129
|
+
body: { stringValue: event.renderMessage({ literal: true }) },
|
|
130
|
+
attributes,
|
|
131
|
+
...event.traceId ? { traceId: event.traceId } : {},
|
|
132
|
+
...event.spanId ? { spanId: event.spanId } : {}
|
|
133
|
+
};
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function env(name) {
|
|
142
|
+
return _optionalChain([globalThis, 'access', _ => _.process, 'optionalAccess', _2 => _2.env, 'optionalAccess', _3 => _3[name]]);
|
|
143
|
+
}
|
|
144
|
+
function envHeaders() {
|
|
145
|
+
const raw = _nullishCoalesce(env("OTEL_EXPORTER_OTLP_LOGS_HEADERS"), () => ( env("OTEL_EXPORTER_OTLP_HEADERS")));
|
|
146
|
+
const out = {};
|
|
147
|
+
if (!raw) return out;
|
|
148
|
+
for (const pair of raw.split(",")) {
|
|
149
|
+
const i = pair.indexOf("=");
|
|
150
|
+
if (i > 0) out[pair.slice(0, i).trim()] = decodeURIComponent(pair.slice(i + 1).trim());
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
function otlpHttpSink(options = {}) {
|
|
155
|
+
const fetchImpl = _nullishCoalesce(options.fetch, () => ( globalThis.fetch));
|
|
156
|
+
if (!fetchImpl) throw new Error("logit: otlpHttpSink needs fetch \u2014 pass one in options.fetch");
|
|
157
|
+
const url = _nullishCoalesce(_nullishCoalesce(options.url, () => ( env("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT"))), () => ( `${(_nullishCoalesce(env("OTEL_EXPORTER_OTLP_ENDPOINT"), () => ( "http://localhost:4318"))).replace(/\/$/, "")}/v1/logs`));
|
|
158
|
+
const serviceName = env("OTEL_SERVICE_NAME");
|
|
159
|
+
const resource = { ...serviceName ? { "service.name": serviceName } : {}, ...options.resource };
|
|
160
|
+
const timeout = _nullishCoalesce(options.timeout, () => ( 1e4));
|
|
161
|
+
return _chunk3FU7DTQEcjs.batchingSink.call(void 0,
|
|
162
|
+
async (events) => {
|
|
163
|
+
const controller = typeof AbortController === "function" ? new AbortController() : void 0;
|
|
164
|
+
const timer = controller ? setTimeout(() => controller.abort(), timeout) : void 0;
|
|
165
|
+
_optionalChain([timer, 'optionalAccess', _4 => _4.unref, 'optionalCall', _5 => _5()]);
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetchImpl(url, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "content-type": "application/json", ...envHeaders(), ...options.headers },
|
|
170
|
+
body: JSON.stringify(encodeOtlpLogs(events, { ...options, resource })),
|
|
171
|
+
signal: _optionalChain([controller, 'optionalAccess', _6 => _6.signal]),
|
|
172
|
+
keepalive: true
|
|
173
|
+
});
|
|
174
|
+
if (!response.ok) throw new Error(`OTLP export failed: HTTP ${response.status}`);
|
|
175
|
+
} finally {
|
|
176
|
+
if (timer) clearTimeout(timer);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
{ name: `otlp(${url})`, ...options }
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
function flattenAttributes(record, prefix = "", into = {}) {
|
|
183
|
+
for (const key of Object.keys(record)) {
|
|
184
|
+
const value = record[key];
|
|
185
|
+
const name = prefix ? `${prefix}.${key}` : key;
|
|
186
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
187
|
+
flattenAttributes(value, name, into);
|
|
188
|
+
} else if (value instanceof Date) {
|
|
189
|
+
into[name] = value.toISOString();
|
|
190
|
+
} else if (Array.isArray(value)) {
|
|
191
|
+
into[name] = value.every((v) => v === null || ["string", "number", "boolean"].includes(typeof v)) ? value : JSON.stringify(value);
|
|
192
|
+
} else {
|
|
193
|
+
into[name] = value;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return into;
|
|
197
|
+
}
|
|
198
|
+
function otelBridgeSink(provider, options = {}) {
|
|
199
|
+
const scope = _nullishCoalesce(options.scope, () => ( { name: "@unhingged/logit" }));
|
|
200
|
+
const otelLogger = provider.getLogger(scope.name, scope.version);
|
|
201
|
+
const templateAttribute = options.templateAttribute === void 0 ? "message_template.text" : options.templateAttribute;
|
|
202
|
+
const flatten = _nullishCoalesce(options.flatten, () => ( true));
|
|
203
|
+
return {
|
|
204
|
+
name: "otel-bridge",
|
|
205
|
+
restrictedToMinimumLevel: options.restrictedToMinimumLevel,
|
|
206
|
+
audit: options.audit,
|
|
207
|
+
emit(event) {
|
|
208
|
+
const raw = { ...event.properties };
|
|
209
|
+
if (templateAttribute) raw[templateAttribute] = event.messageTemplate;
|
|
210
|
+
if (event.error) {
|
|
211
|
+
raw["exception.type"] = event.error.name;
|
|
212
|
+
raw["exception.message"] = event.error.message;
|
|
213
|
+
raw["exception.stacktrace"] = _chunk3FU7DTQEcjs.formatError.call(void 0, event.error);
|
|
214
|
+
}
|
|
215
|
+
const severity = OTEL_SEVERITY[event.level];
|
|
216
|
+
otelLogger.emit({
|
|
217
|
+
timestamp: event.timestamp,
|
|
218
|
+
observedTimestamp: event.timestamp,
|
|
219
|
+
severityNumber: severity.number,
|
|
220
|
+
severityText: severity.text,
|
|
221
|
+
body: event.renderMessage({ literal: true }),
|
|
222
|
+
attributes: flatten ? flattenAttributes(raw) : raw
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
exports.CLEF_MEDIA_TYPE = _chunk3FU7DTQEcjs.CLEF_MEDIA_TYPE; exports.DEFAULT_DESTRUCTURING = _chunk3FU7DTQEcjs.DEFAULT_DESTRUCTURING; exports.DEFAULT_OUTPUT_TEMPLATE = _chunk3FU7DTQEcjs.DEFAULT_OUTPUT_TEMPLATE; exports.LEVELS = _chunk3FU7DTQEcjs.LEVELS; exports.LEVEL_CODES = _chunk3FU7DTQEcjs.LEVEL_CODES; exports.LEVEL_NUMBERS = _chunk3FU7DTQEcjs.LEVEL_NUMBERS; exports.LEVEL_ORDER = _chunk3FU7DTQEcjs.LEVEL_ORDER; exports.LevelSwitch = _chunk3FU7DTQEcjs.LevelSwitch; exports.LogContext = _chunk3FU7DTQEcjs.LogContext; exports.LogEvent = _chunk3FU7DTQEcjs.LogEvent; exports.Logger = _chunk3FU7DTQEcjs.Logger; exports.LoggerConfiguration = _chunk3FU7DTQEcjs.LoggerConfiguration; exports.Matching = _chunk3FU7DTQEcjs.Matching; exports.OTEL_SEVERITY = OTEL_SEVERITY; exports.Operation = _chunk3FU7DTQEcjs.Operation; exports.SERILOG_LEVEL_NAMES = _chunk3FU7DTQEcjs.SERILOG_LEVEL_NAMES; exports.ansi = _chunk3FU7DTQEcjs.ansi; exports.audit = _chunk3FU7DTQEcjs.audit; exports.batchingSink = _chunk3FU7DTQEcjs.batchingSink; exports.byExcluding = _chunk3FU7DTQEcjs.byExcluding; exports.byIncludingOnly = _chunk3FU7DTQEcjs.byIncludingOnly; exports.byTransforming = _chunk3FU7DTQEcjs.byTransforming; exports.callbackSink = _chunk3FU7DTQEcjs.callbackSink; exports.captureError = _chunk3FU7DTQEcjs.captureError; exports.captureProperty = _chunk3FU7DTQEcjs.captureProperty; exports.captureValue = _chunk3FU7DTQEcjs.captureValue; exports.clefFormatter = _chunk3FU7DTQEcjs.clefFormatter; exports.closeAndFlush = _chunk3FU7DTQEcjs.closeAndFlush; exports.conditional = _chunk3FU7DTQEcjs.conditional; exports.configure = _chunk3FU7DTQEcjs.configure; exports.consoleSink = _chunk3FU7DTQEcjs.consoleSink; exports.createLogger = _chunk3FU7DTQEcjs.createLogger; exports.detectColors = _chunk3FU7DTQEcjs.detectColors; exports.diagnosticContext = _chunk3FU7DTQEcjs.diagnosticContext; exports.encodeOtlpLogs = encodeOtlpLogs; exports.flattenAttributes = flattenAttributes; exports.formatDate = _chunk3FU7DTQEcjs.formatDate; exports.formatError = _chunk3FU7DTQEcjs.formatError; exports.formatLevel = _chunk3FU7DTQEcjs.formatLevel; exports.formatNumber = _chunk3FU7DTQEcjs.formatNumber; exports.fromLogContext = _chunk3FU7DTQEcjs.fromLogContext; exports.httpSink = _chunk3FU7DTQEcjs.httpSink; exports.isLevel = _chunk3FU7DTQEcjs.isLevel; exports.isoTimestamp = _chunk3FU7DTQEcjs.isoTimestamp; exports.jsonFormatter = _chunk3FU7DTQEcjs.jsonFormatter; exports.jsonReplacer = _chunk3FU7DTQEcjs.jsonReplacer; exports.levelAtLeast = _chunk3FU7DTQEcjs.levelAtLeast; exports.log = _chunk3FU7DTQEcjs.log; exports.mapSink = _chunk3FU7DTQEcjs.mapSink; exports.memorySink = _chunk3FU7DTQEcjs.memorySink; exports.otelBridgeSink = otelBridgeSink; exports.otlpHttpSink = otlpHttpSink; exports.parseLevel = _chunk3FU7DTQEcjs.parseLevel; exports.parseTemplate = _chunk3FU7DTQEcjs.parseTemplate; exports.prettyFormatter = _chunk3FU7DTQEcjs.prettyFormatter; exports.rateLimited = _chunk3FU7DTQEcjs.rateLimited; exports.renderTemplate = _chunk3FU7DTQEcjs.renderTemplate; exports.renderValue = _chunk3FU7DTQEcjs.renderValue; exports.resolveFormatter = _chunk3FU7DTQEcjs.resolveFormatter; exports.resolveLevel = _chunk3FU7DTQEcjs.resolveLevel; exports.resolveStyles = _chunk3FU7DTQEcjs.resolveStyles; exports.restricted = _chunk3FU7DTQEcjs.restricted; exports.sampled = _chunk3FU7DTQEcjs.sampled; exports.selfLog = _chunk3FU7DTQEcjs.selfLog; exports.seqSink = _chunk3FU7DTQEcjs.seqSink; exports.streamSink = _chunk3FU7DTQEcjs.streamSink; exports.templateHash = _chunk3FU7DTQEcjs.templateHash; exports.textFormatter = _chunk3FU7DTQEcjs.textFormatter; exports.toAnyValue = toAnyValue; exports.toJson = _chunk3FU7DTQEcjs.toJson; exports.withComputed = _chunk3FU7DTQEcjs.withComputed; exports.withEnvironment = _chunk3FU7DTQEcjs.withEnvironment; exports.withProperties = _chunk3FU7DTQEcjs.withProperties; exports.withProperty = _chunk3FU7DTQEcjs.withProperty; exports.withTraceContext = _chunk3FU7DTQEcjs.withTraceContext;
|
|
304
|
+
//# sourceMappingURL=otel.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/logit/logit/packages/logit/dist/otel.cjs","../src/otel.ts"],"names":[],"mappings":"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CC,EAAA;AAEjB,EAAA;AACa,IAAA;AACG,MAAA;AACL,MAAA;AACyC,sBAAA;AACnD,MAAA;AACe,QAAA;AACP,UAAA;AACG,UAAA;AACA,UAAA;AACH,UAAA;AACG,UAAA;AACZ,QAAA;AACiB,QAAA;AAClB,MAAA;AACW,QAAA;AACb,MAAA;AACF,IAAA;AACwB,IAAA;AAC1B,EAAA;AACF;AA4BkC;AACP,EAAA;AACC,IAAA;AACC,IAAA;AACH,IAAA;AACF,MAAA;AACT,IAAA;AACU,MAAA;AACI,IAAA;AACJ,MAAA;AACd,IAAA;AACQ,MAAA;AACf,IAAA;AACF,EAAA;AACO,EAAA;AACT;AAO+B;AACP,EAAA;AACH,EAAA;AACO,EAAA;AACF,EAAA;AACjB,EAAA;AACC,IAAA;AACN,IAAA;AACe,IAAA;AACO,IAAA;AAC4B,MAAA;AACzB,MAAA;AACN,MAAA;AACK,QAAA;AAChB,QAAA;AACA,QAAA;AACN,MAAA;AACiB,MAAA;AACD,MAAA;AACG,QAAA;AACE,QAAA;AACH,QAAA;AACF,QAAA;AACF,QAAA;AACA,QAAA;AACb,MAAA;AACH,IAAA;AACF,EAAA;AACF;AD1B6B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/logit/logit/packages/logit/dist/otel.cjs","sourcesContent":[null,"/**\n * `@unhingged/logit/otel` — OpenTelemetry without the SDK:\n *\n * otlpHttpSink() OTLP/HTTP JSON straight to a collector, Grafana,\n * Honeycomb, Datadog, Dash0… (`/v1/logs`), batched.\n * otelBridgeSink() hands events to an OpenTelemetry `LoggerProvider`\n * you already have, structurally typed so this package\n * does not depend on `@opentelemetry/api-logs`.\n *\n * Mapping follows Serilog.Sinks.OpenTelemetry: the rendered message is the\n * body, every property is an attribute of the same name, the template goes\n * in `message_template.text`, the error in `exception.*`.\n */\nimport type { LogEvent } from './event';\nimport { formatError } from './format/text';\nimport type { LogLevel } from './levels';\nimport { type BatchingOptions, type BatchingSink, batchingSink } from './sinks/batching';\nimport type { FetchLike } from './sinks/http';\nimport type { Sink, SinkOptions } from './sinks/types';\n\nexport * from './index';\n\n/** OpenTelemetry severity numbers for the six levels. */\nexport const OTEL_SEVERITY: Readonly<Record<LogLevel, { number: number; text: string }>> = {\n verbose: { 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 fatal: { number: 21, text: 'FATAL' },\n};\n\ntype AnyValue =\n | { stringValue: string }\n | { intValue: string }\n | { doubleValue: number }\n | { boolValue: boolean }\n | { arrayValue: { values: AnyValue[] } }\n | { kvlistValue: { values: KeyValue[] } };\n\ninterface KeyValue {\n key: string;\n value: AnyValue;\n}\n\n/** Encodes a captured value as an OTLP `AnyValue` (the protobuf JSON mapping: int64 as a string). */\nexport function toAnyValue(value: unknown): AnyValue {\n if (value === null || value === undefined) return { stringValue: '' };\n switch (typeof value) {\n case 'string':\n return { stringValue: value };\n case 'number':\n return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };\n case 'boolean':\n return { boolValue: value };\n case 'bigint':\n return { intValue: value.toString() };\n default:\n break;\n }\n if (value instanceof Date) return { stringValue: value.toISOString() };\n if (Array.isArray(value)) return { arrayValue: { values: value.map(toAnyValue) } };\n if (typeof value === 'object') return { kvlistValue: { values: toKeyValues(value as Record<string, unknown>) } };\n return { stringValue: String(value) };\n}\n\nfunction toKeyValues(record: Record<string, unknown>): KeyValue[] {\n return Object.keys(record).map((key) => ({ key, value: toAnyValue(record[key]) }));\n}\n\nexport interface OtlpAttributes {\n [key: string]: unknown;\n}\n\nexport interface OtlpEncodeOptions {\n /** Resource attributes — `service.name` at least. */\n resource?: OtlpAttributes;\n scope?: { name: string; version?: string };\n /** Attribute name for the message template. Default `message_template.text` (Serilog's). `false` to omit. */\n templateAttribute?: string | false;\n}\n\n/** Builds the `ExportLogsServiceRequest` JSON for a batch. */\nexport function encodeOtlpLogs(events: LogEvent[], options: OtlpEncodeOptions = {}): unknown {\n const templateAttribute = options.templateAttribute === undefined ? 'message_template.text' : options.templateAttribute;\n return {\n resourceLogs: [\n {\n resource: { attributes: toKeyValues({ ...options.resource }) },\n scopeLogs: [\n {\n scope: options.scope ?? { name: '@unhingged/logit' },\n logRecords: events.map((event) => {\n const attributes: KeyValue[] = [];\n if (templateAttribute) attributes.push({ key: templateAttribute, value: { stringValue: event.messageTemplate } });\n for (const key of Object.keys(event.properties)) attributes.push({ key, value: toAnyValue(event.properties[key]) });\n if (event.error) {\n attributes.push({ key: 'exception.type', value: { stringValue: event.error.name } });\n attributes.push({ key: 'exception.message', value: { stringValue: event.error.message } });\n attributes.push({ key: 'exception.stacktrace', value: { stringValue: formatError(event.error) } });\n }\n const severity = OTEL_SEVERITY[event.level];\n const nanos = `${event.timestamp.getTime()}000000`;\n return {\n timeUnixNano: nanos,\n observedTimeUnixNano: nanos,\n severityNumber: severity.number,\n severityText: severity.text,\n body: { stringValue: event.renderMessage({ literal: true }) },\n attributes,\n ...(event.traceId ? { traceId: event.traceId } : {}),\n ...(event.spanId ? { spanId: event.spanId } : {}),\n };\n }),\n },\n ],\n },\n ],\n };\n}\n\nexport interface OtlpHttpSinkOptions extends BatchingOptions, OtlpEncodeOptions {\n /** Default `http://localhost:4318/v1/logs`, or `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` / `OTEL_EXPORTER_OTLP_ENDPOINT` + `/v1/logs`. */\n url?: string;\n headers?: Record<string, string>;\n timeout?: number;\n fetch?: FetchLike;\n}\n\nfunction env(name: string): string | undefined {\n return (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env?.[name];\n}\n\n/** `OTEL_EXPORTER_OTLP_HEADERS=\"key=value,key2=value2\"` */\nfunction envHeaders(): Record<string, string> {\n const raw = env('OTEL_EXPORTER_OTLP_LOGS_HEADERS') ?? env('OTEL_EXPORTER_OTLP_HEADERS');\n const out: Record<string, string> = {};\n if (!raw) return out;\n for (const pair of raw.split(',')) {\n const i = pair.indexOf('=');\n if (i > 0) out[pair.slice(0, i).trim()] = decodeURIComponent(pair.slice(i + 1).trim());\n }\n return out;\n}\n\n/** OTLP/HTTP JSON to `/v1/logs`. Honours the standard `OTEL_EXPORTER_OTLP_*` variables. */\nexport function otlpHttpSink(options: OtlpHttpSinkOptions = {}): BatchingSink {\n const fetchImpl: FetchLike = options.fetch ?? ((globalThis as { fetch?: FetchLike }).fetch as FetchLike);\n if (!fetchImpl) throw new Error('logit: otlpHttpSink needs fetch — pass one in options.fetch');\n const url = options.url ?? env('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT') ?? `${(env('OTEL_EXPORTER_OTLP_ENDPOINT') ?? 'http://localhost:4318').replace(/\\/$/, '')}/v1/logs`;\n const serviceName = env('OTEL_SERVICE_NAME');\n const resource = { ...(serviceName ? { 'service.name': serviceName } : {}), ...options.resource };\n const timeout = options.timeout ?? 10_000;\n\n return batchingSink(\n async (events) => {\n const controller = typeof AbortController === 'function' ? new AbortController() : undefined;\n const timer = controller ? setTimeout(() => controller.abort(), timeout) : undefined;\n (timer as { unref?: () => void } | undefined)?.unref?.();\n try {\n const response = await fetchImpl(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...envHeaders(), ...options.headers },\n body: JSON.stringify(encodeOtlpLogs(events, { ...options, resource })),\n signal: controller?.signal,\n keepalive: true,\n });\n if (!response.ok) throw new Error(`OTLP export failed: HTTP ${response.status}`);\n } finally {\n if (timer) clearTimeout(timer);\n }\n },\n { name: `otlp(${url})`, ...options },\n );\n}\n\n/** The slice of `@opentelemetry/api-logs` we call — structural on purpose. */\nexport interface OtelLogRecord {\n timestamp?: number | Date;\n observedTimestamp?: number | Date;\n severityNumber?: number;\n severityText?: string;\n body?: string;\n attributes?: Record<string, unknown>;\n}\n\nexport interface OtelLogger {\n emit(record: OtelLogRecord): void;\n}\n\nexport interface OtelLoggerProvider {\n getLogger(name: string, version?: string, options?: unknown): OtelLogger;\n}\n\nexport interface OtelBridgeOptions extends SinkOptions {\n scope?: { name: string; version?: string };\n templateAttribute?: string | false;\n /** OpenTelemetry attributes are flat: nested objects are flattened with dots (`user.id`). Default true; `false` passes them through. */\n flatten?: boolean;\n}\n\n/** Flattens nested objects into dotted keys for the OTel attributes API. */\nexport function flattenAttributes(record: Record<string, unknown>, prefix = '', into: Record<string, unknown> = {}): Record<string, unknown> {\n for (const key of Object.keys(record)) {\n const value = record[key];\n const name = prefix ? `${prefix}.${key}` : key;\n if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {\n flattenAttributes(value as Record<string, unknown>, name, into);\n } else if (value instanceof Date) {\n into[name] = value.toISOString();\n } else if (Array.isArray(value)) {\n into[name] = value.every((v) => v === null || ['string', 'number', 'boolean'].includes(typeof v)) ? value : JSON.stringify(value);\n } else {\n into[name] = value as unknown;\n }\n }\n return into;\n}\n\n/**\n * Hands each event to `provider.getLogger(scope)` — use it when the OTel SDK\n * is already set up (`logs.getLoggerProvider()`), so trace context, resource\n * and exporters are all the SDK's.\n */\nexport function otelBridgeSink(provider: OtelLoggerProvider, options: OtelBridgeOptions = {}): Sink {\n const scope = options.scope ?? { name: '@unhingged/logit' };\n const otelLogger = provider.getLogger(scope.name, scope.version);\n const templateAttribute = options.templateAttribute === undefined ? 'message_template.text' : options.templateAttribute;\n const flatten = options.flatten ?? true;\n return {\n name: 'otel-bridge',\n restrictedToMinimumLevel: options.restrictedToMinimumLevel,\n audit: options.audit,\n emit(event: LogEvent) {\n const raw: Record<string, unknown> = { ...event.properties };\n if (templateAttribute) raw[templateAttribute] = event.messageTemplate;\n if (event.error) {\n raw['exception.type'] = event.error.name;\n raw['exception.message'] = event.error.message;\n raw['exception.stacktrace'] = formatError(event.error);\n }\n const severity = OTEL_SEVERITY[event.level];\n otelLogger.emit({\n timestamp: event.timestamp,\n observedTimestamp: event.timestamp,\n severityNumber: severity.number,\n severityText: severity.text,\n body: event.renderMessage({ literal: true }),\n attributes: flatten ? flattenAttributes(raw) : raw,\n });\n },\n };\n}\n"]}
|
package/dist/otel.d.cts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { LogLevel, SinkOptions, BatchingOptions, FetchLike, LogEvent, Sink, BatchingSink } from './index.cjs';
|
|
2
|
+
export { CLEF_MEDIA_TYPE, CapturedError, ClefFormatterOptions, ConsoleSinkOptions, ContextFrame, ContextHandle, ContextStore, DEFAULT_DESTRUCTURING, DEFAULT_OUTPUT_TEMPLATE, DestructuringOptions, DestructuringPolicy, Enricher, Filter, FormatName, Formatter, HoleToken, HttpSinkOptions, JsonFormatterOptions, LEVELS, LEVEL_CODES, LEVEL_NUMBERS, LEVEL_ORDER, LevelOrSwitch, LevelSwitch, LogContext, LogEventInit, LogMethod, Logger, LoggerConfiguration, LoggerOptions, MapSinkOptions, Matching, MemorySink, MessageTemplate, Operation, OperationOptions, PrettyFormatterOptions, RenderOptions, SERILOG_LEVEL_NAMES, SeqSinkOptions, StreamLike, StreamSinkOptions, TemplateToken, TextFormatterOptions, TextToken, TraceContext, ValueStyles, ansi, audit, batchingSink, byExcluding, byIncludingOnly, byTransforming, callbackSink, captureError, captureProperty, captureValue, clefFormatter, closeAndFlush, conditional, configure, consoleSink, createLogger, detectColors, diagnosticContext, formatDate, formatError, formatLevel, formatNumber, fromLogContext, httpSink, isLevel, isoTimestamp, jsonFormatter, jsonReplacer, levelAtLeast, log, mapSink, memorySink, parseLevel, parseTemplate, prettyFormatter, rateLimited, renderTemplate, renderValue, resolveFormatter, resolveLevel, resolveStyles, restricted, sampled, selfLog, seqSink, streamSink, templateHash, textFormatter, toJson, withComputed, withEnvironment, withProperties, withProperty, withTraceContext } from './index.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@unhingged/logit/otel` — OpenTelemetry without the SDK:
|
|
6
|
+
*
|
|
7
|
+
* otlpHttpSink() OTLP/HTTP JSON straight to a collector, Grafana,
|
|
8
|
+
* Honeycomb, Datadog, Dash0… (`/v1/logs`), batched.
|
|
9
|
+
* otelBridgeSink() hands events to an OpenTelemetry `LoggerProvider`
|
|
10
|
+
* you already have, structurally typed so this package
|
|
11
|
+
* does not depend on `@opentelemetry/api-logs`.
|
|
12
|
+
*
|
|
13
|
+
* Mapping follows Serilog.Sinks.OpenTelemetry: the rendered message is the
|
|
14
|
+
* body, every property is an attribute of the same name, the template goes
|
|
15
|
+
* in `message_template.text`, the error in `exception.*`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** OpenTelemetry severity numbers for the six levels. */
|
|
19
|
+
declare const OTEL_SEVERITY: Readonly<Record<LogLevel, {
|
|
20
|
+
number: number;
|
|
21
|
+
text: string;
|
|
22
|
+
}>>;
|
|
23
|
+
type AnyValue = {
|
|
24
|
+
stringValue: string;
|
|
25
|
+
} | {
|
|
26
|
+
intValue: string;
|
|
27
|
+
} | {
|
|
28
|
+
doubleValue: number;
|
|
29
|
+
} | {
|
|
30
|
+
boolValue: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
arrayValue: {
|
|
33
|
+
values: AnyValue[];
|
|
34
|
+
};
|
|
35
|
+
} | {
|
|
36
|
+
kvlistValue: {
|
|
37
|
+
values: KeyValue[];
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
interface KeyValue {
|
|
41
|
+
key: string;
|
|
42
|
+
value: AnyValue;
|
|
43
|
+
}
|
|
44
|
+
/** Encodes a captured value as an OTLP `AnyValue` (the protobuf JSON mapping: int64 as a string). */
|
|
45
|
+
declare function toAnyValue(value: unknown): AnyValue;
|
|
46
|
+
interface OtlpAttributes {
|
|
47
|
+
[key: string]: unknown;
|
|
48
|
+
}
|
|
49
|
+
interface OtlpEncodeOptions {
|
|
50
|
+
/** Resource attributes — `service.name` at least. */
|
|
51
|
+
resource?: OtlpAttributes;
|
|
52
|
+
scope?: {
|
|
53
|
+
name: string;
|
|
54
|
+
version?: string;
|
|
55
|
+
};
|
|
56
|
+
/** Attribute name for the message template. Default `message_template.text` (Serilog's). `false` to omit. */
|
|
57
|
+
templateAttribute?: string | false;
|
|
58
|
+
}
|
|
59
|
+
/** Builds the `ExportLogsServiceRequest` JSON for a batch. */
|
|
60
|
+
declare function encodeOtlpLogs(events: LogEvent[], options?: OtlpEncodeOptions): unknown;
|
|
61
|
+
interface OtlpHttpSinkOptions extends BatchingOptions, OtlpEncodeOptions {
|
|
62
|
+
/** Default `http://localhost:4318/v1/logs`, or `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` / `OTEL_EXPORTER_OTLP_ENDPOINT` + `/v1/logs`. */
|
|
63
|
+
url?: string;
|
|
64
|
+
headers?: Record<string, string>;
|
|
65
|
+
timeout?: number;
|
|
66
|
+
fetch?: FetchLike;
|
|
67
|
+
}
|
|
68
|
+
/** OTLP/HTTP JSON to `/v1/logs`. Honours the standard `OTEL_EXPORTER_OTLP_*` variables. */
|
|
69
|
+
declare function otlpHttpSink(options?: OtlpHttpSinkOptions): BatchingSink;
|
|
70
|
+
/** The slice of `@opentelemetry/api-logs` we call — structural on purpose. */
|
|
71
|
+
interface OtelLogRecord {
|
|
72
|
+
timestamp?: number | Date;
|
|
73
|
+
observedTimestamp?: number | Date;
|
|
74
|
+
severityNumber?: number;
|
|
75
|
+
severityText?: string;
|
|
76
|
+
body?: string;
|
|
77
|
+
attributes?: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
interface OtelLogger {
|
|
80
|
+
emit(record: OtelLogRecord): void;
|
|
81
|
+
}
|
|
82
|
+
interface OtelLoggerProvider {
|
|
83
|
+
getLogger(name: string, version?: string, options?: unknown): OtelLogger;
|
|
84
|
+
}
|
|
85
|
+
interface OtelBridgeOptions extends SinkOptions {
|
|
86
|
+
scope?: {
|
|
87
|
+
name: string;
|
|
88
|
+
version?: string;
|
|
89
|
+
};
|
|
90
|
+
templateAttribute?: string | false;
|
|
91
|
+
/** OpenTelemetry attributes are flat: nested objects are flattened with dots (`user.id`). Default true; `false` passes them through. */
|
|
92
|
+
flatten?: boolean;
|
|
93
|
+
}
|
|
94
|
+
/** Flattens nested objects into dotted keys for the OTel attributes API. */
|
|
95
|
+
declare function flattenAttributes(record: Record<string, unknown>, prefix?: string, into?: Record<string, unknown>): Record<string, unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* Hands each event to `provider.getLogger(scope)` — use it when the OTel SDK
|
|
98
|
+
* is already set up (`logs.getLoggerProvider()`), so trace context, resource
|
|
99
|
+
* and exporters are all the SDK's.
|
|
100
|
+
*/
|
|
101
|
+
declare function otelBridgeSink(provider: OtelLoggerProvider, options?: OtelBridgeOptions): Sink;
|
|
102
|
+
|
|
103
|
+
export { BatchingOptions, BatchingSink, FetchLike, LogEvent, LogLevel, OTEL_SEVERITY, type OtelBridgeOptions, type OtelLogRecord, type OtelLogger, type OtelLoggerProvider, type OtlpAttributes, type OtlpEncodeOptions, type OtlpHttpSinkOptions, Sink, SinkOptions, encodeOtlpLogs, flattenAttributes, otelBridgeSink, otlpHttpSink, toAnyValue };
|
package/dist/otel.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { LogLevel, SinkOptions, BatchingOptions, FetchLike, LogEvent, Sink, BatchingSink } from './index.js';
|
|
2
|
+
export { CLEF_MEDIA_TYPE, CapturedError, ClefFormatterOptions, ConsoleSinkOptions, ContextFrame, ContextHandle, ContextStore, DEFAULT_DESTRUCTURING, DEFAULT_OUTPUT_TEMPLATE, DestructuringOptions, DestructuringPolicy, Enricher, Filter, FormatName, Formatter, HoleToken, HttpSinkOptions, JsonFormatterOptions, LEVELS, LEVEL_CODES, LEVEL_NUMBERS, LEVEL_ORDER, LevelOrSwitch, LevelSwitch, LogContext, LogEventInit, LogMethod, Logger, LoggerConfiguration, LoggerOptions, MapSinkOptions, Matching, MemorySink, MessageTemplate, Operation, OperationOptions, PrettyFormatterOptions, RenderOptions, SERILOG_LEVEL_NAMES, SeqSinkOptions, StreamLike, StreamSinkOptions, TemplateToken, TextFormatterOptions, TextToken, TraceContext, ValueStyles, ansi, audit, batchingSink, byExcluding, byIncludingOnly, byTransforming, callbackSink, captureError, captureProperty, captureValue, clefFormatter, closeAndFlush, conditional, configure, consoleSink, createLogger, detectColors, diagnosticContext, formatDate, formatError, formatLevel, formatNumber, fromLogContext, httpSink, isLevel, isoTimestamp, jsonFormatter, jsonReplacer, levelAtLeast, log, mapSink, memorySink, parseLevel, parseTemplate, prettyFormatter, rateLimited, renderTemplate, renderValue, resolveFormatter, resolveLevel, resolveStyles, restricted, sampled, selfLog, seqSink, streamSink, templateHash, textFormatter, toJson, withComputed, withEnvironment, withProperties, withProperty, withTraceContext } from './index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@unhingged/logit/otel` — OpenTelemetry without the SDK:
|
|
6
|
+
*
|
|
7
|
+
* otlpHttpSink() OTLP/HTTP JSON straight to a collector, Grafana,
|
|
8
|
+
* Honeycomb, Datadog, Dash0… (`/v1/logs`), batched.
|
|
9
|
+
* otelBridgeSink() hands events to an OpenTelemetry `LoggerProvider`
|
|
10
|
+
* you already have, structurally typed so this package
|
|
11
|
+
* does not depend on `@opentelemetry/api-logs`.
|
|
12
|
+
*
|
|
13
|
+
* Mapping follows Serilog.Sinks.OpenTelemetry: the rendered message is the
|
|
14
|
+
* body, every property is an attribute of the same name, the template goes
|
|
15
|
+
* in `message_template.text`, the error in `exception.*`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** OpenTelemetry severity numbers for the six levels. */
|
|
19
|
+
declare const OTEL_SEVERITY: Readonly<Record<LogLevel, {
|
|
20
|
+
number: number;
|
|
21
|
+
text: string;
|
|
22
|
+
}>>;
|
|
23
|
+
type AnyValue = {
|
|
24
|
+
stringValue: string;
|
|
25
|
+
} | {
|
|
26
|
+
intValue: string;
|
|
27
|
+
} | {
|
|
28
|
+
doubleValue: number;
|
|
29
|
+
} | {
|
|
30
|
+
boolValue: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
arrayValue: {
|
|
33
|
+
values: AnyValue[];
|
|
34
|
+
};
|
|
35
|
+
} | {
|
|
36
|
+
kvlistValue: {
|
|
37
|
+
values: KeyValue[];
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
interface KeyValue {
|
|
41
|
+
key: string;
|
|
42
|
+
value: AnyValue;
|
|
43
|
+
}
|
|
44
|
+
/** Encodes a captured value as an OTLP `AnyValue` (the protobuf JSON mapping: int64 as a string). */
|
|
45
|
+
declare function toAnyValue(value: unknown): AnyValue;
|
|
46
|
+
interface OtlpAttributes {
|
|
47
|
+
[key: string]: unknown;
|
|
48
|
+
}
|
|
49
|
+
interface OtlpEncodeOptions {
|
|
50
|
+
/** Resource attributes — `service.name` at least. */
|
|
51
|
+
resource?: OtlpAttributes;
|
|
52
|
+
scope?: {
|
|
53
|
+
name: string;
|
|
54
|
+
version?: string;
|
|
55
|
+
};
|
|
56
|
+
/** Attribute name for the message template. Default `message_template.text` (Serilog's). `false` to omit. */
|
|
57
|
+
templateAttribute?: string | false;
|
|
58
|
+
}
|
|
59
|
+
/** Builds the `ExportLogsServiceRequest` JSON for a batch. */
|
|
60
|
+
declare function encodeOtlpLogs(events: LogEvent[], options?: OtlpEncodeOptions): unknown;
|
|
61
|
+
interface OtlpHttpSinkOptions extends BatchingOptions, OtlpEncodeOptions {
|
|
62
|
+
/** Default `http://localhost:4318/v1/logs`, or `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` / `OTEL_EXPORTER_OTLP_ENDPOINT` + `/v1/logs`. */
|
|
63
|
+
url?: string;
|
|
64
|
+
headers?: Record<string, string>;
|
|
65
|
+
timeout?: number;
|
|
66
|
+
fetch?: FetchLike;
|
|
67
|
+
}
|
|
68
|
+
/** OTLP/HTTP JSON to `/v1/logs`. Honours the standard `OTEL_EXPORTER_OTLP_*` variables. */
|
|
69
|
+
declare function otlpHttpSink(options?: OtlpHttpSinkOptions): BatchingSink;
|
|
70
|
+
/** The slice of `@opentelemetry/api-logs` we call — structural on purpose. */
|
|
71
|
+
interface OtelLogRecord {
|
|
72
|
+
timestamp?: number | Date;
|
|
73
|
+
observedTimestamp?: number | Date;
|
|
74
|
+
severityNumber?: number;
|
|
75
|
+
severityText?: string;
|
|
76
|
+
body?: string;
|
|
77
|
+
attributes?: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
interface OtelLogger {
|
|
80
|
+
emit(record: OtelLogRecord): void;
|
|
81
|
+
}
|
|
82
|
+
interface OtelLoggerProvider {
|
|
83
|
+
getLogger(name: string, version?: string, options?: unknown): OtelLogger;
|
|
84
|
+
}
|
|
85
|
+
interface OtelBridgeOptions extends SinkOptions {
|
|
86
|
+
scope?: {
|
|
87
|
+
name: string;
|
|
88
|
+
version?: string;
|
|
89
|
+
};
|
|
90
|
+
templateAttribute?: string | false;
|
|
91
|
+
/** OpenTelemetry attributes are flat: nested objects are flattened with dots (`user.id`). Default true; `false` passes them through. */
|
|
92
|
+
flatten?: boolean;
|
|
93
|
+
}
|
|
94
|
+
/** Flattens nested objects into dotted keys for the OTel attributes API. */
|
|
95
|
+
declare function flattenAttributes(record: Record<string, unknown>, prefix?: string, into?: Record<string, unknown>): Record<string, unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* Hands each event to `provider.getLogger(scope)` — use it when the OTel SDK
|
|
98
|
+
* is already set up (`logs.getLoggerProvider()`), so trace context, resource
|
|
99
|
+
* and exporters are all the SDK's.
|
|
100
|
+
*/
|
|
101
|
+
declare function otelBridgeSink(provider: OtelLoggerProvider, options?: OtelBridgeOptions): Sink;
|
|
102
|
+
|
|
103
|
+
export { BatchingOptions, BatchingSink, FetchLike, LogEvent, LogLevel, OTEL_SEVERITY, type OtelBridgeOptions, type OtelLogRecord, type OtelLogger, type OtelLoggerProvider, type OtlpAttributes, type OtlpEncodeOptions, type OtlpHttpSinkOptions, Sink, SinkOptions, encodeOtlpLogs, flattenAttributes, otelBridgeSink, otlpHttpSink, toAnyValue };
|