@contrail/telemetry 2.0.8 → 2.0.9-alpha-formatting.1

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.
@@ -2,7 +2,7 @@ import pino from 'pino';
2
2
  export { parseOtelResourceAttributes } from './parse-otel-resource-attributes';
3
3
  export { PINO_LEVEL_TO_OTEL_SEVERITY, PINO_LEVEL_TO_NAME } from './logger-config';
4
4
  export { ATTR_LOG_MESSAGE, ATTR_LOG_BODY, ATTR_LOG_PAYLOAD } from './semantic-conventions';
5
- export { loggerStorage, withLogAttributes } from './log-context';
5
+ export { loggerStorage, withLogAttributes, withLogContext } from './log-context';
6
6
  export declare const baseLogger: pino.Logger<never, boolean>;
7
7
  export declare const logger: pino.Logger;
8
8
  /**
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  var _a, _b, _c, _d, _e, _f, _g;
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.logger = exports.baseLogger = exports.withLogAttributes = exports.loggerStorage = exports.ATTR_LOG_PAYLOAD = exports.ATTR_LOG_BODY = exports.ATTR_LOG_MESSAGE = exports.PINO_LEVEL_TO_NAME = exports.PINO_LEVEL_TO_OTEL_SEVERITY = exports.parseOtelResourceAttributes = void 0;
7
+ exports.logger = exports.baseLogger = exports.withLogContext = exports.withLogAttributes = exports.loggerStorage = exports.ATTR_LOG_PAYLOAD = exports.ATTR_LOG_BODY = exports.ATTR_LOG_MESSAGE = exports.PINO_LEVEL_TO_NAME = exports.PINO_LEVEL_TO_OTEL_SEVERITY = exports.parseOtelResourceAttributes = void 0;
8
8
  exports.addStream = addStream;
9
9
  exports.flushLogs = flushLogs;
10
10
  const pino_1 = __importDefault(require("pino"));
@@ -33,6 +33,7 @@ Object.defineProperty(exports, "ATTR_LOG_PAYLOAD", { enumerable: true, get: func
33
33
  var log_context_1 = require("./log-context");
34
34
  Object.defineProperty(exports, "loggerStorage", { enumerable: true, get: function () { return log_context_1.loggerStorage; } });
35
35
  Object.defineProperty(exports, "withLogAttributes", { enumerable: true, get: function () { return log_context_1.withLogAttributes; } });
36
+ Object.defineProperty(exports, "withLogContext", { enumerable: true, get: function () { return log_context_1.withLogContext; } });
36
37
  // --- Singleton Guard ---
37
38
  // The logger uses AsyncLocalStorage for request context propagation. If two copies
38
39
  // of this module are loaded (e.g. due to a version mismatch causing npm to install
@@ -58,6 +59,11 @@ if (globalRecord[TELEMETRY_SINGLETON_KEY]) {
58
59
  else {
59
60
  globalRecord[TELEMETRY_SINGLETON_KEY] = true;
60
61
  }
62
+ // Capture the real console.log before app-framework's hijackConsole() replaces it.
63
+ // This module loads first (as a dependency), so this is always the original.
64
+ // Using it in the stdout stream avoids the infinite loop (hijacked console → pino → console → …)
65
+ // while preserving single-event CloudWatch output (process.stdout.write splits on newlines).
66
+ const originalConsoleLog = console.log;
61
67
  // --- Environment & Resource Setup ---
62
68
  const semantic_conventions_4 = require("../semantic-conventions");
63
69
  const LAMBDA_ENV_OTEL_ATTRIBUTES = getLambdaEnvAttributes();
@@ -83,7 +89,6 @@ const otelLoggerProvider = new sdk_logs_1.LoggerProvider({
83
89
  });
84
90
  const otelLogger = otelLoggerProvider.getLogger(serviceName);
85
91
  // --- Pino Stream Destinations ---
86
- const stdout_writer_1 = require("./stdout-writer");
87
92
  function isPinoPrettyInstalled() {
88
93
  try {
89
94
  require.resolve('pino-pretty');
@@ -109,24 +114,21 @@ function createStdoutStream() {
109
114
  level: 'trace',
110
115
  stream: new stream_1.Writable({
111
116
  write(chunk, _encoding, callback) {
112
- var _a, _b, _c, _d;
117
+ var _a;
113
118
  let line;
114
119
  try {
115
120
  const logRecord = JSON.parse(chunk.toString());
116
- const time = (_a = logRecord.time) !== null && _a !== void 0 ? _a : new Date().toISOString();
117
- const level = (_b = logger_config_1.PINO_LEVEL_TO_NAME[logRecord.level]) !== null && _b !== void 0 ? _b : 'INFO';
118
- const message = (_c = logRecord[semantic_conventions_2.ATTR_LOG_MESSAGE]) !== null && _c !== void 0 ? _c : '';
119
- const requestId = (_d = getLambdaRequestId()) !== null && _d !== void 0 ? _d : '-';
121
+ const message = (_a = logRecord[semantic_conventions_2.ATTR_LOG_MESSAGE]) !== null && _a !== void 0 ? _a : '';
120
122
  const payload = logRecord[semantic_conventions_2.ATTR_LOG_PAYLOAD];
121
123
  const payloadLine = payload && typeof payload === 'object' && Object.keys(payload).length > 0
122
124
  ? `\n${JSON.stringify(payload, null, 2)}`
123
125
  : '';
124
- line = `${time}\t${requestId}\t${level}\t${message}${payloadLine}`;
126
+ line = `${message}${payloadLine}`;
125
127
  }
126
128
  catch {
127
129
  line = chunk.toString().replace(/\n$/, '');
128
130
  }
129
- stdout_writer_1.stdoutWriter.log(line);
131
+ originalConsoleLog(line);
130
132
  callback();
131
133
  },
132
134
  }),
@@ -59,3 +59,5 @@ export declare function createContextAwareLogger(baseLogger: Logger): Logger;
59
59
  * });
60
60
  */
61
61
  export declare function withLogAttributes<T>(fields: Record<string, unknown>, fn: () => T): T;
62
+ /** @deprecated Use `withLogAttributes` instead. */
63
+ export declare const withLogContext: typeof withLogAttributes;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loggerStorage = void 0;
3
+ exports.withLogContext = exports.loggerStorage = void 0;
4
4
  exports.createContextAwareLogger = createContextAwareLogger;
5
5
  exports.withLogAttributes = withLogAttributes;
6
6
  const async_hooks_1 = require("async_hooks");
@@ -78,3 +78,5 @@ function withLogAttributes(fields, fn) {
78
78
  const child = parent.child(fields);
79
79
  return exports.loggerStorage.run(child, fn);
80
80
  }
81
+ /** @deprecated Use `withLogAttributes` instead. */
82
+ exports.withLogContext = withLogAttributes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/telemetry",
3
- "version": "2.0.8",
3
+ "version": "2.0.9-alpha-formatting.1",
4
4
  "description": "Telemetry and monitoring utilities for contrail services",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -1,6 +0,0 @@
1
- export declare const stdoutWriter: {
2
- log: {
3
- (...data: any[]): void;
4
- (message?: any, ...optionalParams: any[]): void;
5
- };
6
- };
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stdoutWriter = void 0;
4
- // Capture the original console.log before app-framework's hijackConsole() replaces it.
5
- // Lambda treats each console.log() call as a single CloudWatch log event (even with
6
- // embedded newlines), unlike process.stdout.write() which splits on \n. Using the
7
- // original lets us pretty-print objects without them scattering across log events.
8
- //
9
- // Guard: if telemetry is imported after hijackConsole(), the captured function would be
10
- // the hijacked one, creating an infinite loop. Detect by checking for [native code] —
11
- // falls back to process.stdout.write if console.log has been replaced by anything.
12
- const _capturedConsoleLog = console.log;
13
- const isNative = Function.prototype.toString.call(_capturedConsoleLog).includes('[native code]');
14
- // Wrapped in an object so tests can jest.spyOn(stdoutWriter, 'log') regardless
15
- // of Jest's console patching strategy (BufferedConsole vs CustomConsole).
16
- exports.stdoutWriter = {
17
- log: isNative ? _capturedConsoleLog : (...args) => process.stdout.write(args.map(String).join(' ') + '\n'),
18
- };