@omen.foundation/node-microservice-runtime 0.1.60 → 0.1.62

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.
@@ -146,6 +146,11 @@ async function fetchClickHouseCredentials(env) {
146
146
  return credentials;
147
147
  }
148
148
  function getCollectorStoragePath() {
149
+ const productionPath = '/opt/beam/collectors';
150
+ const productionVersionPath = (0, path_1.join)(productionPath, COLLECTOR_VERSION);
151
+ if ((0, fs_1.existsSync)(productionPath)) {
152
+ return productionVersionPath;
153
+ }
149
154
  const tempDir = process.env.TMPDIR || process.env.TMP || '/tmp';
150
155
  return (0, path_1.join)(tempDir, 'beam', 'collectors', COLLECTOR_VERSION);
151
156
  }
@@ -310,12 +315,42 @@ async function resolveCollector(allowDownload = true, logger) {
310
315
  configPath: (0, fs_1.existsSync)(configPath) ? configPath : null,
311
316
  };
312
317
  }
313
- function discoverCollectorViaUDP(timeoutMs = 5000) {
318
+ function discoverCollectorViaUDP(timeoutMs = 1000) {
314
319
  return new Promise((resolve) => {
315
320
  const socket = dgram_1.default.createSocket('udp4');
316
321
  const discovered = [];
317
322
  let timeout;
323
+ let resolved = false;
318
324
  const startTime = Date.now();
325
+ const safetyTimeout = setTimeout(() => {
326
+ if (!resolved) {
327
+ console.log(`[UDP Discovery] Safety timeout triggered - forcing resolution`);
328
+ resolved = true;
329
+ try {
330
+ socket.removeAllListeners();
331
+ socket.close();
332
+ }
333
+ catch (e) {
334
+ }
335
+ clearTimeout(timeout);
336
+ resolve(discovered.length > 0 ? discovered[0] : null);
337
+ }
338
+ }, timeoutMs + 100);
339
+ const doResolve = (result) => {
340
+ if (!resolved) {
341
+ resolved = true;
342
+ clearTimeout(timeout);
343
+ clearTimeout(safetyTimeout);
344
+ try {
345
+ socket.removeAllListeners();
346
+ socket.close();
347
+ }
348
+ catch (e) {
349
+ }
350
+ console.log(`[UDP Discovery] Resolving promise with result: ${result ? 'found' : 'null'}`);
351
+ resolve(result);
352
+ }
353
+ };
319
354
  socket.on('message', (msg) => {
320
355
  try {
321
356
  const message = JSON.parse(msg.toString());
@@ -323,17 +358,16 @@ function discoverCollectorViaUDP(timeoutMs = 5000) {
323
358
  discovered.push(message);
324
359
  const elapsed = Date.now() - startTime;
325
360
  console.log(`[UDP Discovery] Found collector after ${elapsed}ms: ${message.otlpEndpoint}`);
361
+ doResolve(discovered[0]);
326
362
  }
327
363
  }
328
364
  catch (error) {
329
365
  }
330
366
  });
331
367
  socket.on('error', (err) => {
332
- clearTimeout(timeout);
333
- socket.close();
334
368
  const elapsed = Date.now() - startTime;
335
369
  console.log(`[UDP Discovery] Socket error after ${elapsed}ms: ${err.message}`);
336
- resolve(null);
370
+ doResolve(null);
337
371
  });
338
372
  socket.bind(() => {
339
373
  socket.setBroadcast(true);
@@ -346,13 +380,7 @@ function discoverCollectorViaUDP(timeoutMs = 5000) {
346
380
  else {
347
381
  console.log(`[UDP Discovery] Timeout after ${elapsed}ms, no collector found`);
348
382
  }
349
- try {
350
- socket.close(() => {
351
- });
352
- }
353
- catch (closeError) {
354
- }
355
- resolve(discovered.length > 0 ? discovered[0] : null);
383
+ doResolve(discovered.length > 0 ? discovered[0] : null);
356
384
  }, timeoutMs);
357
385
  });
358
386
  });
@@ -417,9 +445,10 @@ async function isCollectorRunning() {
417
445
  try {
418
446
  const udpStartTime = Date.now();
419
447
  console.log('[UDP Discovery] Starting UDP discovery in isCollectorRunning()...');
420
- const discovered = await discoverCollectorViaUDP(2000);
448
+ console.log('[UDP Discovery] Calling discoverCollectorViaUDP(1000)...');
449
+ const discovered = await discoverCollectorViaUDP(1000);
421
450
  const udpElapsed = Date.now() - udpStartTime;
422
- console.log(`[UDP Discovery] UDP discovery promise resolved after ${udpElapsed}ms`);
451
+ console.log(`[UDP Discovery] UDP discovery promise resolved after ${udpElapsed}ms, result: ${discovered ? 'found' : 'null'}`);
423
452
  if (discovered) {
424
453
  console.log(`[UDP Discovery] Found collector in ${udpElapsed}ms: ${discovered.otlpEndpoint}`);
425
454
  return {
@@ -435,7 +464,11 @@ async function isCollectorRunning() {
435
464
  }
436
465
  }
437
466
  catch (error) {
438
- console.log(`[UDP Discovery] Error in isCollectorRunning(): ${error instanceof Error ? error.message : String(error)}`);
467
+ const errorMsg = error instanceof Error ? error.message : String(error);
468
+ console.log(`[UDP Discovery] Error in isCollectorRunning(): ${errorMsg}`);
469
+ if (error instanceof Error && error.stack) {
470
+ console.log(`[UDP Discovery] Error stack: ${error.stack}`);
471
+ }
439
472
  }
440
473
  console.log('[UDP Discovery] Returning default not-running status from isCollectorRunning()');
441
474
  return {
@@ -785,13 +818,14 @@ async function discoverOrStartCollector(logger, standardOtelEnabled, env) {
785
818
  }
786
819
  }
787
820
  if (!globalCollectorProcess) {
788
- logger.info('[Collector] Checking for existing collector via UDP discovery (timeout: 2s)...');
821
+ logger.info('[Collector] Quick check for existing collector via UDP discovery (timeout: 1s, matching C#)...');
789
822
  const udpStartTime = Date.now();
823
+ logger.info('[Collector] Calling isCollectorRunning()...');
790
824
  const status = await isCollectorRunning();
791
825
  const udpElapsed = Date.now() - udpStartTime;
792
- logger.info(`[Collector] UDP discovery completed in ${udpElapsed}ms: isRunning=${status.isRunning}, isReady=${status.isReady}, endpoint=${status.otlpEndpoint || 'none'}`);
826
+ logger.info(`[Collector] isCollectorRunning() returned after ${udpElapsed}ms: isRunning=${status.isRunning}, isReady=${status.isReady}, endpoint=${status.otlpEndpoint || 'none'}`);
793
827
  if (status.isRunning && status.isReady && status.otlpEndpoint) {
794
- logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}`);
828
+ logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}, will reuse it`);
795
829
  return `http://${status.otlpEndpoint}`;
796
830
  }
797
831
  logger.info('[Collector] No existing collector found, will start new one...');
@@ -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,CAsDhC;AAoQD;;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,CAkFnE;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,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwCxB;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,CAuNtD;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,CAuKxB"}
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,CAsDhC;AAuSD;;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,CAuFnE;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,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwCxB;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,CAuNtD;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,CAyKxB"}
@@ -124,9 +124,18 @@ export async function fetchClickHouseCredentials(env) {
124
124
  }
125
125
  /**
126
126
  * Gets the collector storage directory (similar to C# LocalApplicationData/beam/collectors/version)
127
+ * Checks production location first (pre-installed in Docker), then falls back to temp directory
127
128
  */
128
129
  function getCollectorStoragePath() {
129
- // Use temp directory for now - in containers this should be writable
130
+ // Check production location first (pre-installed in Docker image at /opt/beam/collectors)
131
+ // This avoids runtime download delays (~12 seconds)
132
+ const productionPath = '/opt/beam/collectors';
133
+ const productionVersionPath = join(productionPath, COLLECTOR_VERSION);
134
+ // Use production path if it exists (Docker image pre-installed collector)
135
+ if (existsSync(productionPath)) {
136
+ return productionVersionPath;
137
+ }
138
+ // Fallback to temp directory (local development without Docker)
130
139
  const tempDir = process.env.TMPDIR || process.env.TMP || '/tmp';
131
140
  return join(tempDir, 'beam', 'collectors', COLLECTOR_VERSION);
132
141
  }
@@ -314,12 +323,45 @@ async function resolveCollector(allowDownload = true, logger) {
314
323
  /**
315
324
  * Discovers collector via UDP broadcast
316
325
  */
317
- function discoverCollectorViaUDP(timeoutMs = 5000) {
326
+ function discoverCollectorViaUDP(timeoutMs = 1000) {
318
327
  return new Promise((resolve) => {
319
328
  const socket = dgram.createSocket('udp4');
320
329
  const discovered = [];
321
330
  let timeout;
331
+ let resolved = false; // Guard to prevent double resolution
322
332
  const startTime = Date.now();
333
+ // Safety timeout - force resolve after timeout + 100ms buffer
334
+ const safetyTimeout = setTimeout(() => {
335
+ if (!resolved) {
336
+ console.log(`[UDP Discovery] Safety timeout triggered - forcing resolution`);
337
+ resolved = true;
338
+ try {
339
+ socket.removeAllListeners();
340
+ socket.close();
341
+ }
342
+ catch (e) {
343
+ // Ignore
344
+ }
345
+ clearTimeout(timeout);
346
+ resolve(discovered.length > 0 ? discovered[0] : null);
347
+ }
348
+ }, timeoutMs + 100);
349
+ const doResolve = (result) => {
350
+ if (!resolved) {
351
+ resolved = true;
352
+ clearTimeout(timeout);
353
+ clearTimeout(safetyTimeout);
354
+ try {
355
+ socket.removeAllListeners();
356
+ socket.close();
357
+ }
358
+ catch (e) {
359
+ // Ignore
360
+ }
361
+ console.log(`[UDP Discovery] Resolving promise with result: ${result ? 'found' : 'null'}`);
362
+ resolve(result);
363
+ }
364
+ };
323
365
  socket.on('message', (msg) => {
324
366
  try {
325
367
  const message = JSON.parse(msg.toString());
@@ -328,6 +370,8 @@ function discoverCollectorViaUDP(timeoutMs = 5000) {
328
370
  discovered.push(message);
329
371
  const elapsed = Date.now() - startTime;
330
372
  console.log(`[UDP Discovery] Found collector after ${elapsed}ms: ${message.otlpEndpoint}`);
373
+ // Resolve immediately when collector found
374
+ doResolve(discovered[0]);
331
375
  }
332
376
  }
333
377
  catch (error) {
@@ -335,11 +379,9 @@ function discoverCollectorViaUDP(timeoutMs = 5000) {
335
379
  }
336
380
  });
337
381
  socket.on('error', (err) => {
338
- clearTimeout(timeout);
339
- socket.close();
340
382
  const elapsed = Date.now() - startTime;
341
383
  console.log(`[UDP Discovery] Socket error after ${elapsed}ms: ${err.message}`);
342
- resolve(null);
384
+ doResolve(null);
343
385
  });
344
386
  socket.bind(() => {
345
387
  socket.setBroadcast(true);
@@ -352,17 +394,7 @@ function discoverCollectorViaUDP(timeoutMs = 5000) {
352
394
  else {
353
395
  console.log(`[UDP Discovery] Timeout after ${elapsed}ms, no collector found`);
354
396
  }
355
- // Close socket and resolve immediately (don't wait for close callback)
356
- try {
357
- socket.close(() => {
358
- // Socket closed callback (optional, we don't wait for this)
359
- });
360
- }
361
- catch (closeError) {
362
- // Ignore close errors
363
- }
364
- // Return the first discovered collector immediately
365
- resolve(discovered.length > 0 ? discovered[0] : null);
397
+ doResolve(discovered.length > 0 ? discovered[0] : null);
366
398
  }, timeoutMs);
367
399
  });
368
400
  });
@@ -446,9 +478,10 @@ export async function isCollectorRunning() {
446
478
  try {
447
479
  const udpStartTime = Date.now();
448
480
  console.log('[UDP Discovery] Starting UDP discovery in isCollectorRunning()...');
449
- const discovered = await discoverCollectorViaUDP(2000);
481
+ console.log('[UDP Discovery] Calling discoverCollectorViaUDP(1000)...');
482
+ const discovered = await discoverCollectorViaUDP(1000); // Match C#: 1 second max (10 attempts × 100ms)
450
483
  const udpElapsed = Date.now() - udpStartTime;
451
- console.log(`[UDP Discovery] UDP discovery promise resolved after ${udpElapsed}ms`);
484
+ console.log(`[UDP Discovery] UDP discovery promise resolved after ${udpElapsed}ms, result: ${discovered ? 'found' : 'null'}`);
452
485
  if (discovered) {
453
486
  console.log(`[UDP Discovery] Found collector in ${udpElapsed}ms: ${discovered.otlpEndpoint}`);
454
487
  return {
@@ -465,7 +498,11 @@ export async function isCollectorRunning() {
465
498
  }
466
499
  catch (error) {
467
500
  // Discovery failed, collector probably not running
468
- console.log(`[UDP Discovery] Error in isCollectorRunning(): ${error instanceof Error ? error.message : String(error)}`);
501
+ const errorMsg = error instanceof Error ? error.message : String(error);
502
+ console.log(`[UDP Discovery] Error in isCollectorRunning(): ${errorMsg}`);
503
+ if (error instanceof Error && error.stack) {
504
+ console.log(`[UDP Discovery] Error stack: ${error.stack}`);
505
+ }
469
506
  }
470
507
  console.log('[UDP Discovery] Returning default not-running status from isCollectorRunning()');
471
508
  return {
@@ -929,16 +966,18 @@ export async function discoverOrStartCollector(logger, standardOtelEnabled, env)
929
966
  globalCollectorStderr = [];
930
967
  }
931
968
  }
932
- // First, check if collector is already running (via UDP discovery)
969
+ // First, quick check if collector is already running (via UDP discovery)
970
+ // Match C#: 10 attempts × 100ms = 1 second max (much faster than before)
933
971
  // Skip UDP discovery if we already have a process reference (faster)
934
972
  if (!globalCollectorProcess) {
935
- logger.info('[Collector] Checking for existing collector via UDP discovery (timeout: 2s)...');
973
+ logger.info('[Collector] Quick check for existing collector via UDP discovery (timeout: 1s, matching C#)...');
936
974
  const udpStartTime = Date.now();
975
+ logger.info('[Collector] Calling isCollectorRunning()...');
937
976
  const status = await isCollectorRunning();
938
977
  const udpElapsed = Date.now() - udpStartTime;
939
- logger.info(`[Collector] UDP discovery completed in ${udpElapsed}ms: isRunning=${status.isRunning}, isReady=${status.isReady}, endpoint=${status.otlpEndpoint || 'none'}`);
978
+ logger.info(`[Collector] isCollectorRunning() returned after ${udpElapsed}ms: isRunning=${status.isRunning}, isReady=${status.isReady}, endpoint=${status.otlpEndpoint || 'none'}`);
940
979
  if (status.isRunning && status.isReady && status.otlpEndpoint) {
941
- logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}`);
980
+ logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}, will reuse it`);
942
981
  return `http://${status.otlpEndpoint}`;
943
982
  }
944
983
  logger.info('[Collector] No existing collector found, will start new one...');