@payloops/observability 0.0.9 → 0.0.11
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/dist/index.d.ts +20 -8
- package/dist/index.js +99 -86
- package/package.json +2 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
2
|
-
import pino from 'pino';
|
|
3
2
|
import * as _opentelemetry_api from '@opentelemetry/api';
|
|
4
3
|
|
|
5
4
|
interface TelemetryConfig {
|
|
@@ -16,24 +15,37 @@ interface TelemetryConfig {
|
|
|
16
15
|
declare function initTelemetry(config: TelemetryConfig | string, serviceVersion?: string): NodeSDK;
|
|
17
16
|
declare function shutdownTelemetry(): Promise<void>;
|
|
18
17
|
|
|
18
|
+
interface Logger {
|
|
19
|
+
trace(msg: string): void;
|
|
20
|
+
trace(data: Record<string, unknown>, msg: string): void;
|
|
21
|
+
debug(msg: string): void;
|
|
22
|
+
debug(data: Record<string, unknown>, msg: string): void;
|
|
23
|
+
info(msg: string): void;
|
|
24
|
+
info(data: Record<string, unknown>, msg: string): void;
|
|
25
|
+
warn(msg: string): void;
|
|
26
|
+
warn(data: Record<string, unknown>, msg: string): void;
|
|
27
|
+
error(msg: string): void;
|
|
28
|
+
error(data: Record<string, unknown>, msg: string): void;
|
|
29
|
+
fatal(msg: string): void;
|
|
30
|
+
fatal(data: Record<string, unknown>, msg: string): void;
|
|
31
|
+
child(bindings: Record<string, unknown>): Logger;
|
|
32
|
+
}
|
|
19
33
|
/**
|
|
20
|
-
* Base logger
|
|
21
|
-
* In development: pretty print to console + OTLP
|
|
22
|
-
* In production: JSON to stdout + OTLP
|
|
34
|
+
* Base logger instance
|
|
23
35
|
*/
|
|
24
|
-
declare const logger:
|
|
36
|
+
declare const logger: Logger;
|
|
25
37
|
/**
|
|
26
38
|
* Create a child logger for a specific activity
|
|
27
39
|
*/
|
|
28
|
-
declare function createActivityLogger(activityName: string, correlationId?: string):
|
|
40
|
+
declare function createActivityLogger(activityName: string, correlationId?: string): Logger;
|
|
29
41
|
/**
|
|
30
42
|
* Create a child logger for a specific workflow
|
|
31
43
|
*/
|
|
32
|
-
declare function createWorkflowLogger(workflowId: string, correlationId?: string):
|
|
44
|
+
declare function createWorkflowLogger(workflowId: string, correlationId?: string): Logger;
|
|
33
45
|
/**
|
|
34
46
|
* Create a child logger for HTTP requests
|
|
35
47
|
*/
|
|
36
|
-
declare function createRequestLogger(requestId: string, method: string, path: string):
|
|
48
|
+
declare function createRequestLogger(requestId: string, method: string, path: string): Logger;
|
|
37
49
|
|
|
38
50
|
/**
|
|
39
51
|
* Correlation context for tracking requests across services
|
package/dist/index.js
CHANGED
|
@@ -284,9 +284,8 @@ function shutdownTelemetry() {
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
// src/lib/logger.ts
|
|
287
|
-
import pino from "pino";
|
|
288
287
|
import { trace } from "@opentelemetry/api";
|
|
289
|
-
import { logs as logs2, SeverityNumber
|
|
288
|
+
import { logs as logs2, SeverityNumber } from "@opentelemetry/api-logs";
|
|
290
289
|
|
|
291
290
|
// src/lib/context.ts
|
|
292
291
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -333,38 +332,44 @@ function createContextFromMemo(memo) {
|
|
|
333
332
|
// src/lib/logger.ts
|
|
334
333
|
var NODE_ENV = process.env.NODE_ENV || "development";
|
|
335
334
|
var SERVICE_NAME = process.env.OTEL_SERVICE_NAME || "loop";
|
|
336
|
-
var
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
// error
|
|
347
|
-
60: SeverityNumber2.FATAL
|
|
348
|
-
// fatal
|
|
335
|
+
var LOG_LEVEL = process.env.LOG_LEVEL || (NODE_ENV === "production" ? "info" : "debug");
|
|
336
|
+
var colors = {
|
|
337
|
+
reset: "\x1B[0m",
|
|
338
|
+
dim: "\x1B[2m",
|
|
339
|
+
red: "\x1B[31m",
|
|
340
|
+
green: "\x1B[32m",
|
|
341
|
+
yellow: "\x1B[33m",
|
|
342
|
+
blue: "\x1B[34m",
|
|
343
|
+
magenta: "\x1B[35m",
|
|
344
|
+
cyan: "\x1B[36m"
|
|
349
345
|
};
|
|
350
|
-
var
|
|
351
|
-
|
|
346
|
+
var levelConfig = {
|
|
347
|
+
trace: { severity: SeverityNumber.TRACE, color: colors.dim, label: "TRACE", priority: 0 },
|
|
348
|
+
debug: { severity: SeverityNumber.DEBUG, color: colors.blue, label: "DEBUG", priority: 1 },
|
|
349
|
+
info: { severity: SeverityNumber.INFO, color: colors.green, label: "INFO", priority: 2 },
|
|
350
|
+
warn: { severity: SeverityNumber.WARN, color: colors.yellow, label: "WARN", priority: 3 },
|
|
351
|
+
error: { severity: SeverityNumber.ERROR, color: colors.red, label: "ERROR", priority: 4 },
|
|
352
|
+
fatal: { severity: SeverityNumber.FATAL, color: colors.magenta, label: "FATAL", priority: 5 }
|
|
353
|
+
};
|
|
354
|
+
var currentLevelPriority = levelConfig[LOG_LEVEL]?.priority ?? 2;
|
|
355
|
+
function getContext() {
|
|
356
|
+
const ctx = {};
|
|
352
357
|
const span = trace.getActiveSpan();
|
|
353
358
|
if (span) {
|
|
354
359
|
const spanContext = span.spanContext();
|
|
355
|
-
|
|
356
|
-
|
|
360
|
+
ctx.trace_id = spanContext.traceId;
|
|
361
|
+
ctx.span_id = spanContext.spanId;
|
|
357
362
|
}
|
|
358
363
|
const correlationCtx = getCorrelationContext();
|
|
359
364
|
if (correlationCtx) {
|
|
360
|
-
|
|
361
|
-
if (correlationCtx.merchantId)
|
|
362
|
-
if (correlationCtx.orderId)
|
|
363
|
-
if (correlationCtx.workflowId)
|
|
365
|
+
ctx.correlation_id = correlationCtx.correlationId;
|
|
366
|
+
if (correlationCtx.merchantId) ctx.merchant_id = correlationCtx.merchantId;
|
|
367
|
+
if (correlationCtx.orderId) ctx.order_id = correlationCtx.orderId;
|
|
368
|
+
if (correlationCtx.workflowId) ctx.workflow_id = correlationCtx.workflowId;
|
|
364
369
|
}
|
|
365
|
-
return
|
|
366
|
-
}
|
|
367
|
-
function emitToOtel(
|
|
370
|
+
return ctx;
|
|
371
|
+
}
|
|
372
|
+
function emitToOtel(level, message, attributes) {
|
|
368
373
|
try {
|
|
369
374
|
const provider = logs2.getLoggerProvider();
|
|
370
375
|
if (provider.constructor.name === "ProxyLoggerProvider") {
|
|
@@ -373,18 +378,17 @@ function emitToOtel(logRecord) {
|
|
|
373
378
|
const otelLogger = provider.getLogger(SERVICE_NAME);
|
|
374
379
|
const span = trace.getActiveSpan();
|
|
375
380
|
const spanContext = span?.spanContext();
|
|
381
|
+
const config = levelConfig[level];
|
|
376
382
|
otelLogger.emit({
|
|
377
|
-
severityNumber:
|
|
378
|
-
severityText:
|
|
379
|
-
body:
|
|
383
|
+
severityNumber: config?.severity ?? SeverityNumber.INFO,
|
|
384
|
+
severityText: config?.label ?? "INFO",
|
|
385
|
+
body: message,
|
|
380
386
|
attributes: {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
level: void 0,
|
|
385
|
-
time: void 0
|
|
387
|
+
service: SERVICE_NAME,
|
|
388
|
+
env: NODE_ENV,
|
|
389
|
+
...attributes
|
|
386
390
|
},
|
|
387
|
-
timestamp:
|
|
391
|
+
timestamp: Date.now() * 1e6,
|
|
388
392
|
// nanoseconds
|
|
389
393
|
...spanContext && {
|
|
390
394
|
spanId: spanContext.spanId,
|
|
@@ -395,65 +399,74 @@ function emitToOtel(logRecord) {
|
|
|
395
399
|
} catch {
|
|
396
400
|
}
|
|
397
401
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
402
|
+
function formatConsole(level, message, data) {
|
|
403
|
+
const config = levelConfig[level];
|
|
404
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
405
|
+
const color = config?.color ?? colors.reset;
|
|
406
|
+
const label = config?.label ?? level.toUpperCase();
|
|
407
|
+
if (NODE_ENV === "production") {
|
|
408
|
+
return JSON.stringify({
|
|
409
|
+
time: timestamp,
|
|
410
|
+
level: label,
|
|
411
|
+
msg: message,
|
|
405
412
|
service: SERVICE_NAME,
|
|
406
|
-
env: NODE_ENV
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
Object.assign(logRecord, objOrMsg);
|
|
410
|
-
logRecord.msg = msgOrUndefined || "";
|
|
411
|
-
} else {
|
|
412
|
-
logRecord.msg = objOrMsg;
|
|
413
|
-
}
|
|
414
|
-
Object.assign(logRecord, traceMixin());
|
|
415
|
-
emitToOtel(logRecord);
|
|
413
|
+
env: NODE_ENV,
|
|
414
|
+
...data
|
|
415
|
+
});
|
|
416
416
|
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
{
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
417
|
+
const timeStr = `${colors.dim}[${timestamp.split("T")[1].slice(0, -1)}]${colors.reset}`;
|
|
418
|
+
const levelStr = `${color}${label.padEnd(5)}${colors.reset}`;
|
|
419
|
+
const msgStr = `${color}${message}${colors.reset}`;
|
|
420
|
+
const dataEntries = Object.entries(data).filter(([, v]) => v !== void 0);
|
|
421
|
+
const dataStr = dataEntries.length > 0 ? "\n" + dataEntries.map(([k, v]) => ` ${colors.magenta}${k}${colors.reset}: ${JSON.stringify(v)}`).join("\n") : "";
|
|
422
|
+
return `${timeStr} ${levelStr}: ${msgStr}${dataStr}`;
|
|
423
|
+
}
|
|
424
|
+
function log(level, msgOrData, msg) {
|
|
425
|
+
const config = levelConfig[level];
|
|
426
|
+
if (!config || config.priority < currentLevelPriority) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
let message;
|
|
430
|
+
let data;
|
|
431
|
+
if (typeof msgOrData === "string") {
|
|
432
|
+
message = msgOrData;
|
|
433
|
+
data = {};
|
|
434
|
+
} else {
|
|
435
|
+
message = msg ?? "";
|
|
436
|
+
data = msgOrData;
|
|
437
|
+
}
|
|
438
|
+
const context2 = getContext();
|
|
439
|
+
const enrichedData = { ...data, ...context2 };
|
|
440
|
+
console.log(formatConsole(level, message, enrichedData));
|
|
441
|
+
emitToOtel(level, message, enrichedData);
|
|
442
|
+
}
|
|
443
|
+
function createLogger(bindings = {}) {
|
|
444
|
+
const boundLog = (level, msgOrData, msg) => {
|
|
445
|
+
if (typeof msgOrData === "string") {
|
|
446
|
+
log(level, { ...bindings }, msgOrData);
|
|
447
|
+
} else {
|
|
448
|
+
log(level, { ...bindings, ...msgOrData }, msg);
|
|
434
449
|
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
)
|
|
450
|
+
};
|
|
451
|
+
return {
|
|
452
|
+
trace: (msgOrData, msg) => boundLog("trace", msgOrData, msg),
|
|
453
|
+
debug: (msgOrData, msg) => boundLog("debug", msgOrData, msg),
|
|
454
|
+
info: (msgOrData, msg) => boundLog("info", msgOrData, msg),
|
|
455
|
+
warn: (msgOrData, msg) => boundLog("warn", msgOrData, msg),
|
|
456
|
+
error: (msgOrData, msg) => boundLog("error", msgOrData, msg),
|
|
457
|
+
fatal: (msgOrData, msg) => boundLog("fatal", msgOrData, msg),
|
|
458
|
+
child: (childBindings) => createLogger({ ...bindings, ...childBindings })
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
var logger = createLogger({ service: SERVICE_NAME, env: NODE_ENV });
|
|
439
462
|
function createActivityLogger(activityName, correlationId) {
|
|
440
|
-
return logger.child({
|
|
441
|
-
activity: activityName,
|
|
442
|
-
correlationId
|
|
443
|
-
});
|
|
463
|
+
return logger.child({ activity: activityName, correlationId });
|
|
444
464
|
}
|
|
445
465
|
function createWorkflowLogger(workflowId, correlationId) {
|
|
446
|
-
return logger.child({
|
|
447
|
-
workflowId,
|
|
448
|
-
correlationId
|
|
449
|
-
});
|
|
466
|
+
return logger.child({ workflowId, correlationId });
|
|
450
467
|
}
|
|
451
468
|
function createRequestLogger(requestId, method, path) {
|
|
452
|
-
return logger.child({
|
|
453
|
-
requestId,
|
|
454
|
-
method,
|
|
455
|
-
path
|
|
456
|
-
});
|
|
469
|
+
return logger.child({ requestId, method, path });
|
|
457
470
|
}
|
|
458
471
|
|
|
459
472
|
// src/lib/metrics.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloops/observability",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,14 +36,12 @@
|
|
|
36
36
|
"@opentelemetry/sdk-metrics": "^1.30.1",
|
|
37
37
|
"@opentelemetry/sdk-node": "^0.57.0",
|
|
38
38
|
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
39
|
-
"nanoid": "^5.0.9"
|
|
40
|
-
"pino": "^9.6.0"
|
|
39
|
+
"nanoid": "^5.0.9"
|
|
41
40
|
},
|
|
42
41
|
"devDependencies": {
|
|
43
42
|
"@eslint/js": "^9.39.2",
|
|
44
43
|
"@types/node": "^22.0.0",
|
|
45
44
|
"eslint": "^9.0.0",
|
|
46
|
-
"pino-pretty": "^13.0.0",
|
|
47
45
|
"tsup": "^8.3.5",
|
|
48
46
|
"typescript": "^5.9.3",
|
|
49
47
|
"typescript-eslint": "^8.53.0"
|