@glasstrace/sdk 0.13.4 → 0.13.6

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/index.d.cts CHANGED
@@ -361,7 +361,7 @@ interface GlasstraceExporterOptions {
361
361
  environment: string | undefined;
362
362
  endpointUrl: string;
363
363
  createDelegate: ((url: string, headers: Record<string, string>) => SpanExporter) | null;
364
- /** @deprecated No-op retained for backward compatibility. Will be removed in a future major. */
364
+ /** When true, logs diagnostic details about enrichment decisions via sdkLog. */
365
365
  verbose?: boolean;
366
366
  }
367
367
  /**
@@ -383,6 +383,7 @@ declare class GlasstraceExporter implements SpanExporter {
383
383
  private readonly environment;
384
384
  private readonly endpointUrl;
385
385
  private readonly createDelegateFn;
386
+ private readonly verbose;
386
387
  private delegate;
387
388
  private delegateKey;
388
389
  private pendingBatches;
package/dist/index.d.ts CHANGED
@@ -361,7 +361,7 @@ interface GlasstraceExporterOptions {
361
361
  environment: string | undefined;
362
362
  endpointUrl: string;
363
363
  createDelegate: ((url: string, headers: Record<string, string>) => SpanExporter) | null;
364
- /** @deprecated No-op retained for backward compatibility. Will be removed in a future major. */
364
+ /** When true, logs diagnostic details about enrichment decisions via sdkLog. */
365
365
  verbose?: boolean;
366
366
  }
367
367
  /**
@@ -383,6 +383,7 @@ declare class GlasstraceExporter implements SpanExporter {
383
383
  private readonly environment;
384
384
  private readonly endpointUrl;
385
385
  private readonly createDelegateFn;
386
+ private readonly verbose;
386
387
  private delegate;
387
388
  private delegateKey;
388
389
  private pendingBatches;
package/dist/index.js CHANGED
@@ -591,6 +591,7 @@ var GlasstraceExporter = class {
591
591
  environment;
592
592
  endpointUrl;
593
593
  createDelegateFn;
594
+ verbose;
594
595
  delegate = null;
595
596
  delegateKey = null;
596
597
  pendingBatches = [];
@@ -603,6 +604,7 @@ var GlasstraceExporter = class {
603
604
  this.environment = options.environment;
604
605
  this.endpointUrl = options.endpointUrl;
605
606
  this.createDelegateFn = options.createDelegate;
607
+ this.verbose = options.verbose ?? false;
606
608
  }
607
609
  export(spans, resultCallback) {
608
610
  const currentKey = this.getApiKey();
@@ -708,7 +710,17 @@ var GlasstraceExporter = class {
708
710
  if (statusCode !== void 0) {
709
711
  extra[ATTR.HTTP_STATUS_CODE] = statusCode;
710
712
  }
711
- if (method && span.status?.code === SpanStatusCode.ERROR) {
713
+ const isErrorByStatus = span.status?.code === SpanStatusCode.ERROR;
714
+ const isErrorByEvent = hasExceptionEvent(span);
715
+ const isErrorByAttrs = typeof attrs["exception.type"] === "string" || typeof attrs["exception.message"] === "string";
716
+ const statusNotExplicitlyOK = span.status?.code !== SpanStatusCode.OK;
717
+ if (this.verbose && method) {
718
+ sdkLog(
719
+ "info",
720
+ `[glasstrace] enrichSpan "${name}": status.code=${span.status?.code}, http.status_code=${statusCode}, isErrorByStatus=${isErrorByStatus}, isErrorByEvent=${isErrorByEvent}, isErrorByAttrs=${isErrorByAttrs}`
721
+ );
722
+ }
723
+ if (method && statusNotExplicitlyOK && (isErrorByStatus || isErrorByEvent || isErrorByAttrs)) {
712
724
  if (statusCode === void 0 || statusCode === 0 || statusCode === 200) {
713
725
  const httpErrorType = attrs["error.type"];
714
726
  if (typeof httpErrorType === "string") {
@@ -721,6 +733,12 @@ var GlasstraceExporter = class {
721
733
  } else {
722
734
  extra[ATTR.HTTP_STATUS_CODE] = 500;
723
735
  }
736
+ if (this.verbose) {
737
+ sdkLog(
738
+ "info",
739
+ `[glasstrace] enrichSpan "${name}": inferred status_code=${extra[ATTR.HTTP_STATUS_CODE]} (was ${statusCode}), error.type=${attrs["error.type"]}`
740
+ );
741
+ }
724
742
  }
725
743
  }
726
744
  if (span.startTime && span.endTime) {
@@ -731,14 +749,28 @@ var GlasstraceExporter = class {
731
749
  extra[ATTR.HTTP_DURATION_MS] = durationMs;
732
750
  }
733
751
  }
752
+ const eventDetails = statusNotExplicitlyOK ? getExceptionEventDetails(span) : { type: void 0, message: void 0 };
734
753
  const errorMessage = attrs["exception.message"];
735
754
  if (typeof errorMessage === "string") {
736
755
  extra[ATTR.ERROR_MESSAGE] = errorMessage;
756
+ } else if (eventDetails.message) {
757
+ extra[ATTR.ERROR_MESSAGE] = eventDetails.message;
737
758
  }
738
759
  const errorType = attrs["exception.type"];
739
760
  if (typeof errorType === "string") {
740
761
  extra[ATTR.ERROR_CODE] = errorType;
741
762
  extra[ATTR.ERROR_CATEGORY] = deriveErrorCategory(errorType);
763
+ } else if (eventDetails.type) {
764
+ extra[ATTR.ERROR_CODE] = eventDetails.type;
765
+ extra[ATTR.ERROR_CATEGORY] = deriveErrorCategory(eventDetails.type);
766
+ }
767
+ if (this.verbose && (extra[ATTR.ERROR_MESSAGE] || extra[ATTR.ERROR_CODE])) {
768
+ const msgSource = typeof errorMessage === "string" ? "attrs" : eventDetails.message ? "event" : "none";
769
+ const typeSource = typeof errorType === "string" ? "attrs" : eventDetails.type ? "event" : "none";
770
+ sdkLog(
771
+ "info",
772
+ `[glasstrace] enrichSpan "${name}": error.message source=${msgSource}, error.code source=${typeSource}`
773
+ );
742
774
  }
743
775
  const errorField = attrs["error.field"];
744
776
  if (typeof errorField === "string") {
@@ -861,6 +893,21 @@ function createEnrichedSpan(span, extra) {
861
893
  }
862
894
  });
863
895
  }
896
+ function hasExceptionEvent(span) {
897
+ return span.events?.some((e) => e.name === "exception") ?? false;
898
+ }
899
+ function getExceptionEventDetails(span) {
900
+ const event = span.events?.find((e) => e.name === "exception");
901
+ if (!event?.attributes) {
902
+ return { type: void 0, message: void 0 };
903
+ }
904
+ const type = event.attributes["exception.type"];
905
+ const message = event.attributes["exception.message"];
906
+ return {
907
+ type: typeof type === "string" ? type : void 0,
908
+ message: typeof message === "string" ? message : void 0
909
+ };
910
+ }
864
911
  function deriveOrmProvider(instrumentationName) {
865
912
  const lower = instrumentationName.toLowerCase();
866
913
  if (lower.includes("prisma")) {
@@ -3763,7 +3810,8 @@ async function configureOtel(config, sessionManager) {
3763
3810
  getConfig: () => getActiveConfig(),
3764
3811
  environment: config.environment,
3765
3812
  endpointUrl: exporterUrl,
3766
- createDelegate: createOtlpExporter
3813
+ createDelegate: createOtlpExporter,
3814
+ verbose: config.verbose
3767
3815
  });
3768
3816
  _activeExporter = glasstraceExporter;
3769
3817
  const vercelOtel = await tryImport("@vercel/otel");
@@ -3815,24 +3863,10 @@ async function configureOtel(config, sessionManager) {
3815
3863
 
3816
3864
  // src/context-manager.ts
3817
3865
  init_esm_shims();
3818
- var AsyncLocalStorageCtor = null;
3819
- try {
3820
- const importFn = Function("id", "return import(id)");
3821
- importFn("node:async_hooks").then(
3822
- (mod) => {
3823
- AsyncLocalStorageCtor = mod.AsyncLocalStorage;
3824
- },
3825
- () => {
3826
- }
3827
- );
3828
- } catch {
3829
- }
3866
+ import { AsyncLocalStorage } from "async_hooks";
3830
3867
  function installContextManager() {
3831
- if (!AsyncLocalStorageCtor) {
3832
- return false;
3833
- }
3834
3868
  try {
3835
- const als = new AsyncLocalStorageCtor();
3869
+ const als = new AsyncLocalStorage();
3836
3870
  const contextManager = {
3837
3871
  active: () => als.getStore() ?? ROOT_CONTEXT,
3838
3872
  with: (context2, fn, thisArg, ...args) => als.run(context2, () => fn.apply(thisArg, args)),
@@ -4129,8 +4163,8 @@ async function backgroundInit(config, anonKeyForInit, generation) {
4129
4163
  if (config.verbose) {
4130
4164
  console.info("[glasstrace] Background init firing.");
4131
4165
  }
4132
- const healthReport = collectHealthReport("0.13.4");
4133
- const initResult = await performInit(config, anonKeyForInit, "0.13.4", healthReport);
4166
+ const healthReport = collectHealthReport("0.13.6");
4167
+ const initResult = await performInit(config, anonKeyForInit, "0.13.6", healthReport);
4134
4168
  if (generation !== registrationGeneration) return;
4135
4169
  if (initResult?.claimResult) {
4136
4170
  setResolvedApiKey(initResult.claimResult.newApiKey);
@@ -4138,7 +4172,7 @@ async function backgroundInit(config, anonKeyForInit, generation) {
4138
4172
  }
4139
4173
  maybeInstallConsoleCapture();
4140
4174
  if (didLastInitSucceed()) {
4141
- startHeartbeat(config, anonKeyForInit, "0.13.4", generation, (newApiKey) => {
4175
+ startHeartbeat(config, anonKeyForInit, "0.13.6", generation, (newApiKey) => {
4142
4176
  setResolvedApiKey(newApiKey);
4143
4177
  notifyApiKeyResolved();
4144
4178
  });