@glasstrace/sdk 0.13.6 → 0.14.1
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/{chunk-DF52INSK.js → chunk-ECEN724Y.js} +2 -2
- package/dist/{chunk-7MHQRVVW.js → chunk-ERGEG4ZQ.js} +2 -3
- package/dist/chunk-ERGEG4ZQ.js.map +1 -0
- package/dist/{chunk-AMFO5UL4.js → chunk-UPS5BGER.js} +2 -2
- package/dist/{chunk-UJ74MD4Y.js → chunk-YMEXDDTA.js} +7 -3
- package/dist/{chunk-UJ74MD4Y.js.map → chunk-YMEXDDTA.js.map} +1 -1
- package/dist/cli/init.cjs +68 -3
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +3 -3
- package/dist/cli/mcp-add.cjs +2 -1
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +2 -2
- package/dist/cli/status.cjs +65 -1
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.d.cts +22 -1
- package/dist/cli/status.d.ts +22 -1
- package/dist/cli/status.js +65 -1
- package/dist/cli/status.js.map +1 -1
- package/dist/index.cjs +775 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +765 -62
- package/dist/index.js.map +1 -1
- package/dist/{source-map-uploader-EWA2XQI4.js → source-map-uploader-W6VPGY26.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-7MHQRVVW.js.map +0 -1
- /package/dist/{chunk-DF52INSK.js.map → chunk-ECEN724Y.js.map} +0 -0
- /package/dist/{chunk-AMFO5UL4.js.map → chunk-UPS5BGER.js.map} +0 -0
- /package/dist/{source-map-uploader-EWA2XQI4.js.map → source-map-uploader-W6VPGY26.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -13,23 +13,23 @@ import {
|
|
|
13
13
|
uploadSourceMaps,
|
|
14
14
|
uploadSourceMapsAuto,
|
|
15
15
|
uploadSourceMapsPresigned
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ERGEG4ZQ.js";
|
|
17
17
|
import {
|
|
18
18
|
buildImportGraph,
|
|
19
19
|
discoverTestFiles,
|
|
20
20
|
extractImports
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-UPS5BGER.js";
|
|
22
22
|
import {
|
|
23
23
|
getOrCreateAnonKey,
|
|
24
24
|
readAnonKey
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-ECEN724Y.js";
|
|
26
26
|
import {
|
|
27
27
|
DEFAULT_CAPTURE_CONFIG,
|
|
28
28
|
GLASSTRACE_ATTRIBUTE_NAMES,
|
|
29
29
|
SdkCachedConfigSchema,
|
|
30
30
|
SdkInitResponseSchema,
|
|
31
31
|
SessionIdSchema
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-YMEXDDTA.js";
|
|
33
33
|
import {
|
|
34
34
|
DiagLogLevel,
|
|
35
35
|
INVALID_SPAN_CONTEXT,
|
|
@@ -325,7 +325,6 @@ async function sendInitRequest(config, anonKey, sdkVersion, importGraph, healthR
|
|
|
325
325
|
throw new Error("No API key available for init request");
|
|
326
326
|
}
|
|
327
327
|
const payload = {
|
|
328
|
-
apiKey: effectiveKey,
|
|
329
328
|
sdkVersion
|
|
330
329
|
};
|
|
331
330
|
if (config.apiKey && anonKey) {
|
|
@@ -562,7 +561,7 @@ init_esm_shims();
|
|
|
562
561
|
var GlasstraceSpanProcessor = class {
|
|
563
562
|
wrappedProcessor;
|
|
564
563
|
/* eslint-disable @typescript-eslint/no-unused-vars -- backward compat signature */
|
|
565
|
-
constructor(wrappedProcessor,
|
|
564
|
+
constructor(wrappedProcessor, _sessionManager2, _apiKey, _getConfig, _environment) {
|
|
566
565
|
this.wrappedProcessor = wrappedProcessor;
|
|
567
566
|
}
|
|
568
567
|
onStart(span, parentContext) {
|
|
@@ -605,6 +604,7 @@ var GlasstraceExporter = class {
|
|
|
605
604
|
this.endpointUrl = options.endpointUrl;
|
|
606
605
|
this.createDelegateFn = options.createDelegate;
|
|
607
606
|
this.verbose = options.verbose ?? false;
|
|
607
|
+
this[/* @__PURE__ */ Symbol.for("glasstrace.exporter")] = true;
|
|
608
608
|
}
|
|
609
609
|
export(spans, resultCallback) {
|
|
610
610
|
const currentKey = this.getApiKey();
|
|
@@ -702,6 +702,22 @@ var GlasstraceExporter = class {
|
|
|
702
702
|
if (route) {
|
|
703
703
|
extra[ATTR.ROUTE] = route;
|
|
704
704
|
}
|
|
705
|
+
const rawUrl = attrs["http.url"] ?? attrs["url.full"] ?? attrs["http.target"];
|
|
706
|
+
const trpcUrl = typeof rawUrl === "string" ? rawUrl : void 0;
|
|
707
|
+
if (trpcUrl) {
|
|
708
|
+
const trpcMatch = trpcUrl.match(/\/api\/trpc\/([^/?#]+)/);
|
|
709
|
+
if (trpcMatch) {
|
|
710
|
+
let procedure;
|
|
711
|
+
try {
|
|
712
|
+
procedure = decodeURIComponent(trpcMatch[1]);
|
|
713
|
+
} catch {
|
|
714
|
+
procedure = trpcMatch[1];
|
|
715
|
+
}
|
|
716
|
+
if (procedure) {
|
|
717
|
+
extra[ATTR.TRPC_PROCEDURE] = procedure;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
705
721
|
const method = attrs["http.method"] ?? attrs["http.request.method"];
|
|
706
722
|
if (method) {
|
|
707
723
|
extra[ATTR.HTTP_METHOD] = method;
|
|
@@ -776,6 +792,12 @@ var GlasstraceExporter = class {
|
|
|
776
792
|
if (typeof errorField === "string") {
|
|
777
793
|
extra[ATTR.ERROR_FIELD] = errorField;
|
|
778
794
|
}
|
|
795
|
+
if (this.getConfig().errorResponseBodies) {
|
|
796
|
+
const responseBody = attrs["glasstrace.internal.response_body"];
|
|
797
|
+
if (typeof responseBody === "string") {
|
|
798
|
+
extra[ATTR.ERROR_RESPONSE_BODY] = responseBody.slice(0, 500);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
779
801
|
const spanAny = span;
|
|
780
802
|
const instrumentationName = spanAny.instrumentationScope?.name ?? spanAny.instrumentationLibrary?.name ?? "";
|
|
781
803
|
const ormProvider = deriveOrmProvider(instrumentationName);
|
|
@@ -3754,10 +3776,458 @@ var BasicTracerProvider = class {
|
|
|
3754
3776
|
}
|
|
3755
3777
|
};
|
|
3756
3778
|
|
|
3779
|
+
// src/lifecycle.ts
|
|
3780
|
+
init_esm_shims();
|
|
3781
|
+
import { EventEmitter } from "events";
|
|
3782
|
+
var CoreState = {
|
|
3783
|
+
IDLE: "IDLE",
|
|
3784
|
+
REGISTERING: "REGISTERING",
|
|
3785
|
+
KEY_PENDING: "KEY_PENDING",
|
|
3786
|
+
KEY_RESOLVED: "KEY_RESOLVED",
|
|
3787
|
+
ACTIVE: "ACTIVE",
|
|
3788
|
+
ACTIVE_DEGRADED: "ACTIVE_DEGRADED",
|
|
3789
|
+
SHUTTING_DOWN: "SHUTTING_DOWN",
|
|
3790
|
+
SHUTDOWN: "SHUTDOWN",
|
|
3791
|
+
PRODUCTION_DISABLED: "PRODUCTION_DISABLED",
|
|
3792
|
+
REGISTRATION_FAILED: "REGISTRATION_FAILED"
|
|
3793
|
+
};
|
|
3794
|
+
var AuthState = {
|
|
3795
|
+
ANONYMOUS: "ANONYMOUS",
|
|
3796
|
+
AUTHENTICATED: "AUTHENTICATED",
|
|
3797
|
+
CLAIMING: "CLAIMING",
|
|
3798
|
+
CLAIMED: "CLAIMED"
|
|
3799
|
+
};
|
|
3800
|
+
var OtelState = {
|
|
3801
|
+
UNCONFIGURED: "UNCONFIGURED",
|
|
3802
|
+
CONFIGURING: "CONFIGURING",
|
|
3803
|
+
OWNS_PROVIDER: "OWNS_PROVIDER",
|
|
3804
|
+
AUTO_ATTACHED: "AUTO_ATTACHED",
|
|
3805
|
+
PROCESSOR_PRESENT: "PROCESSOR_PRESENT",
|
|
3806
|
+
COEXISTENCE_FAILED: "COEXISTENCE_FAILED"
|
|
3807
|
+
};
|
|
3808
|
+
var VALID_CORE_TRANSITIONS = {
|
|
3809
|
+
[CoreState.IDLE]: [CoreState.REGISTERING, CoreState.REGISTRATION_FAILED, CoreState.SHUTTING_DOWN],
|
|
3810
|
+
[CoreState.REGISTERING]: [
|
|
3811
|
+
CoreState.KEY_PENDING,
|
|
3812
|
+
CoreState.PRODUCTION_DISABLED,
|
|
3813
|
+
CoreState.REGISTRATION_FAILED,
|
|
3814
|
+
CoreState.SHUTTING_DOWN
|
|
3815
|
+
],
|
|
3816
|
+
[CoreState.KEY_PENDING]: [
|
|
3817
|
+
CoreState.KEY_RESOLVED,
|
|
3818
|
+
CoreState.REGISTRATION_FAILED,
|
|
3819
|
+
CoreState.SHUTTING_DOWN
|
|
3820
|
+
],
|
|
3821
|
+
[CoreState.KEY_RESOLVED]: [
|
|
3822
|
+
CoreState.ACTIVE,
|
|
3823
|
+
CoreState.ACTIVE_DEGRADED,
|
|
3824
|
+
CoreState.SHUTTING_DOWN
|
|
3825
|
+
],
|
|
3826
|
+
[CoreState.ACTIVE]: [
|
|
3827
|
+
CoreState.ACTIVE_DEGRADED,
|
|
3828
|
+
CoreState.SHUTTING_DOWN
|
|
3829
|
+
],
|
|
3830
|
+
[CoreState.ACTIVE_DEGRADED]: [
|
|
3831
|
+
CoreState.ACTIVE,
|
|
3832
|
+
CoreState.SHUTTING_DOWN
|
|
3833
|
+
],
|
|
3834
|
+
[CoreState.SHUTTING_DOWN]: [CoreState.SHUTDOWN],
|
|
3835
|
+
[CoreState.SHUTDOWN]: [],
|
|
3836
|
+
[CoreState.PRODUCTION_DISABLED]: [],
|
|
3837
|
+
[CoreState.REGISTRATION_FAILED]: []
|
|
3838
|
+
};
|
|
3839
|
+
var VALID_AUTH_TRANSITIONS = {
|
|
3840
|
+
[AuthState.ANONYMOUS]: [AuthState.CLAIMING],
|
|
3841
|
+
[AuthState.AUTHENTICATED]: [AuthState.CLAIMING],
|
|
3842
|
+
[AuthState.CLAIMING]: [AuthState.CLAIMED],
|
|
3843
|
+
[AuthState.CLAIMED]: [AuthState.CLAIMING]
|
|
3844
|
+
};
|
|
3845
|
+
var VALID_OTEL_TRANSITIONS = {
|
|
3846
|
+
[OtelState.UNCONFIGURED]: [OtelState.CONFIGURING],
|
|
3847
|
+
[OtelState.CONFIGURING]: [
|
|
3848
|
+
OtelState.OWNS_PROVIDER,
|
|
3849
|
+
OtelState.AUTO_ATTACHED,
|
|
3850
|
+
OtelState.PROCESSOR_PRESENT,
|
|
3851
|
+
OtelState.COEXISTENCE_FAILED
|
|
3852
|
+
],
|
|
3853
|
+
[OtelState.OWNS_PROVIDER]: [],
|
|
3854
|
+
[OtelState.AUTO_ATTACHED]: [],
|
|
3855
|
+
[OtelState.PROCESSOR_PRESENT]: [],
|
|
3856
|
+
[OtelState.COEXISTENCE_FAILED]: []
|
|
3857
|
+
};
|
|
3858
|
+
var _coreState = CoreState.IDLE;
|
|
3859
|
+
var _authState = AuthState.ANONYMOUS;
|
|
3860
|
+
var _otelState = OtelState.UNCONFIGURED;
|
|
3861
|
+
var _emitter = new EventEmitter();
|
|
3862
|
+
var _logger = null;
|
|
3863
|
+
var _initialized = false;
|
|
3864
|
+
var _initWarned = false;
|
|
3865
|
+
var _coreReadyEmitted = false;
|
|
3866
|
+
var _authInitialized = false;
|
|
3867
|
+
var _emitting = false;
|
|
3868
|
+
function initLifecycle(options) {
|
|
3869
|
+
if (_initialized) {
|
|
3870
|
+
options.logger("warn", "[glasstrace] initLifecycle() called twice \u2014 ignored.");
|
|
3871
|
+
return;
|
|
3872
|
+
}
|
|
3873
|
+
_logger = options.logger;
|
|
3874
|
+
_initialized = true;
|
|
3875
|
+
}
|
|
3876
|
+
function warnIfNotInitialized() {
|
|
3877
|
+
if (!_initialized && !_initWarned) {
|
|
3878
|
+
_initWarned = true;
|
|
3879
|
+
console.warn(
|
|
3880
|
+
"[glasstrace] Lifecycle state changed before initLifecycle() was called. Logger not available \u2014 errors will be silent."
|
|
3881
|
+
);
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
function setCoreState(to) {
|
|
3885
|
+
warnIfNotInitialized();
|
|
3886
|
+
const from = _coreState;
|
|
3887
|
+
if (from === to) return;
|
|
3888
|
+
const valid = VALID_CORE_TRANSITIONS[from];
|
|
3889
|
+
if (!valid.includes(to)) {
|
|
3890
|
+
_logger?.(
|
|
3891
|
+
"warn",
|
|
3892
|
+
`[glasstrace] Invalid core state transition: ${from} \u2192 ${to}. Ignored.`
|
|
3893
|
+
);
|
|
3894
|
+
return;
|
|
3895
|
+
}
|
|
3896
|
+
_coreState = to;
|
|
3897
|
+
if (_emitting) return;
|
|
3898
|
+
_emitting = true;
|
|
3899
|
+
try {
|
|
3900
|
+
emitSafe("core:state_changed", { from, to });
|
|
3901
|
+
const current = _coreState;
|
|
3902
|
+
if (!_coreReadyEmitted && (current === CoreState.ACTIVE || current === CoreState.ACTIVE_DEGRADED)) {
|
|
3903
|
+
_coreReadyEmitted = true;
|
|
3904
|
+
emitSafe("core:ready", {});
|
|
3905
|
+
}
|
|
3906
|
+
if (current === CoreState.SHUTTING_DOWN) {
|
|
3907
|
+
emitSafe("core:shutdown_started", {});
|
|
3908
|
+
}
|
|
3909
|
+
if (current === CoreState.SHUTDOWN) {
|
|
3910
|
+
emitSafe("core:shutdown_completed", {});
|
|
3911
|
+
}
|
|
3912
|
+
} finally {
|
|
3913
|
+
_emitting = false;
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
function initAuthState(state) {
|
|
3917
|
+
if (_authInitialized) {
|
|
3918
|
+
_logger?.(
|
|
3919
|
+
"warn",
|
|
3920
|
+
"[glasstrace] initAuthState() called after auth state already initialized. Ignored."
|
|
3921
|
+
);
|
|
3922
|
+
return;
|
|
3923
|
+
}
|
|
3924
|
+
_authInitialized = true;
|
|
3925
|
+
_authState = state;
|
|
3926
|
+
}
|
|
3927
|
+
function setAuthState(to) {
|
|
3928
|
+
warnIfNotInitialized();
|
|
3929
|
+
const from = _authState;
|
|
3930
|
+
if (from === to) return;
|
|
3931
|
+
const valid = VALID_AUTH_TRANSITIONS[from];
|
|
3932
|
+
if (!valid.includes(to)) {
|
|
3933
|
+
_logger?.(
|
|
3934
|
+
"warn",
|
|
3935
|
+
`[glasstrace] Invalid auth state transition: ${from} \u2192 ${to}. Ignored.`
|
|
3936
|
+
);
|
|
3937
|
+
return;
|
|
3938
|
+
}
|
|
3939
|
+
_authState = to;
|
|
3940
|
+
}
|
|
3941
|
+
function setOtelState(to) {
|
|
3942
|
+
warnIfNotInitialized();
|
|
3943
|
+
const from = _otelState;
|
|
3944
|
+
if (from === to) return;
|
|
3945
|
+
const valid = VALID_OTEL_TRANSITIONS[from];
|
|
3946
|
+
if (!valid.includes(to)) {
|
|
3947
|
+
_logger?.(
|
|
3948
|
+
"warn",
|
|
3949
|
+
`[glasstrace] Invalid OTel state transition: ${from} \u2192 ${to}. Ignored.`
|
|
3950
|
+
);
|
|
3951
|
+
return;
|
|
3952
|
+
}
|
|
3953
|
+
_otelState = to;
|
|
3954
|
+
}
|
|
3955
|
+
function getCoreState() {
|
|
3956
|
+
return _coreState;
|
|
3957
|
+
}
|
|
3958
|
+
function getSdkState() {
|
|
3959
|
+
return {
|
|
3960
|
+
core: _coreState,
|
|
3961
|
+
auth: _authState,
|
|
3962
|
+
otel: _otelState
|
|
3963
|
+
};
|
|
3964
|
+
}
|
|
3965
|
+
function onLifecycleEvent(event, listener) {
|
|
3966
|
+
_emitter.on(event, listener);
|
|
3967
|
+
}
|
|
3968
|
+
function emitLifecycleEvent(event, payload) {
|
|
3969
|
+
emitSafe(event, payload);
|
|
3970
|
+
}
|
|
3971
|
+
function offLifecycleEvent(event, listener) {
|
|
3972
|
+
_emitter.off(event, listener);
|
|
3973
|
+
}
|
|
3974
|
+
function emitSafe(event, payload) {
|
|
3975
|
+
const listeners = _emitter.listeners(event);
|
|
3976
|
+
for (const listener of listeners) {
|
|
3977
|
+
try {
|
|
3978
|
+
const result = listener(payload);
|
|
3979
|
+
if (result && typeof result.catch === "function") {
|
|
3980
|
+
result.catch((err) => {
|
|
3981
|
+
_logger?.(
|
|
3982
|
+
"error",
|
|
3983
|
+
`[glasstrace] Async error in lifecycle event listener for "${event}": ${err instanceof Error ? err.message : String(err)}`
|
|
3984
|
+
);
|
|
3985
|
+
});
|
|
3986
|
+
}
|
|
3987
|
+
} catch (err) {
|
|
3988
|
+
_logger?.(
|
|
3989
|
+
"error",
|
|
3990
|
+
`[glasstrace] Error in lifecycle event listener for "${event}": ${err instanceof Error ? err.message : String(err)}`
|
|
3991
|
+
);
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3995
|
+
function isReady() {
|
|
3996
|
+
return _coreState === CoreState.ACTIVE || _coreState === CoreState.ACTIVE_DEGRADED;
|
|
3997
|
+
}
|
|
3998
|
+
function waitForReady(timeoutMs = 3e4) {
|
|
3999
|
+
if (isReady()) {
|
|
4000
|
+
return Promise.resolve();
|
|
4001
|
+
}
|
|
4002
|
+
if (_coreState === CoreState.PRODUCTION_DISABLED || _coreState === CoreState.REGISTRATION_FAILED || _coreState === CoreState.SHUTTING_DOWN || _coreState === CoreState.SHUTDOWN) {
|
|
4003
|
+
return Promise.reject(new Error(`SDK is in terminal state: ${_coreState}`));
|
|
4004
|
+
}
|
|
4005
|
+
return new Promise((resolve2, reject) => {
|
|
4006
|
+
let settled = false;
|
|
4007
|
+
const listener = ({ to }) => {
|
|
4008
|
+
if (settled) return;
|
|
4009
|
+
if (to === CoreState.ACTIVE || to === CoreState.ACTIVE_DEGRADED) {
|
|
4010
|
+
settled = true;
|
|
4011
|
+
offLifecycleEvent("core:state_changed", listener);
|
|
4012
|
+
resolve2();
|
|
4013
|
+
} else if (to === CoreState.PRODUCTION_DISABLED || to === CoreState.REGISTRATION_FAILED || to === CoreState.SHUTTING_DOWN || to === CoreState.SHUTDOWN) {
|
|
4014
|
+
settled = true;
|
|
4015
|
+
offLifecycleEvent("core:state_changed", listener);
|
|
4016
|
+
reject(new Error(`SDK reached terminal state: ${to}`));
|
|
4017
|
+
}
|
|
4018
|
+
};
|
|
4019
|
+
onLifecycleEvent("core:state_changed", listener);
|
|
4020
|
+
if (timeoutMs > 0) {
|
|
4021
|
+
const timer = setTimeout(() => {
|
|
4022
|
+
if (settled) return;
|
|
4023
|
+
settled = true;
|
|
4024
|
+
offLifecycleEvent("core:state_changed", listener);
|
|
4025
|
+
reject(new Error(`waitForReady timed out after ${timeoutMs}ms (state: ${_coreState})`));
|
|
4026
|
+
}, timeoutMs);
|
|
4027
|
+
if (typeof timer === "object" && "unref" in timer) {
|
|
4028
|
+
timer.unref();
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
});
|
|
4032
|
+
}
|
|
4033
|
+
function getStatus() {
|
|
4034
|
+
let mode;
|
|
4035
|
+
if (_coreState === CoreState.PRODUCTION_DISABLED) {
|
|
4036
|
+
mode = "disabled";
|
|
4037
|
+
} else if (_authState === AuthState.CLAIMING || _authState === AuthState.CLAIMED) {
|
|
4038
|
+
mode = "claiming";
|
|
4039
|
+
} else if (_authState === AuthState.AUTHENTICATED) {
|
|
4040
|
+
mode = "authenticated";
|
|
4041
|
+
} else {
|
|
4042
|
+
mode = "anonymous";
|
|
4043
|
+
}
|
|
4044
|
+
let tracing;
|
|
4045
|
+
if (_otelState === OtelState.COEXISTENCE_FAILED || _otelState === OtelState.UNCONFIGURED || _otelState === OtelState.CONFIGURING) {
|
|
4046
|
+
tracing = "not-configured";
|
|
4047
|
+
} else if (_coreState === CoreState.ACTIVE_DEGRADED) {
|
|
4048
|
+
tracing = "degraded";
|
|
4049
|
+
} else if (_otelState === OtelState.AUTO_ATTACHED || _otelState === OtelState.PROCESSOR_PRESENT) {
|
|
4050
|
+
tracing = "coexistence";
|
|
4051
|
+
} else {
|
|
4052
|
+
tracing = "active";
|
|
4053
|
+
}
|
|
4054
|
+
return {
|
|
4055
|
+
ready: isReady(),
|
|
4056
|
+
mode,
|
|
4057
|
+
tracing
|
|
4058
|
+
};
|
|
4059
|
+
}
|
|
4060
|
+
var _shutdownHooks = [];
|
|
4061
|
+
var _signalHandlersRegistered = false;
|
|
4062
|
+
var _signalHandler = null;
|
|
4063
|
+
var _beforeExitRegistered = false;
|
|
4064
|
+
var _beforeExitHandler = null;
|
|
4065
|
+
var _shutdownExecuted = false;
|
|
4066
|
+
function registerShutdownHook(hook) {
|
|
4067
|
+
_shutdownHooks.push(hook);
|
|
4068
|
+
_shutdownHooks.sort((a, b) => a.priority - b.priority);
|
|
4069
|
+
}
|
|
4070
|
+
async function executeShutdown(timeoutMs = 5e3) {
|
|
4071
|
+
if (_shutdownExecuted) return;
|
|
4072
|
+
_shutdownExecuted = true;
|
|
4073
|
+
setCoreState(CoreState.SHUTTING_DOWN);
|
|
4074
|
+
for (const hook of _shutdownHooks) {
|
|
4075
|
+
try {
|
|
4076
|
+
const hookPromise = hook.fn();
|
|
4077
|
+
hookPromise.catch(() => {
|
|
4078
|
+
});
|
|
4079
|
+
await Promise.race([
|
|
4080
|
+
hookPromise,
|
|
4081
|
+
new Promise((_, reject) => {
|
|
4082
|
+
const timer = setTimeout(() => reject(new Error(`Shutdown hook "${hook.name}" timed out`)), timeoutMs);
|
|
4083
|
+
if (typeof timer === "object" && "unref" in timer) {
|
|
4084
|
+
timer.unref();
|
|
4085
|
+
}
|
|
4086
|
+
})
|
|
4087
|
+
]);
|
|
4088
|
+
} catch (err) {
|
|
4089
|
+
_logger?.(
|
|
4090
|
+
"warn",
|
|
4091
|
+
`[glasstrace] Shutdown hook "${hook.name}" failed: ${err instanceof Error ? err.message : String(err)}`
|
|
4092
|
+
);
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
setCoreState(CoreState.SHUTDOWN);
|
|
4096
|
+
}
|
|
4097
|
+
function registerSignalHandlers() {
|
|
4098
|
+
if (_signalHandlersRegistered) return;
|
|
4099
|
+
if (typeof process === "undefined" || typeof process.once !== "function") return;
|
|
4100
|
+
_signalHandlersRegistered = true;
|
|
4101
|
+
const handler = (signal) => {
|
|
4102
|
+
void executeShutdown().finally(() => {
|
|
4103
|
+
if (_signalHandler) {
|
|
4104
|
+
process.removeListener("SIGTERM", _signalHandler);
|
|
4105
|
+
process.removeListener("SIGINT", _signalHandler);
|
|
4106
|
+
}
|
|
4107
|
+
process.kill(process.pid, signal);
|
|
4108
|
+
});
|
|
4109
|
+
};
|
|
4110
|
+
_signalHandler = handler;
|
|
4111
|
+
process.once("SIGTERM", handler);
|
|
4112
|
+
process.once("SIGINT", handler);
|
|
4113
|
+
}
|
|
4114
|
+
function registerBeforeExitTrigger() {
|
|
4115
|
+
if (_beforeExitRegistered) return;
|
|
4116
|
+
if (typeof process === "undefined" || typeof process.once !== "function") return;
|
|
4117
|
+
_beforeExitRegistered = true;
|
|
4118
|
+
const handler = () => {
|
|
4119
|
+
void executeShutdown();
|
|
4120
|
+
};
|
|
4121
|
+
_beforeExitHandler = handler;
|
|
4122
|
+
process.once("beforeExit", handler);
|
|
4123
|
+
}
|
|
4124
|
+
|
|
4125
|
+
// src/coexistence.ts
|
|
4126
|
+
init_esm_shims();
|
|
4127
|
+
function createGlasstraceSpanProcessor(options) {
|
|
4128
|
+
const config = resolveConfig(options);
|
|
4129
|
+
const exporterUrl = `${config.endpoint}/v1/traces`;
|
|
4130
|
+
const createOtlpExporter = (url, headers) => new OTLPTraceExporter({ url, headers });
|
|
4131
|
+
const exporter = new GlasstraceExporter({
|
|
4132
|
+
getApiKey: getResolvedApiKey,
|
|
4133
|
+
sessionManager: getSessionManager(),
|
|
4134
|
+
getConfig: () => getActiveConfig(),
|
|
4135
|
+
environment: config.environment,
|
|
4136
|
+
endpointUrl: exporterUrl,
|
|
4137
|
+
createDelegate: createOtlpExporter
|
|
4138
|
+
});
|
|
4139
|
+
registerExporterForKeyNotification(exporter);
|
|
4140
|
+
return new BatchSpanProcessor(exporter, {
|
|
4141
|
+
scheduledDelayMillis: 1e3
|
|
4142
|
+
});
|
|
4143
|
+
}
|
|
4144
|
+
function emitNudgeMessage() {
|
|
4145
|
+
const isSentry = detectSentry();
|
|
4146
|
+
if (isSentry) {
|
|
4147
|
+
sdkLog(
|
|
4148
|
+
"info",
|
|
4149
|
+
`[glasstrace] Detected existing OTel provider \u2014 auto-attached Glasstrace span processor.
|
|
4150
|
+
For a cleaner setup, add Glasstrace to your Sentry config:
|
|
4151
|
+
|
|
4152
|
+
import { createGlasstraceSpanProcessor } from '@glasstrace/sdk';
|
|
4153
|
+
|
|
4154
|
+
Sentry.init({
|
|
4155
|
+
dsn: '...',
|
|
4156
|
+
openTelemetrySpanProcessors: [createGlasstraceSpanProcessor()],
|
|
4157
|
+
});
|
|
4158
|
+
|
|
4159
|
+
This message will not appear once Glasstrace is added to your provider config.`
|
|
4160
|
+
);
|
|
4161
|
+
} else {
|
|
4162
|
+
sdkLog(
|
|
4163
|
+
"info",
|
|
4164
|
+
`[glasstrace] Detected existing OTel provider \u2014 auto-attached Glasstrace span processor.
|
|
4165
|
+
For a cleaner setup, add Glasstrace to your provider config:
|
|
4166
|
+
|
|
4167
|
+
import { createGlasstraceSpanProcessor } from '@glasstrace/sdk';
|
|
4168
|
+
|
|
4169
|
+
const provider = new BasicTracerProvider({
|
|
4170
|
+
spanProcessors: [
|
|
4171
|
+
// ... your existing processors,
|
|
4172
|
+
createGlasstraceSpanProcessor(),
|
|
4173
|
+
],
|
|
4174
|
+
});
|
|
4175
|
+
|
|
4176
|
+
This message will not appear once Glasstrace is added to your provider config.`
|
|
4177
|
+
);
|
|
4178
|
+
}
|
|
4179
|
+
}
|
|
4180
|
+
function emitGuidanceMessage() {
|
|
4181
|
+
const isSentry = detectSentry();
|
|
4182
|
+
if (isSentry) {
|
|
4183
|
+
sdkLog(
|
|
4184
|
+
"warn",
|
|
4185
|
+
`[glasstrace] An existing OTel TracerProvider is registered but Glasstrace could not auto-attach its span processor.
|
|
4186
|
+
Add Glasstrace to your Sentry config:
|
|
4187
|
+
|
|
4188
|
+
import { createGlasstraceSpanProcessor } from '@glasstrace/sdk';
|
|
4189
|
+
|
|
4190
|
+
Sentry.init({
|
|
4191
|
+
dsn: '...',
|
|
4192
|
+
openTelemetrySpanProcessors: [createGlasstraceSpanProcessor()],
|
|
4193
|
+
});`
|
|
4194
|
+
);
|
|
4195
|
+
} else {
|
|
4196
|
+
sdkLog(
|
|
4197
|
+
"warn",
|
|
4198
|
+
`[glasstrace] An existing OTel TracerProvider is registered but Glasstrace could not auto-attach its span processor.
|
|
4199
|
+
Add Glasstrace to your provider configuration:
|
|
4200
|
+
|
|
4201
|
+
import { createGlasstraceSpanProcessor } from '@glasstrace/sdk';
|
|
4202
|
+
|
|
4203
|
+
const provider = new BasicTracerProvider({
|
|
4204
|
+
spanProcessors: [
|
|
4205
|
+
// ... your existing processors,
|
|
4206
|
+
createGlasstraceSpanProcessor(),
|
|
4207
|
+
],
|
|
4208
|
+
});`
|
|
4209
|
+
);
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
function detectSentry() {
|
|
4213
|
+
try {
|
|
4214
|
+
__require.resolve("@sentry/node");
|
|
4215
|
+
return true;
|
|
4216
|
+
} catch {
|
|
4217
|
+
try {
|
|
4218
|
+
__require.resolve("@sentry/nextjs");
|
|
4219
|
+
return true;
|
|
4220
|
+
} catch {
|
|
4221
|
+
return false;
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
|
|
3757
4226
|
// src/otel-config.ts
|
|
3758
4227
|
var _resolvedApiKey = API_KEY_PENDING;
|
|
3759
4228
|
var _activeExporter = null;
|
|
3760
|
-
var
|
|
4229
|
+
var _additionalExporters = [];
|
|
4230
|
+
var _injectedProcessor = null;
|
|
3761
4231
|
function setResolvedApiKey(key) {
|
|
3762
4232
|
_resolvedApiKey = key;
|
|
3763
4233
|
}
|
|
@@ -3766,6 +4236,12 @@ function getResolvedApiKey() {
|
|
|
3766
4236
|
}
|
|
3767
4237
|
function notifyApiKeyResolved() {
|
|
3768
4238
|
_activeExporter?.notifyKeyResolved();
|
|
4239
|
+
for (const exporter of _additionalExporters) {
|
|
4240
|
+
exporter.notifyKeyResolved();
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
function registerExporterForKeyNotification(exporter) {
|
|
4244
|
+
_additionalExporters.push(exporter);
|
|
3769
4245
|
}
|
|
3770
4246
|
async function tryImport(moduleId) {
|
|
3771
4247
|
try {
|
|
@@ -3774,34 +4250,65 @@ async function tryImport(moduleId) {
|
|
|
3774
4250
|
return null;
|
|
3775
4251
|
}
|
|
3776
4252
|
}
|
|
3777
|
-
function
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
4253
|
+
function tryInjectProcessor(tracerProvider, glasstraceExporter) {
|
|
4254
|
+
try {
|
|
4255
|
+
const proxy = tracerProvider;
|
|
4256
|
+
const delegate = typeof proxy.getDelegate === "function" ? proxy.getDelegate() : tracerProvider;
|
|
4257
|
+
const withAdd = delegate;
|
|
4258
|
+
if (typeof withAdd.addSpanProcessor === "function") {
|
|
4259
|
+
if (typeof withAdd.getActiveSpanProcessor === "function") {
|
|
4260
|
+
const active = withAdd.getActiveSpanProcessor();
|
|
4261
|
+
const brand = /* @__PURE__ */ Symbol.for("glasstrace.exporter");
|
|
4262
|
+
const processors = active?._spanProcessors;
|
|
4263
|
+
if (Array.isArray(processors) && processors.some((p) => {
|
|
4264
|
+
const exp = p._exporter;
|
|
4265
|
+
return exp?.[brand] === true;
|
|
4266
|
+
})) {
|
|
4267
|
+
return "already_present";
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
const processor2 = new BatchSpanProcessor(glasstraceExporter, {
|
|
4271
|
+
scheduledDelayMillis: 1e3
|
|
4272
|
+
});
|
|
4273
|
+
withAdd.addSpanProcessor(processor2);
|
|
4274
|
+
_injectedProcessor = processor2;
|
|
4275
|
+
return "v1_public";
|
|
4276
|
+
}
|
|
4277
|
+
const provider = delegate;
|
|
4278
|
+
const multiProcessor = provider._activeSpanProcessor;
|
|
4279
|
+
if (!multiProcessor || !Array.isArray(multiProcessor._spanProcessors)) {
|
|
4280
|
+
return null;
|
|
4281
|
+
}
|
|
4282
|
+
const processor = new BatchSpanProcessor(glasstraceExporter, {
|
|
4283
|
+
scheduledDelayMillis: 1e3
|
|
4284
|
+
});
|
|
4285
|
+
multiProcessor._spanProcessors.push(processor);
|
|
4286
|
+
_injectedProcessor = processor;
|
|
4287
|
+
return "v2_private";
|
|
4288
|
+
} catch {
|
|
4289
|
+
return null;
|
|
3784
4290
|
}
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
4291
|
+
}
|
|
4292
|
+
function isGlasstraceProcessorPresent(tracerProvider) {
|
|
4293
|
+
try {
|
|
4294
|
+
const proxy = tracerProvider;
|
|
4295
|
+
const delegate = typeof proxy.getDelegate === "function" ? proxy.getDelegate() : tracerProvider;
|
|
4296
|
+
const provider = delegate;
|
|
4297
|
+
const processors = provider._activeSpanProcessor?._spanProcessors;
|
|
4298
|
+
if (!Array.isArray(processors)) {
|
|
4299
|
+
return false;
|
|
4300
|
+
}
|
|
4301
|
+
const brand = /* @__PURE__ */ Symbol.for("glasstrace.exporter");
|
|
4302
|
+
return processors.some((p) => {
|
|
4303
|
+
const exporter = p._exporter;
|
|
4304
|
+
return exporter?.[brand] === true;
|
|
3797
4305
|
});
|
|
3798
|
-
}
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
process.once("SIGTERM", handler);
|
|
3802
|
-
process.once("SIGINT", handler);
|
|
4306
|
+
} catch {
|
|
4307
|
+
return false;
|
|
4308
|
+
}
|
|
3803
4309
|
}
|
|
3804
4310
|
async function configureOtel(config, sessionManager) {
|
|
4311
|
+
setOtelState(OtelState.CONFIGURING);
|
|
3805
4312
|
const exporterUrl = `${config.endpoint}/v1/traces`;
|
|
3806
4313
|
const createOtlpExporter = (url, headers) => new OTLPTraceExporter({ url, headers });
|
|
3807
4314
|
const glasstraceExporter = new GlasstraceExporter({
|
|
@@ -3814,29 +4321,87 @@ async function configureOtel(config, sessionManager) {
|
|
|
3814
4321
|
verbose: config.verbose
|
|
3815
4322
|
});
|
|
3816
4323
|
_activeExporter = glasstraceExporter;
|
|
4324
|
+
await new Promise((resolve2) => {
|
|
4325
|
+
if (typeof setImmediate === "function") {
|
|
4326
|
+
setImmediate(resolve2);
|
|
4327
|
+
} else {
|
|
4328
|
+
setTimeout(resolve2, 0);
|
|
4329
|
+
}
|
|
4330
|
+
});
|
|
4331
|
+
const existingProvider = trace.getTracerProvider();
|
|
4332
|
+
const probeTracer = existingProvider.getTracer("glasstrace-probe");
|
|
4333
|
+
const anotherProviderRegistered = probeTracer.constructor.name !== "ProxyTracer";
|
|
4334
|
+
if (anotherProviderRegistered) {
|
|
4335
|
+
if (isGlasstraceProcessorPresent(existingProvider)) {
|
|
4336
|
+
if (config.verbose) {
|
|
4337
|
+
sdkLog("info", "[glasstrace] Existing provider detected \u2014 Glasstrace processor already present.");
|
|
4338
|
+
}
|
|
4339
|
+
_activeExporter = null;
|
|
4340
|
+
setOtelState(OtelState.PROCESSOR_PRESENT);
|
|
4341
|
+
emitLifecycleEvent("otel:configured", { state: OtelState.PROCESSOR_PRESENT, scenario: "B-clean" });
|
|
4342
|
+
return;
|
|
4343
|
+
}
|
|
4344
|
+
const injectionMethod = tryInjectProcessor(existingProvider, glasstraceExporter);
|
|
4345
|
+
if (injectionMethod === "already_present") {
|
|
4346
|
+
if (config.verbose) {
|
|
4347
|
+
sdkLog("info", "[glasstrace] Existing provider detected \u2014 Glasstrace processor already present (v1 check).");
|
|
4348
|
+
}
|
|
4349
|
+
_activeExporter = null;
|
|
4350
|
+
setOtelState(OtelState.PROCESSOR_PRESENT);
|
|
4351
|
+
emitLifecycleEvent("otel:configured", { state: OtelState.PROCESSOR_PRESENT, scenario: "B-clean" });
|
|
4352
|
+
return;
|
|
4353
|
+
}
|
|
4354
|
+
if (injectionMethod) {
|
|
4355
|
+
if (config.verbose) {
|
|
4356
|
+
sdkLog("info", "[glasstrace] Existing provider detected \u2014 auto-attaching Glasstrace processor.");
|
|
4357
|
+
}
|
|
4358
|
+
registerShutdownHook({
|
|
4359
|
+
name: "coexistence-flush",
|
|
4360
|
+
priority: 5,
|
|
4361
|
+
fn: async () => {
|
|
4362
|
+
if (_injectedProcessor) {
|
|
4363
|
+
await _injectedProcessor.forceFlush();
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
});
|
|
4367
|
+
registerBeforeExitTrigger();
|
|
4368
|
+
const scenario = injectionMethod === "v1_public" ? "D1" : "B-auto";
|
|
4369
|
+
setOtelState(OtelState.AUTO_ATTACHED);
|
|
4370
|
+
emitLifecycleEvent("otel:configured", { state: OtelState.AUTO_ATTACHED, scenario });
|
|
4371
|
+
emitLifecycleEvent("otel:injection_succeeded", { method: injectionMethod });
|
|
4372
|
+
emitNudgeMessage();
|
|
4373
|
+
return;
|
|
4374
|
+
}
|
|
4375
|
+
if (config.verbose) {
|
|
4376
|
+
sdkLog("info", "[glasstrace] Existing provider detected \u2014 could not auto-attach.");
|
|
4377
|
+
}
|
|
4378
|
+
emitGuidanceMessage();
|
|
4379
|
+
_activeExporter = null;
|
|
4380
|
+
setOtelState(OtelState.COEXISTENCE_FAILED);
|
|
4381
|
+
emitLifecycleEvent("otel:configured", { state: OtelState.COEXISTENCE_FAILED, scenario: "C/F" });
|
|
4382
|
+
emitLifecycleEvent("otel:injection_failed", { reason: "provider internals inaccessible" });
|
|
4383
|
+
const coreState = getCoreState();
|
|
4384
|
+
if (coreState === CoreState.ACTIVE || coreState === CoreState.KEY_RESOLVED) {
|
|
4385
|
+
setCoreState(CoreState.ACTIVE_DEGRADED);
|
|
4386
|
+
}
|
|
4387
|
+
return;
|
|
4388
|
+
}
|
|
3817
4389
|
const vercelOtel = await tryImport("@vercel/otel");
|
|
3818
4390
|
if (vercelOtel && typeof vercelOtel.registerOTel === "function") {
|
|
3819
4391
|
const otelConfig = {
|
|
3820
4392
|
serviceName: "glasstrace-sdk",
|
|
3821
4393
|
traceExporter: glasstraceExporter
|
|
3822
4394
|
};
|
|
3823
|
-
const
|
|
3824
|
-
if (
|
|
3825
|
-
const PrismaInstrumentation =
|
|
4395
|
+
const prismaModule2 = await tryImport("@prisma/instrumentation");
|
|
4396
|
+
if (prismaModule2) {
|
|
4397
|
+
const PrismaInstrumentation = prismaModule2.PrismaInstrumentation;
|
|
3826
4398
|
if (PrismaInstrumentation) {
|
|
3827
4399
|
otelConfig.instrumentations = [new PrismaInstrumentation()];
|
|
3828
4400
|
}
|
|
3829
4401
|
}
|
|
3830
4402
|
vercelOtel.registerOTel(otelConfig);
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
const existingProvider = trace.getTracerProvider();
|
|
3834
|
-
const probeTracer = existingProvider.getTracer("glasstrace-probe");
|
|
3835
|
-
if (probeTracer.constructor.name !== "ProxyTracer") {
|
|
3836
|
-
console.warn(
|
|
3837
|
-
"[glasstrace] An existing OpenTelemetry TracerProvider is already registered. Glasstrace will not overwrite it. To use Glasstrace alongside another tracing tool, add GlasstraceExporter as an additional span processor on your existing provider."
|
|
3838
|
-
);
|
|
3839
|
-
_activeExporter = null;
|
|
4403
|
+
setOtelState(OtelState.OWNS_PROVIDER);
|
|
4404
|
+
emitLifecycleEvent("otel:configured", { state: OtelState.OWNS_PROVIDER, scenario: "E" });
|
|
3840
4405
|
return;
|
|
3841
4406
|
}
|
|
3842
4407
|
if (config.verbose) {
|
|
@@ -3858,7 +4423,29 @@ async function configureOtel(config, sessionManager) {
|
|
|
3858
4423
|
spanProcessors: [processor]
|
|
3859
4424
|
});
|
|
3860
4425
|
trace.setGlobalTracerProvider(provider);
|
|
3861
|
-
|
|
4426
|
+
registerShutdownHook({
|
|
4427
|
+
name: "otel-provider-shutdown",
|
|
4428
|
+
priority: 0,
|
|
4429
|
+
fn: async () => {
|
|
4430
|
+
await provider.shutdown();
|
|
4431
|
+
}
|
|
4432
|
+
});
|
|
4433
|
+
registerSignalHandlers();
|
|
4434
|
+
registerBeforeExitTrigger();
|
|
4435
|
+
const prismaModule = await tryImport("@prisma/instrumentation");
|
|
4436
|
+
if (prismaModule) {
|
|
4437
|
+
const PrismaInstrumentation = prismaModule.PrismaInstrumentation;
|
|
4438
|
+
if (PrismaInstrumentation) {
|
|
4439
|
+
try {
|
|
4440
|
+
const inst = new PrismaInstrumentation();
|
|
4441
|
+
inst.setTracerProvider(provider);
|
|
4442
|
+
inst.enable();
|
|
4443
|
+
} catch {
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
}
|
|
4447
|
+
setOtelState(OtelState.OWNS_PROVIDER);
|
|
4448
|
+
emitLifecycleEvent("otel:configured", { state: OtelState.OWNS_PROVIDER, scenario: "A" });
|
|
3862
4449
|
}
|
|
3863
4450
|
|
|
3864
4451
|
// src/context-manager.ts
|
|
@@ -3903,7 +4490,7 @@ var heartbeatGeneration = 0;
|
|
|
3903
4490
|
var backoffAttempts = 0;
|
|
3904
4491
|
var backoffUntil = 0;
|
|
3905
4492
|
var tickInProgress = false;
|
|
3906
|
-
var
|
|
4493
|
+
var _shutdownHandler = null;
|
|
3907
4494
|
function startHeartbeat(config, anonKey, sdkVersion, generation, onClaimTransition) {
|
|
3908
4495
|
if (heartbeatTimer !== null) return;
|
|
3909
4496
|
heartbeatGeneration = generation;
|
|
@@ -3956,7 +4543,7 @@ async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTra
|
|
|
3956
4543
|
backoffUntil = 0;
|
|
3957
4544
|
}
|
|
3958
4545
|
if (initResult?.claimResult) {
|
|
3959
|
-
onClaimTransition(initResult.claimResult.newApiKey);
|
|
4546
|
+
onClaimTransition(initResult.claimResult.newApiKey, initResult.claimResult.accountId);
|
|
3960
4547
|
}
|
|
3961
4548
|
if (config.verbose) {
|
|
3962
4549
|
sdkLog("info", "[glasstrace] Heartbeat completed.");
|
|
@@ -3984,39 +4571,124 @@ function registerShutdownHandlers(config, anonKey, sdkVersion) {
|
|
|
3984
4571
|
process.kill(process.pid, signal);
|
|
3985
4572
|
});
|
|
3986
4573
|
};
|
|
3987
|
-
|
|
3988
|
-
process.once("SIGTERM",
|
|
3989
|
-
process.once("SIGINT",
|
|
4574
|
+
_shutdownHandler = handler;
|
|
4575
|
+
process.once("SIGTERM", _shutdownHandler);
|
|
4576
|
+
process.once("SIGINT", _shutdownHandler);
|
|
3990
4577
|
}
|
|
3991
4578
|
function removeShutdownHandlers() {
|
|
3992
|
-
if (
|
|
3993
|
-
process.removeListener("SIGTERM",
|
|
3994
|
-
process.removeListener("SIGINT",
|
|
3995
|
-
|
|
4579
|
+
if (_shutdownHandler && typeof process !== "undefined") {
|
|
4580
|
+
process.removeListener("SIGTERM", _shutdownHandler);
|
|
4581
|
+
process.removeListener("SIGINT", _shutdownHandler);
|
|
4582
|
+
_shutdownHandler = null;
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4585
|
+
|
|
4586
|
+
// src/runtime-state.ts
|
|
4587
|
+
init_esm_shims();
|
|
4588
|
+
import { writeFileSync, renameSync, mkdirSync } from "fs";
|
|
4589
|
+
import { join } from "path";
|
|
4590
|
+
var _projectRoot = null;
|
|
4591
|
+
var _sdkVersion = "unknown";
|
|
4592
|
+
var _lastScenario;
|
|
4593
|
+
var _debounceTimer = null;
|
|
4594
|
+
var _started = false;
|
|
4595
|
+
function startRuntimeStateWriter(options) {
|
|
4596
|
+
if (_started) return;
|
|
4597
|
+
_started = true;
|
|
4598
|
+
_projectRoot = options.projectRoot;
|
|
4599
|
+
_sdkVersion = options.sdkVersion;
|
|
4600
|
+
onLifecycleEvent("core:state_changed", ({ to }) => {
|
|
4601
|
+
if (to === CoreState.SHUTDOWN) {
|
|
4602
|
+
writeStateNow();
|
|
4603
|
+
} else {
|
|
4604
|
+
debouncedWrite();
|
|
4605
|
+
}
|
|
4606
|
+
});
|
|
4607
|
+
onLifecycleEvent("otel:configured", ({ scenario }) => {
|
|
4608
|
+
_lastScenario = scenario;
|
|
4609
|
+
debouncedWrite();
|
|
4610
|
+
});
|
|
4611
|
+
onLifecycleEvent("auth:key_resolved", () => debouncedWrite());
|
|
4612
|
+
onLifecycleEvent("auth:claim_started", () => debouncedWrite());
|
|
4613
|
+
onLifecycleEvent("auth:claim_completed", () => debouncedWrite());
|
|
4614
|
+
writeStateNow();
|
|
4615
|
+
}
|
|
4616
|
+
function debouncedWrite() {
|
|
4617
|
+
if (_debounceTimer) return;
|
|
4618
|
+
_debounceTimer = setTimeout(() => {
|
|
4619
|
+
_debounceTimer = null;
|
|
4620
|
+
writeStateNow();
|
|
4621
|
+
}, 1e3);
|
|
4622
|
+
if (typeof _debounceTimer === "object" && "unref" in _debounceTimer) {
|
|
4623
|
+
_debounceTimer.unref();
|
|
4624
|
+
}
|
|
4625
|
+
}
|
|
4626
|
+
function writeStateNow() {
|
|
4627
|
+
if (!_projectRoot) return;
|
|
4628
|
+
try {
|
|
4629
|
+
const state = getSdkState();
|
|
4630
|
+
const runtimeState = {
|
|
4631
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4632
|
+
pid: process.pid,
|
|
4633
|
+
sdkVersion: _sdkVersion,
|
|
4634
|
+
core: { state: state.core },
|
|
4635
|
+
auth: { state: state.auth },
|
|
4636
|
+
otel: { state: state.otel, scenario: _lastScenario }
|
|
4637
|
+
};
|
|
4638
|
+
const dir = join(_projectRoot, ".glasstrace");
|
|
4639
|
+
const filePath = join(dir, "runtime-state.json");
|
|
4640
|
+
const tmpPath = join(dir, "runtime-state.json.tmp");
|
|
4641
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4642
|
+
writeFileSync(tmpPath, JSON.stringify(runtimeState, null, 2) + "\n", {
|
|
4643
|
+
mode: 384
|
|
4644
|
+
});
|
|
4645
|
+
renameSync(tmpPath, filePath);
|
|
4646
|
+
} catch (err) {
|
|
4647
|
+
sdkLog(
|
|
4648
|
+
"warn",
|
|
4649
|
+
`[glasstrace] Failed to write runtime state: ${err instanceof Error ? err.message : String(err)}`
|
|
4650
|
+
);
|
|
3996
4651
|
}
|
|
3997
4652
|
}
|
|
3998
4653
|
|
|
3999
4654
|
// src/register.ts
|
|
4655
|
+
function maskKey(key) {
|
|
4656
|
+
if (key.length <= 12) return key.slice(0, 4) + "...";
|
|
4657
|
+
return key.slice(0, 8) + "..." + key.slice(-4);
|
|
4658
|
+
}
|
|
4000
4659
|
var consoleCaptureInstalled = false;
|
|
4001
4660
|
var discoveryHandler = null;
|
|
4002
|
-
var isRegistered = false;
|
|
4003
4661
|
var registrationGeneration = 0;
|
|
4662
|
+
var _sessionManager = null;
|
|
4663
|
+
function getSessionManager() {
|
|
4664
|
+
if (!_sessionManager) {
|
|
4665
|
+
_sessionManager = new SessionManager();
|
|
4666
|
+
}
|
|
4667
|
+
return _sessionManager;
|
|
4668
|
+
}
|
|
4004
4669
|
function registerGlasstrace(options) {
|
|
4005
4670
|
try {
|
|
4006
|
-
if (
|
|
4671
|
+
if (getCoreState() !== CoreState.IDLE) {
|
|
4007
4672
|
return;
|
|
4008
4673
|
}
|
|
4674
|
+
initLifecycle({ logger: sdkLog });
|
|
4009
4675
|
if (typeof process === "undefined" || typeof process.versions?.node !== "string") {
|
|
4010
4676
|
console.warn(
|
|
4011
4677
|
"[glasstrace] SDK requires a Node.js runtime. Edge Runtime, browser, and Deno without Node compat are not supported. Glasstrace is disabled in this environment."
|
|
4012
4678
|
);
|
|
4013
4679
|
return;
|
|
4014
4680
|
}
|
|
4681
|
+
setCoreState(CoreState.REGISTERING);
|
|
4682
|
+
startRuntimeStateWriter({
|
|
4683
|
+
projectRoot: process.cwd(),
|
|
4684
|
+
sdkVersion: "0.14.1"
|
|
4685
|
+
});
|
|
4015
4686
|
const config = resolveConfig(options);
|
|
4016
4687
|
if (config.verbose) {
|
|
4017
4688
|
console.info("[glasstrace] Config resolved.");
|
|
4018
4689
|
}
|
|
4019
4690
|
if (isProductionDisabled(config)) {
|
|
4691
|
+
setCoreState(CoreState.PRODUCTION_DISABLED);
|
|
4020
4692
|
console.warn(
|
|
4021
4693
|
"[glasstrace] Disabled in production. Set GLASSTRACE_FORCE_ENABLE=true to override."
|
|
4022
4694
|
);
|
|
@@ -4027,8 +4699,13 @@ function registerGlasstrace(options) {
|
|
|
4027
4699
|
}
|
|
4028
4700
|
const anonymous = isAnonymousMode(config);
|
|
4029
4701
|
let effectiveKey = config.apiKey;
|
|
4702
|
+
initAuthState(anonymous ? AuthState.ANONYMOUS : AuthState.AUTHENTICATED);
|
|
4030
4703
|
if (effectiveKey) {
|
|
4031
4704
|
setResolvedApiKey(effectiveKey);
|
|
4705
|
+
emitLifecycleEvent("auth:key_resolved", {
|
|
4706
|
+
key: maskKey(effectiveKey),
|
|
4707
|
+
mode: anonymous ? "anonymous" : "dev"
|
|
4708
|
+
});
|
|
4032
4709
|
}
|
|
4033
4710
|
if (config.verbose) {
|
|
4034
4711
|
console.info(
|
|
@@ -4044,11 +4721,11 @@ function registerGlasstrace(options) {
|
|
|
4044
4721
|
`[glasstrace] Cached config ${cachedInitResponse ? "loaded and applied" : "not found"}.`
|
|
4045
4722
|
);
|
|
4046
4723
|
}
|
|
4047
|
-
const sessionManager =
|
|
4724
|
+
const sessionManager = getSessionManager();
|
|
4048
4725
|
if (config.verbose) {
|
|
4049
4726
|
console.info("[glasstrace] SessionManager created.");
|
|
4050
4727
|
}
|
|
4051
|
-
|
|
4728
|
+
setCoreState(CoreState.KEY_PENDING);
|
|
4052
4729
|
const currentGeneration = registrationGeneration;
|
|
4053
4730
|
const existingProbe = trace.getTracerProvider().getTracer("glasstrace-probe");
|
|
4054
4731
|
const anotherProviderRegistered = existingProbe.constructor.name !== "ProxyTracer";
|
|
@@ -4101,6 +4778,7 @@ function registerGlasstrace(options) {
|
|
|
4101
4778
|
resolvedAnonKey = anonKey;
|
|
4102
4779
|
setResolvedApiKey(anonKey);
|
|
4103
4780
|
notifyApiKeyResolved();
|
|
4781
|
+
emitLifecycleEvent("auth:key_resolved", { key: maskKey(anonKey), mode: "anonymous" });
|
|
4104
4782
|
effectiveKey = anonKey;
|
|
4105
4783
|
if (currentGeneration !== registrationGeneration) return;
|
|
4106
4784
|
discoveryHandler = createDiscoveryHandler(
|
|
@@ -4122,6 +4800,7 @@ function registerGlasstrace(options) {
|
|
|
4122
4800
|
const anonKey = await getOrCreateAnonKey();
|
|
4123
4801
|
setResolvedApiKey(anonKey);
|
|
4124
4802
|
notifyApiKeyResolved();
|
|
4803
|
+
emitLifecycleEvent("auth:key_resolved", { key: maskKey(anonKey), mode: "anonymous" });
|
|
4125
4804
|
effectiveKey = anonKey;
|
|
4126
4805
|
if (currentGeneration !== registrationGeneration) return;
|
|
4127
4806
|
await backgroundInit(config, anonKey, currentGeneration);
|
|
@@ -4154,6 +4833,7 @@ function registerGlasstrace(options) {
|
|
|
4154
4833
|
console.info("[glasstrace] Import graph building skipped.");
|
|
4155
4834
|
}
|
|
4156
4835
|
} catch (err) {
|
|
4836
|
+
setCoreState(CoreState.REGISTRATION_FAILED);
|
|
4157
4837
|
console.warn(
|
|
4158
4838
|
`[glasstrace] Registration failed: ${err instanceof Error ? err.message : String(err)}`
|
|
4159
4839
|
);
|
|
@@ -4163,18 +4843,37 @@ async function backgroundInit(config, anonKeyForInit, generation) {
|
|
|
4163
4843
|
if (config.verbose) {
|
|
4164
4844
|
console.info("[glasstrace] Background init firing.");
|
|
4165
4845
|
}
|
|
4166
|
-
const healthReport = collectHealthReport("0.
|
|
4167
|
-
const initResult = await performInit(config, anonKeyForInit, "0.
|
|
4846
|
+
const healthReport = collectHealthReport("0.14.1");
|
|
4847
|
+
const initResult = await performInit(config, anonKeyForInit, "0.14.1", healthReport);
|
|
4168
4848
|
if (generation !== registrationGeneration) return;
|
|
4849
|
+
const currentState = getCoreState();
|
|
4850
|
+
if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
|
|
4851
|
+
return;
|
|
4852
|
+
}
|
|
4853
|
+
if (currentState === CoreState.KEY_PENDING) {
|
|
4854
|
+
setCoreState(CoreState.KEY_RESOLVED);
|
|
4855
|
+
}
|
|
4856
|
+
if (getCoreState() === CoreState.KEY_RESOLVED) {
|
|
4857
|
+
setCoreState(didLastInitSucceed() ? CoreState.ACTIVE : CoreState.ACTIVE_DEGRADED);
|
|
4858
|
+
}
|
|
4169
4859
|
if (initResult?.claimResult) {
|
|
4170
|
-
|
|
4860
|
+
const { newApiKey, accountId } = initResult.claimResult;
|
|
4861
|
+
setAuthState(AuthState.CLAIMING);
|
|
4862
|
+
emitLifecycleEvent("auth:claim_started", { accountId });
|
|
4863
|
+
setResolvedApiKey(newApiKey);
|
|
4171
4864
|
notifyApiKeyResolved();
|
|
4865
|
+
setAuthState(AuthState.CLAIMED);
|
|
4866
|
+
emitLifecycleEvent("auth:claim_completed", { newKey: maskKey(newApiKey), accountId });
|
|
4172
4867
|
}
|
|
4173
4868
|
maybeInstallConsoleCapture();
|
|
4174
4869
|
if (didLastInitSucceed()) {
|
|
4175
|
-
startHeartbeat(config, anonKeyForInit, "0.
|
|
4870
|
+
startHeartbeat(config, anonKeyForInit, "0.14.1", generation, (newApiKey, accountId) => {
|
|
4871
|
+
setAuthState(AuthState.CLAIMING);
|
|
4872
|
+
emitLifecycleEvent("auth:claim_started", { accountId });
|
|
4176
4873
|
setResolvedApiKey(newApiKey);
|
|
4177
4874
|
notifyApiKeyResolved();
|
|
4875
|
+
setAuthState(AuthState.CLAIMED);
|
|
4876
|
+
emitLifecycleEvent("auth:claim_completed", { newKey: maskKey(newApiKey), accountId });
|
|
4178
4877
|
});
|
|
4179
4878
|
}
|
|
4180
4879
|
}
|
|
@@ -4245,7 +4944,7 @@ async function handleSourceMapUpload(distDir) {
|
|
|
4245
4944
|
);
|
|
4246
4945
|
return;
|
|
4247
4946
|
}
|
|
4248
|
-
const { discoverSourceMapFiles: discoverSourceMapFiles2, computeBuildHash: computeBuildHash2, uploadSourceMaps: uploadSourceMaps2 } = await import("./source-map-uploader-
|
|
4947
|
+
const { discoverSourceMapFiles: discoverSourceMapFiles2, computeBuildHash: computeBuildHash2, uploadSourceMaps: uploadSourceMaps2 } = await import("./source-map-uploader-W6VPGY26.js");
|
|
4249
4948
|
const files = await discoverSourceMapFiles2(distDir);
|
|
4250
4949
|
if (files.length === 0) {
|
|
4251
4950
|
console.info("[glasstrace] No source map files found. Skipping upload.");
|
|
@@ -4296,6 +4995,7 @@ export {
|
|
|
4296
4995
|
collectSourceMaps,
|
|
4297
4996
|
computeBuildHash,
|
|
4298
4997
|
createDiscoveryHandler,
|
|
4998
|
+
createGlasstraceSpanProcessor,
|
|
4299
4999
|
deriveSessionId,
|
|
4300
5000
|
discoverSourceMapFiles,
|
|
4301
5001
|
discoverTestFiles,
|
|
@@ -4306,8 +5006,10 @@ export {
|
|
|
4306
5006
|
getLinkedAccountId,
|
|
4307
5007
|
getOrCreateAnonKey,
|
|
4308
5008
|
getOrigin,
|
|
5009
|
+
getStatus,
|
|
4309
5010
|
isAnonymousMode,
|
|
4310
5011
|
isProductionDisabled,
|
|
5012
|
+
isReady,
|
|
4311
5013
|
loadCachedConfig,
|
|
4312
5014
|
performInit,
|
|
4313
5015
|
readAnonKey,
|
|
@@ -4319,6 +5021,7 @@ export {
|
|
|
4319
5021
|
uploadSourceMaps,
|
|
4320
5022
|
uploadSourceMapsAuto,
|
|
4321
5023
|
uploadSourceMapsPresigned,
|
|
5024
|
+
waitForReady,
|
|
4322
5025
|
withGlasstraceConfig
|
|
4323
5026
|
};
|
|
4324
5027
|
//# sourceMappingURL=index.js.map
|