@omen.foundation/node-microservice-runtime 0.1.51 → 0.1.53
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/collector-manager.cjs +82 -13
- package/dist/collector-manager.d.ts +17 -4
- package/dist/collector-manager.d.ts.map +1 -1
- package/dist/collector-manager.js +115 -19
- package/dist/collector-manager.js.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/logger.cjs +35 -69
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +49 -100
- package/dist/logger.js.map +1 -1
- package/dist/runtime.cjs +29 -8
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +39 -22
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
- package/src/collector-manager.ts +132 -18
- package/src/index.ts +2 -0
- package/src/logger.ts +60 -121
- package/src/runtime.ts +40 -23
|
@@ -40,6 +40,8 @@ exports.fetchClickHouseCredentials = fetchClickHouseCredentials;
|
|
|
40
40
|
exports.getClickHouseCredentialsStatus = getClickHouseCredentialsStatus;
|
|
41
41
|
exports.isCollectorRunning = isCollectorRunning;
|
|
42
42
|
exports.addAuthEnvironmentVars = addAuthEnvironmentVars;
|
|
43
|
+
exports.startCollectorAndWaitForReady = startCollectorAndWaitForReady;
|
|
44
|
+
exports.startCollectorAsync = startCollectorAsync;
|
|
43
45
|
exports.setupCollectorBeforeLogging = setupCollectorBeforeLogging;
|
|
44
46
|
exports.startCollector = startCollector;
|
|
45
47
|
exports.getCollectorProcessStatus = getCollectorProcessStatus;
|
|
@@ -272,20 +274,24 @@ async function resolveCollector(allowDownload = true, logger) {
|
|
|
272
274
|
else if ((0, fs_1.existsSync)(configPath)) {
|
|
273
275
|
logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Config found at: ${configPath}`);
|
|
274
276
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
283
|
-
logger === null || logger === void 0 ? void 0 : logger.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);
|
|
284
|
-
if (error instanceof Error && errorMsg.includes(item.url)) {
|
|
285
|
-
throw error;
|
|
277
|
+
if (itemsToDownload.length > 0) {
|
|
278
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Downloading ${itemsToDownload.length} item(s) in parallel...`);
|
|
279
|
+
const downloadPromises = itemsToDownload.map(async (item) => {
|
|
280
|
+
try {
|
|
281
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Downloading ${item.url}...`);
|
|
282
|
+
await downloadAndDecompressGzip(item.url, item.path, item.executable);
|
|
283
|
+
logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Downloaded to ${item.path}`);
|
|
286
284
|
}
|
|
287
|
-
|
|
288
|
-
|
|
285
|
+
catch (error) {
|
|
286
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
287
|
+
logger === null || logger === void 0 ? void 0 : logger.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);
|
|
288
|
+
if (error instanceof Error && errorMsg.includes(item.url)) {
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
throw new Error(`Failed to download collector ${item.executable ? 'binary' : 'config'} from ${item.url}: ${errorMsg}`);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
await Promise.all(downloadPromises);
|
|
289
295
|
}
|
|
290
296
|
return {
|
|
291
297
|
binaryPath: (0, fs_1.existsSync)(binaryPath) ? binaryPath : null,
|
|
@@ -423,6 +429,69 @@ function addAuthEnvironmentVars(endpoint, username, password) {
|
|
|
423
429
|
throw new Error(`Failed to set ClickHouse credentials in process.env - this should never happen in Node.js`);
|
|
424
430
|
}
|
|
425
431
|
}
|
|
432
|
+
async function startCollectorAndWaitForReady(env, timeoutMs = 180000) {
|
|
433
|
+
const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
|
|
434
|
+
const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
|
|
435
|
+
const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;
|
|
436
|
+
const hasExplicitEndpoint = !!process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
437
|
+
if (!standardOtelEnabled && !hasExplicitEndpoint) {
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
const initLogger = (0, pino_1.default)({
|
|
441
|
+
name: 'beamable-otlp-init',
|
|
442
|
+
level: 'info',
|
|
443
|
+
}, process.stdout);
|
|
444
|
+
initLogger.info('[OTLP] Setting up collector (waiting for readiness before enabling Portal logs)...');
|
|
445
|
+
const startTime = Date.now();
|
|
446
|
+
let endpoint = null;
|
|
447
|
+
let completed = false;
|
|
448
|
+
const setupPromise = discoverOrStartCollector(initLogger, standardOtelEnabled, env);
|
|
449
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
450
|
+
setTimeout(() => {
|
|
451
|
+
if (!completed) {
|
|
452
|
+
initLogger.warn(`[OTLP] Collector setup timeout after ${timeoutMs}ms, continuing without Portal logs`);
|
|
453
|
+
completed = true;
|
|
454
|
+
resolve(null);
|
|
455
|
+
}
|
|
456
|
+
}, timeoutMs);
|
|
457
|
+
});
|
|
458
|
+
const result = await Promise.race([setupPromise, timeoutPromise]);
|
|
459
|
+
if (result && !completed) {
|
|
460
|
+
endpoint = result;
|
|
461
|
+
completed = true;
|
|
462
|
+
const elapsed = Date.now() - startTime;
|
|
463
|
+
initLogger.info(`[OTLP] Collector ready at ${endpoint} (took ${elapsed}ms). Portal logs now enabled.`);
|
|
464
|
+
return endpoint;
|
|
465
|
+
}
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
function startCollectorAsync(env) {
|
|
469
|
+
const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
|
|
470
|
+
const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
|
|
471
|
+
const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;
|
|
472
|
+
const hasExplicitEndpoint = !!process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
473
|
+
if (!standardOtelEnabled && !hasExplicitEndpoint) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const initLogger = (0, pino_1.default)({
|
|
477
|
+
name: 'beamable-otlp-init',
|
|
478
|
+
level: 'info',
|
|
479
|
+
}, process.stdout);
|
|
480
|
+
initLogger.info('[OTLP] Starting collector setup in background (non-blocking)...');
|
|
481
|
+
discoverOrStartCollector(initLogger, standardOtelEnabled, env)
|
|
482
|
+
.then((result) => {
|
|
483
|
+
if (result) {
|
|
484
|
+
initLogger.info(`[OTLP] Collector setup complete in background, endpoint: ${result}`);
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
initLogger.warn('[OTLP] Collector setup returned null, OTLP logging will be disabled');
|
|
488
|
+
}
|
|
489
|
+
})
|
|
490
|
+
.catch((error) => {
|
|
491
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
492
|
+
initLogger.error(`[OTLP] Failed to setup collector in background: ${errorMsg}`);
|
|
493
|
+
});
|
|
494
|
+
}
|
|
426
495
|
function setupCollectorBeforeLogging(env, timeoutMs = 60000) {
|
|
427
496
|
const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
|
|
428
497
|
const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
|
|
@@ -41,10 +41,23 @@ export declare function isCollectorRunning(): Promise<CollectorStatus>;
|
|
|
41
41
|
*/
|
|
42
42
|
export declare function addAuthEnvironmentVars(endpoint: string, username: string, password: string): void;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
* This ensures
|
|
46
|
-
*
|
|
47
|
-
|
|
44
|
+
* Starts the collector and waits for it to be ready before returning.
|
|
45
|
+
* This ensures Portal logs (structured logs via OTLP) only start appearing AFTER collector is ready.
|
|
46
|
+
* Returns the OTLP endpoint when ready, or null if it times out or fails.
|
|
47
|
+
*/
|
|
48
|
+
export declare function startCollectorAndWaitForReady(env: EnvironmentConfig, timeoutMs?: number): Promise<string | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Starts the collector asynchronously in the background (non-blocking).
|
|
51
|
+
* This allows the service to start immediately while collector downloads/starts.
|
|
52
|
+
* Returns immediately - collector setup happens in background.
|
|
53
|
+
* @deprecated Use startCollectorAndWaitForReady() to ensure Portal logs only appear after collector is ready
|
|
54
|
+
*/
|
|
55
|
+
export declare function startCollectorAsync(env: EnvironmentConfig): void;
|
|
56
|
+
/**
|
|
57
|
+
* Sets up the collector BEFORE logging is initialized (DEPRECATED - blocking approach).
|
|
58
|
+
* This function is kept for backwards compatibility but is no longer recommended.
|
|
59
|
+
* Use startCollectorAsync() for non-blocking startup instead.
|
|
60
|
+
* @deprecated Use startCollectorAsync() for non-blocking startup
|
|
48
61
|
*/
|
|
49
62
|
export declare function setupCollectorBeforeLogging(env: EnvironmentConfig, timeoutMs?: number): string | null;
|
|
50
63
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-manager.d.ts","sourceRoot":"","sources":["../src/collector-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AAOpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAYpD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuCD;;GAEG;AACH,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAqCD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAwChC;
|
|
1
|
+
{"version":3,"file":"collector-manager.d.ts","sourceRoot":"","sources":["../src/collector-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AAOpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAYpD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuCD;;GAEG;AACH,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAqCD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAwChC;AAiPD;;GAEG;AACH,wBAAgB,8BAA8B,IAAI;IAChD,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC;CAC3C,CAoBA;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAyEnE;AA0BD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAYjG;AAED;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,iBAAiB,EACtB,SAAS,GAAE,MAAe,GACzB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmDxB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAsChE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,iBAAiB,EACtB,SAAS,GAAE,MAAc,GACxB,MAAM,GAAG,IAAI,CA8Ef;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,EACrB,GAAG,CAAC,EAAE,iBAAiB,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgNtD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI;IAC3C,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CASA;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,OAAO,EAC5B,GAAG,CAAC,EAAE,iBAAiB,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmJxB"}
|
|
@@ -270,22 +270,28 @@ async function resolveCollector(allowDownload = true, logger) {
|
|
|
270
270
|
else if (existsSync(configPath)) {
|
|
271
271
|
logger?.info(`[Collector] Config found at: ${configPath}`);
|
|
272
272
|
}
|
|
273
|
-
for (
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
282
|
-
logger?.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);
|
|
283
|
-
// Only wrap if the error doesn't already contain the URL
|
|
284
|
-
if (error instanceof Error && errorMsg.includes(item.url)) {
|
|
285
|
-
throw error; // Error already has URL and context
|
|
273
|
+
// Download items in parallel for faster startup (binary and config simultaneously)
|
|
274
|
+
if (itemsToDownload.length > 0) {
|
|
275
|
+
logger?.info(`[Collector] Downloading ${itemsToDownload.length} item(s) in parallel...`);
|
|
276
|
+
const downloadPromises = itemsToDownload.map(async (item) => {
|
|
277
|
+
try {
|
|
278
|
+
logger?.info(`[Collector] Downloading ${item.url}...`);
|
|
279
|
+
await downloadAndDecompressGzip(item.url, item.path, item.executable);
|
|
280
|
+
logger?.info(`[Collector] Downloaded to ${item.path}`);
|
|
286
281
|
}
|
|
287
|
-
|
|
288
|
-
|
|
282
|
+
catch (error) {
|
|
283
|
+
// Don't wrap the error again if it already contains the URL and details
|
|
284
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
285
|
+
logger?.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);
|
|
286
|
+
// Only wrap if the error doesn't already contain the URL
|
|
287
|
+
if (error instanceof Error && errorMsg.includes(item.url)) {
|
|
288
|
+
throw error; // Error already has URL and context
|
|
289
|
+
}
|
|
290
|
+
throw new Error(`Failed to download collector ${item.executable ? 'binary' : 'config'} from ${item.url}: ${errorMsg}`);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
// Wait for all downloads to complete (or fail)
|
|
294
|
+
await Promise.all(downloadPromises);
|
|
289
295
|
}
|
|
290
296
|
return {
|
|
291
297
|
binaryPath: existsSync(binaryPath) ? binaryPath : null,
|
|
@@ -462,10 +468,100 @@ export function addAuthEnvironmentVars(endpoint, username, password) {
|
|
|
462
468
|
}
|
|
463
469
|
}
|
|
464
470
|
/**
|
|
465
|
-
*
|
|
466
|
-
* This ensures
|
|
467
|
-
*
|
|
468
|
-
|
|
471
|
+
* Starts the collector and waits for it to be ready before returning.
|
|
472
|
+
* This ensures Portal logs (structured logs via OTLP) only start appearing AFTER collector is ready.
|
|
473
|
+
* Returns the OTLP endpoint when ready, or null if it times out or fails.
|
|
474
|
+
*/
|
|
475
|
+
export async function startCollectorAndWaitForReady(env, timeoutMs = 180000 // 3 minutes to allow for download + startup
|
|
476
|
+
) {
|
|
477
|
+
// Match C# logic: (this.InDocker() || UseLocalOtel) && !BEAM_DISABLE_STANDARD_OTEL
|
|
478
|
+
const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
|
|
479
|
+
const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
|
|
480
|
+
const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;
|
|
481
|
+
const hasExplicitEndpoint = !!process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
482
|
+
// If OTLP is not needed, return immediately
|
|
483
|
+
if (!standardOtelEnabled && !hasExplicitEndpoint) {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
// Create a minimal console logger for initialization messages (no OTLP yet)
|
|
487
|
+
const initLogger = pino({
|
|
488
|
+
name: 'beamable-otlp-init',
|
|
489
|
+
level: 'info',
|
|
490
|
+
}, process.stdout);
|
|
491
|
+
initLogger.info('[OTLP] Setting up collector (waiting for readiness before enabling Portal logs)...');
|
|
492
|
+
// Wait for collector to be ready with timeout
|
|
493
|
+
const startTime = Date.now();
|
|
494
|
+
let endpoint = null;
|
|
495
|
+
let completed = false;
|
|
496
|
+
// Start collector setup
|
|
497
|
+
const setupPromise = discoverOrStartCollector(initLogger, standardOtelEnabled, env);
|
|
498
|
+
// Set timeout
|
|
499
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
500
|
+
setTimeout(() => {
|
|
501
|
+
if (!completed) {
|
|
502
|
+
initLogger.warn(`[OTLP] Collector setup timeout after ${timeoutMs}ms, continuing without Portal logs`);
|
|
503
|
+
completed = true;
|
|
504
|
+
resolve(null);
|
|
505
|
+
}
|
|
506
|
+
}, timeoutMs);
|
|
507
|
+
});
|
|
508
|
+
// Race between setup and timeout
|
|
509
|
+
const result = await Promise.race([setupPromise, timeoutPromise]);
|
|
510
|
+
if (result && !completed) {
|
|
511
|
+
endpoint = result;
|
|
512
|
+
completed = true;
|
|
513
|
+
const elapsed = Date.now() - startTime;
|
|
514
|
+
initLogger.info(`[OTLP] Collector ready at ${endpoint} (took ${elapsed}ms). Portal logs now enabled.`);
|
|
515
|
+
return endpoint;
|
|
516
|
+
}
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Starts the collector asynchronously in the background (non-blocking).
|
|
521
|
+
* This allows the service to start immediately while collector downloads/starts.
|
|
522
|
+
* Returns immediately - collector setup happens in background.
|
|
523
|
+
* @deprecated Use startCollectorAndWaitForReady() to ensure Portal logs only appear after collector is ready
|
|
524
|
+
*/
|
|
525
|
+
export function startCollectorAsync(env) {
|
|
526
|
+
// Match C# logic: (this.InDocker() || UseLocalOtel) && !BEAM_DISABLE_STANDARD_OTEL
|
|
527
|
+
const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';
|
|
528
|
+
const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;
|
|
529
|
+
const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;
|
|
530
|
+
const hasExplicitEndpoint = !!process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
531
|
+
// If OTLP is not needed, return immediately
|
|
532
|
+
if (!standardOtelEnabled && !hasExplicitEndpoint) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
// Create a minimal console logger for initialization messages (no OTLP yet)
|
|
536
|
+
const initLogger = pino({
|
|
537
|
+
name: 'beamable-otlp-init',
|
|
538
|
+
level: 'info',
|
|
539
|
+
}, process.stdout);
|
|
540
|
+
initLogger.info('[OTLP] Starting collector setup in background (non-blocking)...');
|
|
541
|
+
// Start collector setup asynchronously - don't wait for it
|
|
542
|
+
// The service can start immediately, collector will connect when ready
|
|
543
|
+
discoverOrStartCollector(initLogger, standardOtelEnabled, env)
|
|
544
|
+
.then((result) => {
|
|
545
|
+
if (result) {
|
|
546
|
+
initLogger.info(`[OTLP] Collector setup complete in background, endpoint: ${result}`);
|
|
547
|
+
// Update the global logger provider if it exists to enable OTLP
|
|
548
|
+
// The logger will automatically start using OTLP once the provider is set
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
initLogger.warn('[OTLP] Collector setup returned null, OTLP logging will be disabled');
|
|
552
|
+
}
|
|
553
|
+
})
|
|
554
|
+
.catch((error) => {
|
|
555
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
556
|
+
initLogger.error(`[OTLP] Failed to setup collector in background: ${errorMsg}`);
|
|
557
|
+
});
|
|
558
|
+
// Return immediately - service can start serving requests
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Sets up the collector BEFORE logging is initialized (DEPRECATED - blocking approach).
|
|
562
|
+
* This function is kept for backwards compatibility but is no longer recommended.
|
|
563
|
+
* Use startCollectorAsync() for non-blocking startup instead.
|
|
564
|
+
* @deprecated Use startCollectorAsync() for non-blocking startup
|
|
469
565
|
*/
|
|
470
566
|
export function setupCollectorBeforeLogging(env, timeoutMs = 60000) {
|
|
471
567
|
// Match C# logic: (this.InDocker() || UseLocalOtel) && !BEAM_DISABLE_STANDARD_OTEL
|