@omen.foundation/node-microservice-runtime 0.1.49 → 0.1.50
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 +65 -45
- package/dist/collector-manager.d.ts.map +1 -1
- package/dist/collector-manager.js +88 -57
- package/dist/collector-manager.js.map +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +8 -1
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
- package/src/collector-manager.ts +52 -18
- package/src/runtime.ts +8 -1
|
@@ -82,6 +82,7 @@ let globalCollectorProcess = null;
|
|
|
82
82
|
let globalCollectorStartError = null;
|
|
83
83
|
let globalCollectorExitCode = null;
|
|
84
84
|
let globalCollectorStderr = [];
|
|
85
|
+
let globalCollectorStartupPromise = null;
|
|
85
86
|
let globalCollectorInitError = null;
|
|
86
87
|
function calculateSignature(pid, secret, uriPathAndQuery, body = null, version = '1') {
|
|
87
88
|
let dataToSign = `${secret}${pid}${version}${uriPathAndQuery}`;
|
|
@@ -640,6 +641,18 @@ async function discoverOrStartCollector(logger, standardOtelEnabled, env) {
|
|
|
640
641
|
if (!standardOtelEnabled) {
|
|
641
642
|
return null;
|
|
642
643
|
}
|
|
644
|
+
if (globalCollectorStartupPromise) {
|
|
645
|
+
logger.info('[Collector] Collector startup already in progress, waiting for existing startup to complete...');
|
|
646
|
+
try {
|
|
647
|
+
const result = await globalCollectorStartupPromise;
|
|
648
|
+
globalCollectorStartupPromise = null;
|
|
649
|
+
return result;
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
logger.error(`[Collector] Existing startup promise failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
653
|
+
globalCollectorStartupPromise = null;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
643
656
|
let existingEndpoint;
|
|
644
657
|
if (globalCollectorProcess) {
|
|
645
658
|
const processAlive = globalCollectorProcess.exitCode === null &&
|
|
@@ -664,59 +677,66 @@ async function discoverOrStartCollector(logger, standardOtelEnabled, env) {
|
|
|
664
677
|
return `http://${status.otlpEndpoint}`;
|
|
665
678
|
}
|
|
666
679
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
680
|
+
const startupPromise = (async () => {
|
|
681
|
+
try {
|
|
682
|
+
globalCollectorInitError = null;
|
|
683
|
+
let endpoint;
|
|
684
|
+
if (existingEndpoint) {
|
|
685
|
+
endpoint = existingEndpoint;
|
|
686
|
+
logger.info(`[Collector] Waiting for existing collector to become ready at ${endpoint}...`);
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
logger.info('[Collector] Starting OpenTelemetry collector...');
|
|
690
|
+
const startResult = await startCollector(logger, undefined, env);
|
|
691
|
+
endpoint = startResult.endpoint;
|
|
692
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
693
|
+
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
694
|
+
const errorMsg = `Collector process exited immediately with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
695
|
+
globalCollectorInitError = errorMsg;
|
|
696
|
+
logger.error(`[Collector] ${errorMsg}`);
|
|
697
|
+
return null;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
const maxWaitTime = 60000;
|
|
701
|
+
const checkInterval = 500;
|
|
702
|
+
const maxChecks = Math.floor(maxWaitTime / checkInterval);
|
|
703
|
+
logger.info('[Collector] Waiting for collector to become ready...');
|
|
704
|
+
for (let i = 0; i < maxChecks; i++) {
|
|
705
|
+
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
706
|
+
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
707
|
+
const errorMsg = `Collector process exited during startup with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
708
|
+
globalCollectorInitError = errorMsg;
|
|
709
|
+
logger.error(`[Collector] ${errorMsg}`);
|
|
710
|
+
return null;
|
|
711
|
+
}
|
|
712
|
+
const newStatus = await isCollectorRunning();
|
|
713
|
+
if (newStatus.isRunning && newStatus.isReady) {
|
|
714
|
+
logger.info(`[Collector] Collector is ready at ${newStatus.otlpEndpoint || endpoint}`);
|
|
715
|
+
return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;
|
|
716
|
+
}
|
|
717
|
+
if (i > 0 && i % 4 === 0) {
|
|
718
|
+
logger.info(`[Collector] Still waiting for collector to become ready... (${(i * checkInterval) / 1000}s elapsed)`);
|
|
719
|
+
}
|
|
684
720
|
}
|
|
685
|
-
}
|
|
686
|
-
const maxWaitTime = 60000;
|
|
687
|
-
const checkInterval = 500;
|
|
688
|
-
const maxChecks = Math.floor(maxWaitTime / checkInterval);
|
|
689
|
-
logger.info('[Collector] Waiting for collector to become ready...');
|
|
690
|
-
for (let i = 0; i < maxChecks; i++) {
|
|
691
|
-
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
692
721
|
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
693
|
-
const errorMsg = `Collector process exited
|
|
722
|
+
const errorMsg = `Collector process exited with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
694
723
|
globalCollectorInitError = errorMsg;
|
|
695
724
|
logger.error(`[Collector] ${errorMsg}`);
|
|
696
725
|
return null;
|
|
697
726
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
logger.info(`[Collector] Collector is ready at ${newStatus.otlpEndpoint || endpoint}`);
|
|
701
|
-
return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;
|
|
702
|
-
}
|
|
703
|
-
if (i > 0 && i % 4 === 0) {
|
|
704
|
-
logger.info(`[Collector] Still waiting for collector to become ready... (${(i * checkInterval) / 1000}s elapsed)`);
|
|
705
|
-
}
|
|
727
|
+
logger.error(`[Collector] Collector did not become ready within ${maxWaitTime / 1000} seconds`);
|
|
728
|
+
return null;
|
|
706
729
|
}
|
|
707
|
-
|
|
708
|
-
const errorMsg =
|
|
730
|
+
catch (err) {
|
|
731
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
709
732
|
globalCollectorInitError = errorMsg;
|
|
710
|
-
logger.error(`[Collector] ${errorMsg}`);
|
|
733
|
+
logger.error(`[Collector] Failed to start collector: ${errorMsg}`);
|
|
711
734
|
return null;
|
|
712
735
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
logger.error(`[Collector] Failed to start collector: ${errorMsg}`);
|
|
720
|
-
return null;
|
|
721
|
-
}
|
|
736
|
+
})();
|
|
737
|
+
globalCollectorStartupPromise = startupPromise;
|
|
738
|
+
startupPromise.finally(() => {
|
|
739
|
+
globalCollectorStartupPromise = null;
|
|
740
|
+
});
|
|
741
|
+
return await startupPromise;
|
|
722
742
|
}
|
|
@@ -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;
|
|
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;AA0OD;;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;;;;;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"}
|
|
@@ -41,6 +41,8 @@ let globalCollectorProcess = null;
|
|
|
41
41
|
let globalCollectorStartError = null;
|
|
42
42
|
let globalCollectorExitCode = null;
|
|
43
43
|
let globalCollectorStderr = [];
|
|
44
|
+
// Track if collector startup is in progress to prevent duplicate starts
|
|
45
|
+
let globalCollectorStartupPromise = null;
|
|
44
46
|
let globalCollectorInitError = null; // Tracks errors from discoverOrStartCollector
|
|
45
47
|
/**
|
|
46
48
|
* Calculates Beamable signature for signed requests
|
|
@@ -744,6 +746,24 @@ export async function discoverOrStartCollector(logger, standardOtelEnabled, env)
|
|
|
744
746
|
if (!standardOtelEnabled) {
|
|
745
747
|
return null;
|
|
746
748
|
}
|
|
749
|
+
// CRITICAL: Check if collector startup is already in progress
|
|
750
|
+
// This prevents duplicate collector starts if this function is called multiple times
|
|
751
|
+
// (e.g., if setupCollectorBeforeLogging times out but the promise is still running)
|
|
752
|
+
if (globalCollectorStartupPromise) {
|
|
753
|
+
logger.info('[Collector] Collector startup already in progress, waiting for existing startup to complete...');
|
|
754
|
+
try {
|
|
755
|
+
const result = await globalCollectorStartupPromise;
|
|
756
|
+
// Clear the promise after it completes (success or failure)
|
|
757
|
+
globalCollectorStartupPromise = null;
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
catch (error) {
|
|
761
|
+
logger.error(`[Collector] Existing startup promise failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
762
|
+
// Clear the promise so we can retry
|
|
763
|
+
globalCollectorStartupPromise = null;
|
|
764
|
+
// Fall through to start a new one
|
|
765
|
+
}
|
|
766
|
+
}
|
|
747
767
|
// CRITICAL: Check if we already have a collector process starting/running
|
|
748
768
|
// This prevents duplicate collector starts if this function is called multiple times
|
|
749
769
|
let existingEndpoint;
|
|
@@ -776,72 +796,83 @@ export async function discoverOrStartCollector(logger, standardOtelEnabled, env)
|
|
|
776
796
|
}
|
|
777
797
|
}
|
|
778
798
|
// Collector not running - start it (or wait for existing one to be ready)
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
endpoint
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
logger.info('[Collector] Starting OpenTelemetry collector...');
|
|
791
|
-
const startResult = await startCollector(logger, undefined, env);
|
|
792
|
-
endpoint = startResult.endpoint;
|
|
793
|
-
// Check if collector process exited immediately (crashed)
|
|
794
|
-
// Wait a bit longer to see if it crashes right after starting
|
|
795
|
-
await new Promise(resolve => setTimeout(resolve, 200));
|
|
796
|
-
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
797
|
-
const errorMsg = `Collector process exited immediately with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
798
|
-
globalCollectorInitError = errorMsg;
|
|
799
|
-
logger.error(`[Collector] ${errorMsg}`);
|
|
800
|
-
return null;
|
|
799
|
+
// Wrap the entire startup logic in a promise that we track globally
|
|
800
|
+
// This prevents duplicate starts if this function is called multiple times
|
|
801
|
+
const startupPromise = (async () => {
|
|
802
|
+
try {
|
|
803
|
+
// Clear any previous init error
|
|
804
|
+
globalCollectorInitError = null;
|
|
805
|
+
let endpoint;
|
|
806
|
+
if (existingEndpoint) {
|
|
807
|
+
// Collector already starting, just wait for it to be ready
|
|
808
|
+
endpoint = existingEndpoint;
|
|
809
|
+
logger.info(`[Collector] Waiting for existing collector to become ready at ${endpoint}...`);
|
|
801
810
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
811
|
+
else {
|
|
812
|
+
// Start a new collector
|
|
813
|
+
logger.info('[Collector] Starting OpenTelemetry collector...');
|
|
814
|
+
const startResult = await startCollector(logger, undefined, env);
|
|
815
|
+
endpoint = startResult.endpoint;
|
|
816
|
+
// Check if collector process exited immediately (crashed)
|
|
817
|
+
// Wait a bit longer to see if it crashes right after starting
|
|
818
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
819
|
+
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
820
|
+
const errorMsg = `Collector process exited immediately with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
821
|
+
globalCollectorInitError = errorMsg;
|
|
822
|
+
logger.error(`[Collector] ${errorMsg}`);
|
|
823
|
+
return null;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
// CRITICAL: Wait for collector to be fully ready before returning
|
|
827
|
+
// We'll wait up to 60 seconds, checking every 500ms
|
|
828
|
+
// This ensures the collector is actually ready to receive logs before we continue
|
|
829
|
+
const maxWaitTime = 60000; // 60 seconds
|
|
830
|
+
const checkInterval = 500; // Check every 500ms
|
|
831
|
+
const maxChecks = Math.floor(maxWaitTime / checkInterval);
|
|
832
|
+
logger.info('[Collector] Waiting for collector to become ready...');
|
|
833
|
+
for (let i = 0; i < maxChecks; i++) {
|
|
834
|
+
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
835
|
+
// Check if process exited during wait
|
|
836
|
+
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
837
|
+
const errorMsg = `Collector process exited during startup with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
838
|
+
globalCollectorInitError = errorMsg;
|
|
839
|
+
logger.error(`[Collector] ${errorMsg}`);
|
|
840
|
+
return null;
|
|
841
|
+
}
|
|
842
|
+
const newStatus = await isCollectorRunning();
|
|
843
|
+
if (newStatus.isRunning && newStatus.isReady) {
|
|
844
|
+
logger.info(`[Collector] Collector is ready at ${newStatus.otlpEndpoint || endpoint}`);
|
|
845
|
+
return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;
|
|
846
|
+
}
|
|
847
|
+
// Log progress every 2 seconds
|
|
848
|
+
if (i > 0 && i % 4 === 0) {
|
|
849
|
+
logger.info(`[Collector] Still waiting for collector to become ready... (${(i * checkInterval) / 1000}s elapsed)`);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
// Check one more time if process exited
|
|
813
853
|
if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {
|
|
814
|
-
const errorMsg = `Collector process exited
|
|
854
|
+
const errorMsg = `Collector process exited with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
815
855
|
globalCollectorInitError = errorMsg;
|
|
816
856
|
logger.error(`[Collector] ${errorMsg}`);
|
|
817
857
|
return null;
|
|
818
858
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;
|
|
823
|
-
}
|
|
824
|
-
// Log progress every 2 seconds
|
|
825
|
-
if (i > 0 && i % 4 === 0) {
|
|
826
|
-
logger.info(`[Collector] Still waiting for collector to become ready... (${(i * checkInterval) / 1000}s elapsed)`);
|
|
827
|
-
}
|
|
859
|
+
// Collector did not become ready within timeout
|
|
860
|
+
logger.error(`[Collector] Collector did not become ready within ${maxWaitTime / 1000} seconds`);
|
|
861
|
+
return null;
|
|
828
862
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
const errorMsg = `Collector process exited with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;
|
|
863
|
+
catch (err) {
|
|
864
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
832
865
|
globalCollectorInitError = errorMsg;
|
|
833
|
-
logger.error(`[Collector] ${errorMsg}`);
|
|
866
|
+
logger.error(`[Collector] Failed to start collector: ${errorMsg}`);
|
|
834
867
|
return null;
|
|
835
868
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
return null;
|
|
845
|
-
}
|
|
869
|
+
})();
|
|
870
|
+
// Store the promise globally so other calls to this function can wait for it
|
|
871
|
+
globalCollectorStartupPromise = startupPromise;
|
|
872
|
+
// Clear the promise when it completes (so we don't keep waiting on old promises)
|
|
873
|
+
startupPromise.finally(() => {
|
|
874
|
+
globalCollectorStartupPromise = null;
|
|
875
|
+
});
|
|
876
|
+
return await startupPromise;
|
|
846
877
|
}
|
|
847
878
|
//# sourceMappingURL=collector-manager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-manager.js","sourceRoot":"","sources":["../src/collector-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, ChildProcess } from 'child_process';\r\nimport { createWriteStream, existsSync, chmodSync, mkdirSync } from 'fs';\r\nimport { join, dirname } from 'path';\r\nimport { pipeline } from 'stream/promises';\r\nimport { createGunzip } from 'zlib';\r\nimport { createHash } from 'node:crypto';\r\nimport { createServer } from 'net';\r\nimport type { Logger } from 'pino';\r\nimport pino from 'pino';\r\nimport dgram from 'dgram';\r\nimport deasync from 'deasync';\r\nimport type { EnvironmentConfig } from './types.js';\r\nimport { hostToHttpUrl } from './utils/urls.js';\r\n\r\n// Protocol is httpprotobuf \r\n\r\ninterface CollectorDiscoveryEntry {\r\n version: string;\r\n status: string;\r\n pid: number;\r\n otlpEndpoint: string;\r\n}\r\n\r\nexport interface CollectorStatus {\r\n isRunning: boolean;\r\n isReady: boolean;\r\n pid: number;\r\n otlpEndpoint?: string;\r\n version?: string;\r\n}\r\n\r\nconst COLLECTOR_VERSION = '1.0.1'; // Match C# collector version (from collector-version.json)\r\nconst COLLECTOR_DOWNLOAD_BASE = `https://collectors.beamable.com/version/${COLLECTOR_VERSION}`;\r\nconst DISCOVERY_PORT = parseInt(process.env.BEAM_COLLECTOR_DISCOVERY_PORT || '8688', 10);\r\n\r\n/**\r\n * Finds a free TCP port (matching C# PortUtil.FreeTcpPort())\r\n */\r\nfunction findFreePort(): Promise<number> {\r\n return new Promise((resolve, reject) => {\r\n const server = createServer();\r\n server.listen(0, () => {\r\n const address = server.address();\r\n const port = typeof address === 'object' && address !== null ? address.port : 0;\r\n server.close(() => {\r\n if (port > 0) {\r\n resolve(port);\r\n } else {\r\n // Fallback to a default port if something went wrong\r\n resolve(9090);\r\n }\r\n });\r\n });\r\n server.on('error', (err) => {\r\n reject(err);\r\n });\r\n });\r\n}\r\n\r\n// Global storage for collector process and errors (to prevent GC and track status)\r\nlet globalCollectorProcess: ChildProcess | null = null;\r\nlet globalCollectorStartError: string | null = null;\r\nlet globalCollectorExitCode: number | null = null;\r\nlet globalCollectorStderr: string[] = [];\r\nlet globalCollectorInitError: string | null = null; // Tracks errors from discoverOrStartCollector\r\n\r\n/**\r\n * ClickHouse credentials response from Beamable API\r\n */\r\ninterface ClickHouseCredentials {\r\n endpoint: string;\r\n expiresAt?: string;\r\n password: string;\r\n username: string;\r\n}\r\n\r\n/**\r\n * Calculates Beamable signature for signed requests\r\n * Signature format: MD5(secret + pid + version + uriPathAndQuery + body) as Base64\r\n * Matches C# SignedRequesterHelper.CalculateSignature\r\n */\r\nfunction calculateSignature(\r\n pid: string,\r\n secret: string,\r\n uriPathAndQuery: string,\r\n body: string | null = null,\r\n version: string = '1'\r\n): string {\r\n let dataToSign = `${secret}${pid}${version}${uriPathAndQuery}`;\r\n if (body) {\r\n dataToSign += body;\r\n }\r\n \r\n // MD5 hash to Base64 (matching C# implementation)\r\n const hash = createHash('md5').update(dataToSign, 'utf8').digest('base64');\r\n return hash;\r\n}\r\n\r\n/**\r\n * Extracts path and query from a URL\r\n */\r\nfunction getPathAndQuery(url: string): string {\r\n try {\r\n const urlObj = new URL(url);\r\n return urlObj.pathname + urlObj.search;\r\n } catch {\r\n // If URL parsing fails, return as-is\r\n return url;\r\n }\r\n}\r\n\r\n/**\r\n * Fetches ClickHouse credentials from Beamable API\r\n * GET /api/beamo/otel/auth/writer/config\r\n * Requires signed request authentication (X-BEAM-SIGNATURE header)\r\n */\r\nexport async function fetchClickHouseCredentials(\r\n env: EnvironmentConfig\r\n): Promise<ClickHouseCredentials> {\r\n const apiUrl = hostToHttpUrl(env.host);\r\n const uriPath = '/api/beamo/otel/auth/writer/config';\r\n const configUrl = new URL(uriPath, apiUrl).toString();\r\n \r\n // Get secret from environment (required for signed requests)\r\n const secret = process.env.SECRET;\r\n if (!secret) {\r\n throw new Error('SECRET environment variable is required to fetch ClickHouse credentials');\r\n }\r\n \r\n // Calculate signature for signed request (matching C# HttpSignedRequester)\r\n const pathAndQuery = getPathAndQuery(uriPath);\r\n const signature = calculateSignature(env.pid, secret, pathAndQuery, null, '1');\r\n \r\n // Build headers with signed authentication (matching C# HttpSignedRequester)\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json',\r\n 'X-BEAM-SCOPE': `${env.cid}.${env.pid}`,\r\n 'X-BEAM-SIGNATURE': signature,\r\n };\r\n \r\n const response = await fetch(configUrl, {\r\n method: 'GET',\r\n headers,\r\n });\r\n \r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`Failed to fetch ClickHouse credentials from ${configUrl}: ${response.status} ${response.statusText} - ${errorText.substring(0, 200)}`);\r\n }\r\n \r\n const credentials = await response.json() as ClickHouseCredentials;\r\n \r\n if (!credentials.endpoint || !credentials.username || !credentials.password) {\r\n throw new Error('Invalid ClickHouse credentials response: missing required fields');\r\n }\r\n \r\n return credentials;\r\n}\r\n\r\n/**\r\n * Gets the collector storage directory (similar to C# LocalApplicationData/beam/collectors/version)\r\n */\r\nfunction getCollectorStoragePath(): string {\r\n // Use temp directory for now - in containers this should be writable\r\n const tempDir = process.env.TMPDIR || process.env.TMP || '/tmp';\r\n return join(tempDir, 'beam', 'collectors', COLLECTOR_VERSION);\r\n}\r\n\r\n/**\r\n * Gets the collector binary name for the current platform\r\n */\r\nfunction getCollectorBinaryName(): string {\r\n const platform = process.platform;\r\n const arch = process.arch;\r\n \r\n // Match C# naming: collector-{osArchSuffix}\r\n // C# returns \"collector-linux-amd64\", not \"beamable-collector-linux-amd64\"\r\n if (platform === 'linux' && arch === 'x64') {\r\n return 'collector-linux-amd64';\r\n } else if (platform === 'linux' && arch === 'arm64') {\r\n return 'collector-linux-arm64';\r\n } else if (platform === 'darwin' && arch === 'x64') {\r\n return 'collector-darwin-amd64';\r\n } else if (platform === 'darwin' && arch === 'arm64') {\r\n return 'collector-darwin-arm64';\r\n } else if (platform === 'win32' && arch === 'x64') {\r\n return 'collector-windows-amd64.exe';\r\n }\r\n \r\n throw new Error(`Unsupported platform: ${platform} ${arch}`);\r\n}\r\n\r\n/**\r\n * Downloads and decompresses a gzipped file\r\n */\r\nasync function downloadAndDecompressGzip(url: string, outputPath: string, makeExecutable: boolean = false): Promise<void> {\r\n let response: Response;\r\n try {\r\n // Add timeout and better error handling\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout\r\n \r\n try {\r\n response = await fetch(url, {\r\n signal: controller.signal,\r\n headers: {\r\n 'User-Agent': 'Beamable-Node-Microservice-Runtime/1.0',\r\n },\r\n });\r\n clearTimeout(timeoutId);\r\n } catch (fetchError) {\r\n clearTimeout(timeoutId);\r\n if (fetchError instanceof Error) {\r\n // Extract underlying error details from cause\r\n let underlyingError = '';\r\n if ((fetchError as any).cause) {\r\n const cause = (fetchError as any).cause;\r\n if (cause instanceof Error) {\r\n const causeCode = (cause as any).code;\r\n underlyingError = ` (cause: ${cause.name} - ${cause.message}${causeCode ? ` [code: ${causeCode}]` : ''})`;\r\n } else if (typeof cause === 'object' && cause.code) {\r\n underlyingError = ` (cause code: ${cause.code})`;\r\n }\r\n }\r\n \r\n // Provide more context about the error\r\n if (fetchError.name === 'AbortError') {\r\n throw new Error(`Timeout downloading ${url} (30s limit exceeded)${underlyingError}`);\r\n }\r\n \r\n // Check error code if available (Node.js system errors)\r\n const errorCode = (fetchError as any).code || ((fetchError as any).cause?.code);\r\n if (errorCode) {\r\n if (errorCode === 'ENOTFOUND' || errorCode === 'EAI_AGAIN') {\r\n throw new Error(`DNS resolution failed for ${url} (code: ${errorCode}). Check network connectivity and DNS settings.`);\r\n }\r\n if (errorCode === 'ECONNREFUSED') {\r\n throw new Error(`Connection refused to ${url} (code: ${errorCode}). Server may be down or firewall blocking.`);\r\n }\r\n if (errorCode === 'ETIMEDOUT' || errorCode === 'ECONNRESET') {\r\n throw new Error(`Connection timeout/reset to ${url} (code: ${errorCode}). Network may be slow or unreachable.`);\r\n }\r\n if (errorCode === 'CERT_HAS_EXPIRED' || errorCode === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE') {\r\n throw new Error(`SSL/TLS certificate error connecting to ${url} (code: ${errorCode}): ${fetchError.message}`);\r\n }\r\n }\r\n \r\n // Check for common network errors in message\r\n const errorMsg = fetchError.message.toLowerCase();\r\n if (errorMsg.includes('enotfound') || errorMsg.includes('dns')) {\r\n throw new Error(`DNS resolution failed for ${url}. Check network connectivity and DNS settings.${underlyingError}`);\r\n }\r\n if (errorMsg.includes('econnrefused') || errorMsg.includes('connection refused')) {\r\n throw new Error(`Connection refused to ${url}. Server may be down or firewall blocking.${underlyingError}`);\r\n }\r\n if (errorMsg.includes('etimedout') || errorMsg.includes('timeout')) {\r\n throw new Error(`Connection timeout to ${url}. Network may be slow or unreachable.${underlyingError}`);\r\n }\r\n if (errorMsg.includes('certificate') || errorMsg.includes('ssl') || errorMsg.includes('tls')) {\r\n throw new Error(`SSL/TLS error connecting to ${url}: ${fetchError.message}${underlyingError}`);\r\n }\r\n throw new Error(`Network error downloading ${url}: ${fetchError.name} - ${fetchError.message}${underlyingError}`);\r\n }\r\n throw new Error(`Network error downloading ${url}: ${String(fetchError)}`);\r\n }\r\n } catch (error) {\r\n // Re-throw with more context\r\n if (error instanceof Error) {\r\n if (error.message.includes('Timeout') || error.message.includes('DNS') || error.message.includes('Connection')) {\r\n throw error; // Already has good context\r\n }\r\n throw new Error(`Network error downloading ${url}: ${error.message}`);\r\n }\r\n throw new Error(`Network error downloading ${url}: ${String(error)}`);\r\n }\r\n \r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => '');\r\n throw new Error(`HTTP ${response.status} downloading ${url}: ${response.statusText}${errorText ? ` - ${errorText.substring(0, 200)}` : ''}`);\r\n }\r\n \r\n const dir = dirname(outputPath);\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n \r\n const gunzip = createGunzip();\r\n const writeStream = createWriteStream(outputPath);\r\n \r\n await pipeline(response.body as any, gunzip, writeStream);\r\n \r\n if (makeExecutable && process.platform !== 'win32') {\r\n try {\r\n chmodSync(outputPath, 0o755);\r\n } catch (error) {\r\n console.error(`Failed to make ${outputPath} executable:`, error);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Resolves the collector binary and config, downloading if needed\r\n */\r\nasync function resolveCollector(allowDownload: boolean = true, logger?: Logger): Promise<{ binaryPath: string | null; configPath: string | null }> {\r\n const basePath = getCollectorStoragePath();\r\n const binaryName = getCollectorBinaryName();\r\n const configName = 'clickhouse-config.yaml';\r\n \r\n const binaryPath = join(basePath, binaryName);\r\n const configPath = join(basePath, configName);\r\n \r\n const itemsToDownload: Array<{ url: string; path: string; executable: boolean }> = [];\r\n \r\n if (!existsSync(binaryPath) && allowDownload) {\r\n const binaryUrl = `${COLLECTOR_DOWNLOAD_BASE}/${binaryName}.gz`;\r\n itemsToDownload.push({ url: binaryUrl, path: binaryPath, executable: true });\r\n logger?.info(`[Collector] Will download binary from: ${binaryUrl}`);\r\n } else if (existsSync(binaryPath)) {\r\n logger?.info(`[Collector] Binary found at: ${binaryPath}`);\r\n }\r\n \r\n if (!existsSync(configPath) && allowDownload) {\r\n const configUrl = `${COLLECTOR_DOWNLOAD_BASE}/${configName}.gz`;\r\n itemsToDownload.push({ url: configUrl, path: configPath, executable: false });\r\n logger?.info(`[Collector] Will download config from: ${configUrl}`);\r\n } else if (existsSync(configPath)) {\r\n logger?.info(`[Collector] Config found at: ${configPath}`);\r\n }\r\n \r\n for (const item of itemsToDownload) {\r\n try {\r\n logger?.info(`[Collector] Downloading ${item.url}...`);\r\n await downloadAndDecompressGzip(item.url, item.path, item.executable);\r\n logger?.info(`[Collector] Downloaded to ${item.path}`);\r\n } catch (error) {\r\n // Don't wrap the error again if it already contains the URL and details\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger?.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);\r\n // Only wrap if the error doesn't already contain the URL\r\n if (error instanceof Error && errorMsg.includes(item.url)) {\r\n throw error; // Error already has URL and context\r\n }\r\n throw new Error(`Failed to download collector ${item.executable ? 'binary' : 'config'} from ${item.url}: ${errorMsg}`);\r\n }\r\n }\r\n \r\n return {\r\n binaryPath: existsSync(binaryPath) ? binaryPath : null,\r\n configPath: existsSync(configPath) ? configPath : null,\r\n };\r\n}\r\n\r\n/**\r\n * Discovers collector via UDP broadcast\r\n */\r\nfunction discoverCollectorViaUDP(timeoutMs: number = 5000): Promise<CollectorDiscoveryEntry | null> {\r\n return new Promise((resolve) => {\r\n const socket = dgram.createSocket('udp4');\r\n const discovered: CollectorDiscoveryEntry[] = [];\r\n let timeout: NodeJS.Timeout;\r\n \r\n socket.on('message', (msg) => {\r\n try {\r\n const message = JSON.parse(msg.toString()) as CollectorDiscoveryEntry;\r\n // Check if version matches\r\n if (message.version === COLLECTOR_VERSION && message.status === 'READY') {\r\n discovered.push(message);\r\n }\r\n } catch (error) {\r\n // Ignore parse errors\r\n }\r\n });\r\n \r\n socket.on('error', () => {\r\n clearTimeout(timeout);\r\n socket.close();\r\n resolve(null);\r\n });\r\n \r\n socket.bind(() => {\r\n socket.setBroadcast(true);\r\n \r\n timeout = setTimeout(() => {\r\n socket.close();\r\n // Return the first discovered collector\r\n resolve(discovered.length > 0 ? discovered[0] : null);\r\n }, timeoutMs);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Gets the current status of ClickHouse credentials (from env or API)\r\n */\r\nexport function getClickHouseCredentialsStatus(): {\r\n hasEndpoint: boolean;\r\n hasUsername: boolean;\r\n hasPassword: boolean;\r\n source: 'environment' | 'api' | 'missing';\r\n} {\r\n const hasEndpoint = !!process.env.BEAM_CLICKHOUSE_ENDPOINT;\r\n const hasUsername = !!process.env.BEAM_CLICKHOUSE_USERNAME;\r\n const hasPassword = !!process.env.BEAM_CLICKHOUSE_PASSWORD;\r\n \r\n if (hasEndpoint && hasUsername && hasPassword) {\r\n return {\r\n hasEndpoint: true,\r\n hasUsername: true,\r\n hasPassword: true,\r\n source: 'environment',\r\n };\r\n }\r\n \r\n return {\r\n hasEndpoint,\r\n hasUsername,\r\n hasPassword,\r\n source: 'missing',\r\n };\r\n}\r\n\r\n/**\r\n * Checks if collector is already running via UDP discovery\r\n */\r\nexport async function isCollectorRunning(): Promise<CollectorStatus> {\r\n // First, check if we have a global collector process reference\r\n // If the process is running and we've seen \"Everything is ready\" in stderr, it's ready\r\n if (globalCollectorProcess) {\r\n // Check if process is still alive\r\n try {\r\n // Process is alive if we can access it and it hasn't exited\r\n const processAlive = globalCollectorProcess.exitCode === null && \r\n globalCollectorProcess.killed === false;\r\n \r\n if (processAlive) {\r\n // Check if we've seen the \"Everything is ready\" message in stderr\r\n // This is a reliable indicator that the collector is ready\r\n const stderrText = globalCollectorStderr.join('\\n');\r\n const isReady = stderrText.includes('Everything is ready') || \r\n stderrText.includes('Begin running and processing data');\r\n \r\n if (isReady) {\r\n // Try UDP discovery to get the endpoint, but if it fails, use the configured endpoint\r\n try {\r\n const discovered = await discoverCollectorViaUDP(1000); // Shorter timeout since we know it's running\r\n if (discovered && discovered.status === 'READY') {\r\n return {\r\n isRunning: true,\r\n isReady: true,\r\n pid: discovered.pid || globalCollectorProcess.pid || 0,\r\n otlpEndpoint: discovered.otlpEndpoint,\r\n version: discovered.version,\r\n };\r\n }\r\n } catch {\r\n // UDP discovery failed, but process is alive and has \"Everything is ready\" message\r\n // Use the configured endpoint as fallback\r\n }\r\n \r\n // Process is alive and we've seen \"Everything is ready\" - treat as ready\r\n // Extract endpoint from environment or use default\r\n const configuredEndpoint = process.env.BEAM_OTLP_HTTP_ENDPOINT || '0.0.0.0:4318';\r\n return {\r\n isRunning: true,\r\n isReady: true,\r\n pid: globalCollectorProcess.pid || 0,\r\n otlpEndpoint: configuredEndpoint,\r\n version: COLLECTOR_VERSION,\r\n };\r\n }\r\n }\r\n } catch {\r\n // Process might have exited or is invalid\r\n }\r\n }\r\n \r\n // Try UDP discovery as fallback\r\n try {\r\n const discovered = await discoverCollectorViaUDP(2000);\r\n if (discovered) {\r\n return {\r\n isRunning: true,\r\n isReady: discovered.status === 'READY',\r\n pid: discovered.pid,\r\n otlpEndpoint: discovered.otlpEndpoint,\r\n version: discovered.version,\r\n };\r\n }\r\n } catch (error) {\r\n // Discovery failed, collector probably not running\r\n }\r\n \r\n return {\r\n isRunning: false,\r\n isReady: false,\r\n pid: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Sets default collector configuration environment variables in process.env\r\n * Matches C# CollectorManager.AddCollectorConfigurationToEnvironment()\r\n */\r\nfunction addCollectorConfigurationToEnvironment(): void {\r\n const defaults: Record<string, string> = {\r\n BEAM_CLICKHOUSE_PROCESSOR_TIMEOUT: '5s',\r\n BEAM_CLICKHOUSE_PROCESSOR_BATCH_SIZE: '5000',\r\n BEAM_CLICKHOUSE_EXPORTER_TIMEOUT: '5s',\r\n BEAM_CLICKHOUSE_EXPORTER_QUEUE_SIZE: '1000',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_ENABLED: 'true',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_INITIAL_INTERVAL: '5s',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_MAX_INTERVAL: '30s',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_MAX_ELAPSED_TIME: '300s',\r\n };\r\n \r\n // Only set if not already set (matching C# behavior)\r\n for (const [key, defaultValue] of Object.entries(defaults)) {\r\n if (!process.env[key]) {\r\n process.env[key] = defaultValue;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Sets ClickHouse credentials in process.env (matching C# CollectorManager.AddAuthEnvironmentVars)\r\n */\r\nexport function addAuthEnvironmentVars(endpoint: string, username: string, password: string): void {\r\n // Always set the values when explicitly provided (matching C# behavior)\r\n // This ensures credentials fetched from API override any existing (potentially empty) values\r\n // In Node.js, process.env is a writable object - setting properties here persists for the lifetime of the process\r\n process.env.BEAM_CLICKHOUSE_ENDPOINT = endpoint;\r\n process.env.BEAM_CLICKHOUSE_USERNAME = username;\r\n process.env.BEAM_CLICKHOUSE_PASSWORD = password;\r\n \r\n // Verify they were actually set (for debugging)\r\n if (!process.env.BEAM_CLICKHOUSE_ENDPOINT || !process.env.BEAM_CLICKHOUSE_USERNAME || !process.env.BEAM_CLICKHOUSE_PASSWORD) {\r\n throw new Error(`Failed to set ClickHouse credentials in process.env - this should never happen in Node.js`);\r\n }\r\n}\r\n\r\n/**\r\n * Sets up the collector BEFORE logging is initialized.\r\n * This ensures all startup logs are captured via OTLP.\r\n * Uses a minimal console logger for setup messages.\r\n * Returns the OTLP endpoint if successful, null otherwise.\r\n */\r\nexport function setupCollectorBeforeLogging(\r\n env: EnvironmentConfig,\r\n timeoutMs: number = 60000\r\n): string | null {\r\n // Match C# logic: (this.InDocker() || UseLocalOtel) && !BEAM_DISABLE_STANDARD_OTEL\r\n const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';\r\n const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;\r\n const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;\r\n const hasExplicitEndpoint = !!process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;\r\n\r\n // If OTLP is not needed, return immediately\r\n if (!standardOtelEnabled && !hasExplicitEndpoint) {\r\n return null;\r\n }\r\n\r\n // Create a minimal console logger for initialization messages (no OTLP yet)\r\n const initLogger = pino({\r\n name: 'beamable-otlp-init',\r\n level: 'info',\r\n }, process.stdout);\r\n\r\n initLogger.info('[OTLP] Setting up collector before logging initialization...');\r\n\r\n // Use deasync to wait synchronously for collector setup\r\n let endpoint: string | null = null;\r\n let completed = false;\r\n let setupError: string | null = null;\r\n\r\n // Start collector setup promise\r\n discoverOrStartCollector(initLogger, standardOtelEnabled, env)\r\n .then((result) => {\r\n endpoint = result;\r\n completed = true;\r\n if (result) {\r\n initLogger.info(`[OTLP] Collector setup complete, endpoint: ${result}`);\r\n } else {\r\n initLogger.warn('[OTLP] Collector setup returned null, OTLP logging will be disabled');\r\n }\r\n return result;\r\n })\r\n .catch((error) => {\r\n setupError = error instanceof Error ? error.message : String(error);\r\n completed = true;\r\n initLogger.error(`[OTLP] Failed to setup collector: ${setupError}`);\r\n endpoint = null;\r\n });\r\n\r\n // Wait synchronously for collector setup to complete\r\n const startTime = Date.now();\r\n const timeoutId = setTimeout(() => {\r\n if (!completed) {\r\n initLogger.warn(`[OTLP] Collector setup timeout after ${timeoutMs}ms, continuing without OTLP`);\r\n completed = true;\r\n }\r\n }, timeoutMs);\r\n\r\n try {\r\n // Use deasync to wait for completion (allows event loop to process async operations)\r\n deasync.loopWhile(() => {\r\n const elapsed = Date.now() - startTime;\r\n if (elapsed >= timeoutMs) {\r\n return false; // Stop waiting\r\n }\r\n return !completed; // Continue waiting if not completed\r\n });\r\n } catch (error) {\r\n initLogger.error(`[OTLP] Error during collector setup wait: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (completed && endpoint) {\r\n initLogger.info('[OTLP] Collector is ready, proceeding with logger creation');\r\n return endpoint;\r\n } else if (setupError) {\r\n initLogger.error(`[OTLP] Collector setup failed: ${setupError}, continuing without OTLP`);\r\n return null;\r\n } else {\r\n initLogger.warn('[OTLP] Collector setup did not complete in time, continuing without OTLP');\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Starts the OpenTelemetry collector process\r\n */\r\nexport async function startCollector(\r\n logger: Logger,\r\n otlpEndpoint?: string,\r\n env?: EnvironmentConfig\r\n): Promise<{ process: ChildProcess; endpoint: string }> {\r\n // Clear any previous errors\r\n globalCollectorStartError = null;\r\n globalCollectorInitError = null;\r\n \r\n // CRITICAL: Fetch credentials FIRST, before resolving collector binary/config\r\n // This ensures credentials are in process.env even if collector download fails\r\n // The credentials will persist in process.env for the lifetime of the process.\r\n // Per Gabriel: \"these OTEL related ones you need to do it yourself at the beginning of the microservice startup\"\r\n let clickhouseEndpoint = process.env.BEAM_CLICKHOUSE_ENDPOINT;\r\n let clickhouseUsername = process.env.BEAM_CLICKHOUSE_USERNAME;\r\n let clickhousePassword = process.env.BEAM_CLICKHOUSE_PASSWORD;\r\n \r\n if ((!clickhouseEndpoint || !clickhouseUsername || !clickhousePassword) && env) {\r\n try {\r\n logger.info('[Collector] Fetching ClickHouse credentials from Beamable API...');\r\n const credentials = await fetchClickHouseCredentials(env);\r\n clickhouseEndpoint = credentials.endpoint;\r\n clickhouseUsername = credentials.username;\r\n clickhousePassword = credentials.password;\r\n \r\n // CRITICAL: Set them in process.env IMMEDIATELY after fetching (matching C# CollectorManager.AddAuthEnvironmentVars)\r\n // In Node.js, process.env is a writable object - setting properties here persists for the lifetime of the process\r\n // This ensures they're available to both the Node.js process and inherited by the collector child process\r\n addAuthEnvironmentVars(clickhouseEndpoint, clickhouseUsername, clickhousePassword);\r\n \r\n // Verify they were set (defensive check - should never fail in Node.js)\r\n const verifyEndpoint = process.env.BEAM_CLICKHOUSE_ENDPOINT;\r\n const verifyUsername = process.env.BEAM_CLICKHOUSE_USERNAME;\r\n const verifyPassword = process.env.BEAM_CLICKHOUSE_PASSWORD;\r\n \r\n if (!verifyEndpoint || !verifyUsername || !verifyPassword) {\r\n logger.error(`[Collector] CRITICAL: Credentials were set but are missing from process.env! This should never happen.`);\r\n throw new Error('Failed to persist ClickHouse credentials in process.env');\r\n }\r\n \r\n logger.info('[Collector] ClickHouse credentials fetched from API and verified in process.env');\r\n } catch (error) {\r\n const errorMsg = `[Collector] Failed to fetch ClickHouse credentials from API: ${error instanceof Error ? error.message : String(error)}`;\r\n logger.error(errorMsg);\r\n throw new Error(errorMsg);\r\n }\r\n }\r\n \r\n // Validate required environment variables (matching C# behavior)\r\n // These must be set before starting the collector, otherwise it will fail\r\n if (!clickhouseEndpoint || !clickhouseUsername || !clickhousePassword) {\r\n const errorMsg = `[Collector] Required ClickHouse credentials are missing. Set BEAM_CLICKHOUSE_ENDPOINT, BEAM_CLICKHOUSE_USERNAME, and BEAM_CLICKHOUSE_PASSWORD, or ensure the API endpoint is accessible.`;\r\n logger.error(errorMsg);\r\n throw new Error(errorMsg);\r\n }\r\n \r\n // Now resolve collector binary and config (after credentials are fetched and set)\r\n logger.info('[Collector] Resolving collector binary and config...');\r\n const collectorInfo = await resolveCollector(true, logger);\r\n \r\n if (!collectorInfo.binaryPath) {\r\n logger.error('[Collector] Binary not found and download failed');\r\n throw new Error('Collector binary not found and download failed');\r\n }\r\n \r\n if (!collectorInfo.configPath) {\r\n logger.error('[Collector] Config not found and download failed');\r\n throw new Error('Collector config not found and download failed');\r\n }\r\n \r\n logger.info(`[Collector] Using binary: ${collectorInfo.binaryPath}`);\r\n logger.info(`[Collector] Using config: ${collectorInfo.configPath}`);\r\n \r\n // Verify binary exists\r\n if (!collectorInfo.binaryPath || !existsSync(collectorInfo.binaryPath)) {\r\n throw new Error(`Collector binary not found at ${collectorInfo.binaryPath}`);\r\n }\r\n \r\n // Check if binary is executable (Unix only - Windows doesn't have execute permission)\r\n if (process.platform !== 'win32') {\r\n try {\r\n const fsPromises = await import('fs/promises');\r\n const stats = await fsPromises.stat(collectorInfo.binaryPath);\r\n const mode = Number(stats.mode);\r\n const isExecutable = !!(mode & parseInt('111', 8)); // Check execute bit\r\n if (!isExecutable) {\r\n logger.warn(`[Collector] Binary may not be executable. Mode: ${mode.toString(8)}`);\r\n // Try to make it executable again\r\n try {\r\n chmodSync(collectorInfo.binaryPath, 0o755);\r\n logger.info(`[Collector] Made binary executable`);\r\n } catch (chmodError) {\r\n logger.error(`[Collector] Failed to make binary executable: ${chmodError instanceof Error ? chmodError.message : String(chmodError)}`);\r\n }\r\n }\r\n } catch (statError) {\r\n logger.warn(`[Collector] Could not check binary permissions: ${statError instanceof Error ? statError.message : String(statError)}`);\r\n }\r\n }\r\n\r\n // Set default collector configuration environment variables in process.env\r\n // This ensures they're available to both the Node.js process and the collector child process\r\n // Matches C# CollectorManager.AddCollectorConfigurationToEnvironment()\r\n addCollectorConfigurationToEnvironment();\r\n \r\n // CRITICAL: Set BEAM_COLLECTOR_DISCOVERY_PORT if not already set (matching C# AddDefaultCollectorHostAndPortFallback)\r\n // This MUST be set before starting the collector\r\n if (!process.env.BEAM_COLLECTOR_DISCOVERY_PORT) {\r\n process.env.BEAM_COLLECTOR_DISCOVERY_PORT = String(DISCOVERY_PORT);\r\n logger.info(`[Collector] Set BEAM_COLLECTOR_DISCOVERY_PORT=${DISCOVERY_PORT} (default)`);\r\n }\r\n \r\n // Determine OTLP endpoint\r\n // Use a free port if not specified (like C# does with PortUtil.FreeEndpoint())\r\n let localEndpoint = otlpEndpoint;\r\n if (!localEndpoint) {\r\n // For now, use default OTLP HTTP port\r\n // In production, this would be discovered or set by Beamable\r\n localEndpoint = '0.0.0.0:4318';\r\n }\r\n localEndpoint = localEndpoint.replace(/^http:\\/\\//, '').replace(/^https:\\/\\//, '');\r\n \r\n // Find a free port for Prometheus (matching C# PortUtil.FreeTcpPort())\r\n // We'll use a simple approach: bind to port 0 and let the OS assign a port\r\n // For now, use a default port (9090 is common for Prometheus) or find a free one\r\n // C# uses PortUtil.FreeTcpPort() which finds an available TCP port\r\n // We'll use a simple helper to find a free port\r\n const prometheusPort = await findFreePort();\r\n \r\n // Set environment variables for collector\r\n // Note: BEAM_CLICKHOUSE_ENDPOINT is for collector → ClickHouse communication\r\n // This is different from the OTLP endpoint (microservice → collector)\r\n // The collector process will inherit all environment variables from process.env automatically\r\n // We only need to set the OTLP endpoint, discovery port, and Prometheus port explicitly here\r\n const collectorEnv: NodeJS.ProcessEnv = {\r\n ...process.env, // Inherit all process.env (including credentials and config we just set)\r\n BEAM_OTLP_HTTP_ENDPOINT: localEndpoint,\r\n BEAM_COLLECTOR_DISCOVERY_PORT: String(DISCOVERY_PORT),\r\n BEAM_COLLECTOR_PROMETHEUS_PORT: String(prometheusPort),\r\n };\r\n \r\n // Start collector process\r\n const collectorProcess = spawn(collectorInfo.binaryPath, ['--config', collectorInfo.configPath], {\r\n env: collectorEnv,\r\n stdio: ['ignore', 'pipe', 'pipe'],\r\n detached: false,\r\n });\r\n \r\n // Store globally to prevent GC and track status\r\n globalCollectorProcess = collectorProcess;\r\n globalCollectorStartError = null;\r\n globalCollectorExitCode = null;\r\n globalCollectorStderr = [];\r\n \r\n // Set up handlers BEFORE we check if process started, so we capture all output\r\n collectorProcess.stdout?.on('data', (data) => {\r\n const outputLine = data.toString().trim();\r\n // Log stdout at info level to see collector output\r\n logger.info(`[Collector OUT] ${outputLine}`);\r\n });\r\n \r\n collectorProcess.stderr?.on('data', (data) => {\r\n const errorLine = data.toString().trim();\r\n globalCollectorStderr.push(errorLine);\r\n // Keep only last 50 lines to prevent memory issues\r\n if (globalCollectorStderr.length > 50) {\r\n globalCollectorStderr.shift();\r\n }\r\n // Log stderr at info level so we can see why collector crashes\r\n logger.info(`[Collector ERR] ${errorLine}`);\r\n });\r\n \r\n collectorProcess.on('error', (err) => {\r\n globalCollectorStartError = err.message;\r\n logger.error(`[Collector] Failed to start: ${err.message}`);\r\n });\r\n \r\n collectorProcess.on('exit', (code, signal) => {\r\n globalCollectorExitCode = code;\r\n logger.warn(`[Collector] Process exited with code ${code}${signal ? `, signal ${signal}` : ''}`);\r\n \r\n // If process exited with an error code, log accumulated stderr\r\n if (code !== 0 && globalCollectorStderr.length > 0) {\r\n logger.error(`[Collector] Exit error - Last ${Math.min(10, globalCollectorStderr.length)} stderr lines:`);\r\n globalCollectorStderr.slice(-10).forEach((line) => {\r\n logger.error(`[Collector ERR] ${line}`);\r\n });\r\n }\r\n \r\n // Don't clear reference immediately - keep it for status checks\r\n // globalCollectorProcess = null; // Keep reference for getCollectorProcessStatus()\r\n });\r\n \r\n logger.info(`[Collector] Started with PID ${collectorProcess.pid}, endpoint: ${localEndpoint}`);\r\n \r\n // Give the process a moment to start and potentially write to stderr\r\n // This helps capture immediate startup errors\r\n // Wait a bit longer to ensure we catch immediate crashes\r\n await new Promise(resolve => setTimeout(resolve, 500));\r\n \r\n // Check if process already exited (immediate crash)\r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const stderrMsg = globalCollectorStderr.length > 0 \r\n ? ` Stderr: ${globalCollectorStderr.join('; ')}` \r\n : ' No stderr output captured.';\r\n throw new Error(`Collector process exited immediately after startup with code ${globalCollectorExitCode}.${stderrMsg}`);\r\n }\r\n \r\n return {\r\n process: collectorProcess,\r\n endpoint: `http://${localEndpoint}`,\r\n };\r\n}\r\n\r\n/**\r\n * Gets detailed collector status including process info and errors\r\n */\r\nexport function getCollectorProcessStatus(): {\r\n hasProcess: boolean;\r\n pid: number | null;\r\n exitCode: number | null;\r\n startError: string | null;\r\n initError: string | null;\r\n stderr: string[];\r\n} {\r\n return {\r\n hasProcess: globalCollectorProcess !== null,\r\n pid: globalCollectorProcess?.pid ?? null,\r\n exitCode: globalCollectorExitCode,\r\n startError: globalCollectorStartError,\r\n initError: globalCollectorInitError,\r\n stderr: [...globalCollectorStderr], // Return a copy\r\n };\r\n}\r\n\r\n/**\r\n * Discovers or starts the collector and returns the OTLP endpoint\r\n */\r\nexport async function discoverOrStartCollector(\r\n logger: Logger,\r\n standardOtelEnabled: boolean,\r\n env?: EnvironmentConfig\r\n): Promise<string | null> {\r\n if (!standardOtelEnabled) {\r\n return null;\r\n }\r\n \r\n // CRITICAL: Check if we already have a collector process starting/running\r\n // This prevents duplicate collector starts if this function is called multiple times\r\n let existingEndpoint: string | undefined;\r\n if (globalCollectorProcess) {\r\n // Check if process is still alive\r\n const processAlive = globalCollectorProcess.exitCode === null && \r\n globalCollectorProcess.killed === false;\r\n \r\n if (processAlive) {\r\n logger.info(`[Collector] Collector process already exists (PID ${globalCollectorProcess.pid}), waiting for it to be ready...`);\r\n // Use the configured endpoint from environment (we started it earlier)\r\n existingEndpoint = process.env.BEAM_OTLP_HTTP_ENDPOINT ? \r\n `http://${process.env.BEAM_OTLP_HTTP_ENDPOINT}` : \r\n 'http://0.0.0.0:4318';\r\n // Fall through to the wait logic below (don't start a new collector)\r\n } else {\r\n // Process is dead, clear it and start fresh\r\n logger.warn(`[Collector] Previous collector process (PID ${globalCollectorProcess.pid}) is dead, starting new one...`);\r\n globalCollectorProcess = null;\r\n globalCollectorExitCode = null;\r\n globalCollectorStderr = [];\r\n }\r\n }\r\n \r\n // First, check if collector is already running (via UDP discovery)\r\n if (!globalCollectorProcess) {\r\n const status = await isCollectorRunning();\r\n if (status.isRunning && status.isReady && status.otlpEndpoint) {\r\n logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}`);\r\n return `http://${status.otlpEndpoint}`;\r\n }\r\n }\r\n \r\n // Collector not running - start it (or wait for existing one to be ready)\r\n try {\r\n // Clear any previous init error\r\n globalCollectorInitError = null;\r\n \r\n let endpoint: string;\r\n if (existingEndpoint) {\r\n // Collector already starting, just wait for it to be ready\r\n endpoint = existingEndpoint;\r\n logger.info(`[Collector] Waiting for existing collector to become ready at ${endpoint}...`);\r\n } else {\r\n // Start a new collector\r\n logger.info('[Collector] Starting OpenTelemetry collector...');\r\n const startResult = await startCollector(logger, undefined, env);\r\n endpoint = startResult.endpoint;\r\n \r\n // Check if collector process exited immediately (crashed)\r\n // Wait a bit longer to see if it crashes right after starting\r\n await new Promise(resolve => setTimeout(resolve, 200));\r\n \r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const errorMsg = `Collector process exited immediately with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] ${errorMsg}`);\r\n return null;\r\n }\r\n }\r\n \r\n // CRITICAL: Wait for collector to be fully ready before returning\r\n // We'll wait up to 60 seconds, checking every 500ms\r\n // This ensures the collector is actually ready to receive logs before we continue\r\n const maxWaitTime = 60000; // 60 seconds\r\n const checkInterval = 500; // Check every 500ms\r\n const maxChecks = Math.floor(maxWaitTime / checkInterval);\r\n \r\n logger.info('[Collector] Waiting for collector to become ready...');\r\n \r\n for (let i = 0; i < maxChecks; i++) {\r\n await new Promise(resolve => setTimeout(resolve, checkInterval));\r\n \r\n // Check if process exited during wait\r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const errorMsg = `Collector process exited during startup with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] ${errorMsg}`);\r\n return null;\r\n }\r\n \r\n const newStatus = await isCollectorRunning();\r\n if (newStatus.isRunning && newStatus.isReady) {\r\n logger.info(`[Collector] Collector is ready at ${newStatus.otlpEndpoint || endpoint}`);\r\n return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;\r\n }\r\n \r\n // Log progress every 2 seconds\r\n if (i > 0 && i % 4 === 0) {\r\n logger.info(`[Collector] Still waiting for collector to become ready... (${(i * checkInterval) / 1000}s elapsed)`);\r\n }\r\n }\r\n \r\n // Check one more time if process exited\r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const errorMsg = `Collector process exited with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] ${errorMsg}`);\r\n return null;\r\n }\r\n \r\n // Collector did not become ready within timeout\r\n logger.error(`[Collector] Collector did not become ready within ${maxWaitTime / 1000} seconds`);\r\n return null;\r\n } catch (err) {\r\n const errorMsg = err instanceof Error ? err.message : String(err);\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] Failed to start collector: ${errorMsg}`);\r\n return null;\r\n }\r\n}\r\n\r\n"]}
|
|
1
|
+
{"version":3,"file":"collector-manager.js","sourceRoot":"","sources":["../src/collector-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, ChildProcess } from 'child_process';\r\nimport { createWriteStream, existsSync, chmodSync, mkdirSync } from 'fs';\r\nimport { join, dirname } from 'path';\r\nimport { pipeline } from 'stream/promises';\r\nimport { createGunzip } from 'zlib';\r\nimport { createHash } from 'node:crypto';\r\nimport { createServer } from 'net';\r\nimport type { Logger } from 'pino';\r\nimport pino from 'pino';\r\nimport dgram from 'dgram';\r\nimport deasync from 'deasync';\r\nimport type { EnvironmentConfig } from './types.js';\r\nimport { hostToHttpUrl } from './utils/urls.js';\r\n\r\n// Protocol is httpprotobuf \r\n\r\ninterface CollectorDiscoveryEntry {\r\n version: string;\r\n status: string;\r\n pid: number;\r\n otlpEndpoint: string;\r\n}\r\n\r\nexport interface CollectorStatus {\r\n isRunning: boolean;\r\n isReady: boolean;\r\n pid: number;\r\n otlpEndpoint?: string;\r\n version?: string;\r\n}\r\n\r\nconst COLLECTOR_VERSION = '1.0.1'; // Match C# collector version (from collector-version.json)\r\nconst COLLECTOR_DOWNLOAD_BASE = `https://collectors.beamable.com/version/${COLLECTOR_VERSION}`;\r\nconst DISCOVERY_PORT = parseInt(process.env.BEAM_COLLECTOR_DISCOVERY_PORT || '8688', 10);\r\n\r\n/**\r\n * Finds a free TCP port (matching C# PortUtil.FreeTcpPort())\r\n */\r\nfunction findFreePort(): Promise<number> {\r\n return new Promise((resolve, reject) => {\r\n const server = createServer();\r\n server.listen(0, () => {\r\n const address = server.address();\r\n const port = typeof address === 'object' && address !== null ? address.port : 0;\r\n server.close(() => {\r\n if (port > 0) {\r\n resolve(port);\r\n } else {\r\n // Fallback to a default port if something went wrong\r\n resolve(9090);\r\n }\r\n });\r\n });\r\n server.on('error', (err) => {\r\n reject(err);\r\n });\r\n });\r\n}\r\n\r\n// Global storage for collector process and errors (to prevent GC and track status)\r\nlet globalCollectorProcess: ChildProcess | null = null;\r\nlet globalCollectorStartError: string | null = null;\r\nlet globalCollectorExitCode: number | null = null;\r\nlet globalCollectorStderr: string[] = [];\r\n// Track if collector startup is in progress to prevent duplicate starts\r\nlet globalCollectorStartupPromise: Promise<string | null> | null = null;\r\nlet globalCollectorInitError: string | null = null; // Tracks errors from discoverOrStartCollector\r\n\r\n/**\r\n * ClickHouse credentials response from Beamable API\r\n */\r\ninterface ClickHouseCredentials {\r\n endpoint: string;\r\n expiresAt?: string;\r\n password: string;\r\n username: string;\r\n}\r\n\r\n/**\r\n * Calculates Beamable signature for signed requests\r\n * Signature format: MD5(secret + pid + version + uriPathAndQuery + body) as Base64\r\n * Matches C# SignedRequesterHelper.CalculateSignature\r\n */\r\nfunction calculateSignature(\r\n pid: string,\r\n secret: string,\r\n uriPathAndQuery: string,\r\n body: string | null = null,\r\n version: string = '1'\r\n): string {\r\n let dataToSign = `${secret}${pid}${version}${uriPathAndQuery}`;\r\n if (body) {\r\n dataToSign += body;\r\n }\r\n \r\n // MD5 hash to Base64 (matching C# implementation)\r\n const hash = createHash('md5').update(dataToSign, 'utf8').digest('base64');\r\n return hash;\r\n}\r\n\r\n/**\r\n * Extracts path and query from a URL\r\n */\r\nfunction getPathAndQuery(url: string): string {\r\n try {\r\n const urlObj = new URL(url);\r\n return urlObj.pathname + urlObj.search;\r\n } catch {\r\n // If URL parsing fails, return as-is\r\n return url;\r\n }\r\n}\r\n\r\n/**\r\n * Fetches ClickHouse credentials from Beamable API\r\n * GET /api/beamo/otel/auth/writer/config\r\n * Requires signed request authentication (X-BEAM-SIGNATURE header)\r\n */\r\nexport async function fetchClickHouseCredentials(\r\n env: EnvironmentConfig\r\n): Promise<ClickHouseCredentials> {\r\n const apiUrl = hostToHttpUrl(env.host);\r\n const uriPath = '/api/beamo/otel/auth/writer/config';\r\n const configUrl = new URL(uriPath, apiUrl).toString();\r\n \r\n // Get secret from environment (required for signed requests)\r\n const secret = process.env.SECRET;\r\n if (!secret) {\r\n throw new Error('SECRET environment variable is required to fetch ClickHouse credentials');\r\n }\r\n \r\n // Calculate signature for signed request (matching C# HttpSignedRequester)\r\n const pathAndQuery = getPathAndQuery(uriPath);\r\n const signature = calculateSignature(env.pid, secret, pathAndQuery, null, '1');\r\n \r\n // Build headers with signed authentication (matching C# HttpSignedRequester)\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json',\r\n 'X-BEAM-SCOPE': `${env.cid}.${env.pid}`,\r\n 'X-BEAM-SIGNATURE': signature,\r\n };\r\n \r\n const response = await fetch(configUrl, {\r\n method: 'GET',\r\n headers,\r\n });\r\n \r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => 'Unknown error');\r\n throw new Error(`Failed to fetch ClickHouse credentials from ${configUrl}: ${response.status} ${response.statusText} - ${errorText.substring(0, 200)}`);\r\n }\r\n \r\n const credentials = await response.json() as ClickHouseCredentials;\r\n \r\n if (!credentials.endpoint || !credentials.username || !credentials.password) {\r\n throw new Error('Invalid ClickHouse credentials response: missing required fields');\r\n }\r\n \r\n return credentials;\r\n}\r\n\r\n/**\r\n * Gets the collector storage directory (similar to C# LocalApplicationData/beam/collectors/version)\r\n */\r\nfunction getCollectorStoragePath(): string {\r\n // Use temp directory for now - in containers this should be writable\r\n const tempDir = process.env.TMPDIR || process.env.TMP || '/tmp';\r\n return join(tempDir, 'beam', 'collectors', COLLECTOR_VERSION);\r\n}\r\n\r\n/**\r\n * Gets the collector binary name for the current platform\r\n */\r\nfunction getCollectorBinaryName(): string {\r\n const platform = process.platform;\r\n const arch = process.arch;\r\n \r\n // Match C# naming: collector-{osArchSuffix}\r\n // C# returns \"collector-linux-amd64\", not \"beamable-collector-linux-amd64\"\r\n if (platform === 'linux' && arch === 'x64') {\r\n return 'collector-linux-amd64';\r\n } else if (platform === 'linux' && arch === 'arm64') {\r\n return 'collector-linux-arm64';\r\n } else if (platform === 'darwin' && arch === 'x64') {\r\n return 'collector-darwin-amd64';\r\n } else if (platform === 'darwin' && arch === 'arm64') {\r\n return 'collector-darwin-arm64';\r\n } else if (platform === 'win32' && arch === 'x64') {\r\n return 'collector-windows-amd64.exe';\r\n }\r\n \r\n throw new Error(`Unsupported platform: ${platform} ${arch}`);\r\n}\r\n\r\n/**\r\n * Downloads and decompresses a gzipped file\r\n */\r\nasync function downloadAndDecompressGzip(url: string, outputPath: string, makeExecutable: boolean = false): Promise<void> {\r\n let response: Response;\r\n try {\r\n // Add timeout and better error handling\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout\r\n \r\n try {\r\n response = await fetch(url, {\r\n signal: controller.signal,\r\n headers: {\r\n 'User-Agent': 'Beamable-Node-Microservice-Runtime/1.0',\r\n },\r\n });\r\n clearTimeout(timeoutId);\r\n } catch (fetchError) {\r\n clearTimeout(timeoutId);\r\n if (fetchError instanceof Error) {\r\n // Extract underlying error details from cause\r\n let underlyingError = '';\r\n if ((fetchError as any).cause) {\r\n const cause = (fetchError as any).cause;\r\n if (cause instanceof Error) {\r\n const causeCode = (cause as any).code;\r\n underlyingError = ` (cause: ${cause.name} - ${cause.message}${causeCode ? ` [code: ${causeCode}]` : ''})`;\r\n } else if (typeof cause === 'object' && cause.code) {\r\n underlyingError = ` (cause code: ${cause.code})`;\r\n }\r\n }\r\n \r\n // Provide more context about the error\r\n if (fetchError.name === 'AbortError') {\r\n throw new Error(`Timeout downloading ${url} (30s limit exceeded)${underlyingError}`);\r\n }\r\n \r\n // Check error code if available (Node.js system errors)\r\n const errorCode = (fetchError as any).code || ((fetchError as any).cause?.code);\r\n if (errorCode) {\r\n if (errorCode === 'ENOTFOUND' || errorCode === 'EAI_AGAIN') {\r\n throw new Error(`DNS resolution failed for ${url} (code: ${errorCode}). Check network connectivity and DNS settings.`);\r\n }\r\n if (errorCode === 'ECONNREFUSED') {\r\n throw new Error(`Connection refused to ${url} (code: ${errorCode}). Server may be down or firewall blocking.`);\r\n }\r\n if (errorCode === 'ETIMEDOUT' || errorCode === 'ECONNRESET') {\r\n throw new Error(`Connection timeout/reset to ${url} (code: ${errorCode}). Network may be slow or unreachable.`);\r\n }\r\n if (errorCode === 'CERT_HAS_EXPIRED' || errorCode === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE') {\r\n throw new Error(`SSL/TLS certificate error connecting to ${url} (code: ${errorCode}): ${fetchError.message}`);\r\n }\r\n }\r\n \r\n // Check for common network errors in message\r\n const errorMsg = fetchError.message.toLowerCase();\r\n if (errorMsg.includes('enotfound') || errorMsg.includes('dns')) {\r\n throw new Error(`DNS resolution failed for ${url}. Check network connectivity and DNS settings.${underlyingError}`);\r\n }\r\n if (errorMsg.includes('econnrefused') || errorMsg.includes('connection refused')) {\r\n throw new Error(`Connection refused to ${url}. Server may be down or firewall blocking.${underlyingError}`);\r\n }\r\n if (errorMsg.includes('etimedout') || errorMsg.includes('timeout')) {\r\n throw new Error(`Connection timeout to ${url}. Network may be slow or unreachable.${underlyingError}`);\r\n }\r\n if (errorMsg.includes('certificate') || errorMsg.includes('ssl') || errorMsg.includes('tls')) {\r\n throw new Error(`SSL/TLS error connecting to ${url}: ${fetchError.message}${underlyingError}`);\r\n }\r\n throw new Error(`Network error downloading ${url}: ${fetchError.name} - ${fetchError.message}${underlyingError}`);\r\n }\r\n throw new Error(`Network error downloading ${url}: ${String(fetchError)}`);\r\n }\r\n } catch (error) {\r\n // Re-throw with more context\r\n if (error instanceof Error) {\r\n if (error.message.includes('Timeout') || error.message.includes('DNS') || error.message.includes('Connection')) {\r\n throw error; // Already has good context\r\n }\r\n throw new Error(`Network error downloading ${url}: ${error.message}`);\r\n }\r\n throw new Error(`Network error downloading ${url}: ${String(error)}`);\r\n }\r\n \r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => '');\r\n throw new Error(`HTTP ${response.status} downloading ${url}: ${response.statusText}${errorText ? ` - ${errorText.substring(0, 200)}` : ''}`);\r\n }\r\n \r\n const dir = dirname(outputPath);\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true });\r\n }\r\n \r\n const gunzip = createGunzip();\r\n const writeStream = createWriteStream(outputPath);\r\n \r\n await pipeline(response.body as any, gunzip, writeStream);\r\n \r\n if (makeExecutable && process.platform !== 'win32') {\r\n try {\r\n chmodSync(outputPath, 0o755);\r\n } catch (error) {\r\n console.error(`Failed to make ${outputPath} executable:`, error);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Resolves the collector binary and config, downloading if needed\r\n */\r\nasync function resolveCollector(allowDownload: boolean = true, logger?: Logger): Promise<{ binaryPath: string | null; configPath: string | null }> {\r\n const basePath = getCollectorStoragePath();\r\n const binaryName = getCollectorBinaryName();\r\n const configName = 'clickhouse-config.yaml';\r\n \r\n const binaryPath = join(basePath, binaryName);\r\n const configPath = join(basePath, configName);\r\n \r\n const itemsToDownload: Array<{ url: string; path: string; executable: boolean }> = [];\r\n \r\n if (!existsSync(binaryPath) && allowDownload) {\r\n const binaryUrl = `${COLLECTOR_DOWNLOAD_BASE}/${binaryName}.gz`;\r\n itemsToDownload.push({ url: binaryUrl, path: binaryPath, executable: true });\r\n logger?.info(`[Collector] Will download binary from: ${binaryUrl}`);\r\n } else if (existsSync(binaryPath)) {\r\n logger?.info(`[Collector] Binary found at: ${binaryPath}`);\r\n }\r\n \r\n if (!existsSync(configPath) && allowDownload) {\r\n const configUrl = `${COLLECTOR_DOWNLOAD_BASE}/${configName}.gz`;\r\n itemsToDownload.push({ url: configUrl, path: configPath, executable: false });\r\n logger?.info(`[Collector] Will download config from: ${configUrl}`);\r\n } else if (existsSync(configPath)) {\r\n logger?.info(`[Collector] Config found at: ${configPath}`);\r\n }\r\n \r\n for (const item of itemsToDownload) {\r\n try {\r\n logger?.info(`[Collector] Downloading ${item.url}...`);\r\n await downloadAndDecompressGzip(item.url, item.path, item.executable);\r\n logger?.info(`[Collector] Downloaded to ${item.path}`);\r\n } catch (error) {\r\n // Don't wrap the error again if it already contains the URL and details\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger?.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);\r\n // Only wrap if the error doesn't already contain the URL\r\n if (error instanceof Error && errorMsg.includes(item.url)) {\r\n throw error; // Error already has URL and context\r\n }\r\n throw new Error(`Failed to download collector ${item.executable ? 'binary' : 'config'} from ${item.url}: ${errorMsg}`);\r\n }\r\n }\r\n \r\n return {\r\n binaryPath: existsSync(binaryPath) ? binaryPath : null,\r\n configPath: existsSync(configPath) ? configPath : null,\r\n };\r\n}\r\n\r\n/**\r\n * Discovers collector via UDP broadcast\r\n */\r\nfunction discoverCollectorViaUDP(timeoutMs: number = 5000): Promise<CollectorDiscoveryEntry | null> {\r\n return new Promise((resolve) => {\r\n const socket = dgram.createSocket('udp4');\r\n const discovered: CollectorDiscoveryEntry[] = [];\r\n let timeout: NodeJS.Timeout;\r\n \r\n socket.on('message', (msg) => {\r\n try {\r\n const message = JSON.parse(msg.toString()) as CollectorDiscoveryEntry;\r\n // Check if version matches\r\n if (message.version === COLLECTOR_VERSION && message.status === 'READY') {\r\n discovered.push(message);\r\n }\r\n } catch (error) {\r\n // Ignore parse errors\r\n }\r\n });\r\n \r\n socket.on('error', () => {\r\n clearTimeout(timeout);\r\n socket.close();\r\n resolve(null);\r\n });\r\n \r\n socket.bind(() => {\r\n socket.setBroadcast(true);\r\n \r\n timeout = setTimeout(() => {\r\n socket.close();\r\n // Return the first discovered collector\r\n resolve(discovered.length > 0 ? discovered[0] : null);\r\n }, timeoutMs);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Gets the current status of ClickHouse credentials (from env or API)\r\n */\r\nexport function getClickHouseCredentialsStatus(): {\r\n hasEndpoint: boolean;\r\n hasUsername: boolean;\r\n hasPassword: boolean;\r\n source: 'environment' | 'api' | 'missing';\r\n} {\r\n const hasEndpoint = !!process.env.BEAM_CLICKHOUSE_ENDPOINT;\r\n const hasUsername = !!process.env.BEAM_CLICKHOUSE_USERNAME;\r\n const hasPassword = !!process.env.BEAM_CLICKHOUSE_PASSWORD;\r\n \r\n if (hasEndpoint && hasUsername && hasPassword) {\r\n return {\r\n hasEndpoint: true,\r\n hasUsername: true,\r\n hasPassword: true,\r\n source: 'environment',\r\n };\r\n }\r\n \r\n return {\r\n hasEndpoint,\r\n hasUsername,\r\n hasPassword,\r\n source: 'missing',\r\n };\r\n}\r\n\r\n/**\r\n * Checks if collector is already running via UDP discovery\r\n */\r\nexport async function isCollectorRunning(): Promise<CollectorStatus> {\r\n // First, check if we have a global collector process reference\r\n // If the process is running and we've seen \"Everything is ready\" in stderr, it's ready\r\n if (globalCollectorProcess) {\r\n // Check if process is still alive\r\n try {\r\n // Process is alive if we can access it and it hasn't exited\r\n const processAlive = globalCollectorProcess.exitCode === null && \r\n globalCollectorProcess.killed === false;\r\n \r\n if (processAlive) {\r\n // Check if we've seen the \"Everything is ready\" message in stderr\r\n // This is a reliable indicator that the collector is ready\r\n const stderrText = globalCollectorStderr.join('\\n');\r\n const isReady = stderrText.includes('Everything is ready') || \r\n stderrText.includes('Begin running and processing data');\r\n \r\n if (isReady) {\r\n // Try UDP discovery to get the endpoint, but if it fails, use the configured endpoint\r\n try {\r\n const discovered = await discoverCollectorViaUDP(1000); // Shorter timeout since we know it's running\r\n if (discovered && discovered.status === 'READY') {\r\n return {\r\n isRunning: true,\r\n isReady: true,\r\n pid: discovered.pid || globalCollectorProcess.pid || 0,\r\n otlpEndpoint: discovered.otlpEndpoint,\r\n version: discovered.version,\r\n };\r\n }\r\n } catch {\r\n // UDP discovery failed, but process is alive and has \"Everything is ready\" message\r\n // Use the configured endpoint as fallback\r\n }\r\n \r\n // Process is alive and we've seen \"Everything is ready\" - treat as ready\r\n // Extract endpoint from environment or use default\r\n const configuredEndpoint = process.env.BEAM_OTLP_HTTP_ENDPOINT || '0.0.0.0:4318';\r\n return {\r\n isRunning: true,\r\n isReady: true,\r\n pid: globalCollectorProcess.pid || 0,\r\n otlpEndpoint: configuredEndpoint,\r\n version: COLLECTOR_VERSION,\r\n };\r\n }\r\n }\r\n } catch {\r\n // Process might have exited or is invalid\r\n }\r\n }\r\n \r\n // Try UDP discovery as fallback\r\n try {\r\n const discovered = await discoverCollectorViaUDP(2000);\r\n if (discovered) {\r\n return {\r\n isRunning: true,\r\n isReady: discovered.status === 'READY',\r\n pid: discovered.pid,\r\n otlpEndpoint: discovered.otlpEndpoint,\r\n version: discovered.version,\r\n };\r\n }\r\n } catch (error) {\r\n // Discovery failed, collector probably not running\r\n }\r\n \r\n return {\r\n isRunning: false,\r\n isReady: false,\r\n pid: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Sets default collector configuration environment variables in process.env\r\n * Matches C# CollectorManager.AddCollectorConfigurationToEnvironment()\r\n */\r\nfunction addCollectorConfigurationToEnvironment(): void {\r\n const defaults: Record<string, string> = {\r\n BEAM_CLICKHOUSE_PROCESSOR_TIMEOUT: '5s',\r\n BEAM_CLICKHOUSE_PROCESSOR_BATCH_SIZE: '5000',\r\n BEAM_CLICKHOUSE_EXPORTER_TIMEOUT: '5s',\r\n BEAM_CLICKHOUSE_EXPORTER_QUEUE_SIZE: '1000',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_ENABLED: 'true',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_INITIAL_INTERVAL: '5s',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_MAX_INTERVAL: '30s',\r\n BEAM_CLICKHOUSE_EXPORTER_RETRY_MAX_ELAPSED_TIME: '300s',\r\n };\r\n \r\n // Only set if not already set (matching C# behavior)\r\n for (const [key, defaultValue] of Object.entries(defaults)) {\r\n if (!process.env[key]) {\r\n process.env[key] = defaultValue;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Sets ClickHouse credentials in process.env (matching C# CollectorManager.AddAuthEnvironmentVars)\r\n */\r\nexport function addAuthEnvironmentVars(endpoint: string, username: string, password: string): void {\r\n // Always set the values when explicitly provided (matching C# behavior)\r\n // This ensures credentials fetched from API override any existing (potentially empty) values\r\n // In Node.js, process.env is a writable object - setting properties here persists for the lifetime of the process\r\n process.env.BEAM_CLICKHOUSE_ENDPOINT = endpoint;\r\n process.env.BEAM_CLICKHOUSE_USERNAME = username;\r\n process.env.BEAM_CLICKHOUSE_PASSWORD = password;\r\n \r\n // Verify they were actually set (for debugging)\r\n if (!process.env.BEAM_CLICKHOUSE_ENDPOINT || !process.env.BEAM_CLICKHOUSE_USERNAME || !process.env.BEAM_CLICKHOUSE_PASSWORD) {\r\n throw new Error(`Failed to set ClickHouse credentials in process.env - this should never happen in Node.js`);\r\n }\r\n}\r\n\r\n/**\r\n * Sets up the collector BEFORE logging is initialized.\r\n * This ensures all startup logs are captured via OTLP.\r\n * Uses a minimal console logger for setup messages.\r\n * Returns the OTLP endpoint if successful, null otherwise.\r\n */\r\nexport function setupCollectorBeforeLogging(\r\n env: EnvironmentConfig,\r\n timeoutMs: number = 60000\r\n): string | null {\r\n // Match C# logic: (this.InDocker() || UseLocalOtel) && !BEAM_DISABLE_STANDARD_OTEL\r\n const isInDocker = process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true';\r\n const useLocalOtel = !!process.env.BEAM_LOCAL_OTEL;\r\n const standardOtelEnabled = (isInDocker || useLocalOtel) && !process.env.BEAM_DISABLE_STANDARD_OTEL;\r\n const hasExplicitEndpoint = !!process.env.BEAM_OTEL_EXPORTER_OTLP_ENDPOINT;\r\n\r\n // If OTLP is not needed, return immediately\r\n if (!standardOtelEnabled && !hasExplicitEndpoint) {\r\n return null;\r\n }\r\n\r\n // Create a minimal console logger for initialization messages (no OTLP yet)\r\n const initLogger = pino({\r\n name: 'beamable-otlp-init',\r\n level: 'info',\r\n }, process.stdout);\r\n\r\n initLogger.info('[OTLP] Setting up collector before logging initialization...');\r\n\r\n // Use deasync to wait synchronously for collector setup\r\n let endpoint: string | null = null;\r\n let completed = false;\r\n let setupError: string | null = null;\r\n\r\n // Start collector setup promise\r\n discoverOrStartCollector(initLogger, standardOtelEnabled, env)\r\n .then((result) => {\r\n endpoint = result;\r\n completed = true;\r\n if (result) {\r\n initLogger.info(`[OTLP] Collector setup complete, endpoint: ${result}`);\r\n } else {\r\n initLogger.warn('[OTLP] Collector setup returned null, OTLP logging will be disabled');\r\n }\r\n return result;\r\n })\r\n .catch((error) => {\r\n setupError = error instanceof Error ? error.message : String(error);\r\n completed = true;\r\n initLogger.error(`[OTLP] Failed to setup collector: ${setupError}`);\r\n endpoint = null;\r\n });\r\n\r\n // Wait synchronously for collector setup to complete\r\n const startTime = Date.now();\r\n const timeoutId = setTimeout(() => {\r\n if (!completed) {\r\n initLogger.warn(`[OTLP] Collector setup timeout after ${timeoutMs}ms, continuing without OTLP`);\r\n completed = true;\r\n }\r\n }, timeoutMs);\r\n\r\n try {\r\n // Use deasync to wait for completion (allows event loop to process async operations)\r\n deasync.loopWhile(() => {\r\n const elapsed = Date.now() - startTime;\r\n if (elapsed >= timeoutMs) {\r\n return false; // Stop waiting\r\n }\r\n return !completed; // Continue waiting if not completed\r\n });\r\n } catch (error) {\r\n initLogger.error(`[OTLP] Error during collector setup wait: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (completed && endpoint) {\r\n initLogger.info('[OTLP] Collector is ready, proceeding with logger creation');\r\n return endpoint;\r\n } else if (setupError) {\r\n initLogger.error(`[OTLP] Collector setup failed: ${setupError}, continuing without OTLP`);\r\n return null;\r\n } else {\r\n initLogger.warn('[OTLP] Collector setup did not complete in time, continuing without OTLP');\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Starts the OpenTelemetry collector process\r\n */\r\nexport async function startCollector(\r\n logger: Logger,\r\n otlpEndpoint?: string,\r\n env?: EnvironmentConfig\r\n): Promise<{ process: ChildProcess; endpoint: string }> {\r\n // Clear any previous errors\r\n globalCollectorStartError = null;\r\n globalCollectorInitError = null;\r\n \r\n // CRITICAL: Fetch credentials FIRST, before resolving collector binary/config\r\n // This ensures credentials are in process.env even if collector download fails\r\n // The credentials will persist in process.env for the lifetime of the process.\r\n // Per Gabriel: \"these OTEL related ones you need to do it yourself at the beginning of the microservice startup\"\r\n let clickhouseEndpoint = process.env.BEAM_CLICKHOUSE_ENDPOINT;\r\n let clickhouseUsername = process.env.BEAM_CLICKHOUSE_USERNAME;\r\n let clickhousePassword = process.env.BEAM_CLICKHOUSE_PASSWORD;\r\n \r\n if ((!clickhouseEndpoint || !clickhouseUsername || !clickhousePassword) && env) {\r\n try {\r\n logger.info('[Collector] Fetching ClickHouse credentials from Beamable API...');\r\n const credentials = await fetchClickHouseCredentials(env);\r\n clickhouseEndpoint = credentials.endpoint;\r\n clickhouseUsername = credentials.username;\r\n clickhousePassword = credentials.password;\r\n \r\n // CRITICAL: Set them in process.env IMMEDIATELY after fetching (matching C# CollectorManager.AddAuthEnvironmentVars)\r\n // In Node.js, process.env is a writable object - setting properties here persists for the lifetime of the process\r\n // This ensures they're available to both the Node.js process and inherited by the collector child process\r\n addAuthEnvironmentVars(clickhouseEndpoint, clickhouseUsername, clickhousePassword);\r\n \r\n // Verify they were set (defensive check - should never fail in Node.js)\r\n const verifyEndpoint = process.env.BEAM_CLICKHOUSE_ENDPOINT;\r\n const verifyUsername = process.env.BEAM_CLICKHOUSE_USERNAME;\r\n const verifyPassword = process.env.BEAM_CLICKHOUSE_PASSWORD;\r\n \r\n if (!verifyEndpoint || !verifyUsername || !verifyPassword) {\r\n logger.error(`[Collector] CRITICAL: Credentials were set but are missing from process.env! This should never happen.`);\r\n throw new Error('Failed to persist ClickHouse credentials in process.env');\r\n }\r\n \r\n logger.info('[Collector] ClickHouse credentials fetched from API and verified in process.env');\r\n } catch (error) {\r\n const errorMsg = `[Collector] Failed to fetch ClickHouse credentials from API: ${error instanceof Error ? error.message : String(error)}`;\r\n logger.error(errorMsg);\r\n throw new Error(errorMsg);\r\n }\r\n }\r\n \r\n // Validate required environment variables (matching C# behavior)\r\n // These must be set before starting the collector, otherwise it will fail\r\n if (!clickhouseEndpoint || !clickhouseUsername || !clickhousePassword) {\r\n const errorMsg = `[Collector] Required ClickHouse credentials are missing. Set BEAM_CLICKHOUSE_ENDPOINT, BEAM_CLICKHOUSE_USERNAME, and BEAM_CLICKHOUSE_PASSWORD, or ensure the API endpoint is accessible.`;\r\n logger.error(errorMsg);\r\n throw new Error(errorMsg);\r\n }\r\n \r\n // Now resolve collector binary and config (after credentials are fetched and set)\r\n logger.info('[Collector] Resolving collector binary and config...');\r\n const collectorInfo = await resolveCollector(true, logger);\r\n \r\n if (!collectorInfo.binaryPath) {\r\n logger.error('[Collector] Binary not found and download failed');\r\n throw new Error('Collector binary not found and download failed');\r\n }\r\n \r\n if (!collectorInfo.configPath) {\r\n logger.error('[Collector] Config not found and download failed');\r\n throw new Error('Collector config not found and download failed');\r\n }\r\n \r\n logger.info(`[Collector] Using binary: ${collectorInfo.binaryPath}`);\r\n logger.info(`[Collector] Using config: ${collectorInfo.configPath}`);\r\n \r\n // Verify binary exists\r\n if (!collectorInfo.binaryPath || !existsSync(collectorInfo.binaryPath)) {\r\n throw new Error(`Collector binary not found at ${collectorInfo.binaryPath}`);\r\n }\r\n \r\n // Check if binary is executable (Unix only - Windows doesn't have execute permission)\r\n if (process.platform !== 'win32') {\r\n try {\r\n const fsPromises = await import('fs/promises');\r\n const stats = await fsPromises.stat(collectorInfo.binaryPath);\r\n const mode = Number(stats.mode);\r\n const isExecutable = !!(mode & parseInt('111', 8)); // Check execute bit\r\n if (!isExecutable) {\r\n logger.warn(`[Collector] Binary may not be executable. Mode: ${mode.toString(8)}`);\r\n // Try to make it executable again\r\n try {\r\n chmodSync(collectorInfo.binaryPath, 0o755);\r\n logger.info(`[Collector] Made binary executable`);\r\n } catch (chmodError) {\r\n logger.error(`[Collector] Failed to make binary executable: ${chmodError instanceof Error ? chmodError.message : String(chmodError)}`);\r\n }\r\n }\r\n } catch (statError) {\r\n logger.warn(`[Collector] Could not check binary permissions: ${statError instanceof Error ? statError.message : String(statError)}`);\r\n }\r\n }\r\n\r\n // Set default collector configuration environment variables in process.env\r\n // This ensures they're available to both the Node.js process and the collector child process\r\n // Matches C# CollectorManager.AddCollectorConfigurationToEnvironment()\r\n addCollectorConfigurationToEnvironment();\r\n \r\n // CRITICAL: Set BEAM_COLLECTOR_DISCOVERY_PORT if not already set (matching C# AddDefaultCollectorHostAndPortFallback)\r\n // This MUST be set before starting the collector\r\n if (!process.env.BEAM_COLLECTOR_DISCOVERY_PORT) {\r\n process.env.BEAM_COLLECTOR_DISCOVERY_PORT = String(DISCOVERY_PORT);\r\n logger.info(`[Collector] Set BEAM_COLLECTOR_DISCOVERY_PORT=${DISCOVERY_PORT} (default)`);\r\n }\r\n \r\n // Determine OTLP endpoint\r\n // Use a free port if not specified (like C# does with PortUtil.FreeEndpoint())\r\n let localEndpoint = otlpEndpoint;\r\n if (!localEndpoint) {\r\n // For now, use default OTLP HTTP port\r\n // In production, this would be discovered or set by Beamable\r\n localEndpoint = '0.0.0.0:4318';\r\n }\r\n localEndpoint = localEndpoint.replace(/^http:\\/\\//, '').replace(/^https:\\/\\//, '');\r\n \r\n // Find a free port for Prometheus (matching C# PortUtil.FreeTcpPort())\r\n // We'll use a simple approach: bind to port 0 and let the OS assign a port\r\n // For now, use a default port (9090 is common for Prometheus) or find a free one\r\n // C# uses PortUtil.FreeTcpPort() which finds an available TCP port\r\n // We'll use a simple helper to find a free port\r\n const prometheusPort = await findFreePort();\r\n \r\n // Set environment variables for collector\r\n // Note: BEAM_CLICKHOUSE_ENDPOINT is for collector → ClickHouse communication\r\n // This is different from the OTLP endpoint (microservice → collector)\r\n // The collector process will inherit all environment variables from process.env automatically\r\n // We only need to set the OTLP endpoint, discovery port, and Prometheus port explicitly here\r\n const collectorEnv: NodeJS.ProcessEnv = {\r\n ...process.env, // Inherit all process.env (including credentials and config we just set)\r\n BEAM_OTLP_HTTP_ENDPOINT: localEndpoint,\r\n BEAM_COLLECTOR_DISCOVERY_PORT: String(DISCOVERY_PORT),\r\n BEAM_COLLECTOR_PROMETHEUS_PORT: String(prometheusPort),\r\n };\r\n \r\n // Start collector process\r\n const collectorProcess = spawn(collectorInfo.binaryPath, ['--config', collectorInfo.configPath], {\r\n env: collectorEnv,\r\n stdio: ['ignore', 'pipe', 'pipe'],\r\n detached: false,\r\n });\r\n \r\n // Store globally to prevent GC and track status\r\n globalCollectorProcess = collectorProcess;\r\n globalCollectorStartError = null;\r\n globalCollectorExitCode = null;\r\n globalCollectorStderr = [];\r\n \r\n // Set up handlers BEFORE we check if process started, so we capture all output\r\n collectorProcess.stdout?.on('data', (data) => {\r\n const outputLine = data.toString().trim();\r\n // Log stdout at info level to see collector output\r\n logger.info(`[Collector OUT] ${outputLine}`);\r\n });\r\n \r\n collectorProcess.stderr?.on('data', (data) => {\r\n const errorLine = data.toString().trim();\r\n globalCollectorStderr.push(errorLine);\r\n // Keep only last 50 lines to prevent memory issues\r\n if (globalCollectorStderr.length > 50) {\r\n globalCollectorStderr.shift();\r\n }\r\n // Log stderr at info level so we can see why collector crashes\r\n logger.info(`[Collector ERR] ${errorLine}`);\r\n });\r\n \r\n collectorProcess.on('error', (err) => {\r\n globalCollectorStartError = err.message;\r\n logger.error(`[Collector] Failed to start: ${err.message}`);\r\n });\r\n \r\n collectorProcess.on('exit', (code, signal) => {\r\n globalCollectorExitCode = code;\r\n logger.warn(`[Collector] Process exited with code ${code}${signal ? `, signal ${signal}` : ''}`);\r\n \r\n // If process exited with an error code, log accumulated stderr\r\n if (code !== 0 && globalCollectorStderr.length > 0) {\r\n logger.error(`[Collector] Exit error - Last ${Math.min(10, globalCollectorStderr.length)} stderr lines:`);\r\n globalCollectorStderr.slice(-10).forEach((line) => {\r\n logger.error(`[Collector ERR] ${line}`);\r\n });\r\n }\r\n \r\n // Don't clear reference immediately - keep it for status checks\r\n // globalCollectorProcess = null; // Keep reference for getCollectorProcessStatus()\r\n });\r\n \r\n logger.info(`[Collector] Started with PID ${collectorProcess.pid}, endpoint: ${localEndpoint}`);\r\n \r\n // Give the process a moment to start and potentially write to stderr\r\n // This helps capture immediate startup errors\r\n // Wait a bit longer to ensure we catch immediate crashes\r\n await new Promise(resolve => setTimeout(resolve, 500));\r\n \r\n // Check if process already exited (immediate crash)\r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const stderrMsg = globalCollectorStderr.length > 0 \r\n ? ` Stderr: ${globalCollectorStderr.join('; ')}` \r\n : ' No stderr output captured.';\r\n throw new Error(`Collector process exited immediately after startup with code ${globalCollectorExitCode}.${stderrMsg}`);\r\n }\r\n \r\n return {\r\n process: collectorProcess,\r\n endpoint: `http://${localEndpoint}`,\r\n };\r\n}\r\n\r\n/**\r\n * Gets detailed collector status including process info and errors\r\n */\r\nexport function getCollectorProcessStatus(): {\r\n hasProcess: boolean;\r\n pid: number | null;\r\n exitCode: number | null;\r\n startError: string | null;\r\n initError: string | null;\r\n stderr: string[];\r\n} {\r\n return {\r\n hasProcess: globalCollectorProcess !== null,\r\n pid: globalCollectorProcess?.pid ?? null,\r\n exitCode: globalCollectorExitCode,\r\n startError: globalCollectorStartError,\r\n initError: globalCollectorInitError,\r\n stderr: [...globalCollectorStderr], // Return a copy\r\n };\r\n}\r\n\r\n/**\r\n * Discovers or starts the collector and returns the OTLP endpoint\r\n */\r\nexport async function discoverOrStartCollector(\r\n logger: Logger,\r\n standardOtelEnabled: boolean,\r\n env?: EnvironmentConfig\r\n): Promise<string | null> {\r\n if (!standardOtelEnabled) {\r\n return null;\r\n }\r\n \r\n // CRITICAL: Check if collector startup is already in progress\r\n // This prevents duplicate collector starts if this function is called multiple times\r\n // (e.g., if setupCollectorBeforeLogging times out but the promise is still running)\r\n if (globalCollectorStartupPromise) {\r\n logger.info('[Collector] Collector startup already in progress, waiting for existing startup to complete...');\r\n try {\r\n const result = await globalCollectorStartupPromise;\r\n // Clear the promise after it completes (success or failure)\r\n globalCollectorStartupPromise = null;\r\n return result;\r\n } catch (error) {\r\n logger.error(`[Collector] Existing startup promise failed: ${error instanceof Error ? error.message : String(error)}`);\r\n // Clear the promise so we can retry\r\n globalCollectorStartupPromise = null;\r\n // Fall through to start a new one\r\n }\r\n }\r\n \r\n // CRITICAL: Check if we already have a collector process starting/running\r\n // This prevents duplicate collector starts if this function is called multiple times\r\n let existingEndpoint: string | undefined;\r\n if (globalCollectorProcess) {\r\n // Check if process is still alive\r\n const processAlive = globalCollectorProcess.exitCode === null && \r\n globalCollectorProcess.killed === false;\r\n \r\n if (processAlive) {\r\n logger.info(`[Collector] Collector process already exists (PID ${globalCollectorProcess.pid}), waiting for it to be ready...`);\r\n // Use the configured endpoint from environment (we started it earlier)\r\n existingEndpoint = process.env.BEAM_OTLP_HTTP_ENDPOINT ? \r\n `http://${process.env.BEAM_OTLP_HTTP_ENDPOINT}` : \r\n 'http://0.0.0.0:4318';\r\n // Fall through to the wait logic below (don't start a new collector)\r\n } else {\r\n // Process is dead, clear it and start fresh\r\n logger.warn(`[Collector] Previous collector process (PID ${globalCollectorProcess.pid}) is dead, starting new one...`);\r\n globalCollectorProcess = null;\r\n globalCollectorExitCode = null;\r\n globalCollectorStderr = [];\r\n }\r\n }\r\n \r\n // First, check if collector is already running (via UDP discovery)\r\n if (!globalCollectorProcess) {\r\n const status = await isCollectorRunning();\r\n if (status.isRunning && status.isReady && status.otlpEndpoint) {\r\n logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}`);\r\n return `http://${status.otlpEndpoint}`;\r\n }\r\n }\r\n \r\n // Collector not running - start it (or wait for existing one to be ready)\r\n // Wrap the entire startup logic in a promise that we track globally\r\n // This prevents duplicate starts if this function is called multiple times\r\n const startupPromise = (async (): Promise<string | null> => {\r\n try {\r\n // Clear any previous init error\r\n globalCollectorInitError = null;\r\n \r\n let endpoint: string;\r\n if (existingEndpoint) {\r\n // Collector already starting, just wait for it to be ready\r\n endpoint = existingEndpoint;\r\n logger.info(`[Collector] Waiting for existing collector to become ready at ${endpoint}...`);\r\n } else {\r\n // Start a new collector\r\n logger.info('[Collector] Starting OpenTelemetry collector...');\r\n const startResult = await startCollector(logger, undefined, env);\r\n endpoint = startResult.endpoint;\r\n \r\n // Check if collector process exited immediately (crashed)\r\n // Wait a bit longer to see if it crashes right after starting\r\n await new Promise(resolve => setTimeout(resolve, 200));\r\n \r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const errorMsg = `Collector process exited immediately with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] ${errorMsg}`);\r\n return null;\r\n }\r\n }\r\n \r\n // CRITICAL: Wait for collector to be fully ready before returning\r\n // We'll wait up to 60 seconds, checking every 500ms\r\n // This ensures the collector is actually ready to receive logs before we continue\r\n const maxWaitTime = 60000; // 60 seconds\r\n const checkInterval = 500; // Check every 500ms\r\n const maxChecks = Math.floor(maxWaitTime / checkInterval);\r\n \r\n logger.info('[Collector] Waiting for collector to become ready...');\r\n \r\n for (let i = 0; i < maxChecks; i++) {\r\n await new Promise(resolve => setTimeout(resolve, checkInterval));\r\n \r\n // Check if process exited during wait\r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const errorMsg = `Collector process exited during startup with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] ${errorMsg}`);\r\n return null;\r\n }\r\n \r\n const newStatus = await isCollectorRunning();\r\n if (newStatus.isRunning && newStatus.isReady) {\r\n logger.info(`[Collector] Collector is ready at ${newStatus.otlpEndpoint || endpoint}`);\r\n return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;\r\n }\r\n \r\n // Log progress every 2 seconds\r\n if (i > 0 && i % 4 === 0) {\r\n logger.info(`[Collector] Still waiting for collector to become ready... (${(i * checkInterval) / 1000}s elapsed)`);\r\n }\r\n }\r\n \r\n // Check one more time if process exited\r\n if (globalCollectorExitCode !== null && globalCollectorExitCode !== 0) {\r\n const errorMsg = `Collector process exited with code ${globalCollectorExitCode}. ${globalCollectorStderr.length > 0 ? `Stderr: ${globalCollectorStderr.join('; ')}` : 'No stderr output.'}`;\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] ${errorMsg}`);\r\n return null;\r\n }\r\n \r\n // Collector did not become ready within timeout\r\n logger.error(`[Collector] Collector did not become ready within ${maxWaitTime / 1000} seconds`);\r\n return null;\r\n } catch (err) {\r\n const errorMsg = err instanceof Error ? err.message : String(err);\r\n globalCollectorInitError = errorMsg;\r\n logger.error(`[Collector] Failed to start collector: ${errorMsg}`);\r\n return null;\r\n }\r\n })();\r\n \r\n // Store the promise globally so other calls to this function can wait for it\r\n globalCollectorStartupPromise = startupPromise;\r\n \r\n // Clear the promise when it completes (so we don't keep waiting on old promises)\r\n startupPromise.finally(() => {\r\n globalCollectorStartupPromise = null;\r\n });\r\n \r\n return await startupPromise;\r\n}\r\n\r\n"]}
|
package/dist/runtime.cjs
CHANGED
|
@@ -41,7 +41,7 @@ class MicroserviceRuntime {
|
|
|
41
41
|
const primaryService = registered[0];
|
|
42
42
|
const qualifiedServiceName = `micro_${primaryService.qualifiedName}`;
|
|
43
43
|
startupLogger.info('Setting up OpenTelemetry collector...');
|
|
44
|
-
const otlpEndpoint = (0, collector_manager_js_1.setupCollectorBeforeLogging)(this.env,
|
|
44
|
+
const otlpEndpoint = (0, collector_manager_js_1.setupCollectorBeforeLogging)(this.env, 120000);
|
|
45
45
|
if (otlpEndpoint) {
|
|
46
46
|
startupLogger.info(`Collector ready at ${otlpEndpoint}, creating main logger...`);
|
|
47
47
|
}
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,iBAAiB,EAOlB,MAAM,YAAY,CAAC;AA2BpB,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,OAAO,CAAkB;gBAErB,GAAG,CAAC,EAAE,iBAAiB;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,iBAAiB,EAOlB,MAAM,YAAY,CAAC;AA2BpB,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IACxD,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,OAAO,CAAC,OAAO,CAAkB;gBAErB,GAAG,CAAC,EAAE,iBAAiB;IA2F7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6DtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YASjB,sBAAsB;YA2CtB,qBAAqB;YAarB,eAAe;YA+Gf,WAAW;IA8BzB,OAAO,CAAC,gBAAgB;IAkFxB,OAAO,CAAC,kBAAkB;YAUZ,QAAQ;IAsDtB,OAAO,CAAC,wBAAwB;YAmBlB,mBAAmB;YAiBnB,sBAAsB;YAStB,wBAAwB;YAoBxB,mBAAmB;IA2GjC,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,gBAAgB;YA+BV,6BAA6B;IA6B3C,OAAO,CAAC,kBAAkB;CAK3B;AA+GD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAoDrD;AAED,UAAU,sBAAsB;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,4CAA4C,CAC1D,SAAS,GAAE,OAAO,CAAC,iBAAiB,CAAM,EAC1C,OAAO,GAAE,sBAA2B,GACnC,OAAO,CA6BT"}
|
package/dist/runtime.js
CHANGED
|
@@ -48,7 +48,14 @@ export class MicroserviceRuntime {
|
|
|
48
48
|
// STEP 3: Setup collector BEFORE creating the main logger
|
|
49
49
|
// This ensures all logs from the main logger are captured via OTLP
|
|
50
50
|
startupLogger.info('Setting up OpenTelemetry collector...');
|
|
51
|
-
|
|
51
|
+
// Timeout needs to account for:
|
|
52
|
+
// - API call for credentials (~1-2 seconds)
|
|
53
|
+
// - Downloading collector binary (~12MB, can take 5-10+ seconds on slow networks)
|
|
54
|
+
// - Downloading collector config (~1 second)
|
|
55
|
+
// - Starting collector process (~1 second)
|
|
56
|
+
// - Waiting for collector to be ready (up to 60 seconds)
|
|
57
|
+
// Total: ~70-80 seconds minimum, so use 120 seconds for safety
|
|
58
|
+
const otlpEndpoint = setupCollectorBeforeLogging(this.env, 120000 // 120 second timeout to allow for download + startup + readiness
|
|
52
59
|
);
|
|
53
60
|
if (otlpEndpoint) {
|
|
54
61
|
startupLogger.info(`Collector ready at ${otlpEndpoint}, creating main logger...`);
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto';\r\nimport { BeamableWebSocket } from './websocket.js';\r\nimport { GatewayRequester } from './requester.js';\r\nimport { AuthManager } from './auth.js';\r\nimport { createLogger } from './logger.js';\r\nimport { loadEnvironmentConfig } from './env.js';\r\nimport { setupCollectorBeforeLogging } from './collector-manager.js';\r\nimport pino from 'pino';\r\nimport { listRegisteredServices, getServiceOptions, getConfigureServicesHandlers, getInitializeServicesHandlers } from './decorators.js';\r\nimport { generateOpenApiDocument } from './docs.js';\r\nimport { VERSION } from './index.js';\r\nimport { DiscoveryBroadcaster } from './discovery.js';\r\nimport { BeamableRuntimeError, MissingScopesError, UnauthorizedUserError, UnknownRouteError } from './errors.js';\r\nimport type {\r\n EnvironmentConfig,\r\n RequestContext,\r\n ServiceDefinition,\r\n ServiceCallableMetadata,\r\n GatewayResponse,\r\n WebsocketEventEnvelope,\r\n ServiceAccess,\r\n} from './types.js';\r\nimport type { Logger } from 'pino';\r\nimport { BeamableServiceManager } from './services.js';\r\nimport {\r\n DependencyBuilder,\r\n LOGGER_TOKEN,\r\n ENVIRONMENT_CONFIG_TOKEN,\r\n REQUEST_CONTEXT_TOKEN,\r\n BEAMABLE_SERVICES_TOKEN,\r\n ServiceProvider,\r\n MutableDependencyScope,\r\n} from './dependency.js';\r\nimport { hostToHttpUrl, hostToPortalUrl } from './utils/urls.js';\r\nimport { FederationRegistry, getFederationComponents, getFederatedInventoryMetadata } from './federation.js';\r\nimport type { FederatedRequestContext } from './federation.js';\r\nimport { createServer, type Server } from 'node:http';\r\n\r\ninterface ServiceInstance {\r\n definition: ServiceDefinition;\r\n instance: Record<string, unknown>;\r\n configureHandlers: ReturnType<typeof getConfigureServicesHandlers>;\r\n initializeHandlers: ReturnType<typeof getInitializeServicesHandlers>;\r\n provider?: ServiceProvider;\r\n logger: Logger;\r\n federationRegistry: FederationRegistry;\r\n}\r\n\r\nexport class MicroserviceRuntime {\r\n private readonly env: EnvironmentConfig;\r\n private readonly logger: Logger;\r\n private readonly services: ServiceInstance[];\r\n private readonly webSocket: BeamableWebSocket;\r\n private readonly requester: GatewayRequester;\r\n private readonly authManager: AuthManager;\r\n private readonly discovery?: DiscoveryBroadcaster;\r\n private readonly microServiceId = randomUUID();\r\n private readonly serviceManager: BeamableServiceManager;\r\n private healthCheckServer?: Server;\r\n private isReady: boolean = false;\r\n\r\n constructor(env?: EnvironmentConfig) {\r\n this.env = env ?? loadEnvironmentConfig();\r\n \r\n // STEP 1: Create minimal console logger for startup messages (before collector setup)\r\n // This ensures we have logging available immediately, even before collector is ready\r\n const startupLogger = pino({\r\n name: 'beamable-runtime-startup',\r\n level: 'info',\r\n }, process.stdout);\r\n startupLogger.info('Starting Beamable Node microservice runtime.');\r\n \r\n // STEP 2: Get registered services to extract service name\r\n const registered = listRegisteredServices();\r\n if (registered.length === 0) {\r\n throw new Error('No microservices registered. Use the @Microservice decorator to register at least one class.');\r\n }\r\n \r\n // Use the first service's name for the main logger (for CloudWatch filtering and ClickHouse compatibility)\r\n const primaryService = registered[0];\r\n const qualifiedServiceName = `micro_${primaryService.qualifiedName}`;\r\n \r\n // STEP 3: Setup collector BEFORE creating the main logger\r\n // This ensures all logs from the main logger are captured via OTLP\r\n startupLogger.info('Setting up OpenTelemetry collector...');\r\n const otlpEndpoint = setupCollectorBeforeLogging(\r\n this.env,\r\n 60000 // 60 second timeout\r\n );\r\n \r\n if (otlpEndpoint) {\r\n startupLogger.info(`Collector ready at ${otlpEndpoint}, creating main logger...`);\r\n } else {\r\n startupLogger.warn('Collector setup did not complete, continuing without OTLP logging');\r\n }\r\n \r\n // STEP 4: Create main logger (collector is now ready, so all logs will be captured)\r\n // Pass the OTLP endpoint to skip re-discovery/startup\r\n this.logger = createLogger(this.env, {\r\n name: 'beamable-node-microservice',\r\n serviceName: primaryService.name,\r\n qualifiedServiceName: qualifiedServiceName,\r\n otlpEndpoint: otlpEndpoint || undefined, // Pass endpoint if collector was set up\r\n });\r\n this.serviceManager = new BeamableServiceManager(this.env, this.logger);\r\n\r\n this.services = registered.map((definition) => {\r\n const instance = new definition.ctor() as Record<string, unknown>;\r\n const configureHandlers = getConfigureServicesHandlers(definition.ctor);\r\n const initializeHandlers = getInitializeServicesHandlers(definition.ctor);\r\n const logger = this.logger.child({ service: definition.name });\r\n const federationRegistry = new FederationRegistry(logger);\r\n const decoratedFederations = getFederationComponents(definition.ctor);\r\n for (const component of decoratedFederations) {\r\n federationRegistry.register(component);\r\n }\r\n const inventoryMetadata = getFederatedInventoryMetadata(definition.ctor);\r\n if (inventoryMetadata.length > 0) {\r\n federationRegistry.registerInventoryHandlers(instance, inventoryMetadata);\r\n }\r\n this.serviceManager.registerFederationRegistry(definition.name, federationRegistry);\r\n return { definition, instance, configureHandlers, initializeHandlers, logger, federationRegistry };\r\n });\r\n\r\n const socketUrl = this.env.host.endsWith('/socket') ? this.env.host : `${this.env.host}/socket`;\r\n this.webSocket = new BeamableWebSocket({ url: socketUrl, logger: this.logger });\r\n this.webSocket.on('message', (payload) => {\r\n this.logger.debug({ payload }, 'Runtime observed websocket frame.');\r\n });\r\n this.requester = new GatewayRequester(this.webSocket, this.logger);\r\n this.authManager = new AuthManager(this.env, this.requester);\r\n this.requester.on('event', (envelope) => this.handleEvent(envelope));\r\n\r\n // Discovery broadcaster only runs in local development (not in containers)\r\n // This allows the portal to detect that the service is running locally\r\n if (!isRunningInContainer() && this.services.length > 0) {\r\n this.discovery = new DiscoveryBroadcaster({\r\n env: this.env,\r\n serviceName: this.services[0].definition.name,\r\n routingKey: this.env.routingKey,\r\n logger: this.logger.child({ component: 'DiscoveryBroadcaster' }),\r\n });\r\n }\r\n }\r\n\r\n async start(): Promise<void> {\r\n // Immediate console output for container logs (before logger is ready)\r\n debugLog('[BEAMABLE-NODE] MicroserviceRuntime.start() called');\r\n debugLog(`[BEAMABLE-NODE] Service count: ${this.services.length}`);\r\n \r\n this.printHelpfulUrls(this.services[0]);\r\n this.logger.info('Starting Beamable Node microservice runtime.');\r\n \r\n // Start health check server FIRST - this is critical for container health checks\r\n // Even if startup fails, the health check server must be running so we can debug\r\n debugLog('[BEAMABLE-NODE] Starting health check server...');\r\n await this.startHealthCheckServer();\r\n debugLog('[BEAMABLE-NODE] Health check server started');\r\n \r\n try {\r\n this.logger.info('Connecting to Beamable gateway...');\r\n await this.webSocket.connect();\r\n await new Promise((resolve) => setTimeout(resolve, 250));\r\n \r\n this.logger.info('Authenticating with Beamable...');\r\n await this.authManager.authenticate();\r\n \r\n this.logger.info('Initializing Beamable SDK services...');\r\n await this.serviceManager.initialize();\r\n \r\n this.logger.info('Initializing dependency providers...');\r\n await this.initializeDependencyProviders();\r\n \r\n this.logger.info('Registering service with gateway...');\r\n await this.registerService();\r\n \r\n this.logger.info('Starting discovery broadcaster...');\r\n await this.discovery?.start();\r\n \r\n // Mark as ready only after service is fully registered and discovery is started\r\n this.isReady = true;\r\n this.logger.info('Beamable microservice runtime is ready to accept traffic.');\r\n } catch (error) {\r\n // Log the error with full context but don't crash - health check server is running\r\n // This allows the container to stay alive so we can debug the issue\r\n // Debug output for local development only (in containers, logger handles this)\r\n debugLog('[BEAMABLE-NODE] FATAL ERROR during startup:');\r\n debugLog(`[BEAMABLE-NODE] Error message: ${error instanceof Error ? error.message : String(error)}`);\r\n debugLog(`[BEAMABLE-NODE] Error stack: ${error instanceof Error ? error.stack : 'No stack trace'}`);\r\n debugLog(`[BEAMABLE-NODE] isReady: ${this.isReady}`);\r\n \r\n this.logger.error(\r\n { \r\n err: error,\r\n errorMessage: error instanceof Error ? error.message : String(error),\r\n errorStack: error instanceof Error ? error.stack : undefined,\r\n isReady: this.isReady,\r\n },\r\n 'Failed to fully initialize microservice runtime. Health check will continue to return 503 until initialization completes.'\r\n );\r\n // DON'T re-throw - keep process alive so health check can show 503\r\n // This allows us to see the error in logs\r\n this.isReady = false;\r\n }\r\n }\r\n\r\n async shutdown(): Promise<void> {\r\n this.logger.info('Shutting down microservice runtime.');\r\n this.isReady = false; // Mark as not ready during shutdown\r\n this.discovery?.stop();\r\n await this.stopHealthCheckServer();\r\n this.requester.dispose();\r\n await this.webSocket.close();\r\n }\r\n\r\n private async startHealthCheckServer(): Promise<void> {\r\n // For deployed services, always start health check server (required for container health checks)\r\n // For local development, only start if healthPort is explicitly set\r\n // IMPORTANT: Always default to 6565 if HEALTH_PORT env var is not set, as this is the standard port\r\n const healthPort = this.env.healthPort || 6565;\r\n \r\n // Always start health check server if we have a valid port\r\n // The container orchestrator expects this endpoint to be available\r\n if (!healthPort || healthPort === 0) {\r\n // Health check server not needed (local development without explicit port)\r\n this.logger.debug('Health check server skipped (no healthPort set)');\r\n return;\r\n }\r\n\r\n this.healthCheckServer = createServer((req, res) => {\r\n if (req.url === '/health' && req.method === 'GET') {\r\n // Only return success if service is fully ready (registered and accepting traffic)\r\n if (this.isReady) {\r\n res.writeHead(200, { 'Content-Type': 'text/plain' });\r\n res.end('responsive');\r\n } else {\r\n // Service is still starting up\r\n res.writeHead(503, { 'Content-Type': 'text/plain' });\r\n res.end('Service Unavailable');\r\n }\r\n } else {\r\n res.writeHead(404, { 'Content-Type': 'text/plain' });\r\n res.end('Not Found');\r\n }\r\n });\r\n\r\n return new Promise((resolve, reject) => {\r\n this.healthCheckServer!.listen(healthPort, '0.0.0.0', () => {\r\n this.logger.info({ port: healthPort }, 'Health check server started on port');\r\n resolve();\r\n });\r\n this.healthCheckServer!.on('error', (err) => {\r\n this.logger.error({ err, port: healthPort }, 'Failed to start health check server');\r\n reject(err);\r\n });\r\n });\r\n }\r\n\r\n private async stopHealthCheckServer(): Promise<void> {\r\n if (!this.healthCheckServer) {\r\n return;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n this.healthCheckServer!.close(() => {\r\n this.logger.info('Health check server stopped');\r\n resolve();\r\n });\r\n });\r\n }\r\n\r\n private async registerService(): Promise<void> {\r\n const primary = this.services[0]?.definition;\r\n if (!primary) {\r\n throw new Error('Unexpected missing service definition during registration.');\r\n }\r\n const options = getServiceOptions(primary.ctor) ?? {};\r\n // Match C# exactly: use qualifiedName (preserves case) for name field.\r\n // The gateway lowercases service names when creating bindings, but uses the original case\r\n // from the registration request when constructing routing key lookups.\r\n // This ensures the routing key format matches what the gateway expects.\r\n // The gateway's binding lookup behavior:\r\n // - Gateway error shows: \"No binding found for service ...micro_examplenodeservice.basic\"\r\n // - This means the gateway lowercases the service name for binding storage/lookup\r\n // - Portal sends requests with mixed case in URL and routing key header\r\n // - The gateway lowercases the URL path for binding lookup, which should work\r\n // - But we need to register with the format the gateway expects for the binding key\r\n // - The gateway constructs binding key as: {cid}.{pid}.{lowercaseServiceName}.{type}\r\n // - So we register with lowercase to match what the gateway stores in the binding\r\n // - The portal will still send mixed case, and the gateway will lowercase it for lookup\r\n // Register with mixed-case qualifiedName to match C# behavior\r\n // The gateway will lowercase the service name when creating the binding key,\r\n // but the registration request should use the original case (as C# does)\r\n // This ensures the service name in the registration matches what the portal expects\r\n // Register with mixed-case qualifiedName to match C# behavior\r\n // The gateway's ServiceIdentity.fullNameNoType lowercases the service name when creating bindings,\r\n // but the registration request should use the original case (as C# does)\r\n // This ensures the service name in the registration matches what the portal expects\r\n const isDeployed = isRunningInContainer();\r\n \r\n // For deployed services, routingKey should be null/undefined (None in Scala)\r\n // For local dev, routingKey should be the actual routing key string\r\n // The backend expects Option[String] = None for deployed services\r\n // Note: microServiceId is not part of SocketSessionProviderRegisterRequest, so we don't include it\r\n // All fields except 'type' are Option[T] in Scala, so undefined fields will be omitted from JSON\r\n // This matches C# behavior where null/None fields are not serialized\r\n const request: Record<string, unknown> = {\r\n type: 'basic',\r\n name: primary.qualifiedName, // Use mixed-case as C# does - gateway handles lowercasing for binding storage\r\n beamoName: primary.name,\r\n };\r\n \r\n // Only include routingKey and startedById if they have values (for local dev)\r\n // For deployed services, these should be omitted (undefined) to match None in Scala\r\n if (!isDeployed && this.env.routingKey) {\r\n request.routingKey = this.env.routingKey;\r\n }\r\n if (!isDeployed && this.env.accountId) {\r\n request.startedById = this.env.accountId;\r\n }\r\n\r\n // Log registration request to match C# behavior exactly\r\n // Also log the actual JSON that will be sent (undefined fields will be omitted)\r\n const serializedRequest = JSON.stringify(request);\r\n this.logger.debug(\r\n {\r\n request: {\r\n type: request.type,\r\n name: request.name,\r\n beamoName: request.beamoName,\r\n routingKey: request.routingKey,\r\n startedById: request.startedById,\r\n },\r\n serializedJson: serializedRequest,\r\n isDeployed,\r\n },\r\n 'Registering service provider with gateway.',\r\n );\r\n\r\n try {\r\n await this.requester.request('post', 'gateway/provider', request);\r\n this.logger.info({ serviceName: primary.qualifiedName }, 'Service provider registered successfully.');\r\n \r\n // After registration, the gateway's BasicServiceProvider.start() is called asynchronously\r\n // This triggers afterRabbitInit() -> setupDirectServiceCommunication() -> scheduleServiceBindingCheck()\r\n // The first updateBindings() call happens immediately (0.millisecond delay)\r\n // We wait a bit to allow the gateway to set up the HTTP binding and call updateBindings()\r\n // This is especially important for deployed services where the gateway needs to establish\r\n // the external host binding before bindings can be created\r\n if (isDeployed) {\r\n this.logger.debug('Waiting for gateway to establish bindings after registration...');\r\n await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 second wait for deployed services\r\n this.logger.debug('Wait complete, gateway should have established bindings by now.');\r\n }\r\n } catch (error) {\r\n this.logger.error(\r\n {\r\n err: error,\r\n request,\r\n serviceName: primary.qualifiedName,\r\n errorMessage: error instanceof Error ? error.message : String(error),\r\n },\r\n 'Failed to register service provider with gateway. This will prevent the service from receiving requests.'\r\n );\r\n throw error; // Re-throw so startup fails and we can see the error\r\n }\r\n\r\n if (options.disableAllBeamableEvents) {\r\n this.logger.info('Beamable events disabled by configuration.');\r\n } else {\r\n const eventRequest = {\r\n type: 'event',\r\n evtWhitelist: ['content.manifest', 'realm.config', 'logging.context'],\r\n };\r\n try {\r\n await this.requester.request('post', 'gateway/provider', eventRequest);\r\n } catch (error) {\r\n this.logger.warn({ err: error }, 'Failed to register event provider. Continuing without events.');\r\n }\r\n }\r\n }\r\n\r\n private async handleEvent(envelope: WebsocketEventEnvelope): Promise<void> {\r\n try {\r\n if (!envelope.path) {\r\n this.logger.debug({ envelope }, 'Ignoring websocket event without path.');\r\n return;\r\n }\r\n\r\n if (envelope.path.startsWith('event/')) {\r\n await this.requester.acknowledge(envelope.id);\r\n return;\r\n }\r\n\r\n const context = this.toRequestContext(envelope);\r\n await this.dispatch(context);\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n this.logger.error({ err, envelope }, 'Failed to handle websocket event.');\r\n const status = this.resolveErrorStatus(err);\r\n const response: GatewayResponse = {\r\n id: envelope.id,\r\n status,\r\n body: {\r\n error: err.name,\r\n message: err.message,\r\n },\r\n };\r\n await this.requester.sendResponse(response);\r\n }\r\n }\r\n\r\n private toRequestContext(envelope: WebsocketEventEnvelope): RequestContext {\r\n const path = envelope.path ?? '';\r\n const method = envelope.method ?? 'post';\r\n const userId = typeof envelope.from === 'number' ? envelope.from : 0;\r\n const headers = envelope.headers ?? {};\r\n \r\n // Extract scopes from envelope.scopes array\r\n // Note: X-DE-SCOPE header contains CID.PID, not scope values\r\n // The gateway sends scopes in envelope.scopes array\r\n // For admin endpoints, the gateway may not send scopes in the envelope,\r\n // so we infer admin scope from the path if it's an admin route\r\n const envelopeScopes = envelope.scopes ?? [];\r\n let scopes = normalizeScopes(envelopeScopes);\r\n \r\n // If this is an admin endpoint and no scopes are provided, infer admin scope\r\n // The gateway may not always send scopes for admin routes\r\n const pathLower = path.toLowerCase();\r\n if (pathLower.includes('/admin/') && scopes.size === 0) {\r\n scopes = normalizeScopes(['admin']);\r\n }\r\n\r\n let body: Record<string, unknown> | undefined;\r\n if (envelope.body && typeof envelope.body === 'string') {\r\n try {\r\n body = JSON.parse(envelope.body) as Record<string, unknown>;\r\n } catch (error) {\r\n this.logger.warn({ err: error, raw: envelope.body }, 'Failed to parse body string.');\r\n }\r\n } else if (envelope.body && typeof envelope.body === 'object') {\r\n body = envelope.body as Record<string, unknown>;\r\n }\r\n\r\n let payload: unknown;\r\n if (body && typeof body === 'object' && 'payload' in body) {\r\n const rawPayload = (body as Record<string, unknown>).payload;\r\n if (typeof rawPayload === 'string') {\r\n try {\r\n payload = JSON.parse(rawPayload) as unknown[];\r\n } catch (error) {\r\n this.logger.warn({ err: error }, 'Failed to parse payload JSON.');\r\n payload = rawPayload;\r\n }\r\n } else {\r\n payload = rawPayload;\r\n }\r\n }\r\n\r\n const targetService = this.findServiceForPath(path);\r\n const services = this.serviceManager.createFacade(userId, scopes, targetService?.definition.name);\r\n const provider = this.createRequestScope(path, targetService);\r\n\r\n const context: RequestContext = {\r\n id: envelope.id,\r\n path,\r\n method,\r\n status: envelope.status ?? 0,\r\n userId,\r\n payload,\r\n body,\r\n scopes,\r\n headers,\r\n cid: this.env.cid,\r\n pid: this.env.pid,\r\n services,\r\n throwIfCancelled: () => {},\r\n isCancelled: () => false,\r\n hasScopes: (...requiredScopes: string[]) => requiredScopes.every((scope) => scopeSetHas(scopes, scope)),\r\n requireScopes: (...requiredScopes: string[]) => {\r\n const missingScopes = requiredScopes.filter((scope) => !scopeSetHas(scopes, scope));\r\n if (missingScopes.length > 0) {\r\n throw new MissingScopesError(missingScopes);\r\n }\r\n },\r\n provider,\r\n };\r\n\r\n provider.setInstance(REQUEST_CONTEXT_TOKEN, context);\r\n provider.setInstance(BEAMABLE_SERVICES_TOKEN, services);\r\n\r\n return context;\r\n }\r\n\r\n private findServiceForPath(path: string): ServiceInstance | undefined {\r\n // Gateway sends paths with lowercase service names, so we need case-insensitive matching\r\n // Match by comparing lowercase versions to handle gateway's lowercase path format\r\n const pathLower = path.toLowerCase();\r\n return this.services.find((service) => {\r\n const qualifiedNameLower = service.definition.qualifiedName.toLowerCase();\r\n return pathLower.startsWith(`${qualifiedNameLower}/`);\r\n });\r\n }\r\n\r\n private async dispatch(ctx: RequestContext): Promise<void> {\r\n const service = this.findServiceForPath(ctx.path);\r\n if (!service) {\r\n throw new UnknownRouteError(ctx.path);\r\n }\r\n\r\n if (await this.tryHandleFederationRoute(ctx, service)) {\r\n return;\r\n }\r\n\r\n if (await this.tryHandleAdminRoute(ctx, service)) {\r\n return;\r\n }\r\n\r\n // Extract route from path - handle case-insensitive path matching\r\n const pathLower = ctx.path.toLowerCase();\r\n const qualifiedNameLower = service.definition.qualifiedName.toLowerCase();\r\n const route = pathLower.substring(qualifiedNameLower.length + 1);\r\n const metadata = service.definition.callables.get(route);\r\n if (!metadata) {\r\n throw new UnknownRouteError(ctx.path);\r\n }\r\n\r\n // For server and admin access, allow userId: 0 if the appropriate scope is present\r\n // For client access, always require userId > 0\r\n if (metadata.requireAuth && ctx.userId <= 0) {\r\n if (metadata.access === 'server' && scopeSetHas(ctx.scopes, 'server')) {\r\n // Server callables with server scope don't need a user ID\r\n } else if (metadata.access === 'admin' && scopeSetHas(ctx.scopes, 'admin')) {\r\n // Admin callables with admin scope don't need a user ID\r\n } else {\r\n throw new UnauthorizedUserError(route);\r\n }\r\n }\r\n\r\n enforceAccess(metadata.access, ctx);\r\n\r\n if (metadata.requiredScopes.length > 0) {\r\n const missing = metadata.requiredScopes.filter((scope) => !scopeSetHas(ctx.scopes, scope));\r\n if (missing.length > 0) {\r\n throw new MissingScopesError(missing);\r\n }\r\n }\r\n\r\n const handler = service.instance[metadata.displayName];\r\n if (typeof handler !== 'function') {\r\n throw new Error(`Callable ${metadata.displayName} is not a function on service ${service.definition.name}.`);\r\n }\r\n\r\n const args = this.buildInvocationArguments(handler as (...args: unknown[]) => unknown, ctx);\r\n const result = await Promise.resolve((handler as (...args: unknown[]) => unknown).apply(service.instance, args));\r\n await this.sendSuccessResponse(ctx, metadata, result);\r\n }\r\n\r\n private buildInvocationArguments(\r\n handler: (...args: unknown[]) => unknown,\r\n ctx: RequestContext,\r\n ): unknown[] {\r\n const payload = Array.isArray(ctx.payload)\r\n ? ctx.payload\r\n : typeof ctx.payload === 'string'\r\n ? [ctx.payload]\r\n : ctx.payload === undefined\r\n ? []\r\n : [ctx.payload];\r\n\r\n const expectedParams = handler.length;\r\n if (expectedParams === payload.length + 1) {\r\n return [ctx, ...payload];\r\n }\r\n return payload;\r\n }\r\n\r\n private async sendSuccessResponse(ctx: RequestContext, metadata: ServiceCallableMetadata, result: unknown): Promise<void> {\r\n let body: unknown;\r\n if (metadata.useLegacySerialization) {\r\n const serialized = typeof result === 'string' ? result : JSON.stringify(result ?? null);\r\n body = { payload: serialized };\r\n } else {\r\n body = result ?? null;\r\n }\r\n\r\n const response: GatewayResponse = {\r\n id: ctx.id,\r\n status: 200,\r\n body,\r\n };\r\n await this.requester.sendResponse(response);\r\n }\r\n\r\n private async sendFederationResponse(ctx: RequestContext, result: unknown): Promise<void> {\r\n const response: GatewayResponse = {\r\n id: ctx.id,\r\n status: 200,\r\n body: result ?? null,\r\n };\r\n await this.requester.sendResponse(response);\r\n }\r\n\r\n private async tryHandleFederationRoute(ctx: RequestContext, service: ServiceInstance): Promise<boolean> {\r\n // Gateway sends paths with lowercase service names, so we need case-insensitive matching\r\n const pathLower = ctx.path.toLowerCase();\r\n const qualifiedNameLower = service.definition.qualifiedName.toLowerCase();\r\n const prefixLower = `${qualifiedNameLower}/`;\r\n if (!pathLower.startsWith(prefixLower)) {\r\n return false;\r\n }\r\n // Extract relative path - use lowercase length since gateway sends lowercase paths\r\n const relativePath = ctx.path.substring(qualifiedNameLower.length + 1);\r\n const handler = service.federationRegistry.resolve(relativePath);\r\n if (!handler) {\r\n return false;\r\n }\r\n\r\n const result = await handler.invoke(ctx as FederatedRequestContext);\r\n await this.sendFederationResponse(ctx, result);\r\n return true;\r\n }\r\n\r\n private async tryHandleAdminRoute(ctx: RequestContext, service: ServiceInstance): Promise<boolean> {\r\n // Gateway sends paths with lowercase service names, so we need case-insensitive matching\r\n // Check if path starts with the admin prefix (case-insensitive)\r\n const pathLower = ctx.path.toLowerCase();\r\n const adminPrefixLower = `${service.definition.qualifiedName.toLowerCase()}/admin/`;\r\n if (!pathLower.startsWith(adminPrefixLower)) {\r\n return false;\r\n }\r\n\r\n const options = getServiceOptions(service.definition.ctor) ?? {};\r\n\r\n const action = pathLower.substring(adminPrefixLower.length);\r\n const requiresAdmin = action === 'metadata' || action === 'docs';\r\n if (requiresAdmin && !scopeSetHas(ctx.scopes, 'admin')) {\r\n // For portal requests to admin endpoints, the gateway may not send scopes\r\n // The X-DE-SCOPE header contains CID.PID, not scope values\r\n // If this is a portal request (has X-DE-SCOPE header), grant admin scope\r\n const hasPortalHeader = ctx.headers['X-DE-SCOPE'] || ctx.headers['x-de-scope'];\r\n if (hasPortalHeader) {\r\n // Grant admin scope for portal requests to admin endpoints\r\n ctx.scopes.add('admin');\r\n } else {\r\n throw new MissingScopesError(['admin']);\r\n }\r\n }\r\n\r\n switch (action) {\r\n case 'health':\r\n case 'healthcheck':\r\n await this.requester.sendResponse({ id: ctx.id, status: 200, body: 'responsive' });\r\n return true;\r\n case 'metadata':\r\n case 'docs':\r\n break;\r\n default:\r\n if (!scopeSetHas(ctx.scopes, 'admin')) {\r\n throw new MissingScopesError(['admin']);\r\n }\r\n throw new UnknownRouteError(ctx.path);\r\n }\r\n\r\n if (action === 'metadata') {\r\n const federatedComponents = service.federationRegistry\r\n .list()\r\n .map((component) => ({\r\n federationNamespace: component.federationNamespace,\r\n federationType: component.federationType,\r\n }));\r\n\r\n await this.requester.sendResponse({\r\n id: ctx.id,\r\n status: 200,\r\n body: {\r\n serviceName: service.definition.name,\r\n sdkVersion: this.env.sdkVersionExecution,\r\n sdkBaseBuildVersion: this.env.sdkVersionExecution,\r\n sdkExecutionVersion: this.env.sdkVersionExecution,\r\n useLegacySerialization: Boolean(options.useLegacySerialization),\r\n disableAllBeamableEvents: Boolean(options.disableAllBeamableEvents),\r\n enableEagerContentLoading: false,\r\n instanceId: this.microServiceId,\r\n routingKey: this.env.routingKey ?? '',\r\n federatedComponents,\r\n },\r\n });\r\n return true;\r\n }\r\n\r\n if (action === 'docs') {\r\n try {\r\n const document = generateOpenApiDocument(\r\n {\r\n qualifiedName: service.definition.qualifiedName,\r\n name: service.definition.name,\r\n callables: Array.from(service.definition.callables.values()).map((callable) => ({\r\n name: callable.displayName,\r\n route: callable.route,\r\n metadata: callable,\r\n handler: typeof service.instance[callable.displayName] === 'function'\r\n ? (service.instance[callable.displayName] as (...args: unknown[]) => unknown)\r\n : undefined,\r\n })),\r\n },\r\n this.env,\r\n VERSION,\r\n );\r\n\r\n // Ensure document is valid (not empty)\r\n if (!document || Object.keys(document).length === 0) {\r\n this.logger.warn({ serviceName: service.definition.name }, 'Generated OpenAPI document is empty');\r\n }\r\n\r\n await this.requester.sendResponse({\r\n id: ctx.id,\r\n status: 200,\r\n body: document,\r\n });\r\n return true;\r\n } catch (error) {\r\n this.logger.error({ err: error, serviceName: service.definition.name }, 'Failed to generate or send docs');\r\n throw error;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private resolveErrorStatus(error: Error): number {\r\n if (error instanceof UnauthorizedUserError) {\r\n return 401;\r\n }\r\n if (error instanceof MissingScopesError) {\r\n return 403;\r\n }\r\n if (error instanceof UnknownRouteError) {\r\n return 404;\r\n }\r\n if (error instanceof BeamableRuntimeError) {\r\n return 500;\r\n }\r\n return 500;\r\n }\r\n\r\n private printHelpfulUrls(service?: ServiceInstance): void {\r\n if (!service) {\r\n return;\r\n }\r\n\r\n // Only print helpful URLs when IS_LOCAL=1 is set\r\n // In deployed containers, we want only JSON logs for proper log collection\r\n if (process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true') {\r\n return;\r\n }\r\n\r\n const docsUrl = buildDocsPortalUrl(this.env, service.definition);\r\n const endpointBase = buildPostmanBaseUrl(this.env, service.definition);\r\n\r\n const green = (text: string) => `\\x1b[32m${text}\\x1b[0m`;\r\n const yellow = (text: string) => `\\x1b[33m${text}\\x1b[0m`;\r\n\r\n const bannerLines = [\r\n '',\r\n yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'),\r\n ` ${green('Beamable Node microservice ready:')} ${green(service.definition.name)}`,\r\n yellow(' Quick shortcuts'),\r\n ` ${yellow('Docs:')} ${docsUrl}`,\r\n ` ${yellow('Endpoint:')} ${endpointBase}`,\r\n yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'),\r\n '',\r\n ];\r\n\r\n process.stdout.write(`${bannerLines.join('\\n')}`);\r\n }\r\n\r\n private async initializeDependencyProviders(): Promise<void> {\r\n for (const service of this.services) {\r\n const builder = new DependencyBuilder();\r\n builder.tryAddSingletonInstance(LOGGER_TOKEN, service.logger);\r\n builder.tryAddSingletonInstance(ENVIRONMENT_CONFIG_TOKEN, this.env);\r\n builder.tryAddSingletonInstance(BeamableServiceManager, this.serviceManager);\r\n builder.tryAddSingletonInstance(service.definition.ctor, service.instance);\r\n builder.tryAddSingletonInstance(FederationRegistry, service.federationRegistry);\r\n\r\n for (const handler of service.configureHandlers) {\r\n await handler(builder);\r\n }\r\n\r\n const provider = builder.build();\r\n service.provider = provider;\r\n\r\n for (const handler of service.initializeHandlers) {\r\n await handler(provider);\r\n }\r\n\r\n Object.defineProperty(service.instance, 'provider', {\r\n value: provider,\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n });\r\n }\r\n }\r\n\r\n private createRequestScope(path: string, service?: ServiceInstance): MutableDependencyScope {\r\n const targetService = service ?? this.findServiceForPath(path);\r\n const provider = targetService?.provider ?? new DependencyBuilder().build();\r\n return provider.createScope();\r\n }\r\n}\r\n\r\nfunction enforceAccess(access: ServiceAccess, ctx: RequestContext): void {\r\n switch (access) {\r\n case 'client':\r\n if (ctx.userId <= 0) {\r\n throw new UnauthorizedUserError(ctx.path);\r\n }\r\n break;\r\n case 'server':\r\n if (!scopeSetHas(ctx.scopes, 'server')) {\r\n throw new MissingScopesError(['server']);\r\n }\r\n break;\r\n case 'admin':\r\n if (!scopeSetHas(ctx.scopes, 'admin')) {\r\n throw new MissingScopesError(['admin']);\r\n }\r\n break;\r\n default:\r\n break;\r\n }\r\n}\r\n\r\n/**\r\n * Conditionally output to console.error only when running locally (not in container).\r\n * In containers, we want only Pino JSON logs to stdout for proper log collection.\r\n */\r\nfunction debugLog(...args: unknown[]): void {\r\n // Only output debug logs when IS_LOCAL=1 is set\r\n if (process.env.IS_LOCAL === '1' || process.env.IS_LOCAL === 'true') {\r\n console.error(...args);\r\n }\r\n}\r\n\r\n/**\r\n * Determines if we're running in a deployed container.\r\n * Used for service registration logic (routing key handling, discovery broadcaster, etc.)\r\n * \r\n * Note: For log formatting, use IS_LOCAL env var instead.\r\n */\r\nfunction isRunningInContainer(): boolean {\r\n // Check for Docker container\r\n try {\r\n const fs = require('fs');\r\n if (fs.existsSync('/.dockerenv')) {\r\n return true;\r\n }\r\n } catch {\r\n // fs might not be available\r\n }\r\n \r\n // Check for Docker container hostname pattern (12 hex chars)\r\n const hostname = process.env.HOSTNAME || '';\r\n if (hostname && /^[a-f0-9]{12}$/i.test(hostname)) {\r\n return true;\r\n }\r\n \r\n // Explicit container indicators\r\n if (\r\n process.env.DOTNET_RUNNING_IN_CONTAINER === 'true' ||\r\n process.env.CONTAINER === 'beamable' ||\r\n !!process.env.ECS_CONTAINER_METADATA_URI ||\r\n !!process.env.KUBERNETES_SERVICE_HOST\r\n ) {\r\n return true;\r\n }\r\n \r\n // Default: assume local development\r\n return false;\r\n}\r\n\r\nfunction normalizeScopes(scopes: Array<unknown>): Set<string> {\r\n const normalized = new Set<string>();\r\n for (const scope of scopes) {\r\n if (typeof scope !== 'string' || scope.trim().length === 0) {\r\n continue;\r\n }\r\n normalized.add(scope.trim().toLowerCase());\r\n }\r\n return normalized;\r\n}\r\n\r\nfunction scopeSetHas(scopes: Set<string>, scope: string): boolean {\r\n const normalized = scope.trim().toLowerCase();\r\n if (normalized.length === 0) {\r\n return false;\r\n }\r\n return scopes.has('*') || scopes.has(normalized);\r\n}\r\n\r\nfunction buildPostmanBaseUrl(env: EnvironmentConfig, service: ServiceDefinition): string {\r\n const httpHost = hostToHttpUrl(env.host);\r\n const routingKeyPart = env.routingKey ? env.routingKey : '';\r\n return `${httpHost}/basic/${env.cid}.${env.pid}.${routingKeyPart}${service.qualifiedName}/`;\r\n}\r\n\r\nfunction buildDocsPortalUrl(env: EnvironmentConfig, service: ServiceDefinition): string {\r\n const portalHost = hostToPortalUrl(hostToHttpUrl(env.host));\r\n const queryParams: Record<string, string> = { srcTool: 'node-runtime' };\r\n if (env.routingKey) {\r\n queryParams.routingKey = env.routingKey;\r\n }\r\n const query = new URLSearchParams(queryParams);\r\n if (env.refreshToken) {\r\n query.set('refresh_token', env.refreshToken);\r\n }\r\n const beamoId = service.name;\r\n return `${portalHost}/${env.cid}/games/${env.pid}/realms/${env.pid}/microservices/micro_${beamoId}/docs?${query.toString()}`;\r\n}\r\n\r\nexport async function runMicroservice(): Promise<void> {\r\n // Immediate console output to verify process is starting (local dev only)\r\n // In containers, we rely on Pino logger for all output\r\n debugLog('[BEAMABLE-NODE] Starting microservice...');\r\n debugLog(`[BEAMABLE-NODE] Node version: ${process.version}`);\r\n debugLog(`[BEAMABLE-NODE] Working directory: ${process.cwd()}`);\r\n debugLog(`[BEAMABLE-NODE] Environment: ${JSON.stringify({\r\n NODE_ENV: process.env.NODE_ENV,\r\n CID: process.env.CID ? 'SET' : 'NOT SET',\r\n PID: process.env.PID ? 'SET' : 'NOT SET',\r\n HOST: process.env.HOST ? 'SET' : 'NOT SET',\r\n SECRET: process.env.SECRET ? 'SET' : 'NOT SET',\r\n })}`);\r\n if (process.env.BEAMABLE_SKIP_RUNTIME === 'true') {\r\n return;\r\n }\r\n const runtime = new MicroserviceRuntime();\r\n \r\n // Handle uncaught errors - log them but don't crash immediately\r\n // This allows the health check server to keep running so we can debug\r\n // In containers, errors will be logged by the logger in the runtime\r\n // Locally, use console.error for visibility\r\n process.on('uncaughtException', (error) => {\r\n // In containers, the logger will handle this; locally, show in console\r\n debugLog('Uncaught Exception:', error);\r\n // Don't exit - let the health check server keep running\r\n });\r\n \r\n process.on('unhandledRejection', (reason, promise) => {\r\n // In containers, the logger will handle this; locally, show in console\r\n debugLog('Unhandled Rejection at:', promise, 'reason:', reason);\r\n // Don't exit - let the health check server keep running\r\n });\r\n \r\n try {\r\n await runtime.start();\r\n } catch (error) {\r\n // Log the error but don't exit - health check server is running\r\n // This allows the container to stay alive so we can see what went wrong\r\n // In containers, the logger already logged it in start(); locally, also use console.error\r\n debugLog('Failed to start microservice runtime:', error);\r\n // Keep the process alive so health check can continue\r\n // The health check will return 503 until isReady is true\r\n }\r\n \r\n const shutdownSignals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\r\n shutdownSignals.forEach((signal) => {\r\n process.once(signal, async () => {\r\n await runtime.shutdown();\r\n process.exit(0);\r\n });\r\n });\r\n}\r\n\r\ninterface GenerateOpenApiOptions {\r\n serviceName?: string;\r\n}\r\n\r\nexport function generateOpenApiDocumentForRegisteredServices(\r\n overrides: Partial<EnvironmentConfig> = {},\r\n options: GenerateOpenApiOptions = {},\r\n): unknown {\r\n const services = listRegisteredServices();\r\n if (services.length === 0) {\r\n throw new Error('No microservices registered. Import your service module before generating documentation.');\r\n }\r\n\r\n const baseEnv = buildEnvironmentConfig(overrides);\r\n const primary = options.serviceName\r\n ? services.find((svc) => svc.name === options.serviceName || svc.qualifiedName === options.serviceName)\r\n : services[0];\r\n\r\n if (!primary) {\r\n throw new Error(`No registered microservice matched '${options.serviceName}'.`);\r\n }\r\n\r\n return generateOpenApiDocument(\r\n {\r\n qualifiedName: primary.qualifiedName,\r\n name: primary.name,\r\n callables: Array.from(primary.callables.entries()).map(([displayName, metadata]) => ({\r\n name: displayName,\r\n route: metadata.route,\r\n metadata,\r\n handler: undefined,\r\n })),\r\n },\r\n baseEnv,\r\n VERSION,\r\n );\r\n}\r\n\r\nfunction buildEnvironmentConfig(overrides: Partial<EnvironmentConfig>): EnvironmentConfig {\r\n const merged: Partial<EnvironmentConfig> = { ...overrides };\r\n\r\n const ensure = (key: keyof EnvironmentConfig, fallbackEnv?: string) => {\r\n if (merged[key] !== undefined) {\r\n return;\r\n }\r\n if (fallbackEnv && process.env[fallbackEnv]) {\r\n merged[key] = process.env[fallbackEnv] as never;\r\n }\r\n };\r\n\r\n ensure('cid', 'CID');\r\n ensure('pid', 'PID');\r\n ensure('host', 'HOST');\r\n ensure('secret', 'SECRET');\r\n ensure('refreshToken', 'REFRESH_TOKEN');\r\n // Routing key is optional for deployed services (in containers)\r\n // It will be resolved to empty string if not provided and running in container\r\n if (!merged.routingKey && !isRunningInContainer()) {\r\n ensure('routingKey', 'NAME_PREFIX');\r\n }\r\n\r\n if (!merged.cid || !merged.pid || !merged.host) {\r\n throw new Error('CID, PID, and HOST are required to generate documentation.');\r\n }\r\n\r\n const base = loadEnvironmentConfig();\r\n\r\n return {\r\n ...base,\r\n ...merged,\r\n routingKey: merged.routingKey ?? base.routingKey,\r\n };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto';\r\nimport { BeamableWebSocket } from './websocket.js';\r\nimport { GatewayRequester } from './requester.js';\r\nimport { AuthManager } from './auth.js';\r\nimport { createLogger } from './logger.js';\r\nimport { loadEnvironmentConfig } from './env.js';\r\nimport { setupCollectorBeforeLogging } from './collector-manager.js';\r\nimport pino from 'pino';\r\nimport { listRegisteredServices, getServiceOptions, getConfigureServicesHandlers, getInitializeServicesHandlers } from './decorators.js';\r\nimport { generateOpenApiDocument } from './docs.js';\r\nimport { VERSION } from './index.js';\r\nimport { DiscoveryBroadcaster } from './discovery.js';\r\nimport { BeamableRuntimeError, MissingScopesError, UnauthorizedUserError, UnknownRouteError } from './errors.js';\r\nimport type {\r\n EnvironmentConfig,\r\n RequestContext,\r\n ServiceDefinition,\r\n ServiceCallableMetadata,\r\n GatewayResponse,\r\n WebsocketEventEnvelope,\r\n ServiceAccess,\r\n} from './types.js';\r\nimport type { Logger } from 'pino';\r\nimport { BeamableServiceManager } from './services.js';\r\nimport {\r\n DependencyBuilder,\r\n LOGGER_TOKEN,\r\n ENVIRONMENT_CONFIG_TOKEN,\r\n REQUEST_CONTEXT_TOKEN,\r\n BEAMABLE_SERVICES_TOKEN,\r\n ServiceProvider,\r\n MutableDependencyScope,\r\n} from './dependency.js';\r\nimport { hostToHttpUrl, hostToPortalUrl } from './utils/urls.js';\r\nimport { FederationRegistry, getFederationComponents, getFederatedInventoryMetadata } from './federation.js';\r\nimport type { FederatedRequestContext } from './federation.js';\r\nimport { createServer, type Server } from 'node:http';\r\n\r\ninterface ServiceInstance {\r\n definition: ServiceDefinition;\r\n instance: Record<string, unknown>;\r\n configureHandlers: ReturnType<typeof getConfigureServicesHandlers>;\r\n initializeHandlers: ReturnType<typeof getInitializeServicesHandlers>;\r\n provider?: ServiceProvider;\r\n logger: Logger;\r\n federationRegistry: FederationRegistry;\r\n}\r\n\r\nexport class MicroserviceRuntime {\r\n private readonly env: EnvironmentConfig;\r\n private readonly logger: Logger;\r\n private readonly services: ServiceInstance[];\r\n private readonly webSocket: BeamableWebSocket;\r\n private readonly requester: GatewayRequester;\r\n private readonly authManager: AuthManager;\r\n private readonly discovery?: DiscoveryBroadcaster;\r\n private readonly microServiceId = randomUUID();\r\n private readonly serviceManager: BeamableServiceManager;\r\n private healthCheckServer?: Server;\r\n private isReady: boolean = false;\r\n\r\n constructor(env?: EnvironmentConfig) {\r\n this.env = env ?? loadEnvironmentConfig();\r\n \r\n // STEP 1: Create minimal console logger for startup messages (before collector setup)\r\n // This ensures we have logging available immediately, even before collector is ready\r\n const startupLogger = pino({\r\n name: 'beamable-runtime-startup',\r\n level: 'info',\r\n }, process.stdout);\r\n startupLogger.info('Starting Beamable Node microservice runtime.');\r\n \r\n // STEP 2: Get registered services to extract service name\r\n const registered = listRegisteredServices();\r\n if (registered.length === 0) {\r\n throw new Error('No microservices registered. Use the @Microservice decorator to register at least one class.');\r\n }\r\n \r\n // Use the first service's name for the main logger (for CloudWatch filtering and ClickHouse compatibility)\r\n const primaryService = registered[0];\r\n const qualifiedServiceName = `micro_${primaryService.qualifiedName}`;\r\n \r\n // STEP 3: Setup collector BEFORE creating the main logger\r\n // This ensures all logs from the main logger are captured via OTLP\r\n startupLogger.info('Setting up OpenTelemetry collector...');\r\n // Timeout needs to account for:\r\n // - API call for credentials (~1-2 seconds)\r\n // - Downloading collector binary (~12MB, can take 5-10+ seconds on slow networks)\r\n // - Downloading collector config (~1 second)\r\n // - Starting collector process (~1 second)\r\n // - Waiting for collector to be ready (up to 60 seconds)\r\n // Total: ~70-80 seconds minimum, so use 120 seconds for safety\r\n const otlpEndpoint = setupCollectorBeforeLogging(\r\n this.env,\r\n 120000 // 120 second timeout to allow for download + startup + readiness\r\n );\r\n \r\n if (otlpEndpoint) {\r\n startupLogger.info(`Collector ready at ${otlpEndpoint}, creating main logger...`);\r\n } else {\r\n startupLogger.warn('Collector setup did not complete, continuing without OTLP logging');\r\n }\r\n \r\n // STEP 4: Create main logger (collector is now ready, so all logs will be captured)\r\n // Pass the OTLP endpoint to skip re-discovery/startup\r\n this.logger = createLogger(this.env, {\r\n name: 'beamable-node-microservice',\r\n serviceName: primaryService.name,\r\n qualifiedServiceName: qualifiedServiceName,\r\n otlpEndpoint: otlpEndpoint || undefined, // Pass endpoint if collector was set up\r\n });\r\n this.serviceManager = new BeamableServiceManager(this.env, this.logger);\r\n\r\n this.services = registered.map((definition) => {\r\n const instance = new definition.ctor() as Record<string, unknown>;\r\n const configureHandlers = getConfigureServicesHandlers(definition.ctor);\r\n const initializeHandlers = getInitializeServicesHandlers(definition.ctor);\r\n const logger = this.logger.child({ service: definition.name });\r\n const federationRegistry = new FederationRegistry(logger);\r\n const decoratedFederations = getFederationComponents(definition.ctor);\r\n for (const component of decoratedFederations) {\r\n federationRegistry.register(component);\r\n }\r\n const inventoryMetadata = getFederatedInventoryMetadata(definition.ctor);\r\n if (inventoryMetadata.length > 0) {\r\n federationRegistry.registerInventoryHandlers(instance, inventoryMetadata);\r\n }\r\n this.serviceManager.registerFederationRegistry(definition.name, federationRegistry);\r\n return { definition, instance, configureHandlers, initializeHandlers, logger, federationRegistry };\r\n });\r\n\r\n const socketUrl = this.env.host.endsWith('/socket') ? this.env.host : `${this.env.host}/socket`;\r\n this.webSocket = new BeamableWebSocket({ url: socketUrl, logger: this.logger });\r\n this.webSocket.on('message', (payload) => {\r\n this.logger.debug({ payload }, 'Runtime observed websocket frame.');\r\n });\r\n this.requester = new GatewayRequester(this.webSocket, this.logger);\r\n this.authManager = new AuthManager(this.env, this.requester);\r\n this.requester.on('event', (envelope) => this.handleEvent(envelope));\r\n\r\n // Discovery broadcaster only runs in local development (not in containers)\r\n // This allows the portal to detect that the service is running locally\r\n if (!isRunningInContainer() && this.services.length > 0) {\r\n this.discovery = new DiscoveryBroadcaster({\r\n env: this.env,\r\n serviceName: this.services[0].definition.name,\r\n routingKey: this.env.routingKey,\r\n logger: this.logger.child({ component: 'DiscoveryBroadcaster' }),\r\n });\r\n }\r\n }\r\n\r\n async start(): Promise<void> {\r\n // Immediate console output for container logs (before logger is ready)\r\n debugLog('[BEAMABLE-NODE] MicroserviceRuntime.start() called');\r\n debugLog(`[BEAMABLE-NODE] Service count: ${this.services.length}`);\r\n \r\n this.printHelpfulUrls(this.services[0]);\r\n this.logger.info('Starting Beamable Node microservice runtime.');\r\n \r\n // Start health check server FIRST - this is critical for container health checks\r\n // Even if startup fails, the health check server must be running so we can debug\r\n debugLog('[BEAMABLE-NODE] Starting health check server...');\r\n await this.startHealthCheckServer();\r\n debugLog('[BEAMABLE-NODE] Health check server started');\r\n \r\n try {\r\n this.logger.info('Connecting to Beamable gateway...');\r\n await this.webSocket.connect();\r\n await new Promise((resolve) => setTimeout(resolve, 250));\r\n \r\n this.logger.info('Authenticating with Beamable...');\r\n await this.authManager.authenticate();\r\n \r\n this.logger.info('Initializing Beamable SDK services...');\r\n await this.serviceManager.initialize();\r\n \r\n this.logger.info('Initializing dependency providers...');\r\n await this.initializeDependencyProviders();\r\n \r\n this.logger.info('Registering service with gateway...');\r\n await this.registerService();\r\n \r\n this.logger.info('Starting discovery broadcaster...');\r\n await this.discovery?.start();\r\n \r\n // Mark as ready only after service is fully registered and discovery is started\r\n this.isReady = true;\r\n this.logger.info('Beamable microservice runtime is ready to accept traffic.');\r\n } catch (error) {\r\n // Log the error with full context but don't crash - health check server is running\r\n // This allows the container to stay alive so we can debug the issue\r\n // Debug output for local development only (in containers, logger handles this)\r\n debugLog('[BEAMABLE-NODE] FATAL ERROR during startup:');\r\n debugLog(`[BEAMABLE-NODE] Error message: ${error instanceof Error ? error.message : String(error)}`);\r\n debugLog(`[BEAMABLE-NODE] Error stack: ${error instanceof Error ? error.stack : 'No stack trace'}`);\r\n debugLog(`[BEAMABLE-NODE] isReady: ${this.isReady}`);\r\n \r\n this.logger.error(\r\n { \r\n err: error,\r\n errorMessage: error instanceof Error ? error.message : String(error),\r\n errorStack: error instanceof Error ? error.stack : undefined,\r\n isReady: this.isReady,\r\n },\r\n 'Failed to fully initialize microservice runtime. Health check will continue to return 503 until initialization completes.'\r\n );\r\n // DON'T re-throw - keep process alive so health check can show 503\r\n // This allows us to see the error in logs\r\n this.isReady = false;\r\n }\r\n }\r\n\r\n async shutdown(): Promise<void> {\r\n this.logger.info('Shutting down microservice runtime.');\r\n this.isReady = false; // Mark as not ready during shutdown\r\n this.discovery?.stop();\r\n await this.stopHealthCheckServer();\r\n this.requester.dispose();\r\n await this.webSocket.close();\r\n }\r\n\r\n private async startHealthCheckServer(): Promise<void> {\r\n // For deployed services, always start health check server (required for container health checks)\r\n // For local development, only start if healthPort is explicitly set\r\n // IMPORTANT: Always default to 6565 if HEALTH_PORT env var is not set, as this is the standard port\r\n const healthPort = this.env.healthPort || 6565;\r\n \r\n // Always start health check server if we have a valid port\r\n // The container orchestrator expects this endpoint to be available\r\n if (!healthPort || healthPort === 0) {\r\n // Health check server not needed (local development without explicit port)\r\n this.logger.debug('Health check server skipped (no healthPort set)');\r\n return;\r\n }\r\n\r\n this.healthCheckServer = createServer((req, res) => {\r\n if (req.url === '/health' && req.method === 'GET') {\r\n // Only return success if service is fully ready (registered and accepting traffic)\r\n if (this.isReady) {\r\n res.writeHead(200, { 'Content-Type': 'text/plain' });\r\n res.end('responsive');\r\n } else {\r\n // Service is still starting up\r\n res.writeHead(503, { 'Content-Type': 'text/plain' });\r\n res.end('Service Unavailable');\r\n }\r\n } else {\r\n res.writeHead(404, { 'Content-Type': 'text/plain' });\r\n res.end('Not Found');\r\n }\r\n });\r\n\r\n return new Promise((resolve, reject) => {\r\n this.healthCheckServer!.listen(healthPort, '0.0.0.0', () => {\r\n this.logger.info({ port: healthPort }, 'Health check server started on port');\r\n resolve();\r\n });\r\n this.healthCheckServer!.on('error', (err) => {\r\n this.logger.error({ err, port: healthPort }, 'Failed to start health check server');\r\n reject(err);\r\n });\r\n });\r\n }\r\n\r\n private async stopHealthCheckServer(): Promise<void> {\r\n if (!this.healthCheckServer) {\r\n return;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n this.healthCheckServer!.close(() => {\r\n this.logger.info('Health check server stopped');\r\n resolve();\r\n });\r\n });\r\n }\r\n\r\n private async registerService(): Promise<void> {\r\n const primary = this.services[0]?.definition;\r\n if (!primary) {\r\n throw new Error('Unexpected missing service definition during registration.');\r\n }\r\n const options = getServiceOptions(primary.ctor) ?? {};\r\n // Match C# exactly: use qualifiedName (preserves case) for name field.\r\n // The gateway lowercases service names when creating bindings, but uses the original case\r\n // from the registration request when constructing routing key lookups.\r\n // This ensures the routing key format matches what the gateway expects.\r\n // The gateway's binding lookup behavior:\r\n // - Gateway error shows: \"No binding found for service ...micro_examplenodeservice.basic\"\r\n // - This means the gateway lowercases the service name for binding storage/lookup\r\n // - Portal sends requests with mixed case in URL and routing key header\r\n // - The gateway lowercases the URL path for binding lookup, which should work\r\n // - But we need to register with the format the gateway expects for the binding key\r\n // - The gateway constructs binding key as: {cid}.{pid}.{lowercaseServiceName}.{type}\r\n // - So we register with lowercase to match what the gateway stores in the binding\r\n // - The portal will still send mixed case, and the gateway will lowercase it for lookup\r\n // Register with mixed-case qualifiedName to match C# behavior\r\n // The gateway will lowercase the service name when creating the binding key,\r\n // but the registration request should use the original case (as C# does)\r\n // This ensures the service name in the registration matches what the portal expects\r\n // Register with mixed-case qualifiedName to match C# behavior\r\n // The gateway's ServiceIdentity.fullNameNoType lowercases the service name when creating bindings,\r\n // but the registration request should use the original case (as C# does)\r\n // This ensures the service name in the registration matches what the portal expects\r\n const isDeployed = isRunningInContainer();\r\n \r\n // For deployed services, routingKey should be null/undefined (None in Scala)\r\n // For local dev, routingKey should be the actual routing key string\r\n // The backend expects Option[String] = None for deployed services\r\n // Note: microServiceId is not part of SocketSessionProviderRegisterRequest, so we don't include it\r\n // All fields except 'type' are Option[T] in Scala, so undefined fields will be omitted from JSON\r\n // This matches C# behavior where null/None fields are not serialized\r\n const request: Record<string, unknown> = {\r\n type: 'basic',\r\n name: primary.qualifiedName, // Use mixed-case as C# does - gateway handles lowercasing for binding storage\r\n beamoName: primary.name,\r\n };\r\n \r\n // Only include routingKey and startedById if they have values (for local dev)\r\n // For deployed services, these should be omitted (undefined) to match None in Scala\r\n if (!isDeployed && this.env.routingKey) {\r\n request.routingKey = this.env.routingKey;\r\n }\r\n if (!isDeployed && this.env.accountId) {\r\n request.startedById = this.env.accountId;\r\n }\r\n\r\n // Log registration request to match C# behavior exactly\r\n // Also log the actual JSON that will be sent (undefined fields will be omitted)\r\n const serializedRequest = JSON.stringify(request);\r\n this.logger.debug(\r\n {\r\n request: {\r\n type: request.type,\r\n name: request.name,\r\n beamoName: request.beamoName,\r\n routingKey: request.routingKey,\r\n startedById: request.startedById,\r\n },\r\n serializedJson: serializedRequest,\r\n isDeployed,\r\n },\r\n 'Registering service provider with gateway.',\r\n );\r\n\r\n try {\r\n await this.requester.request('post', 'gateway/provider', request);\r\n this.logger.info({ serviceName: primary.qualifiedName }, 'Service provider registered successfully.');\r\n \r\n // After registration, the gateway's BasicServiceProvider.start() is called asynchronously\r\n // This triggers afterRabbitInit() -> setupDirectServiceCommunication() -> scheduleServiceBindingCheck()\r\n // The first updateBindings() call happens immediately (0.millisecond delay)\r\n // We wait a bit to allow the gateway to set up the HTTP binding and call updateBindings()\r\n // This is especially important for deployed services where the gateway needs to establish\r\n // the external host binding before bindings can be created\r\n if (isDeployed) {\r\n this.logger.debug('Waiting for gateway to establish bindings after registration...');\r\n await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 second wait for deployed services\r\n this.logger.debug('Wait complete, gateway should have established bindings by now.');\r\n }\r\n } catch (error) {\r\n this.logger.error(\r\n {\r\n err: error,\r\n request,\r\n serviceName: primary.qualifiedName,\r\n errorMessage: error instanceof Error ? error.message : String(error),\r\n },\r\n 'Failed to register service provider with gateway. This will prevent the service from receiving requests.'\r\n );\r\n throw error; // Re-throw so startup fails and we can see the error\r\n }\r\n\r\n if (options.disableAllBeamableEvents) {\r\n this.logger.info('Beamable events disabled by configuration.');\r\n } else {\r\n const eventRequest = {\r\n type: 'event',\r\n evtWhitelist: ['content.manifest', 'realm.config', 'logging.context'],\r\n };\r\n try {\r\n await this.requester.request('post', 'gateway/provider', eventRequest);\r\n } catch (error) {\r\n this.logger.warn({ err: error }, 'Failed to register event provider. Continuing without events.');\r\n }\r\n }\r\n }\r\n\r\n private async handleEvent(envelope: WebsocketEventEnvelope): Promise<void> {\r\n try {\r\n if (!envelope.path) {\r\n this.logger.debug({ envelope }, 'Ignoring websocket event without path.');\r\n return;\r\n }\r\n\r\n if (envelope.path.startsWith('event/')) {\r\n await this.requester.acknowledge(envelope.id);\r\n return;\r\n }\r\n\r\n const context = this.toRequestContext(envelope);\r\n await this.dispatch(context);\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n this.logger.error({ err, envelope }, 'Failed to handle websocket event.');\r\n const status = this.resolveErrorStatus(err);\r\n const response: GatewayResponse = {\r\n id: envelope.id,\r\n status,\r\n body: {\r\n error: err.name,\r\n message: err.message,\r\n },\r\n };\r\n await this.requester.sendResponse(response);\r\n }\r\n }\r\n\r\n private toRequestContext(envelope: WebsocketEventEnvelope): RequestContext {\r\n const path = envelope.path ?? '';\r\n const method = envelope.method ?? 'post';\r\n const userId = typeof envelope.from === 'number' ? envelope.from : 0;\r\n const headers = envelope.headers ?? {};\r\n \r\n // Extract scopes from envelope.scopes array\r\n // Note: X-DE-SCOPE header contains CID.PID, not scope values\r\n // The gateway sends scopes in envelope.scopes array\r\n // For admin endpoints, the gateway may not send scopes in the envelope,\r\n // so we infer admin scope from the path if it's an admin route\r\n const envelopeScopes = envelope.scopes ?? [];\r\n let scopes = normalizeScopes(envelopeScopes);\r\n \r\n // If this is an admin endpoint and no scopes are provided, infer admin scope\r\n // The gateway may not always send scopes for admin routes\r\n const pathLower = path.toLowerCase();\r\n if (pathLower.includes('/admin/') && scopes.size === 0) {\r\n scopes = normalizeScopes(['admin']);\r\n }\r\n\r\n let body: Record<string, unknown> | undefined;\r\n if (envelope.body && typeof envelope.body === 'string') {\r\n try {\r\n body = JSON.parse(envelope.body) as Record<string, unknown>;\r\n } catch (error) {\r\n this.logger.warn({ err: error, raw: envelope.body }, 'Failed to parse body string.');\r\n }\r\n } else if (envelope.body && typeof envelope.body === 'object') {\r\n body = envelope.body as Record<string, unknown>;\r\n }\r\n\r\n let payload: unknown;\r\n if (body && typeof body === 'object' && 'payload' in body) {\r\n const rawPayload = (body as Record<string, unknown>).payload;\r\n if (typeof rawPayload === 'string') {\r\n try {\r\n payload = JSON.parse(rawPayload) as unknown[];\r\n } catch (error) {\r\n this.logger.warn({ err: error }, 'Failed to parse payload JSON.');\r\n payload = rawPayload;\r\n }\r\n } else {\r\n payload = rawPayload;\r\n }\r\n }\r\n\r\n const targetService = this.findServiceForPath(path);\r\n const services = this.serviceManager.createFacade(userId, scopes, targetService?.definition.name);\r\n const provider = this.createRequestScope(path, targetService);\r\n\r\n const context: RequestContext = {\r\n id: envelope.id,\r\n path,\r\n method,\r\n status: envelope.status ?? 0,\r\n userId,\r\n payload,\r\n body,\r\n scopes,\r\n headers,\r\n cid: this.env.cid,\r\n pid: this.env.pid,\r\n services,\r\n throwIfCancelled: () => {},\r\n isCancelled: () => false,\r\n hasScopes: (...requiredScopes: string[]) => requiredScopes.every((scope) => scopeSetHas(scopes, scope)),\r\n requireScopes: (...requiredScopes: string[]) => {\r\n const missingScopes = requiredScopes.filter((scope) => !scopeSetHas(scopes, scope));\r\n if (missingScopes.length > 0) {\r\n throw new MissingScopesError(missingScopes);\r\n }\r\n },\r\n provider,\r\n };\r\n\r\n provider.setInstance(REQUEST_CONTEXT_TOKEN, context);\r\n provider.setInstance(BEAMABLE_SERVICES_TOKEN, services);\r\n\r\n return context;\r\n }\r\n\r\n private findServiceForPath(path: string): ServiceInstance | undefined {\r\n // Gateway sends paths with lowercase service names, so we need case-insensitive matching\r\n // Match by comparing lowercase versions to handle gateway's lowercase path format\r\n const pathLower = path.toLowerCase();\r\n return this.services.find((service) => {\r\n const qualifiedNameLower = service.definition.qualifiedName.toLowerCase();\r\n return pathLower.startsWith(`${qualifiedNameLower}/`);\r\n });\r\n }\r\n\r\n private async dispatch(ctx: RequestContext): Promise<void> {\r\n const service = this.findServiceForPath(ctx.path);\r\n if (!service) {\r\n throw new UnknownRouteError(ctx.path);\r\n }\r\n\r\n if (await this.tryHandleFederationRoute(ctx, service)) {\r\n return;\r\n }\r\n\r\n if (await this.tryHandleAdminRoute(ctx, service)) {\r\n return;\r\n }\r\n\r\n // Extract route from path - handle case-insensitive path matching\r\n const pathLower = ctx.path.toLowerCase();\r\n const qualifiedNameLower = service.definition.qualifiedName.toLowerCase();\r\n const route = pathLower.substring(qualifiedNameLower.length + 1);\r\n const metadata = service.definition.callables.get(route);\r\n if (!metadata) {\r\n throw new UnknownRouteError(ctx.path);\r\n }\r\n\r\n // For server and admin access, allow userId: 0 if the appropriate scope is present\r\n // For client access, always require userId > 0\r\n if (metadata.requireAuth && ctx.userId <= 0) {\r\n if (metadata.access === 'server' && scopeSetHas(ctx.scopes, 'server')) {\r\n // Server callables with server scope don't need a user ID\r\n } else if (metadata.access === 'admin' && scopeSetHas(ctx.scopes, 'admin')) {\r\n // Admin callables with admin scope don't need a user ID\r\n } else {\r\n throw new UnauthorizedUserError(route);\r\n }\r\n }\r\n\r\n enforceAccess(metadata.access, ctx);\r\n\r\n if (metadata.requiredScopes.length > 0) {\r\n const missing = metadata.requiredScopes.filter((scope) => !scopeSetHas(ctx.scopes, scope));\r\n if (missing.length > 0) {\r\n throw new MissingScopesError(missing);\r\n }\r\n }\r\n\r\n const handler = service.instance[metadata.displayName];\r\n if (typeof handler !== 'function') {\r\n throw new Error(`Callable ${metadata.displayName} is not a function on service ${service.definition.name}.`);\r\n }\r\n\r\n const args = this.buildInvocationArguments(handler as (...args: unknown[]) => unknown, ctx);\r\n const result = await Promise.resolve((handler as (...args: unknown[]) => unknown).apply(service.instance, args));\r\n await this.sendSuccessResponse(ctx, metadata, result);\r\n }\r\n\r\n private buildInvocationArguments(\r\n handler: (...args: unknown[]) => unknown,\r\n ctx: RequestContext,\r\n ): unknown[] {\r\n const payload = Array.isArray(ctx.payload)\r\n ? ctx.payload\r\n : typeof ctx.payload === 'string'\r\n ? [ctx.payload]\r\n : ctx.payload === undefined\r\n ? []\r\n : [ctx.payload];\r\n\r\n const expectedParams = handler.length;\r\n if (expectedParams === payload.length + 1) {\r\n return [ctx, ...payload];\r\n }\r\n return payload;\r\n }\r\n\r\n private async sendSuccessResponse(ctx: RequestContext, metadata: ServiceCallableMetadata, result: unknown): Promise<void> {\r\n let body: unknown;\r\n if (metadata.useLegacySerialization) {\r\n const serialized = typeof result === 'string' ? result : JSON.stringify(result ?? null);\r\n body = { payload: serialized };\r\n } else {\r\n body = result ?? null;\r\n }\r\n\r\n const response: GatewayResponse = {\r\n id: ctx.id,\r\n status: 200,\r\n body,\r\n };\r\n await this.requester.sendResponse(response);\r\n }\r\n\r\n private async sendFederationResponse(ctx: RequestContext, result: unknown): Promise<void> {\r\n const response: GatewayResponse = {\r\n id: ctx.id,\r\n status: 200,\r\n body: result ?? null,\r\n };\r\n await this.requester.sendResponse(response);\r\n }\r\n\r\n private async tryHandleFederationRoute(ctx: RequestContext, service: ServiceInstance): Promise<boolean> {\r\n // Gateway sends paths with lowercase service names, so we need case-insensitive matching\r\n const pathLower = ctx.path.toLowerCase();\r\n const qualifiedNameLower = service.definition.qualifiedName.toLowerCase();\r\n const prefixLower = `${qualifiedNameLower}/`;\r\n if (!pathLower.startsWith(prefixLower)) {\r\n return false;\r\n }\r\n // Extract relative path - use lowercase length since gateway sends lowercase paths\r\n const relativePath = ctx.path.substring(qualifiedNameLower.length + 1);\r\n const handler = service.federationRegistry.resolve(relativePath);\r\n if (!handler) {\r\n return false;\r\n }\r\n\r\n const result = await handler.invoke(ctx as FederatedRequestContext);\r\n await this.sendFederationResponse(ctx, result);\r\n return true;\r\n }\r\n\r\n private async tryHandleAdminRoute(ctx: RequestContext, service: ServiceInstance): Promise<boolean> {\r\n // Gateway sends paths with lowercase service names, so we need case-insensitive matching\r\n // Check if path starts with the admin prefix (case-insensitive)\r\n const pathLower = ctx.path.toLowerCase();\r\n const adminPrefixLower = `${service.definition.qualifiedName.toLowerCase()}/admin/`;\r\n if (!pathLower.startsWith(adminPrefixLower)) {\r\n return false;\r\n }\r\n\r\n const options = getServiceOptions(service.definition.ctor) ?? {};\r\n\r\n const action = pathLower.substring(adminPrefixLower.length);\r\n const requiresAdmin = action === 'metadata' || action === 'docs';\r\n if (requiresAdmin && !scopeSetHas(ctx.scopes, 'admin')) {\r\n // For portal requests to admin endpoints, the gateway may not send scopes\r\n // The X-DE-SCOPE header contains CID.PID, not scope values\r\n // If this is a portal request (has X-DE-SCOPE header), grant admin scope\r\n const hasPortalHeader = ctx.headers['X-DE-SCOPE'] || ctx.headers['x-de-scope'];\r\n if (hasPortalHeader) {\r\n // Grant admin scope for portal requests to admin endpoints\r\n ctx.scopes.add('admin');\r\n } else {\r\n throw new MissingScopesError(['admin']);\r\n }\r\n }\r\n\r\n switch (action) {\r\n case 'health':\r\n case 'healthcheck':\r\n await this.requester.sendResponse({ id: ctx.id, status: 200, body: 'responsive' });\r\n return true;\r\n case 'metadata':\r\n case 'docs':\r\n break;\r\n default:\r\n if (!scopeSetHas(ctx.scopes, 'admin')) {\r\n throw new MissingScopesError(['admin']);\r\n }\r\n throw new UnknownRouteError(ctx.path);\r\n }\r\n\r\n if (action === 'metadata') {\r\n const federatedComponents = service.federationRegistry\r\n .list()\r\n .map((component) => ({\r\n federationNamespace: component.federationNamespace,\r\n federationType: component.federationType,\r\n }));\r\n\r\n await this.requester.sendResponse({\r\n id: ctx.id,\r\n status: 200,\r\n body: {\r\n serviceName: service.definition.name,\r\n sdkVersion: this.env.sdkVersionExecution,\r\n sdkBaseBuildVersion: this.env.sdkVersionExecution,\r\n sdkExecutionVersion: this.env.sdkVersionExecution,\r\n useLegacySerialization: Boolean(options.useLegacySerialization),\r\n disableAllBeamableEvents: Boolean(options.disableAllBeamableEvents),\r\n enableEagerContentLoading: false,\r\n instanceId: this.microServiceId,\r\n routingKey: this.env.routingKey ?? '',\r\n federatedComponents,\r\n },\r\n });\r\n return true;\r\n }\r\n\r\n if (action === 'docs') {\r\n try {\r\n const document = generateOpenApiDocument(\r\n {\r\n qualifiedName: service.definition.qualifiedName,\r\n name: service.definition.name,\r\n callables: Array.from(service.definition.callables.values()).map((callable) => ({\r\n name: callable.displayName,\r\n route: callable.route,\r\n metadata: callable,\r\n handler: typeof service.instance[callable.displayName] === 'function'\r\n ? (service.instance[callable.displayName] as (...args: unknown[]) => unknown)\r\n : undefined,\r\n })),\r\n },\r\n this.env,\r\n VERSION,\r\n );\r\n\r\n // Ensure document is valid (not empty)\r\n if (!document || Object.keys(document).length === 0) {\r\n this.logger.warn({ serviceName: service.definition.name }, 'Generated OpenAPI document is empty');\r\n }\r\n\r\n await this.requester.sendResponse({\r\n id: ctx.id,\r\n status: 200,\r\n body: document,\r\n });\r\n return true;\r\n } catch (error) {\r\n this.logger.error({ err: error, serviceName: service.definition.name }, 'Failed to generate or send docs');\r\n throw error;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private resolveErrorStatus(error: Error): number {\r\n if (error instanceof UnauthorizedUserError) {\r\n return 401;\r\n }\r\n if (error instanceof MissingScopesError) {\r\n return 403;\r\n }\r\n if (error instanceof UnknownRouteError) {\r\n return 404;\r\n }\r\n if (error instanceof BeamableRuntimeError) {\r\n return 500;\r\n }\r\n return 500;\r\n }\r\n\r\n private printHelpfulUrls(service?: ServiceInstance): void {\r\n if (!service) {\r\n return;\r\n }\r\n\r\n // Only print helpful URLs when IS_LOCAL=1 is set\r\n // In deployed containers, we want only JSON logs for proper log collection\r\n if (process.env.IS_LOCAL !== '1' && process.env.IS_LOCAL !== 'true') {\r\n return;\r\n }\r\n\r\n const docsUrl = buildDocsPortalUrl(this.env, service.definition);\r\n const endpointBase = buildPostmanBaseUrl(this.env, service.definition);\r\n\r\n const green = (text: string) => `\\x1b[32m${text}\\x1b[0m`;\r\n const yellow = (text: string) => `\\x1b[33m${text}\\x1b[0m`;\r\n\r\n const bannerLines = [\r\n '',\r\n yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'),\r\n ` ${green('Beamable Node microservice ready:')} ${green(service.definition.name)}`,\r\n yellow(' Quick shortcuts'),\r\n ` ${yellow('Docs:')} ${docsUrl}`,\r\n ` ${yellow('Endpoint:')} ${endpointBase}`,\r\n yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'),\r\n '',\r\n ];\r\n\r\n process.stdout.write(`${bannerLines.join('\\n')}`);\r\n }\r\n\r\n private async initializeDependencyProviders(): Promise<void> {\r\n for (const service of this.services) {\r\n const builder = new DependencyBuilder();\r\n builder.tryAddSingletonInstance(LOGGER_TOKEN, service.logger);\r\n builder.tryAddSingletonInstance(ENVIRONMENT_CONFIG_TOKEN, this.env);\r\n builder.tryAddSingletonInstance(BeamableServiceManager, this.serviceManager);\r\n builder.tryAddSingletonInstance(service.definition.ctor, service.instance);\r\n builder.tryAddSingletonInstance(FederationRegistry, service.federationRegistry);\r\n\r\n for (const handler of service.configureHandlers) {\r\n await handler(builder);\r\n }\r\n\r\n const provider = builder.build();\r\n service.provider = provider;\r\n\r\n for (const handler of service.initializeHandlers) {\r\n await handler(provider);\r\n }\r\n\r\n Object.defineProperty(service.instance, 'provider', {\r\n value: provider,\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n });\r\n }\r\n }\r\n\r\n private createRequestScope(path: string, service?: ServiceInstance): MutableDependencyScope {\r\n const targetService = service ?? this.findServiceForPath(path);\r\n const provider = targetService?.provider ?? new DependencyBuilder().build();\r\n return provider.createScope();\r\n }\r\n}\r\n\r\nfunction enforceAccess(access: ServiceAccess, ctx: RequestContext): void {\r\n switch (access) {\r\n case 'client':\r\n if (ctx.userId <= 0) {\r\n throw new UnauthorizedUserError(ctx.path);\r\n }\r\n break;\r\n case 'server':\r\n if (!scopeSetHas(ctx.scopes, 'server')) {\r\n throw new MissingScopesError(['server']);\r\n }\r\n break;\r\n case 'admin':\r\n if (!scopeSetHas(ctx.scopes, 'admin')) {\r\n throw new MissingScopesError(['admin']);\r\n }\r\n break;\r\n default:\r\n break;\r\n }\r\n}\r\n\r\n/**\r\n * Conditionally output to console.error only when running locally (not in container).\r\n * In containers, we want only Pino JSON logs to stdout for proper log collection.\r\n */\r\nfunction debugLog(...args: unknown[]): void {\r\n // Only output debug logs when IS_LOCAL=1 is set\r\n if (process.env.IS_LOCAL === '1' || process.env.IS_LOCAL === 'true') {\r\n console.error(...args);\r\n }\r\n}\r\n\r\n/**\r\n * Determines if we're running in a deployed container.\r\n * Used for service registration logic (routing key handling, discovery broadcaster, etc.)\r\n * \r\n * Note: For log formatting, use IS_LOCAL env var instead.\r\n */\r\nfunction isRunningInContainer(): boolean {\r\n // Check for Docker container\r\n try {\r\n const fs = require('fs');\r\n if (fs.existsSync('/.dockerenv')) {\r\n return true;\r\n }\r\n } catch {\r\n // fs might not be available\r\n }\r\n \r\n // Check for Docker container hostname pattern (12 hex chars)\r\n const hostname = process.env.HOSTNAME || '';\r\n if (hostname && /^[a-f0-9]{12}$/i.test(hostname)) {\r\n return true;\r\n }\r\n \r\n // Explicit container indicators\r\n if (\r\n process.env.DOTNET_RUNNING_IN_CONTAINER === 'true' ||\r\n process.env.CONTAINER === 'beamable' ||\r\n !!process.env.ECS_CONTAINER_METADATA_URI ||\r\n !!process.env.KUBERNETES_SERVICE_HOST\r\n ) {\r\n return true;\r\n }\r\n \r\n // Default: assume local development\r\n return false;\r\n}\r\n\r\nfunction normalizeScopes(scopes: Array<unknown>): Set<string> {\r\n const normalized = new Set<string>();\r\n for (const scope of scopes) {\r\n if (typeof scope !== 'string' || scope.trim().length === 0) {\r\n continue;\r\n }\r\n normalized.add(scope.trim().toLowerCase());\r\n }\r\n return normalized;\r\n}\r\n\r\nfunction scopeSetHas(scopes: Set<string>, scope: string): boolean {\r\n const normalized = scope.trim().toLowerCase();\r\n if (normalized.length === 0) {\r\n return false;\r\n }\r\n return scopes.has('*') || scopes.has(normalized);\r\n}\r\n\r\nfunction buildPostmanBaseUrl(env: EnvironmentConfig, service: ServiceDefinition): string {\r\n const httpHost = hostToHttpUrl(env.host);\r\n const routingKeyPart = env.routingKey ? env.routingKey : '';\r\n return `${httpHost}/basic/${env.cid}.${env.pid}.${routingKeyPart}${service.qualifiedName}/`;\r\n}\r\n\r\nfunction buildDocsPortalUrl(env: EnvironmentConfig, service: ServiceDefinition): string {\r\n const portalHost = hostToPortalUrl(hostToHttpUrl(env.host));\r\n const queryParams: Record<string, string> = { srcTool: 'node-runtime' };\r\n if (env.routingKey) {\r\n queryParams.routingKey = env.routingKey;\r\n }\r\n const query = new URLSearchParams(queryParams);\r\n if (env.refreshToken) {\r\n query.set('refresh_token', env.refreshToken);\r\n }\r\n const beamoId = service.name;\r\n return `${portalHost}/${env.cid}/games/${env.pid}/realms/${env.pid}/microservices/micro_${beamoId}/docs?${query.toString()}`;\r\n}\r\n\r\nexport async function runMicroservice(): Promise<void> {\r\n // Immediate console output to verify process is starting (local dev only)\r\n // In containers, we rely on Pino logger for all output\r\n debugLog('[BEAMABLE-NODE] Starting microservice...');\r\n debugLog(`[BEAMABLE-NODE] Node version: ${process.version}`);\r\n debugLog(`[BEAMABLE-NODE] Working directory: ${process.cwd()}`);\r\n debugLog(`[BEAMABLE-NODE] Environment: ${JSON.stringify({\r\n NODE_ENV: process.env.NODE_ENV,\r\n CID: process.env.CID ? 'SET' : 'NOT SET',\r\n PID: process.env.PID ? 'SET' : 'NOT SET',\r\n HOST: process.env.HOST ? 'SET' : 'NOT SET',\r\n SECRET: process.env.SECRET ? 'SET' : 'NOT SET',\r\n })}`);\r\n if (process.env.BEAMABLE_SKIP_RUNTIME === 'true') {\r\n return;\r\n }\r\n const runtime = new MicroserviceRuntime();\r\n \r\n // Handle uncaught errors - log them but don't crash immediately\r\n // This allows the health check server to keep running so we can debug\r\n // In containers, errors will be logged by the logger in the runtime\r\n // Locally, use console.error for visibility\r\n process.on('uncaughtException', (error) => {\r\n // In containers, the logger will handle this; locally, show in console\r\n debugLog('Uncaught Exception:', error);\r\n // Don't exit - let the health check server keep running\r\n });\r\n \r\n process.on('unhandledRejection', (reason, promise) => {\r\n // In containers, the logger will handle this; locally, show in console\r\n debugLog('Unhandled Rejection at:', promise, 'reason:', reason);\r\n // Don't exit - let the health check server keep running\r\n });\r\n \r\n try {\r\n await runtime.start();\r\n } catch (error) {\r\n // Log the error but don't exit - health check server is running\r\n // This allows the container to stay alive so we can see what went wrong\r\n // In containers, the logger already logged it in start(); locally, also use console.error\r\n debugLog('Failed to start microservice runtime:', error);\r\n // Keep the process alive so health check can continue\r\n // The health check will return 503 until isReady is true\r\n }\r\n \r\n const shutdownSignals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\r\n shutdownSignals.forEach((signal) => {\r\n process.once(signal, async () => {\r\n await runtime.shutdown();\r\n process.exit(0);\r\n });\r\n });\r\n}\r\n\r\ninterface GenerateOpenApiOptions {\r\n serviceName?: string;\r\n}\r\n\r\nexport function generateOpenApiDocumentForRegisteredServices(\r\n overrides: Partial<EnvironmentConfig> = {},\r\n options: GenerateOpenApiOptions = {},\r\n): unknown {\r\n const services = listRegisteredServices();\r\n if (services.length === 0) {\r\n throw new Error('No microservices registered. Import your service module before generating documentation.');\r\n }\r\n\r\n const baseEnv = buildEnvironmentConfig(overrides);\r\n const primary = options.serviceName\r\n ? services.find((svc) => svc.name === options.serviceName || svc.qualifiedName === options.serviceName)\r\n : services[0];\r\n\r\n if (!primary) {\r\n throw new Error(`No registered microservice matched '${options.serviceName}'.`);\r\n }\r\n\r\n return generateOpenApiDocument(\r\n {\r\n qualifiedName: primary.qualifiedName,\r\n name: primary.name,\r\n callables: Array.from(primary.callables.entries()).map(([displayName, metadata]) => ({\r\n name: displayName,\r\n route: metadata.route,\r\n metadata,\r\n handler: undefined,\r\n })),\r\n },\r\n baseEnv,\r\n VERSION,\r\n );\r\n}\r\n\r\nfunction buildEnvironmentConfig(overrides: Partial<EnvironmentConfig>): EnvironmentConfig {\r\n const merged: Partial<EnvironmentConfig> = { ...overrides };\r\n\r\n const ensure = (key: keyof EnvironmentConfig, fallbackEnv?: string) => {\r\n if (merged[key] !== undefined) {\r\n return;\r\n }\r\n if (fallbackEnv && process.env[fallbackEnv]) {\r\n merged[key] = process.env[fallbackEnv] as never;\r\n }\r\n };\r\n\r\n ensure('cid', 'CID');\r\n ensure('pid', 'PID');\r\n ensure('host', 'HOST');\r\n ensure('secret', 'SECRET');\r\n ensure('refreshToken', 'REFRESH_TOKEN');\r\n // Routing key is optional for deployed services (in containers)\r\n // It will be resolved to empty string if not provided and running in container\r\n if (!merged.routingKey && !isRunningInContainer()) {\r\n ensure('routingKey', 'NAME_PREFIX');\r\n }\r\n\r\n if (!merged.cid || !merged.pid || !merged.host) {\r\n throw new Error('CID, PID, and HOST are required to generate documentation.');\r\n }\r\n\r\n const base = loadEnvironmentConfig();\r\n\r\n return {\r\n ...base,\r\n ...merged,\r\n routingKey: merged.routingKey ?? base.routingKey,\r\n };\r\n}\r\n"]}
|
package/package.json
CHANGED
package/src/collector-manager.ts
CHANGED
|
@@ -62,6 +62,8 @@ let globalCollectorProcess: ChildProcess | null = null;
|
|
|
62
62
|
let globalCollectorStartError: string | null = null;
|
|
63
63
|
let globalCollectorExitCode: number | null = null;
|
|
64
64
|
let globalCollectorStderr: string[] = [];
|
|
65
|
+
// Track if collector startup is in progress to prevent duplicate starts
|
|
66
|
+
let globalCollectorStartupPromise: Promise<string | null> | null = null;
|
|
65
67
|
let globalCollectorInitError: string | null = null; // Tracks errors from discoverOrStartCollector
|
|
66
68
|
|
|
67
69
|
/**
|
|
@@ -878,6 +880,24 @@ export async function discoverOrStartCollector(
|
|
|
878
880
|
return null;
|
|
879
881
|
}
|
|
880
882
|
|
|
883
|
+
// CRITICAL: Check if collector startup is already in progress
|
|
884
|
+
// This prevents duplicate collector starts if this function is called multiple times
|
|
885
|
+
// (e.g., if setupCollectorBeforeLogging times out but the promise is still running)
|
|
886
|
+
if (globalCollectorStartupPromise) {
|
|
887
|
+
logger.info('[Collector] Collector startup already in progress, waiting for existing startup to complete...');
|
|
888
|
+
try {
|
|
889
|
+
const result = await globalCollectorStartupPromise;
|
|
890
|
+
// Clear the promise after it completes (success or failure)
|
|
891
|
+
globalCollectorStartupPromise = null;
|
|
892
|
+
return result;
|
|
893
|
+
} catch (error) {
|
|
894
|
+
logger.error(`[Collector] Existing startup promise failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
895
|
+
// Clear the promise so we can retry
|
|
896
|
+
globalCollectorStartupPromise = null;
|
|
897
|
+
// Fall through to start a new one
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
881
901
|
// CRITICAL: Check if we already have a collector process starting/running
|
|
882
902
|
// This prevents duplicate collector starts if this function is called multiple times
|
|
883
903
|
let existingEndpoint: string | undefined;
|
|
@@ -912,15 +932,18 @@ export async function discoverOrStartCollector(
|
|
|
912
932
|
}
|
|
913
933
|
|
|
914
934
|
// Collector not running - start it (or wait for existing one to be ready)
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
endpoint
|
|
923
|
-
|
|
935
|
+
// Wrap the entire startup logic in a promise that we track globally
|
|
936
|
+
// This prevents duplicate starts if this function is called multiple times
|
|
937
|
+
const startupPromise = (async (): Promise<string | null> => {
|
|
938
|
+
try {
|
|
939
|
+
// Clear any previous init error
|
|
940
|
+
globalCollectorInitError = null;
|
|
941
|
+
|
|
942
|
+
let endpoint: string;
|
|
943
|
+
if (existingEndpoint) {
|
|
944
|
+
// Collector already starting, just wait for it to be ready
|
|
945
|
+
endpoint = existingEndpoint;
|
|
946
|
+
logger.info(`[Collector] Waiting for existing collector to become ready at ${endpoint}...`);
|
|
924
947
|
} else {
|
|
925
948
|
// Start a new collector
|
|
926
949
|
logger.info('[Collector] Starting OpenTelemetry collector...');
|
|
@@ -979,14 +1002,25 @@ export async function discoverOrStartCollector(
|
|
|
979
1002
|
return null;
|
|
980
1003
|
}
|
|
981
1004
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1005
|
+
// Collector did not become ready within timeout
|
|
1006
|
+
logger.error(`[Collector] Collector did not become ready within ${maxWaitTime / 1000} seconds`);
|
|
1007
|
+
return null;
|
|
1008
|
+
} catch (err) {
|
|
1009
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
1010
|
+
globalCollectorInitError = errorMsg;
|
|
1011
|
+
logger.error(`[Collector] Failed to start collector: ${errorMsg}`);
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
1014
|
+
})();
|
|
1015
|
+
|
|
1016
|
+
// Store the promise globally so other calls to this function can wait for it
|
|
1017
|
+
globalCollectorStartupPromise = startupPromise;
|
|
1018
|
+
|
|
1019
|
+
// Clear the promise when it completes (so we don't keep waiting on old promises)
|
|
1020
|
+
startupPromise.finally(() => {
|
|
1021
|
+
globalCollectorStartupPromise = null;
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
return await startupPromise;
|
|
991
1025
|
}
|
|
992
1026
|
|
package/src/runtime.ts
CHANGED
|
@@ -83,9 +83,16 @@ export class MicroserviceRuntime {
|
|
|
83
83
|
// STEP 3: Setup collector BEFORE creating the main logger
|
|
84
84
|
// This ensures all logs from the main logger are captured via OTLP
|
|
85
85
|
startupLogger.info('Setting up OpenTelemetry collector...');
|
|
86
|
+
// Timeout needs to account for:
|
|
87
|
+
// - API call for credentials (~1-2 seconds)
|
|
88
|
+
// - Downloading collector binary (~12MB, can take 5-10+ seconds on slow networks)
|
|
89
|
+
// - Downloading collector config (~1 second)
|
|
90
|
+
// - Starting collector process (~1 second)
|
|
91
|
+
// - Waiting for collector to be ready (up to 60 seconds)
|
|
92
|
+
// Total: ~70-80 seconds minimum, so use 120 seconds for safety
|
|
86
93
|
const otlpEndpoint = setupCollectorBeforeLogging(
|
|
87
94
|
this.env,
|
|
88
|
-
|
|
95
|
+
120000 // 120 second timeout to allow for download + startup + readiness
|
|
89
96
|
);
|
|
90
97
|
|
|
91
98
|
if (otlpEndpoint) {
|