@omen.foundation/node-microservice-runtime 0.1.63 → 0.1.64

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,480 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createLogger = createLogger;
37
+ const pino_1 = __importStar(require("pino"));
38
+ const node_stream_1 = require("node:stream");
39
+ const node_module_1 = require("node:module");
40
+ const env_js_1 = require("./env.js");
41
+ const api_logs_1 = require("@opentelemetry/api-logs");
42
+ const sdk_logs_1 = require("@opentelemetry/sdk-logs");
43
+ const exporter_logs_otlp_http_1 = require("@opentelemetry/exporter-logs-otlp-http");
44
+ const resources_1 = require("@opentelemetry/resources");
45
+ const collector_manager_js_1 = require("./collector-manager.js");
46
+ function getRequire() {
47
+ if (typeof require !== 'undefined' && typeof require.main !== 'undefined') {
48
+ return require;
49
+ }
50
+ return (0, node_module_1.createRequire)(import.meta.url);
51
+ }
52
+ function shouldUsePrettyLogs() {
53
+ return process.env.IS_LOCAL === '1' || process.env.IS_LOCAL === 'true';
54
+ }
55
+ function mapPinoLevelToBeamableLevel(level) {
56
+ switch (level) {
57
+ case 10:
58
+ return 'Debug';
59
+ case 20:
60
+ return 'Debug';
61
+ case 30:
62
+ return 'Info';
63
+ case 40:
64
+ return 'Warning';
65
+ case 50:
66
+ return 'Error';
67
+ case 60:
68
+ return 'Fatal';
69
+ default:
70
+ return 'Info';
71
+ }
72
+ }
73
+ async function initializeOtlpLogging(serviceName, qualifiedServiceName, env, logger) {
74
+ const otlpEndpoint = process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT
75
+ || process.env.OTEL_EXPORTER_OTLP_ENDPOINT
76
+ || (process.env.OTEL_EXPORTER_OTLP_ENDPOINT_LOGS ? process.env.OTEL_EXPORTER_OTLP_ENDPOINT_LOGS : null);
77
+ const otlpProtocol = process.env.BEAM_OTEL_EXPORTER_OTLP_PROTOCOL
78
+ || process.env.OTEL_EXPORTER_OTLP_PROTOCOL
79
+ || process.env.OTEL_EXPORTER_OTLP_PROTOCOL_LOGS;
80
+ const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
81
+ const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
82
+ const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;
83
+ if (!otlpEndpoint && !standardOtelEnabled) {
84
+ return Promise.resolve(null);
85
+ }
86
+ try {
87
+ const resourceAttributes = {};
88
+ if (serviceName) {
89
+ resourceAttributes['service.namespace'] = serviceName;
90
+ resourceAttributes['service.name'] = serviceName;
91
+ }
92
+ if (qualifiedServiceName) {
93
+ resourceAttributes['service.instance.id'] = qualifiedServiceName;
94
+ }
95
+ if (env === null || env === void 0 ? void 0 : env.cid) {
96
+ resourceAttributes['beam.cid'] = String(env.cid);
97
+ }
98
+ if (env === null || env === void 0 ? void 0 : env.pid) {
99
+ resourceAttributes['beam.pid'] = String(env.pid);
100
+ }
101
+ if (env === null || env === void 0 ? void 0 : env.routingKey) {
102
+ resourceAttributes['beam.routing_key'] = String(env.routingKey);
103
+ }
104
+ let endpointUrl = otlpEndpoint;
105
+ if (!endpointUrl && standardOtelEnabled && logger) {
106
+ try {
107
+ const discoveredEndpoint = await (0, collector_manager_js_1.discoverOrStartCollector)(logger, standardOtelEnabled, env);
108
+ if (discoveredEndpoint) {
109
+ endpointUrl = discoveredEndpoint;
110
+ }
111
+ else {
112
+ console.error('[OTLP] Standard OTLP is enabled but could not discover or start collector.');
113
+ return Promise.resolve(null);
114
+ }
115
+ }
116
+ catch (error) {
117
+ console.error('[OTLP] Failed to discover/start collector:', error instanceof Error ? error.message : String(error));
118
+ return Promise.resolve(null);
119
+ }
120
+ }
121
+ if (!endpointUrl) {
122
+ if (standardOtelEnabled) {
123
+ console.error('[OTLP] Standard OTLP is enabled but no endpoint available. Set BEAM_OTEL_EXPORTER_OTLP_ENDPOINT to enable OTLP logging.');
124
+ }
125
+ return Promise.resolve(null);
126
+ }
127
+ let finalEndpointUrl = endpointUrl;
128
+ if (otlpProtocol && otlpProtocol.toLowerCase() === 'grpc') {
129
+ console.warn('[OTLP] Grpc protocol specified but not yet supported, using HTTP endpoint format');
130
+ finalEndpointUrl = endpointUrl.includes('/v1/logs')
131
+ ? endpointUrl
132
+ : `${endpointUrl.replace(/\/$/, '')}/v1/logs`;
133
+ }
134
+ else {
135
+ finalEndpointUrl = endpointUrl.includes('/v1/logs')
136
+ ? endpointUrl
137
+ : `${endpointUrl.replace(/\/$/, '')}/v1/logs`;
138
+ }
139
+ const exporterOptions = {
140
+ url: finalEndpointUrl,
141
+ };
142
+ if (otlpProtocol) {
143
+ const protocol = otlpProtocol.toLowerCase();
144
+ if (protocol === 'httpprotobuf' || protocol === 'protobuf') {
145
+ exporterOptions.contentType = 'application/x-protobuf';
146
+ }
147
+ else if (protocol === 'httpjson' || protocol === 'json') {
148
+ exporterOptions.contentType = 'application/json';
149
+ }
150
+ else if (protocol === 'grpc') {
151
+ console.warn('[OTLP] Grpc protocol is not yet supported in Node.js runtime, falling back to HttpProtobuf');
152
+ exporterOptions.contentType = 'application/x-protobuf';
153
+ }
154
+ else {
155
+ console.warn(`[OTLP] Unknown protocol "${otlpProtocol}", defaulting to HttpProtobuf`);
156
+ exporterOptions.contentType = 'application/x-protobuf';
157
+ }
158
+ }
159
+ else {
160
+ exporterOptions.contentType = 'application/x-protobuf';
161
+ }
162
+ if (process.env.BEAM_OTEL_EXPORTER_OTLP_HEADERS) {
163
+ exporterOptions.headers = JSON.parse(process.env.BEAM_OTEL_EXPORTER_OTLP_HEADERS);
164
+ }
165
+ const exporter = new exporter_logs_otlp_http_1.OTLPLogExporter(exporterOptions);
166
+ const baseResource = (0, resources_1.defaultResource)();
167
+ const customResource = (0, resources_1.resourceFromAttributes)(resourceAttributes);
168
+ const resource = baseResource.merge(customResource);
169
+ const processor = new sdk_logs_1.SimpleLogRecordProcessor(exporter);
170
+ const loggerProvider = new sdk_logs_1.LoggerProvider({
171
+ resource: resource,
172
+ processors: [processor],
173
+ });
174
+ api_logs_1.logs.setGlobalLoggerProvider(loggerProvider);
175
+ console.error(`[OTLP] OpenTelemetry logging initialized. Endpoint: ${finalEndpointUrl}, Service: ${serviceName || 'unknown'}`);
176
+ if (standardOtelEnabled && logger) {
177
+ try {
178
+ const { isCollectorRunning } = await Promise.resolve().then(() => __importStar(require('./collector-manager.js')));
179
+ for (let i = 0; i < 50; i++) {
180
+ const status = await isCollectorRunning();
181
+ if (status.isRunning && status.isReady) {
182
+ if (logger) {
183
+ logger.info(`[OTLP] Collector confirmed ready at ${status.otlpEndpoint || finalEndpointUrl}`);
184
+ }
185
+ break;
186
+ }
187
+ await new Promise(resolve => setTimeout(resolve, 100));
188
+ }
189
+ }
190
+ catch (error) {
191
+ if (logger) {
192
+ logger.warn(`[OTLP] Could not verify collector readiness: ${error instanceof Error ? error.message : String(error)}`);
193
+ }
194
+ }
195
+ }
196
+ return Promise.resolve(loggerProvider);
197
+ }
198
+ catch (error) {
199
+ console.error('[OTLP] Failed to initialize OTLP logging:', error instanceof Error ? error.message : String(error));
200
+ if (error instanceof Error && error.stack) {
201
+ console.error('[OTLP] Stack trace:', error.stack);
202
+ }
203
+ return Promise.resolve(null);
204
+ }
205
+ }
206
+ function createBeamableLogFormatter(serviceName, qualifiedServiceName, otlpProviderRef) {
207
+ return new node_stream_1.Transform({
208
+ objectMode: false,
209
+ transform(chunk, _encoding, callback) {
210
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
211
+ try {
212
+ const line = buffer.toString('utf8');
213
+ if (!line.trim()) {
214
+ callback();
215
+ return;
216
+ }
217
+ const pinoLog = JSON.parse(line);
218
+ let timestamp;
219
+ if (typeof pinoLog.time === 'string') {
220
+ timestamp = pinoLog.time;
221
+ }
222
+ else if (typeof pinoLog.time === 'number') {
223
+ timestamp = new Date(pinoLog.time).toISOString();
224
+ }
225
+ else {
226
+ timestamp = new Date().toISOString();
227
+ }
228
+ const level = mapPinoLevelToBeamableLevel(pinoLog.level);
229
+ const messageParts = [];
230
+ if (pinoLog.msg) {
231
+ messageParts.push(pinoLog.msg);
232
+ }
233
+ if (pinoLog.err) {
234
+ const err = pinoLog.err;
235
+ const errMsg = err.message || err.msg || 'Error';
236
+ const errStack = err.stack ? `\n${err.stack}` : '';
237
+ messageParts.push(`${errMsg}${errStack}`);
238
+ }
239
+ const beamableLog = {
240
+ __t: timestamp,
241
+ __l: level,
242
+ __m: messageParts.length > 0 ? messageParts.join(' ') : 'No message',
243
+ };
244
+ const contextFields = {};
245
+ if (pinoLog.cid)
246
+ contextFields.cid = pinoLog.cid;
247
+ if (pinoLog.pid)
248
+ contextFields.pid = pinoLog.pid;
249
+ if (pinoLog.routingKey)
250
+ contextFields.routingKey = pinoLog.routingKey;
251
+ if (pinoLog.service)
252
+ contextFields.service = pinoLog.service;
253
+ if (pinoLog.component)
254
+ contextFields.component = pinoLog.component;
255
+ if (serviceName) {
256
+ contextFields.serviceName = serviceName;
257
+ }
258
+ if (qualifiedServiceName) {
259
+ contextFields.qualifiedServiceName = qualifiedServiceName;
260
+ }
261
+ const standardPinoFields = ['level', 'time', 'pid', 'hostname', 'name', 'msg', 'err', 'v', 'cid', 'pid', 'routingKey', 'sdkVersionExecution', 'service', 'component'];
262
+ for (const [key, value] of Object.entries(pinoLog)) {
263
+ if (!standardPinoFields.includes(key) && value !== undefined && value !== null) {
264
+ contextFields[key] = value;
265
+ }
266
+ }
267
+ if (Object.keys(contextFields).length > 0) {
268
+ beamableLog.__c = contextFields;
269
+ }
270
+ const otelFields = {};
271
+ const resourceAttributes = {};
272
+ if (serviceName) {
273
+ resourceAttributes['service.namespace'] = serviceName;
274
+ resourceAttributes['service.name'] = serviceName;
275
+ }
276
+ if (qualifiedServiceName) {
277
+ resourceAttributes['service.qualifiedName'] = qualifiedServiceName;
278
+ }
279
+ if (pinoLog.cid) {
280
+ resourceAttributes['beam.cid'] = String(pinoLog.cid);
281
+ }
282
+ if (pinoLog.pid) {
283
+ resourceAttributes['beam.pid'] = String(pinoLog.pid);
284
+ }
285
+ if (pinoLog.routingKey) {
286
+ resourceAttributes['beam.routing_key'] = String(pinoLog.routingKey);
287
+ }
288
+ const logAttributes = {};
289
+ if (pinoLog.component) {
290
+ logAttributes['component'] = String(pinoLog.component);
291
+ }
292
+ if (pinoLog.err) {
293
+ const err = pinoLog.err;
294
+ if (err.message)
295
+ logAttributes['exception.message'] = String(err.message);
296
+ if (err.stack)
297
+ logAttributes['exception.stacktrace'] = String(err.stack);
298
+ if (err.type)
299
+ logAttributes['exception.type'] = String(err.type);
300
+ }
301
+ const severityTextMap = {
302
+ 'Debug': 'Debug',
303
+ 'Info': 'Information',
304
+ 'Warning': 'Warning',
305
+ 'Error': 'Error',
306
+ 'Fatal': 'Critical',
307
+ };
308
+ const severityText = severityTextMap[level] || 'Information';
309
+ if (serviceName && !resourceAttributes['service.namespace']) {
310
+ resourceAttributes['service.namespace'] = serviceName;
311
+ resourceAttributes['service.name'] = serviceName;
312
+ }
313
+ otelFields['Timestamp'] = timestamp;
314
+ otelFields['SeverityText'] = severityText;
315
+ otelFields['Body'] = messageParts.length > 0 ? messageParts.join(' ') : 'No message';
316
+ otelFields['ResourceAttributes'] = resourceAttributes;
317
+ otelFields['LogAttributes'] = logAttributes;
318
+ Object.assign(beamableLog, otelFields);
319
+ if (otlpProviderRef === null || otlpProviderRef === void 0 ? void 0 : otlpProviderRef.provider) {
320
+ try {
321
+ const otlpLogger = otlpProviderRef.provider.getLogger(serviceName || 'beamable-node-runtime', undefined, {
322
+ schemaUrl: undefined,
323
+ });
324
+ const severityNumberMap = {
325
+ 'Debug': 5,
326
+ 'Info': 9,
327
+ 'Warning': 13,
328
+ 'Error': 17,
329
+ 'Fatal': 21,
330
+ };
331
+ otlpLogger.emit({
332
+ severityNumber: severityNumberMap[level] || 9,
333
+ severityText: severityText,
334
+ body: messageParts.length > 0 ? messageParts.join(' ') : 'No message',
335
+ attributes: {
336
+ ...logAttributes,
337
+ ...(pinoLog.component ? { component: String(pinoLog.component) } : {}),
338
+ },
339
+ timestamp: new Date(timestamp).getTime() * 1000000,
340
+ observedTimestamp: Date.now() * 1000000,
341
+ });
342
+ }
343
+ catch (otlpError) {
344
+ }
345
+ }
346
+ const output = JSON.stringify(beamableLog) + '\n';
347
+ callback(null, Buffer.from(output, 'utf8'));
348
+ }
349
+ catch (error) {
350
+ const fallbackLog = {
351
+ __t: new Date().toISOString(),
352
+ __l: 'Error',
353
+ __m: `Failed to parse log entry: ${chunk.toString().substring(0, 200)}`,
354
+ };
355
+ callback(null, Buffer.from(JSON.stringify(fallbackLog) + '\n', 'utf8'));
356
+ }
357
+ },
358
+ });
359
+ }
360
+ function createLogger(env, options = {}) {
361
+ var _a, _b, _c;
362
+ const configuredDestination = (_a = options.destinationPath) !== null && _a !== void 0 ? _a : process.env.LOG_PATH;
363
+ const usePrettyLogs = shouldUsePrettyLogs();
364
+ const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
365
+ const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
366
+ const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;
367
+ const otlpProviderRef = { provider: null };
368
+ if (options.otlpEndpoint) {
369
+ const originalEndpoint = process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;
370
+ process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT = options.otlpEndpoint;
371
+ const initLogger = (0, pino_1.default)({
372
+ name: 'beamable-otlp-init',
373
+ level: 'info',
374
+ }, process.stdout);
375
+ initializeOtlpLogging(options.serviceName, options.qualifiedServiceName, env, initLogger).then((provider) => {
376
+ if (provider) {
377
+ otlpProviderRef.provider = provider;
378
+ initLogger.info(`[OTLP] OTLP provider created using existing collector at ${options.otlpEndpoint}`);
379
+ initLogger.info(`[OTLP] OpenTelemetry logging initialized. Endpoint: ${options.otlpEndpoint}/v1/logs, Service: ${options.serviceName || 'unknown'}`);
380
+ }
381
+ else {
382
+ initLogger.warn('[OTLP] OTLP provider creation returned null, structured logs will not be sent via OTLP');
383
+ otlpProviderRef.provider = null;
384
+ }
385
+ }).catch((error) => {
386
+ const errorMsg = error instanceof Error ? error.message : String(error);
387
+ initLogger.error(`[OTLP] Failed to create OTLP provider: ${errorMsg}`);
388
+ otlpProviderRef.provider = null;
389
+ });
390
+ if (originalEndpoint !== undefined) {
391
+ process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT = originalEndpoint;
392
+ }
393
+ else {
394
+ delete process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;
395
+ }
396
+ }
397
+ else {
398
+ otlpProviderRef.provider = null;
399
+ if (standardOtelEnabled) {
400
+ (async () => {
401
+ const bgLogger = (0, pino_1.default)({ name: 'beamable-otlp-bg', level: 'info' }, process.stdout);
402
+ const maxAttempts = 30;
403
+ const checkInterval = 1000;
404
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
405
+ try {
406
+ const { isCollectorRunning } = await Promise.resolve().then(() => __importStar(require('./collector-manager.js')));
407
+ const collectorStatus = await isCollectorRunning();
408
+ if (collectorStatus.isRunning && collectorStatus.isReady && collectorStatus.otlpEndpoint) {
409
+ const endpoint = collectorStatus.otlpEndpoint.startsWith('http')
410
+ ? collectorStatus.otlpEndpoint
411
+ : `http://${collectorStatus.otlpEndpoint}`;
412
+ const newProvider = await initializeOtlpLogging(options.serviceName, options.qualifiedServiceName, env, bgLogger);
413
+ if (newProvider) {
414
+ otlpProviderRef.provider = newProvider;
415
+ console.error(`[OTLP] Connected to collector at ${endpoint} (background connection)`);
416
+ break;
417
+ }
418
+ }
419
+ }
420
+ catch (error) {
421
+ }
422
+ if (attempt < maxAttempts - 1) {
423
+ await new Promise(resolve => setTimeout(resolve, checkInterval));
424
+ }
425
+ }
426
+ })();
427
+ }
428
+ }
429
+ const pinoOptions = {
430
+ name: (_b = options.name) !== null && _b !== void 0 ? _b : 'beamable-node-runtime',
431
+ level: env.logLevel,
432
+ base: {
433
+ cid: env.cid,
434
+ pid: env.pid,
435
+ routingKey: (_c = env.routingKey) !== null && _c !== void 0 ? _c : null,
436
+ sdkVersionExecution: env.sdkVersionExecution,
437
+ serviceName: options.serviceName,
438
+ qualifiedServiceName: options.qualifiedServiceName,
439
+ },
440
+ redact: {
441
+ paths: ['secret', 'refreshToken'],
442
+ censor: '***',
443
+ },
444
+ timestamp: pino_1.default.stdTimeFunctions.isoTime,
445
+ };
446
+ if (!configuredDestination || configuredDestination === '-' || configuredDestination === 'stdout' || configuredDestination === 'console') {
447
+ if (!usePrettyLogs) {
448
+ const beamableFormatter = createBeamableLogFormatter(options.serviceName, options.qualifiedServiceName, otlpProviderRef);
449
+ beamableFormatter.pipe(process.stdout);
450
+ return (0, pino_1.default)(pinoOptions, beamableFormatter);
451
+ }
452
+ else {
453
+ try {
454
+ const requireFn = getRequire();
455
+ const pinoPretty = requireFn('pino-pretty');
456
+ const prettyStream = pinoPretty({
457
+ colorize: true,
458
+ translateTime: 'HH:MM:ss.l',
459
+ ignore: 'pid,hostname',
460
+ singleLine: false,
461
+ });
462
+ return (0, pino_1.default)(pinoOptions, prettyStream);
463
+ }
464
+ catch {
465
+ return (0, pino_1.default)(pinoOptions, process.stdout);
466
+ }
467
+ }
468
+ }
469
+ const resolvedDestination = configuredDestination === 'temp' ? (0, env_js_1.ensureWritableTempDirectory)() : configuredDestination;
470
+ if (!usePrettyLogs) {
471
+ const beamableFormatter = createBeamableLogFormatter(options.serviceName, options.qualifiedServiceName, otlpProviderRef);
472
+ const fileStream = (0, pino_1.destination)({ dest: resolvedDestination, mkdir: true, append: true, sync: false });
473
+ beamableFormatter.pipe(fileStream);
474
+ return (0, pino_1.default)(pinoOptions, beamableFormatter);
475
+ }
476
+ else {
477
+ const fileStream = (0, pino_1.destination)({ dest: resolvedDestination, mkdir: true, append: true, sync: false });
478
+ return (0, pino_1.default)(pinoOptions, fileStream);
479
+ }
480
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAa,EAAe,KAAK,MAAM,EAAsB,MAAM,MAAM,CAAC;AAI1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAiCpD,UAAU,oBAAoB;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA8eD,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAgN/F"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAa,EAAe,KAAK,MAAM,EAAsB,MAAM,MAAM,CAAC;AAI1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAiCpD,UAAU,oBAAoB;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA8eD,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CA6L/F"}
package/dist/logger.js CHANGED
@@ -501,42 +501,26 @@ export function createLogger(env, options = {}) {
501
501
  name: 'beamable-otlp-init',
502
502
  level: 'info',
503
503
  }, process.stdout);
504
- // Create provider synchronously - since endpoint is explicitly provided,
505
- // initializeOtlpLogging will skip discovery and create provider directly
506
- let provider = null;
507
- let completed = false;
508
- initializeOtlpLogging(options.serviceName, options.qualifiedServiceName, env, initLogger).then((result) => {
509
- provider = result;
510
- completed = true;
511
- if (result) {
504
+ // Create OTLP provider asynchronously (non-blocking)
505
+ // Since endpoint is explicitly provided and collector is already ready,
506
+ // this should complete quickly, but we don't block for it
507
+ initializeOtlpLogging(options.serviceName, options.qualifiedServiceName, env, initLogger).then((provider) => {
508
+ if (provider) {
509
+ otlpProviderRef.provider = provider;
512
510
  initLogger.info(`[OTLP] OTLP provider created using existing collector at ${options.otlpEndpoint}`);
511
+ initLogger.info(`[OTLP] OpenTelemetry logging initialized. Endpoint: ${options.otlpEndpoint}/v1/logs, Service: ${options.serviceName || 'unknown'}`);
513
512
  }
514
- }).catch((error) => {
515
- initLogger.error(`[OTLP] Failed to create OTLP provider: ${error instanceof Error ? error.message : String(error)}`);
516
- completed = true;
517
- provider = null;
518
- });
519
- // Wait briefly for provider creation (should be very fast, < 1 second)
520
- // eslint-disable-next-line @typescript-eslint/no-require-imports
521
- const deasync = require('deasync');
522
- const startTime = Date.now();
523
- const timeout = 2000; // 2 second timeout (should be fast since no discovery needed)
524
- deasync.loopWhile(() => {
525
- if (Date.now() - startTime >= timeout) {
526
- return false;
513
+ else {
514
+ initLogger.warn('[OTLP] OTLP provider creation returned null, structured logs will not be sent via OTLP');
515
+ otlpProviderRef.provider = null;
527
516
  }
528
- return !completed;
529
- });
530
- // CRITICAL: Only set provider if it was successfully created
531
- // This ensures structured logs are only created when OTLP is ready
532
- if (provider) {
533
- otlpProviderRef.provider = provider;
534
- initLogger.info(`[OTLP] OpenTelemetry logging initialized. Endpoint: ${options.otlpEndpoint}/v1/logs, Service: ${options.serviceName || 'unknown'}`);
535
- }
536
- else {
537
- initLogger.warn('[OTLP] OTLP provider creation failed, structured logs will not be sent via OTLP');
517
+ }).catch((error) => {
518
+ const errorMsg = error instanceof Error ? error.message : String(error);
519
+ initLogger.error(`[OTLP] Failed to create OTLP provider: ${errorMsg}`);
538
520
  otlpProviderRef.provider = null;
539
- }
521
+ });
522
+ // Don't wait - logger will work immediately with console output,
523
+ // and OTLP will be added when the provider is ready (very quickly since collector is already running)
540
524
  // Restore original endpoint if it existed
541
525
  if (originalEndpoint !== undefined) {
542
526
  process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT = originalEndpoint;