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