@omen.foundation/node-microservice-runtime 0.1.52 → 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/src/runtime.ts CHANGED
@@ -4,7 +4,7 @@ import { GatewayRequester } from './requester.js';
4
4
  import { AuthManager } from './auth.js';
5
5
  import { createLogger } from './logger.js';
6
6
  import { loadEnvironmentConfig } from './env.js';
7
- import { startCollectorAsync } from './collector-manager.js';
7
+ import { startCollectorAndWaitForReady } from './collector-manager.js';
8
8
  import pino from 'pino';
9
9
  import { listRegisteredServices, getServiceOptions, getConfigureServicesHandlers, getInitializeServicesHandlers } from './decorators.js';
10
10
  import { generateOpenApiDocument } from './docs.js';
@@ -80,20 +80,52 @@ export class MicroserviceRuntime {
80
80
  const primaryService = registered[0];
81
81
  const qualifiedServiceName = `micro_${primaryService.qualifiedName}`;
82
82
 
83
- // STEP 3: Start collector asynchronously in background (NON-BLOCKING)
84
- // This allows the service to start immediately while collector downloads/starts
85
- // Logs will work immediately (stdout), OTLP will connect when collector is ready
86
- startupLogger.info('Starting OpenTelemetry collector setup in background (non-blocking)...');
87
- startCollectorAsync(this.env);
83
+ // STEP 3: Wait for collector to be ready BEFORE creating structured logger
84
+ // Portal logs (structured logs via OTLP) should only appear AFTER collector is ready
85
+ // This ensures all runtime startup logs are captured and appear in Portal
86
+ // Use deasync to wait synchronously (constructor can't be async)
87
+ startupLogger.info('Setting up OpenTelemetry collector (waiting for readiness before enabling Portal logs)...');
88
88
 
89
- // STEP 4: Create main logger immediately (service can start serving requests)
90
- // Logger works immediately via stdout, OTLP will connect when collector is ready
91
- // The logger will automatically start using OTLP once the collector is available
89
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
90
+ const deasync = require('deasync');
91
+ let otlpEndpoint: string | null = null;
92
+ let collectorReady = false;
93
+ let collectorError: string | null = null;
94
+
95
+ // Start collector setup asynchronously
96
+ startCollectorAndWaitForReady(this.env, 180000)
97
+ .then((endpoint) => {
98
+ otlpEndpoint = endpoint;
99
+ collectorReady = true;
100
+ if (endpoint) {
101
+ startupLogger.info(`Collector ready at ${endpoint}, creating structured logger for Portal logs...`);
102
+ } else {
103
+ startupLogger.warn('Collector setup did not complete in time, Portal logs will not be available');
104
+ }
105
+ })
106
+ .catch((error) => {
107
+ collectorError = error instanceof Error ? error.message : String(error);
108
+ collectorReady = true;
109
+ startupLogger.error(`Failed to setup collector: ${collectorError}`);
110
+ });
111
+
112
+ // Wait synchronously for collector to be ready (with timeout)
113
+ const startTime = Date.now();
114
+ const timeoutMs = 180000; // 3 minutes
115
+ deasync.loopWhile(() => {
116
+ if (Date.now() - startTime >= timeoutMs) {
117
+ return false; // Timeout
118
+ }
119
+ return !collectorReady; // Continue waiting if not ready
120
+ });
121
+
122
+ // STEP 4: Create main structured logger (collector is now ready, Portal logs will work)
123
+ // Pass the OTLP endpoint to ensure it uses the ready collector
92
124
  this.logger = createLogger(this.env, {
93
125
  name: 'beamable-node-microservice',
94
126
  serviceName: primaryService.name,
95
127
  qualifiedServiceName: qualifiedServiceName,
96
- // Don't pass otlpEndpoint - let it discover/connect when collector is ready
128
+ otlpEndpoint: otlpEndpoint || undefined, // Pass endpoint if collector was set up
97
129
  });
98
130
  this.serviceManager = new BeamableServiceManager(this.env, this.logger);
99
131