@point3/observability 0.2.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 +383 -0
- package/dist/index.cjs +346 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +344 -0
- package/dist/index.js.map +1 -0
- package/dist/nest/index.cjs +274 -0
- package/dist/nest/index.cjs.map +1 -0
- package/dist/nest/index.d.cts +19 -0
- package/dist/nest/index.d.ts +19 -0
- package/dist/nest/index.js +272 -0
- package/dist/nest/index.js.map +1 -0
- package/dist/register.cjs +345 -0
- package/dist/register.cjs.map +1 -0
- package/dist/register.d.cts +33 -0
- package/dist/register.d.ts +33 -0
- package/dist/register.js +343 -0
- package/dist/register.js.map +1 -0
- package/package.json +65 -0
package/dist/register.js
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { parse, join, dirname, resolve } from 'path';
|
|
3
|
+
import { NodeSDK, resources } from '@opentelemetry/sdk-node';
|
|
4
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
5
|
+
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
|
|
6
|
+
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
|
|
7
|
+
import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';
|
|
8
|
+
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
|
|
9
|
+
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
10
|
+
import { RuntimeNodeInstrumentation } from '@opentelemetry/instrumentation-runtime-node';
|
|
11
|
+
import { ATTR_SERVICE_VERSION, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
|
|
12
|
+
import { format as format$1 } from 'util';
|
|
13
|
+
import { trace } from '@opentelemetry/api';
|
|
14
|
+
import { SeverityNumber, logs } from '@opentelemetry/api-logs';
|
|
15
|
+
|
|
16
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
17
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
18
|
+
}) : x)(function(x) {
|
|
19
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
20
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
21
|
+
});
|
|
22
|
+
var LOG_LEVEL_PRIORITY = {
|
|
23
|
+
fatal: 0,
|
|
24
|
+
error: 1,
|
|
25
|
+
warn: 2,
|
|
26
|
+
info: 3,
|
|
27
|
+
debug: 4,
|
|
28
|
+
verbose: 5
|
|
29
|
+
};
|
|
30
|
+
var SEVERITY_NUMBER = {
|
|
31
|
+
fatal: SeverityNumber.FATAL,
|
|
32
|
+
error: SeverityNumber.ERROR,
|
|
33
|
+
warn: SeverityNumber.WARN,
|
|
34
|
+
info: SeverityNumber.INFO,
|
|
35
|
+
debug: SeverityNumber.DEBUG,
|
|
36
|
+
verbose: SeverityNumber.TRACE
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/log/stdout-formatter.ts
|
|
40
|
+
var RESET = "\x1B[0m";
|
|
41
|
+
var RED = "\x1B[31m";
|
|
42
|
+
var YELLOW = "\x1B[33m";
|
|
43
|
+
var GREEN = "\x1B[32m";
|
|
44
|
+
var GRAY = "\x1B[90m";
|
|
45
|
+
var MAGENTA = "\x1B[35m";
|
|
46
|
+
var CYAN = "\x1B[36m";
|
|
47
|
+
var LEVEL_COLOR = {
|
|
48
|
+
fatal: MAGENTA,
|
|
49
|
+
error: RED,
|
|
50
|
+
warn: YELLOW,
|
|
51
|
+
info: GREEN,
|
|
52
|
+
debug: CYAN,
|
|
53
|
+
verbose: GRAY
|
|
54
|
+
};
|
|
55
|
+
function formatTimestamp(date) {
|
|
56
|
+
return date.toISOString();
|
|
57
|
+
}
|
|
58
|
+
function formatPretty(entry) {
|
|
59
|
+
const color = LEVEL_COLOR[entry.level];
|
|
60
|
+
const level = `${color}${entry.level.toUpperCase().padEnd(7)}${RESET}`;
|
|
61
|
+
const timestamp = `${GRAY}${formatTimestamp(entry.timestamp)}${RESET}`;
|
|
62
|
+
const message = entry.message;
|
|
63
|
+
let line = `${level} ${timestamp} ${message}`;
|
|
64
|
+
if (entry.traceId) {
|
|
65
|
+
line += ` ${GRAY}trace_id=${entry.traceId}${RESET}`;
|
|
66
|
+
}
|
|
67
|
+
if (entry.error) {
|
|
68
|
+
line += `
|
|
69
|
+
${RED}${entry.error.stack ?? entry.error.message}${RESET}`;
|
|
70
|
+
}
|
|
71
|
+
if (entry.attributes && Object.keys(entry.attributes).length > 0) {
|
|
72
|
+
line += ` ${GRAY}${JSON.stringify(entry.attributes)}${RESET}`;
|
|
73
|
+
}
|
|
74
|
+
return line;
|
|
75
|
+
}
|
|
76
|
+
function formatJson(entry) {
|
|
77
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
78
|
+
const record = {
|
|
79
|
+
level: entry.level,
|
|
80
|
+
message: entry.message,
|
|
81
|
+
timestamp: entry.timestamp.toISOString()
|
|
82
|
+
};
|
|
83
|
+
if (entry.traceId) record.trace_id = entry.traceId;
|
|
84
|
+
if (entry.spanId) record.span_id = entry.spanId;
|
|
85
|
+
if (entry.attributes) record.attributes = entry.attributes;
|
|
86
|
+
if (entry.error) {
|
|
87
|
+
record.error = {
|
|
88
|
+
name: entry.error.name,
|
|
89
|
+
message: entry.error.message,
|
|
90
|
+
stack: entry.error.stack
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return JSON.stringify(record, (_key, value) => {
|
|
94
|
+
if (typeof value === "object" && value !== null) {
|
|
95
|
+
if (seen.has(value)) return "[Circular]";
|
|
96
|
+
seen.add(value);
|
|
97
|
+
}
|
|
98
|
+
return value;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function format(entry) {
|
|
102
|
+
if (process.env.NODE_ENV === "production") {
|
|
103
|
+
return formatJson(entry);
|
|
104
|
+
}
|
|
105
|
+
return formatPretty(entry);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/log/emit.ts
|
|
109
|
+
var LIB_NAME = "@point3/observability";
|
|
110
|
+
var _originalConsole = {
|
|
111
|
+
log: console.log,
|
|
112
|
+
info: console.info,
|
|
113
|
+
warn: console.warn,
|
|
114
|
+
error: console.error,
|
|
115
|
+
debug: console.debug
|
|
116
|
+
};
|
|
117
|
+
var _isEmitting = false;
|
|
118
|
+
var _otelLogger;
|
|
119
|
+
function getOtelLogger() {
|
|
120
|
+
if (!_otelLogger) {
|
|
121
|
+
_otelLogger = logs.getLogger(LIB_NAME);
|
|
122
|
+
}
|
|
123
|
+
return _otelLogger;
|
|
124
|
+
}
|
|
125
|
+
function getOriginalConsole() {
|
|
126
|
+
return _originalConsole;
|
|
127
|
+
}
|
|
128
|
+
function getConfiguredLogLevel() {
|
|
129
|
+
const env = process.env.LOG_LEVEL?.toLowerCase();
|
|
130
|
+
if (env && env in LOG_LEVEL_PRIORITY) {
|
|
131
|
+
return env;
|
|
132
|
+
}
|
|
133
|
+
return "info";
|
|
134
|
+
}
|
|
135
|
+
function shouldLog(level) {
|
|
136
|
+
return LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[getConfiguredLogLevel()];
|
|
137
|
+
}
|
|
138
|
+
function isPlainObject(value) {
|
|
139
|
+
if (value === null || typeof value !== "object") return false;
|
|
140
|
+
if (value instanceof Error) return false;
|
|
141
|
+
const proto = Object.getPrototypeOf(value);
|
|
142
|
+
return proto === Object.prototype || proto === null;
|
|
143
|
+
}
|
|
144
|
+
function extractActiveSpan() {
|
|
145
|
+
const span = trace.getActiveSpan();
|
|
146
|
+
if (!span) return {};
|
|
147
|
+
const ctx = span.spanContext();
|
|
148
|
+
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
|
149
|
+
}
|
|
150
|
+
function buildMessage(args) {
|
|
151
|
+
if (args.length === 0) return { message: "" };
|
|
152
|
+
const first = args[0];
|
|
153
|
+
if (isPlainObject(first)) {
|
|
154
|
+
const { message, ...rest } = first;
|
|
155
|
+
const msg = typeof message === "string" ? message : format$1(first);
|
|
156
|
+
const attributes = Object.keys(rest).length > 0 ? rest : void 0;
|
|
157
|
+
return { message: msg, attributes };
|
|
158
|
+
}
|
|
159
|
+
let error;
|
|
160
|
+
for (const arg of args) {
|
|
161
|
+
if (arg instanceof Error) {
|
|
162
|
+
error = arg;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return { message: format$1(...args), error };
|
|
167
|
+
}
|
|
168
|
+
var STDERR_LEVELS = /* @__PURE__ */ new Set(["error", "fatal"]);
|
|
169
|
+
function emitLog(level, args) {
|
|
170
|
+
if (!shouldLog(level)) return;
|
|
171
|
+
if (_isEmitting) {
|
|
172
|
+
const consoleFn = STDERR_LEVELS.has(level) ? _originalConsole.error : _originalConsole.log;
|
|
173
|
+
consoleFn(format$1(...args));
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
_isEmitting = true;
|
|
177
|
+
try {
|
|
178
|
+
const { message, attributes, error } = buildMessage(args);
|
|
179
|
+
const { traceId, spanId } = extractActiveSpan();
|
|
180
|
+
const entry = {
|
|
181
|
+
level,
|
|
182
|
+
message,
|
|
183
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
184
|
+
traceId,
|
|
185
|
+
spanId,
|
|
186
|
+
attributes,
|
|
187
|
+
error
|
|
188
|
+
};
|
|
189
|
+
const output = format(entry);
|
|
190
|
+
if (STDERR_LEVELS.has(level)) {
|
|
191
|
+
process.stderr.write(output + "\n");
|
|
192
|
+
} else {
|
|
193
|
+
process.stdout.write(output + "\n");
|
|
194
|
+
}
|
|
195
|
+
const otelLogger = getOtelLogger();
|
|
196
|
+
otelLogger.emit({
|
|
197
|
+
severityNumber: SEVERITY_NUMBER[level],
|
|
198
|
+
severityText: level.toUpperCase(),
|
|
199
|
+
body: message,
|
|
200
|
+
attributes: {
|
|
201
|
+
...attributes,
|
|
202
|
+
...error && {
|
|
203
|
+
"exception.type": error.name,
|
|
204
|
+
"exception.message": error.message,
|
|
205
|
+
"exception.stacktrace": error.stack
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
} finally {
|
|
210
|
+
_isEmitting = false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/log/console-patch.ts
|
|
215
|
+
var _isPatched = false;
|
|
216
|
+
function patchConsole() {
|
|
217
|
+
if (_isPatched) return;
|
|
218
|
+
console.log = (...args) => {
|
|
219
|
+
emitLog("info", args);
|
|
220
|
+
};
|
|
221
|
+
console.info = (...args) => {
|
|
222
|
+
emitLog("info", args);
|
|
223
|
+
};
|
|
224
|
+
console.warn = (...args) => {
|
|
225
|
+
emitLog("warn", args);
|
|
226
|
+
};
|
|
227
|
+
console.error = (...args) => {
|
|
228
|
+
emitLog("error", args);
|
|
229
|
+
};
|
|
230
|
+
console.debug = (...args) => {
|
|
231
|
+
emitLog("debug", args);
|
|
232
|
+
};
|
|
233
|
+
_isPatched = true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/register.ts
|
|
237
|
+
var DEFAULT_ENDPOINT = "http://alloy:4318";
|
|
238
|
+
var METRIC_EXPORT_INTERVAL_MS = 2e3;
|
|
239
|
+
var RUNTIME_MONITORING_PRECISION_MS = 2e3;
|
|
240
|
+
var initialized = false;
|
|
241
|
+
function getMainModuleFilename() {
|
|
242
|
+
try {
|
|
243
|
+
return __require.main?.filename;
|
|
244
|
+
} catch {
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function resolveStartDir() {
|
|
249
|
+
const mainFilename = getMainModuleFilename();
|
|
250
|
+
if (mainFilename) return dirname(mainFilename);
|
|
251
|
+
if (process.argv[1]) return dirname(resolve(process.argv[1]));
|
|
252
|
+
return process.cwd();
|
|
253
|
+
}
|
|
254
|
+
function findPackageJsonPath(startDir) {
|
|
255
|
+
const { root } = parse(startDir);
|
|
256
|
+
let dir = startDir;
|
|
257
|
+
while (true) {
|
|
258
|
+
const candidate = join(dir, "package.json");
|
|
259
|
+
if (existsSync(candidate)) return candidate;
|
|
260
|
+
if (dir === root) return null;
|
|
261
|
+
dir = dirname(dir);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function readConsumerPackageJson() {
|
|
265
|
+
try {
|
|
266
|
+
const pkgPath = findPackageJsonPath(resolveStartDir());
|
|
267
|
+
if (!pkgPath) return {};
|
|
268
|
+
const { name, version } = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
269
|
+
return { name, version };
|
|
270
|
+
} catch {
|
|
271
|
+
return {};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function createDefaultInstrumentations() {
|
|
275
|
+
return [
|
|
276
|
+
...getNodeAutoInstrumentations(),
|
|
277
|
+
new RuntimeNodeInstrumentation({
|
|
278
|
+
monitoringPrecision: RUNTIME_MONITORING_PRECISION_MS
|
|
279
|
+
})
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
function register(options) {
|
|
283
|
+
if (initialized) {
|
|
284
|
+
getOriginalConsole().warn("[@point3/observability] Already initialized. Skipping.");
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
initialized = true;
|
|
288
|
+
const pkg = readConsumerPackageJson();
|
|
289
|
+
const serviceName = process.env.OTEL_SERVICE_NAME ?? options?.serviceName ?? pkg.name ?? "unknown_service";
|
|
290
|
+
const serviceVersion = process.env.OTEL_SERVICE_VERSION ?? options?.serviceVersion ?? pkg.version ?? "0.0.0";
|
|
291
|
+
const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? DEFAULT_ENDPOINT;
|
|
292
|
+
if (serviceName === "unknown_service") {
|
|
293
|
+
getOriginalConsole().warn(
|
|
294
|
+
"[@point3/observability] OTEL_SERVICE_NAME\uC774 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uACE0 package.json name\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
const defaultInstrumentations = createDefaultInstrumentations();
|
|
298
|
+
const instrumentations = options?.instrumentations ? options.instrumentations(defaultInstrumentations) : defaultInstrumentations;
|
|
299
|
+
const sdk = new NodeSDK({
|
|
300
|
+
resource: resources.resourceFromAttributes({
|
|
301
|
+
[ATTR_SERVICE_NAME]: serviceName,
|
|
302
|
+
[ATTR_SERVICE_VERSION]: serviceVersion
|
|
303
|
+
}),
|
|
304
|
+
traceExporter: options?.traceExporter ?? new OTLPTraceExporter({
|
|
305
|
+
url: `${endpoint}/v1/traces`
|
|
306
|
+
}),
|
|
307
|
+
metricReaders: options?.metricReaders ?? [
|
|
308
|
+
new PeriodicExportingMetricReader({
|
|
309
|
+
exporter: new OTLPMetricExporter({
|
|
310
|
+
url: `${endpoint}/v1/metrics`
|
|
311
|
+
}),
|
|
312
|
+
exportIntervalMillis: METRIC_EXPORT_INTERVAL_MS
|
|
313
|
+
})
|
|
314
|
+
],
|
|
315
|
+
logRecordProcessors: options?.logRecordProcessors ?? [
|
|
316
|
+
new BatchLogRecordProcessor(
|
|
317
|
+
new OTLPLogExporter({
|
|
318
|
+
url: `${endpoint}/v1/logs`
|
|
319
|
+
})
|
|
320
|
+
)
|
|
321
|
+
],
|
|
322
|
+
instrumentations
|
|
323
|
+
});
|
|
324
|
+
sdk.start();
|
|
325
|
+
if (options?.patchConsole !== false) {
|
|
326
|
+
patchConsole();
|
|
327
|
+
}
|
|
328
|
+
let shuttingDown = false;
|
|
329
|
+
const shutdown = () => {
|
|
330
|
+
if (shuttingDown) return;
|
|
331
|
+
shuttingDown = true;
|
|
332
|
+
sdk.shutdown().then(() => process.exit(0)).catch((error) => {
|
|
333
|
+
getOriginalConsole().error("[@point3/observability] SDK Clean-up \uC2E4\uD328", error);
|
|
334
|
+
process.exit(1);
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
process.on("SIGINT", shutdown);
|
|
338
|
+
process.on("SIGTERM", shutdown);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export { register };
|
|
342
|
+
//# sourceMappingURL=register.js.map
|
|
343
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/log/types.ts","../src/log/stdout-formatter.ts","../src/log/emit.ts","../src/log/console-patch.ts","../src/register.ts"],"names":["utilFormat"],"mappings":"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","file":"register.js","sourcesContent":["import { SeverityNumber } from \"@opentelemetry/api-logs\";\n\nexport type LogLevel = \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"verbose\";\n\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n fatal: 0,\n error: 1,\n warn: 2,\n info: 3,\n debug: 4,\n verbose: 5,\n};\n\nexport const SEVERITY_NUMBER: Record<LogLevel, SeverityNumber> = {\n fatal: SeverityNumber.FATAL,\n error: SeverityNumber.ERROR,\n warn: SeverityNumber.WARN,\n info: SeverityNumber.INFO,\n debug: SeverityNumber.DEBUG,\n verbose: SeverityNumber.TRACE,\n};\n\nexport interface LogEntry {\n level: LogLevel;\n message: string;\n timestamp: Date;\n traceId?: string;\n spanId?: string;\n attributes?: Record<string, unknown>;\n error?: Error;\n}\n","import type { LogEntry, LogLevel } from \"./types\";\n\nconst RESET = \"\\x1b[0m\";\nconst RED = \"\\x1b[31m\";\nconst YELLOW = \"\\x1b[33m\";\nconst GREEN = \"\\x1b[32m\";\nconst GRAY = \"\\x1b[90m\";\nconst MAGENTA = \"\\x1b[35m\";\nconst CYAN = \"\\x1b[36m\";\n\nconst LEVEL_COLOR: Record<LogLevel, string> = {\n fatal: MAGENTA,\n error: RED,\n warn: YELLOW,\n info: GREEN,\n debug: CYAN,\n verbose: GRAY,\n};\n\nfunction formatTimestamp(date: Date): string {\n return date.toISOString();\n}\n\nexport function formatPretty(entry: LogEntry): string {\n const color = LEVEL_COLOR[entry.level];\n const level = `${color}${entry.level.toUpperCase().padEnd(7)}${RESET}`;\n const timestamp = `${GRAY}${formatTimestamp(entry.timestamp)}${RESET}`;\n const message = entry.message;\n\n let line = `${level} ${timestamp} ${message}`;\n\n if (entry.traceId) {\n line += ` ${GRAY}trace_id=${entry.traceId}${RESET}`;\n }\n\n if (entry.error) {\n line += `\\n${RED}${entry.error.stack ?? entry.error.message}${RESET}`;\n }\n\n if (entry.attributes && Object.keys(entry.attributes).length > 0) {\n line += ` ${GRAY}${JSON.stringify(entry.attributes)}${RESET}`;\n }\n\n return line;\n}\n\nexport function formatJson(entry: LogEntry): string {\n const seen = new WeakSet<object>();\n\n const record: Record<string, unknown> = {\n level: entry.level,\n message: entry.message,\n timestamp: entry.timestamp.toISOString(),\n };\n\n if (entry.traceId) record.trace_id = entry.traceId;\n if (entry.spanId) record.span_id = entry.spanId;\n if (entry.attributes) record.attributes = entry.attributes;\n if (entry.error) {\n record.error = {\n name: entry.error.name,\n message: entry.error.message,\n stack: entry.error.stack,\n };\n }\n\n return JSON.stringify(record, (_key, value: unknown) => {\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n return value;\n });\n}\n\nexport function format(entry: LogEntry): string {\n if (process.env.NODE_ENV === \"production\") {\n return formatJson(entry);\n }\n return formatPretty(entry);\n}\n","import { format as utilFormat } from \"node:util\";\nimport { trace } from \"@opentelemetry/api\";\nimport { logs, SeverityNumber } from \"@opentelemetry/api-logs\";\nimport type { Logger } from \"@opentelemetry/api-logs\";\n\nimport type { LogEntry, LogLevel } from \"./types\";\nimport { LOG_LEVEL_PRIORITY, SEVERITY_NUMBER } from \"./types\";\nimport { format } from \"./stdout-formatter\";\n\nconst LIB_NAME = \"@point3/observability\";\n\nconst _originalConsole = {\n log: console.log,\n info: console.info,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n} as const;\n\nlet _isEmitting = false;\n\nlet _otelLogger: Logger | undefined;\n\nfunction getOtelLogger(): Logger {\n if (!_otelLogger) {\n _otelLogger = logs.getLogger(LIB_NAME);\n }\n return _otelLogger;\n}\n\nexport function getOriginalConsole(): typeof _originalConsole {\n return _originalConsole;\n}\n\nexport function getConfiguredLogLevel(): LogLevel {\n const env = process.env.LOG_LEVEL?.toLowerCase();\n if (env && env in LOG_LEVEL_PRIORITY) {\n return env as LogLevel;\n }\n return \"info\";\n}\n\nexport function shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[getConfiguredLogLevel()];\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (value instanceof Error) return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\nfunction extractActiveSpan(): { traceId?: string; spanId?: string } {\n const span = trace.getActiveSpan();\n if (!span) return {};\n\n const ctx = span.spanContext();\n return { traceId: ctx.traceId, spanId: ctx.spanId };\n}\n\nfunction buildMessage(args: unknown[]): { message: string; attributes?: Record<string, unknown>; error?: Error } {\n if (args.length === 0) return { message: \"\" };\n\n const first = args[0];\n\n if (isPlainObject(first)) {\n const { message, ...rest } = first;\n const msg = typeof message === \"string\" ? message : utilFormat(first);\n const attributes = Object.keys(rest).length > 0 ? rest : undefined;\n return { message: msg, attributes };\n }\n\n let error: Error | undefined;\n for (const arg of args) {\n if (arg instanceof Error) {\n error = arg;\n break;\n }\n }\n\n return { message: utilFormat(...args), error };\n}\n\nconst STDERR_LEVELS: ReadonlySet<LogLevel> = new Set([\"error\", \"fatal\"]);\n\nexport function emitLog(level: LogLevel, args: unknown[]): void {\n if (!shouldLog(level)) return;\n\n if (_isEmitting) {\n const consoleFn = STDERR_LEVELS.has(level) ? _originalConsole.error : _originalConsole.log;\n consoleFn(utilFormat(...args));\n return;\n }\n\n _isEmitting = true;\n try {\n const { message, attributes, error } = buildMessage(args);\n const { traceId, spanId } = extractActiveSpan();\n\n const entry: LogEntry = {\n level,\n message,\n timestamp: new Date(),\n traceId,\n spanId,\n attributes,\n error,\n };\n\n const output = format(entry);\n if (STDERR_LEVELS.has(level)) {\n process.stderr.write(output + \"\\n\");\n } else {\n process.stdout.write(output + \"\\n\");\n }\n\n const otelLogger = getOtelLogger();\n otelLogger.emit({\n severityNumber: SEVERITY_NUMBER[level],\n severityText: level.toUpperCase(),\n body: message,\n attributes: {\n ...attributes,\n ...(error && {\n \"exception.type\": error.name,\n \"exception.message\": error.message,\n \"exception.stacktrace\": error.stack,\n }),\n },\n });\n } finally {\n _isEmitting = false;\n }\n}\n","import { emitLog, getOriginalConsole } from \"./emit\";\n\nlet _isPatched = false;\n\nconst _savedConsole = {\n log: console.log,\n info: console.info,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n};\n\nexport function patchConsole(): void {\n if (_isPatched) return;\n\n const originalConsole = getOriginalConsole();\n\n console.log = (...args: unknown[]) => {\n emitLog(\"info\", args);\n };\n\n console.info = (...args: unknown[]) => {\n emitLog(\"info\", args);\n };\n\n console.warn = (...args: unknown[]) => {\n emitLog(\"warn\", args);\n };\n\n console.error = (...args: unknown[]) => {\n emitLog(\"error\", args);\n };\n\n console.debug = (...args: unknown[]) => {\n emitLog(\"debug\", args);\n };\n\n _isPatched = true;\n}\n\nexport function unpatchConsole(): void {\n if (!_isPatched) return;\n\n console.log = _savedConsole.log;\n console.info = _savedConsole.info;\n console.warn = _savedConsole.warn;\n console.error = _savedConsole.error;\n console.debug = _savedConsole.debug;\n\n _isPatched = false;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, parse, resolve } from \"node:path\";\nimport { NodeSDK, resources } from \"@opentelemetry/sdk-node\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\";\nimport { OTLPLogExporter } from \"@opentelemetry/exporter-logs-otlp-http\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\";\nimport { BatchLogRecordProcessor } from \"@opentelemetry/sdk-logs\";\nimport { PeriodicExportingMetricReader } from \"@opentelemetry/sdk-metrics\";\nimport { getNodeAutoInstrumentations } from \"@opentelemetry/auto-instrumentations-node\";\nimport { RuntimeNodeInstrumentation } from \"@opentelemetry/instrumentation-runtime-node\";\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from \"@opentelemetry/semantic-conventions\";\n\nimport type { Instrumentation } from \"@opentelemetry/instrumentation\";\nimport type { ObservabilityOptions } from \"./types\";\nimport { patchConsole } from \"./log/console-patch\";\nimport { getOriginalConsole } from \"./log/emit\";\n\nconst DEFAULT_ENDPOINT = \"http://alloy:4318\";\nconst METRIC_EXPORT_INTERVAL_MS = 2000;\nconst RUNTIME_MONITORING_PRECISION_MS = 2000;\n\nlet initialized = false;\n\nfunction getMainModuleFilename(): string | undefined {\n try {\n return require.main?.filename;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveStartDir(): string {\n const mainFilename = getMainModuleFilename();\n if (mainFilename) return dirname(mainFilename);\n\n if (process.argv[1]) return dirname(resolve(process.argv[1]));\n\n return process.cwd();\n}\n\nfunction findPackageJsonPath(startDir: string): string | null {\n const { root } = parse(startDir);\n let dir = startDir;\n\n while (true) {\n const candidate = join(dir, \"package.json\");\n if (existsSync(candidate)) return candidate;\n if (dir === root) return null;\n dir = dirname(dir);\n }\n}\n\nfunction readConsumerPackageJson(): { name?: string; version?: string } {\n try {\n const pkgPath = findPackageJsonPath(resolveStartDir());\n if (!pkgPath) return {};\n\n const { name, version } = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n return { name, version };\n } catch {\n return {};\n }\n}\n\nfunction createDefaultInstrumentations(): Instrumentation[] {\n return [\n ...getNodeAutoInstrumentations(),\n new RuntimeNodeInstrumentation({\n monitoringPrecision: RUNTIME_MONITORING_PRECISION_MS,\n }),\n ];\n}\n\nexport function register(options?: ObservabilityOptions): void {\n if (initialized) {\n getOriginalConsole().warn(\"[@point3/observability] Already initialized. Skipping.\");\n return;\n }\n initialized = true;\n\n const pkg = readConsumerPackageJson();\n\n const serviceName =\n process.env.OTEL_SERVICE_NAME ?? options?.serviceName ?? pkg.name ?? \"unknown_service\";\n\n const serviceVersion =\n process.env.OTEL_SERVICE_VERSION ?? options?.serviceVersion ?? pkg.version ?? \"0.0.0\";\n\n const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? DEFAULT_ENDPOINT;\n\n if (serviceName === \"unknown_service\") {\n getOriginalConsole().warn(\n \"[@point3/observability] OTEL_SERVICE_NAME이 설정되지 않았고 package.json name도 없습니다.\",\n );\n }\n\n const defaultInstrumentations = createDefaultInstrumentations();\n const instrumentations = options?.instrumentations\n ? options.instrumentations(defaultInstrumentations)\n : defaultInstrumentations;\n\n const sdk = new NodeSDK({\n resource: resources.resourceFromAttributes({\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_SERVICE_VERSION]: serviceVersion,\n }),\n traceExporter:\n options?.traceExporter ??\n new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n }),\n metricReaders:\n options?.metricReaders ?? [\n new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({\n url: `${endpoint}/v1/metrics`,\n }),\n exportIntervalMillis: METRIC_EXPORT_INTERVAL_MS,\n }),\n ],\n logRecordProcessors:\n options?.logRecordProcessors ?? [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({\n url: `${endpoint}/v1/logs`,\n }),\n ),\n ],\n instrumentations,\n });\n\n sdk.start();\n\n if (options?.patchConsole !== false) {\n patchConsole();\n }\n\n let shuttingDown = false;\n const shutdown = () => {\n if (shuttingDown) return;\n shuttingDown = true;\n sdk\n .shutdown()\n .then(() => process.exit(0))\n .catch((error) => {\n getOriginalConsole().error(\"[@point3/observability] SDK Clean-up 실패\", error);\n process.exit(1);\n });\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n}\n\nexport type { ObservabilityOptions } from \"./types\";\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@point3/observability",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "OpenTelemetry SDK wrapper for Point3 services",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./register": {
|
|
16
|
+
"types": "./dist/register.d.ts",
|
|
17
|
+
"import": "./dist/register.js",
|
|
18
|
+
"require": "./dist/register.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./nest": {
|
|
21
|
+
"types": "./dist/nest/index.d.ts",
|
|
22
|
+
"import": "./dist/nest/index.js",
|
|
23
|
+
"require": "./dist/nest/index.cjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"./dist/index.*"
|
|
28
|
+
],
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsup",
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@opentelemetry/api-logs": "^0.211.0",
|
|
38
|
+
"@opentelemetry/auto-instrumentations-node": "^0.69.0",
|
|
39
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.211.0",
|
|
40
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.211.0",
|
|
41
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.211.0",
|
|
42
|
+
"@opentelemetry/instrumentation-runtime-node": "^0.24.0",
|
|
43
|
+
"@opentelemetry/sdk-logs": "^0.211.0",
|
|
44
|
+
"@opentelemetry/sdk-metrics": "^2.5.0",
|
|
45
|
+
"@opentelemetry/sdk-node": "^0.211.0",
|
|
46
|
+
"@opentelemetry/semantic-conventions": "^1.39.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
50
|
+
"@opentelemetry/api": "^1.9.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependenciesMeta": {
|
|
53
|
+
"@nestjs/common": {
|
|
54
|
+
"optional": true
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@nestjs/common": "^11.1.13",
|
|
59
|
+
"@nestjs/core": "^11.1.13",
|
|
60
|
+
"reflect-metadata": "^0.2.2",
|
|
61
|
+
"rxjs": "^7.8.2",
|
|
62
|
+
"tsup": "^8.0.0",
|
|
63
|
+
"typescript": "^5.7.0"
|
|
64
|
+
}
|
|
65
|
+
}
|