netra-sdk 1.3.0 → 1.4.0

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.js CHANGED
@@ -4,8 +4,8 @@ import { createRequire } from 'module';
4
4
  import { AsyncLocalStorage } from 'async_hooks';
5
5
  import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
6
6
  import { initialize } from '@traceloop/node-server-sdk';
7
- import * as dotenv from 'dotenv';
8
7
  import shimmer from 'shimmer';
8
+ import * as dotenv from 'dotenv';
9
9
  import { CompositePropagator, W3CTraceContextPropagator, W3CBaggagePropagator, ExportResultCode } from '@opentelemetry/core';
10
10
  import * as http from 'http';
11
11
  import * as https from 'https';
@@ -22,6 +22,9 @@ var Logger = class {
22
22
  static get isDebug() {
23
23
  return this._debugMode || ["1", "true"].includes((process.env.NETRA_DEBUG ?? "").toLowerCase());
24
24
  }
25
+ static isDebugMode() {
26
+ return this.isDebug;
27
+ }
25
28
  static debug(...args) {
26
29
  if (this.isDebug) console.debug(PREFIX, ...args);
27
30
  }
@@ -575,6 +578,9 @@ var Usage = class {
575
578
  }
576
579
  };
577
580
 
581
+ // src/version.ts
582
+ var SDK_VERSION = "1.4.0";
583
+
578
584
  // src/config.ts
579
585
  var NetraInstruments = /* @__PURE__ */ ((NetraInstruments2) => {
580
586
  NetraInstruments2["ALL"] = "__all__";
@@ -773,11 +779,34 @@ var Config = class {
773
779
  const headerStr = Object.entries(this.headers).map(([k, v]) => `${k}=${v}`).join(",");
774
780
  process.env.TRACELOOP_HEADERS = headerStr;
775
781
  }
782
+ this._setResourceAttributesEnv();
783
+ }
784
+ _setResourceAttributesEnv() {
785
+ const attrs = {
786
+ "deployment.environment": this.environment,
787
+ "service.name": this.appName
788
+ };
789
+ for (const [k, v] of Object.entries(this.resourceAttributes)) {
790
+ attrs[k] = String(v);
791
+ }
792
+ const existing = process.env.OTEL_RESOURCE_ATTRIBUTES;
793
+ if (existing) {
794
+ for (const pair of existing.split(",")) {
795
+ const eqIdx = pair.indexOf("=");
796
+ if (eqIdx <= 0) continue;
797
+ const key = decodeURIComponent(pair.slice(0, eqIdx).trim());
798
+ if (key) {
799
+ attrs[key] = decodeURIComponent(pair.slice(eqIdx + 1).trim());
800
+ }
801
+ }
802
+ }
803
+ const encodeAttrValue = (s) => encodeURIComponent(s);
804
+ process.env.OTEL_RESOURCE_ATTRIBUTES = Object.entries(attrs).map(([k, v]) => `${encodeAttrValue(k)}=${encodeAttrValue(v)}`).join(",");
776
805
  }
777
806
  };
778
807
  Config.SDK_NAME = "netra";
779
808
  Config.LIBRARY_NAME = "netra";
780
- Config.LIBRARY_VERSION = "1.0.0";
809
+ Config.LIBRARY_VERSION = SDK_VERSION;
781
810
  Config.TRIAL_BLOCK_DURATION_SECONDS = 900;
782
811
  // 15 minutes
783
812
  Config.ATTRIBUTE_MAX_LEN = parseInt(
@@ -786,6 +815,9 @@ Config.ATTRIBUTE_MAX_LEN = parseInt(
786
815
  Config.CONVERSATION_MAX_LEN = parseInt(
787
816
  process.env.NETRA_CONVERSATION_CONTENT_MAX_LEN || "50000"
788
817
  );
818
+ Config.SPAN_ATTRIBUTE_MAX_SIZE = parseInt(
819
+ process.env.NETRA_SPAN_ATTRIBUTE_MAX_SIZE || "30000"
820
+ );
789
821
 
790
822
  // src/utils/pattern-matching.ts
791
823
  function compilePatterns(patterns) {
@@ -1047,6 +1079,57 @@ var ConversationType = /* @__PURE__ */ ((ConversationType3) => {
1047
1079
  return ConversationType3;
1048
1080
  })(ConversationType || {});
1049
1081
 
1082
+ // src/utils/serialization.ts
1083
+ var ELLIPSIS = "...";
1084
+ function truncate(s, maxLength) {
1085
+ if (s.length <= maxLength) return s;
1086
+ if (maxLength <= ELLIPSIS.length) return s.slice(0, maxLength);
1087
+ return s.slice(0, maxLength - ELLIPSIS.length) + ELLIPSIS;
1088
+ }
1089
+ function safeStringify(value, maxLength) {
1090
+ if (typeof value === "string") {
1091
+ if (maxLength && value.length > maxLength) {
1092
+ return truncate(value, maxLength);
1093
+ }
1094
+ return value;
1095
+ }
1096
+ const seen = /* @__PURE__ */ new WeakSet();
1097
+ let result;
1098
+ try {
1099
+ result = JSON.stringify(value, (_key, val) => {
1100
+ if (typeof val === "function")
1101
+ return `[Function: ${val.name || "anonymous"}]`;
1102
+ if (typeof val === "symbol") return val.toString();
1103
+ if (typeof val === "bigint") return val.toString();
1104
+ if (val !== null && typeof val === "object") {
1105
+ if (seen.has(val)) return "[Circular]";
1106
+ seen.add(val);
1107
+ const name = val.constructor?.name;
1108
+ if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
1109
+ return `[${name}]`;
1110
+ }
1111
+ }
1112
+ return val;
1113
+ }) ?? String(value);
1114
+ } catch {
1115
+ result = value?.constructor?.name ? `[${value.constructor.name}]` : String(value);
1116
+ }
1117
+ if (maxLength && result.length > maxLength) {
1118
+ return truncate(result, maxLength);
1119
+ }
1120
+ return result;
1121
+ }
1122
+ function serializeValue(value, maxLength) {
1123
+ if (value === null || value === void 0) return String(value);
1124
+ const t = typeof value;
1125
+ if (t === "string" || t === "number" || t === "boolean") {
1126
+ const s = String(value);
1127
+ if (maxLength && s.length > maxLength) return truncate(s, maxLength);
1128
+ return s;
1129
+ }
1130
+ return safeStringify(value, maxLength);
1131
+ }
1132
+
1050
1133
  // src/session-manager.ts
1051
1134
  var MODULE_NAME = "netra.session-manager";
1052
1135
  var entityStorage = new AsyncLocalStorage();
@@ -1060,12 +1143,6 @@ var globalFallbackContext = {
1060
1143
  function getEntityContext() {
1061
1144
  return entityStorage.getStore() ?? globalFallbackContext;
1062
1145
  }
1063
- function serializeValue(value) {
1064
- if (typeof value === "string") {
1065
- return value.substring(0, Config.ATTRIBUTE_MAX_LEN);
1066
- }
1067
- return JSON.stringify(value).substring(0, Config.ATTRIBUTE_MAX_LEN);
1068
- }
1069
1146
  var SessionManager = class _SessionManager {
1070
1147
  // Span registry (name → stack)
1071
1148
  static registerSpan(name, span2) {
@@ -1180,7 +1257,10 @@ var SessionManager = class _SessionManager {
1180
1257
  */
1181
1258
  static setInput(value) {
1182
1259
  try {
1183
- _SessionManager.setAttributeOnActiveSpan("netra.user.input", serializeValue(value));
1260
+ _SessionManager.setAttributeOnActiveSpan(
1261
+ "netra.user.input",
1262
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1263
+ );
1184
1264
  } catch (e) {
1185
1265
  Logger.error("setInput failed:", e);
1186
1266
  }
@@ -1192,7 +1272,10 @@ var SessionManager = class _SessionManager {
1192
1272
  */
1193
1273
  static setOutput(value) {
1194
1274
  try {
1195
- _SessionManager.setAttributeOnActiveSpan("netra.user.output", serializeValue(value));
1275
+ _SessionManager.setAttributeOnActiveSpan(
1276
+ "netra.user.output",
1277
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1278
+ );
1196
1279
  } catch (e) {
1197
1280
  Logger.error("setOutput failed:", e);
1198
1281
  }
@@ -1204,7 +1287,10 @@ var SessionManager = class _SessionManager {
1204
1287
  */
1205
1288
  static setRootInput(value) {
1206
1289
  try {
1207
- RootSpanProcessor.setAttributeOnRootSpan("netra.user.input", serializeValue(value));
1290
+ RootSpanProcessor.setAttributeOnRootSpan(
1291
+ "netra.user.input",
1292
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1293
+ );
1208
1294
  } catch (e) {
1209
1295
  Logger.error("setRootInput failed:", e);
1210
1296
  }
@@ -1216,7 +1302,10 @@ var SessionManager = class _SessionManager {
1216
1302
  */
1217
1303
  static setRootOutput(value) {
1218
1304
  try {
1219
- RootSpanProcessor.setAttributeOnRootSpan("netra.user.output", serializeValue(value));
1305
+ RootSpanProcessor.setAttributeOnRootSpan(
1306
+ "netra.user.output",
1307
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1308
+ );
1220
1309
  } catch (e) {
1221
1310
  Logger.error("setRootOutput failed:", e);
1222
1311
  }
@@ -2783,6 +2872,58 @@ var Prompts = class {
2783
2872
  }
2784
2873
  };
2785
2874
 
2875
+ // src/processors/attribute-size-limit-processor.ts
2876
+ var DEFAULT_MAX_ATTRIBUTE_SIZE = 32e3;
2877
+ var AttributeSizeLimitProcessor = class {
2878
+ constructor(maxAttributeSize) {
2879
+ this.maxAttributeSize = maxAttributeSize ?? DEFAULT_MAX_ATTRIBUTE_SIZE;
2880
+ }
2881
+ onStart(span2, _parentContext) {
2882
+ try {
2883
+ this._wrapSetAttribute(span2);
2884
+ } catch (e) {
2885
+ Logger.debug("AttributeSizeLimitProcessor.onStart error:", e);
2886
+ }
2887
+ }
2888
+ onEnd(_span) {
2889
+ }
2890
+ shutdown() {
2891
+ return Promise.resolve();
2892
+ }
2893
+ forceFlush() {
2894
+ return Promise.resolve();
2895
+ }
2896
+ _wrapSetAttribute(span2) {
2897
+ const original = span2.setAttribute.bind(span2);
2898
+ const maxLen = this.maxAttributeSize;
2899
+ const patched = (key, value) => {
2900
+ try {
2901
+ return original(key, truncateValue(value, maxLen));
2902
+ } catch {
2903
+ try {
2904
+ return original(key, value);
2905
+ } catch {
2906
+ return span2;
2907
+ }
2908
+ }
2909
+ };
2910
+ span2.setAttribute = patched;
2911
+ }
2912
+ };
2913
+ function truncateValue(value, maxLen) {
2914
+ if (typeof value === "string") {
2915
+ return value.length > maxLen ? value.substring(0, maxLen) : value;
2916
+ }
2917
+ if (Array.isArray(value)) {
2918
+ const serialized = JSON.stringify(value);
2919
+ if (serialized.length > maxLen) {
2920
+ return serialized.substring(0, maxLen);
2921
+ }
2922
+ return value;
2923
+ }
2924
+ return value;
2925
+ }
2926
+
2786
2927
  // src/processors/instrumentation-span-processor.ts
2787
2928
  var ALLOWED_INSTRUMENTATION_NAMES = /* @__PURE__ */ new Set([
2788
2929
  "openai",
@@ -3188,6 +3329,9 @@ function setSessionBaggage(key, value) {
3188
3329
  }
3189
3330
  }
3190
3331
  var SessionSpanProcessor = class {
3332
+ constructor(environment = "local") {
3333
+ this.environment = environment;
3334
+ }
3191
3335
  /**
3192
3336
  * Called when a span starts. Adds session and entity context attributes.
3193
3337
  */
@@ -3196,6 +3340,7 @@ var SessionSpanProcessor = class {
3196
3340
  span2.setAttribute("library.name", Config.LIBRARY_NAME);
3197
3341
  span2.setAttribute("library.version", Config.LIBRARY_VERSION);
3198
3342
  span2.setAttribute("sdk.name", Config.SDK_NAME);
3343
+ span2.setAttribute("deployment.environment", this.environment);
3199
3344
  const ctxToUse = parentContext || context.active();
3200
3345
  const baggage = propagation.getBaggage(ctxToUse);
3201
3346
  const sessionId = baggage?.getEntry("session_id")?.value ?? sessionValues.get("session_id");
@@ -3602,6 +3747,184 @@ var SpanIOProcessor = class {
3602
3747
  }
3603
3748
  };
3604
3749
 
3750
+ // src/instrumentation/anthropic/version.ts
3751
+ var __version__ = "1.0.0";
3752
+
3753
+ // src/utils/response-handler.ts
3754
+ function isAsyncIterable(value) {
3755
+ return value != null && typeof value[Symbol.asyncIterator] === "function";
3756
+ }
3757
+ function isPromise(value) {
3758
+ return value != null && typeof value.then === "function";
3759
+ }
3760
+ var ITERATOR_METHODS = /* @__PURE__ */ new Set(["next", "return", "throw"]);
3761
+ function wrapAsyncIterable(source, callbacks) {
3762
+ function createWrappedIterator() {
3763
+ const iterator = source[Symbol.asyncIterator]();
3764
+ let done = false;
3765
+ const safeFinalize = (status) => {
3766
+ if (done) return;
3767
+ done = true;
3768
+ try {
3769
+ callbacks.finalize(status);
3770
+ } catch (e) {
3771
+ Logger.error("netra: finalize callback error", e);
3772
+ }
3773
+ };
3774
+ return {
3775
+ async next(value) {
3776
+ try {
3777
+ const result = await callbacks.withContext(() => iterator.next(value));
3778
+ if (!result.done) {
3779
+ try {
3780
+ callbacks.onChunk?.(result.value);
3781
+ } catch (e) {
3782
+ Logger.error("netra: onChunk callback error", e);
3783
+ }
3784
+ } else {
3785
+ safeFinalize("ok");
3786
+ }
3787
+ return result;
3788
+ } catch (e) {
3789
+ try {
3790
+ callbacks.onError(e);
3791
+ } catch {
3792
+ Logger.error("netra: onError callback error", e);
3793
+ }
3794
+ safeFinalize("error");
3795
+ throw e;
3796
+ }
3797
+ },
3798
+ async return(value) {
3799
+ try {
3800
+ const result = await callbacks.withContext(
3801
+ () => iterator.return?.(value) ?? { done: true, value }
3802
+ );
3803
+ safeFinalize("ok");
3804
+ return result;
3805
+ } catch (e) {
3806
+ try {
3807
+ callbacks.onError(e);
3808
+ } catch {
3809
+ Logger.error("netra: onError callback error", e);
3810
+ }
3811
+ safeFinalize("error");
3812
+ throw e;
3813
+ }
3814
+ },
3815
+ async throw(e) {
3816
+ try {
3817
+ const result = await callbacks.withContext(() => {
3818
+ if (iterator.throw) return iterator.throw(e);
3819
+ throw e;
3820
+ });
3821
+ if (result.done) safeFinalize("ok");
3822
+ return result;
3823
+ } catch (err) {
3824
+ try {
3825
+ callbacks.onError(err);
3826
+ } catch {
3827
+ Logger.error("netra: onError callback error", err);
3828
+ }
3829
+ safeFinalize("error");
3830
+ throw err;
3831
+ }
3832
+ }
3833
+ };
3834
+ }
3835
+ let directIterator = null;
3836
+ return new Proxy(source, {
3837
+ get(target, prop) {
3838
+ if (prop === Symbol.asyncIterator) {
3839
+ return () => createWrappedIterator();
3840
+ }
3841
+ if (typeof prop === "string" && ITERATOR_METHODS.has(prop)) {
3842
+ if (!directIterator) directIterator = createWrappedIterator();
3843
+ return directIterator[prop].bind(directIterator);
3844
+ }
3845
+ const value = target[prop];
3846
+ if (typeof value === "function") return value.bind(target);
3847
+ return value;
3848
+ }
3849
+ });
3850
+ }
3851
+ function wrapPromise(promise, callbacks, options) {
3852
+ let finalized = false;
3853
+ function safeFinalize(status) {
3854
+ if (finalized) return;
3855
+ finalized = true;
3856
+ try {
3857
+ callbacks.finalize(status);
3858
+ } catch (e) {
3859
+ Logger.error("netra: finalize callback error", e);
3860
+ }
3861
+ }
3862
+ const instrumentedPromise = (async () => {
3863
+ try {
3864
+ const value = await promise;
3865
+ if (isAsyncIterable(value)) {
3866
+ return wrapAsyncIterable(value, callbacks);
3867
+ }
3868
+ try {
3869
+ callbacks.onSuccess?.(value);
3870
+ } catch (e) {
3871
+ Logger.error("netra: onSuccess callback error", e);
3872
+ }
3873
+ safeFinalize("ok");
3874
+ return value;
3875
+ } catch (error) {
3876
+ try {
3877
+ callbacks.onError(error);
3878
+ } catch {
3879
+ Logger.error("netra: onError callback error", error);
3880
+ }
3881
+ safeFinalize("error");
3882
+ throw error;
3883
+ }
3884
+ })();
3885
+ if (!options?.preserveOriginal) {
3886
+ return instrumentedPromise;
3887
+ }
3888
+ const original = options.preserveOriginal;
3889
+ return new Proxy(instrumentedPromise, {
3890
+ get(target, prop, receiver) {
3891
+ if (prop === "then" || prop === "catch" || prop === "finally") {
3892
+ const value2 = Reflect.get(target, prop, receiver);
3893
+ if (typeof value2 === "function") return value2.bind(target);
3894
+ return value2;
3895
+ }
3896
+ const originalValue = original[prop];
3897
+ if (originalValue !== void 0) {
3898
+ if (typeof originalValue === "function")
3899
+ return originalValue.bind(original);
3900
+ return originalValue;
3901
+ }
3902
+ const value = Reflect.get(target, prop, receiver);
3903
+ if (typeof value === "function") return value.bind(target);
3904
+ return value;
3905
+ }
3906
+ });
3907
+ }
3908
+ function wrapResponse(response, callbacks, options) {
3909
+ if (isAsyncIterable(response)) {
3910
+ return wrapAsyncIterable(response, callbacks);
3911
+ }
3912
+ if (isPromise(response)) {
3913
+ return wrapPromise(response, callbacks, options);
3914
+ }
3915
+ try {
3916
+ callbacks.onSuccess?.(response);
3917
+ } catch (e) {
3918
+ Logger.error("netra: onSuccess callback error", e);
3919
+ }
3920
+ try {
3921
+ callbacks.finalize("ok");
3922
+ } catch (e) {
3923
+ Logger.error("netra: finalize callback error", e);
3924
+ }
3925
+ return response;
3926
+ }
3927
+
3605
3928
  // src/instrumentation/span-attributes.ts
3606
3929
  var SpanAttributes2 = {
3607
3930
  LLM_SYSTEM: "gen_ai.system",
@@ -3612,10 +3935,14 @@ var SpanAttributes2 = {
3612
3935
  LLM_REQUEST_TOP_P: "gen_ai.request.top_p",
3613
3936
  LLM_REQUEST_REASONING: "gen_ai.request.reasoning",
3614
3937
  LLM_REQUEST_REASONING_EFFORT: "gen_ai.request.reasoning_effort",
3938
+ LLM_REQUEST_TOOL_NAME: "gen_ai.request.tool.name",
3939
+ LLM_REQUEST_TOOL_ID: "gen_ai.request.tool.id",
3615
3940
  LLM_RESPONSE_MODEL: "gen_ai.response.model",
3941
+ LLM_RESPONSE_FINISH_REASON: "llm.response.finish_reason",
3616
3942
  LLM_USAGE_PROMPT_TOKENS: "gen_ai.usage.prompt_tokens",
3617
3943
  LLM_USAGE_COMPLETION_TOKENS: "gen_ai.usage.completion_tokens",
3618
3944
  LLM_USAGE_CACHE_READ_INPUT_TOKENS: "gen_ai.usage.cache_read_input_tokens",
3945
+ LLM_USAGE_CACHE_CREATION_INPUT_TOKENS: "gen_ai.usage.cache_creation_input_tokens",
3619
3946
  LLM_USAGE_REASONING_TOKENS: "gen_ai.usage.reasoning_tokens",
3620
3947
  LLM_USAGE_TOTAL_TOKENS: "llm.usage.total_tokens",
3621
3948
  LLM_FREQUENCY_PENALTY: "llm.frequency_penalty",
@@ -3625,8 +3952,6 @@ var SpanAttributes2 = {
3625
3952
  LLM_COMPLETIONS: "gen_ai.completion",
3626
3953
  LLM_PROMPTS: "gen_ai.prompt"
3627
3954
  };
3628
-
3629
- // src/instrumentation/utils.ts
3630
3955
  var VALID_NATIVE_TRACING_MODES = /* @__PURE__ */ new Set(["both", "netra", "netra-strict"]);
3631
3956
  function parseNativeTracingEnv(name) {
3632
3957
  const val = process.env[name];
@@ -3639,9 +3964,6 @@ function shouldSuppressInstrumentation() {
3639
3964
  const ctx = context.active();
3640
3965
  return ctx.getValue(SUPPRESS_INSTRUMENTATION_KEY) === true;
3641
3966
  }
3642
- function isPromise(value) {
3643
- return value instanceof Promise;
3644
- }
3645
3967
  function defineHidden(target, key, value) {
3646
3968
  Object.defineProperty(target, key, {
3647
3969
  value,
@@ -3671,18 +3993,6 @@ function isTraceContentEnabled() {
3671
3993
  const raw = process.env.TRACELOOP_TRACE_CONTENT ?? process.env.NETRA_TRACE_CONTENT ?? "";
3672
3994
  return ["1", "true"].includes(String(raw).toLowerCase());
3673
3995
  }
3674
- function safeStringify(value) {
3675
- if (typeof value === "string") return value;
3676
- try {
3677
- return JSON.stringify(value);
3678
- } catch {
3679
- return String(value);
3680
- }
3681
- }
3682
- function truncate(value, maxLen) {
3683
- if (!value || value.length <= maxLen) return value;
3684
- return value.slice(0, maxLen) + "...(truncated)";
3685
- }
3686
3996
  function hasContent(value) {
3687
3997
  if (value === void 0 || value === null) return false;
3688
3998
  if (typeof value === "string") return value.length > 0;
@@ -3713,7 +4023,7 @@ function setModelParams(span2, kwargs) {
3713
4023
  }
3714
4024
  function buildInputMessages(kwargs, requestType) {
3715
4025
  const messages = [];
3716
- if (requestType === "chat") {
4026
+ if (requestType === "chat" || requestType === "beta") {
3717
4027
  if (hasContent(kwargs.system)) {
3718
4028
  const systemContent = typeof kwargs.system === "string" ? kwargs.system : safeStringify(kwargs.system);
3719
4029
  messages.push({ role: "system", content: systemContent });
@@ -3721,12 +4031,34 @@ function buildInputMessages(kwargs, requestType) {
3721
4031
  const rawMessages = kwargs.messages;
3722
4032
  if (!Array.isArray(rawMessages)) return messages;
3723
4033
  for (const msg of rawMessages) {
3724
- if (!isDict(msg)) continue;
3725
- if (hasContent(msg.role) && hasContent(msg.content)) {
4034
+ if (!isDict(msg) || !hasContent(msg.role) || !hasContent(msg.content)) {
4035
+ continue;
4036
+ }
4037
+ if (msg.role !== "user" || !Array.isArray(msg.content)) {
3726
4038
  messages.push({
3727
4039
  role: msg.role,
3728
4040
  content: safeStringify(msg.content)
3729
4041
  });
4042
+ continue;
4043
+ }
4044
+ const isToolResult = (b) => isDict(b) && b.type === "tool_result";
4045
+ const userBlocks = msg.content.filter((b) => !isToolResult(b));
4046
+ if (userBlocks.length) {
4047
+ messages.push({
4048
+ role: "user",
4049
+ content: safeStringify(userBlocks)
4050
+ });
4051
+ }
4052
+ for (const block of msg.content) {
4053
+ if (!isToolResult(block)) continue;
4054
+ messages.push({
4055
+ role: "tool",
4056
+ content: safeStringify({
4057
+ tool_use_id: block.tool_use_id,
4058
+ content: block.content,
4059
+ is_error: block.is_error ?? false
4060
+ }, Config.CONVERSATION_MAX_LEN)
4061
+ });
3730
4062
  }
3731
4063
  }
3732
4064
  } else if (requestType === "response") {
@@ -3755,10 +4087,7 @@ function buildInputMessages(kwargs, requestType) {
3755
4087
  } else {
3756
4088
  const input = kwargs.input ?? kwargs.inputs;
3757
4089
  if (hasContent(input)) {
3758
- const content = truncate(
3759
- safeStringify(input),
3760
- Config.CONVERSATION_MAX_LEN
3761
- );
4090
+ const content = safeStringify(input, Config.CONVERSATION_MAX_LEN);
3762
4091
  messages.push({ role: "user", content });
3763
4092
  }
3764
4093
  }
@@ -3825,7 +4154,7 @@ function buildOutputMessages(response) {
3825
4154
  } else if (block.type === "tool_use" && block.name) {
3826
4155
  messages.push({
3827
4156
  role: "tool",
3828
- content: JSON.stringify({ name: block.name, input: block.input })
4157
+ content: JSON.stringify({ id: block.id, name: block.name, input: block.input })
3829
4158
  });
3830
4159
  }
3831
4160
  }
@@ -3835,13 +4164,14 @@ function buildOutputMessages(response) {
3835
4164
  function writePromptAttributes(span2, messages) {
3836
4165
  if (messages.length === 0) return;
3837
4166
  for (let i = 0; i < messages.length; i++) {
4167
+ const msg = messages[i];
3838
4168
  span2.setAttribute(
3839
4169
  `${SpanAttributes2.LLM_PROMPTS}.${i}.role`,
3840
- messages[i].role
4170
+ msg.role
3841
4171
  );
3842
4172
  span2.setAttribute(
3843
4173
  `${SpanAttributes2.LLM_PROMPTS}.${i}.content`,
3844
- messages[i].content
4174
+ msg.content
3845
4175
  );
3846
4176
  }
3847
4177
  span2.setAttribute("input", JSON.stringify(messages));
@@ -3893,6 +4223,9 @@ function setRequestAttributes(span2, kwargs, requestType, system) {
3893
4223
  span2.setAttribute(SpanAttributes2.LLM_REQUEST_MODEL, String(kwargs.model));
3894
4224
  }
3895
4225
  setModelParams(span2, kwargs);
4226
+ if (Array.isArray(kwargs.tools)) {
4227
+ span2.setAttribute("tools", safeStringify(kwargs.tools, Config.ATTRIBUTE_MAX_LEN));
4228
+ }
3896
4229
  if (kwargs.reasoning !== void 0) {
3897
4230
  span2.setAttribute(
3898
4231
  SpanAttributes2.LLM_REQUEST_REASONING,
@@ -3905,7 +4238,7 @@ function setRequestAttributes(span2, kwargs, requestType, system) {
3905
4238
  if (kwargs.suffix !== void 0) {
3906
4239
  span2.setAttribute(
3907
4240
  "llm.request.suffix",
3908
- truncate(safeStringify(kwargs.suffix), Config.CONVERSATION_MAX_LEN)
4241
+ safeStringify(kwargs.suffix, Config.CONVERSATION_MAX_LEN)
3909
4242
  );
3910
4243
  }
3911
4244
  }
@@ -3928,12 +4261,20 @@ function setResponseAttributes(span2, response) {
3928
4261
  }
3929
4262
  }
3930
4263
  function setFinishReason(span2, response) {
4264
+ if (response.stop_reason) {
4265
+ span2.setAttribute(
4266
+ SpanAttributes2.LLM_RESPONSE_FINISH_REASON,
4267
+ String(response.stop_reason)
4268
+ );
4269
+ span2.setAttribute("gen_ai.response.finish_reason", String(response.stop_reason));
4270
+ }
3931
4271
  const choices = response.choices;
3932
- if (!Array.isArray(choices) || choices.length === 0) return;
3933
- const reason = choices[0].finish_reason ?? choices[0].finishReason;
3934
- if (reason) {
3935
- span2.setAttribute("gen_ai.response.finish_reason", String(reason));
3936
- span2.setAttribute("llm.response.finish_reason", String(reason));
4272
+ if (Array.isArray(choices) && choices.length > 0) {
4273
+ const reason = choices[0].finish_reason ?? choices[0].finishReason;
4274
+ if (reason) {
4275
+ span2.setAttribute(SpanAttributes2.LLM_RESPONSE_FINISH_REASON, String(reason));
4276
+ span2.setAttribute("gen_ai.response.finish_reason", String(reason));
4277
+ }
3937
4278
  }
3938
4279
  }
3939
4280
  function setUsageAttributes(span2, response) {
@@ -3960,11 +4301,18 @@ function setUsageAttributes(span2, response) {
3960
4301
  Number(totalTokens)
3961
4302
  );
3962
4303
  }
3963
- const cacheTokens = (usage.prompt_tokens_details ?? usage.input_tokens_details)?.cached_tokens;
3964
- if (cacheTokens !== void 0) {
4304
+ const cacheReadTokens = usage.cache_read_input_tokens ?? (usage.prompt_tokens_details ?? usage.input_tokens_details)?.cached_tokens;
4305
+ if (cacheReadTokens !== void 0) {
3965
4306
  span2.setAttribute(
3966
4307
  SpanAttributes2.LLM_USAGE_CACHE_READ_INPUT_TOKENS,
3967
- Number(cacheTokens)
4308
+ Number(cacheReadTokens)
4309
+ );
4310
+ }
4311
+ const cacheCreationTokens = usage.cache_creation_input_tokens;
4312
+ if (cacheCreationTokens !== void 0) {
4313
+ span2.setAttribute(
4314
+ SpanAttributes2.LLM_USAGE_CACHE_CREATION_INPUT_TOKENS,
4315
+ Number(cacheCreationTokens)
3968
4316
  );
3969
4317
  }
3970
4318
  const reasoningTokens = (usage.completion_tokens_details ?? usage.output_tokens_details)?.reasoning_tokens;
@@ -3986,188 +4334,181 @@ function setEmbeddingResponseMeta(span2, response) {
3986
4334
  }
3987
4335
  }
3988
4336
 
3989
- // src/instrumentation/anthropic/utils.ts
3990
- function setRequestAttributes2(span2, kwargs, requestType) {
3991
- if (!span2.isRecording()) {
3992
- Logger.log("Span is not recording");
3993
- return;
3994
- }
3995
- setRequestAttributes(span2, kwargs, requestType, "anthropic");
3996
- }
3997
- function setResponseAttributes2(span2, response) {
3998
- if (!span2.isRecording()) {
3999
- Logger.log("Span is not recording");
4000
- return;
4001
- }
4002
- if (response?.type === "message_batch") {
4003
- span2.setAttribute("status", response?.processing_status);
4004
- }
4005
- setResponseAttributes(span2, response);
4006
- }
4337
+ // src/instrumentation/anthropic/types.ts
4338
+ var SPAN_NAMES = {
4339
+ CHAT: "anthropic.chat",
4340
+ STREAM: "anthropic.stream",
4341
+ BATCHES: "anthropic.batches",
4342
+ BETA: "anthropic.beta",
4343
+ BETA_STREAM: "anthropic.beta.stream",
4344
+ BETA_TOOL_RUNNER: "anthropic.beta.tool.runner"
4345
+ };
4007
4346
 
4008
- // src/instrumentation/anthropic/version.ts
4009
- var __version__ = "1.0.0";
4010
- var CHAT_SPAN_NAME = "anthropic.chat";
4011
- var BETA_SPAN_NAME = "anthropic.beta";
4012
- var BATCHES_SPAN_NAME = "anthropic.batches";
4013
- var STREAM_ENABLED_REQUESTS = ["chat", "beta"];
4014
- function anthropicWrapper(tracer, spanName, requestType) {
4015
- return function wrapper(wrapped, instance, args, kwargs) {
4016
- if (shouldSuppressInstrumentation()) {
4017
- const result = wrapped.call(instance, ...args);
4018
- return isPromise(result) ? result.then((value) => value) : result;
4019
- }
4020
- const currentContext = context.active();
4021
- const isStreaming = args[0]?.stream === true;
4022
- const activeSpan = trace.getSpan(context.active());
4023
- Logger.debug(`Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
4024
- if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
4025
- const span2 = tracer.startSpan(
4026
- spanName + ".create",
4027
- {
4028
- kind: SpanKind.CLIENT,
4029
- attributes: {
4030
- "llm.request.type": requestType,
4031
- "llm.streaming": true
4032
- }
4033
- },
4034
- currentContext
4035
- );
4036
- try {
4037
- setRequestAttributes2(span2, kwargs, requestType);
4038
- const startTime = Date.now();
4039
- const spanContext = trace.setSpan(currentContext, span2);
4040
- const response = context.with(spanContext, () => wrapped.call(instance, ...args));
4041
- if (isPromise(response)) {
4042
- return (async () => {
4043
- try {
4044
- const stream = await response;
4045
- return new AsyncStreamingWrapper(span2, stream, startTime, kwargs, spanContext);
4046
- } catch (error) {
4047
- Logger.error("netra.instrumentation.anthropic:", error);
4048
- span2.setStatus({
4049
- code: SpanStatusCode.ERROR,
4050
- message: error instanceof Error ? error.message : String(error)
4051
- });
4052
- span2.recordException(error);
4053
- span2.end();
4054
- throw error;
4055
- }
4056
- })();
4057
- } else {
4058
- return new AsyncStreamingWrapper(span2, response, startTime, kwargs, spanContext);
4347
+ // src/instrumentation/anthropic/utils.ts
4348
+ function processStreamChunk(completeResponse, chunk, span2) {
4349
+ try {
4350
+ switch (chunk.type) {
4351
+ case "message_start": {
4352
+ if (chunk.message?.model) {
4353
+ completeResponse.model = chunk.message.model;
4059
4354
  }
4060
- } catch (error) {
4061
- Logger.error("netra.instrumentation.anthropic:", error);
4062
- span2.setStatus({
4063
- code: SpanStatusCode.ERROR,
4064
- message: error instanceof Error ? error.message : String(error)
4065
- });
4066
- span2.recordException(error);
4067
- span2.end();
4068
- throw error;
4355
+ if (chunk.message?.usage) {
4356
+ completeResponse.usage = chunk.message.usage;
4357
+ }
4358
+ break;
4069
4359
  }
4070
- } else {
4071
- return tracer.startActiveSpan(
4072
- spanName,
4073
- {
4074
- kind: SpanKind.CLIENT,
4075
- attributes: { "llm.request.type": requestType }
4076
- },
4077
- (span2) => {
4078
- try {
4079
- setRequestAttributes2(span2, kwargs, requestType);
4080
- const startTime = Date.now();
4081
- const spanContext = trace.setSpan(currentContext, span2);
4082
- const response = context.with(spanContext, () => wrapped.call(instance, ...args));
4083
- if (isPromise(response)) {
4084
- const instrumentedPromise = (async () => {
4085
- try {
4086
- const value = await response;
4087
- const endTime = Date.now();
4088
- const responseDict = modelAsDict(value);
4089
- setResponseAttributes2(span2, responseDict);
4090
- span2.setAttribute(
4091
- "llm.response.duration",
4092
- (endTime - startTime) / 1e3
4093
- );
4094
- span2.setStatus({ code: SpanStatusCode.OK });
4095
- span2.end();
4096
- return value;
4097
- } catch (error) {
4098
- Logger.error("netra.instrumentation.anthropic:", error);
4099
- span2.setStatus({
4100
- code: SpanStatusCode.ERROR,
4101
- message: error instanceof Error ? error.message : String(error)
4102
- });
4103
- span2.recordException(error);
4104
- span2.end();
4105
- throw error;
4106
- }
4107
- })();
4108
- return new Proxy(instrumentedPromise, {
4109
- get(target, prop, receiver) {
4110
- if (prop === "then" || prop === "catch" || prop === "finally") {
4111
- const value2 = Reflect.get(target, prop, receiver);
4112
- if (typeof value2 === "function") {
4113
- return value2.bind(target);
4114
- }
4115
- return value2;
4116
- }
4117
- const responseValue = response[prop];
4118
- if (responseValue !== void 0) {
4119
- if (typeof responseValue === "function") {
4120
- return responseValue.bind(response);
4121
- }
4122
- return responseValue;
4123
- }
4124
- const value = Reflect.get(target, prop, receiver);
4125
- if (typeof value === "function") {
4126
- return value.bind(target);
4127
- }
4128
- return value;
4129
- }
4130
- });
4131
- } else {
4132
- const endTime = Date.now();
4133
- const responseDict = modelAsDict(response);
4134
- setResponseAttributes2(span2, responseDict);
4135
- span2.setAttribute(
4136
- "llm.response.duration",
4137
- (endTime - startTime) / 1e3
4360
+ case "content_block_start": {
4361
+ if (!completeResponse.content) {
4362
+ completeResponse.content = [];
4363
+ }
4364
+ const block = chunk.content_block;
4365
+ if (!block) break;
4366
+ if (block.type === "tool_use") {
4367
+ completeResponse.content.push({
4368
+ type: "tool_use",
4369
+ id: block.id,
4370
+ name: block.name,
4371
+ input: ""
4372
+ });
4373
+ } else {
4374
+ completeResponse.content.push({
4375
+ type: block.type,
4376
+ text: ""
4377
+ });
4378
+ }
4379
+ break;
4380
+ }
4381
+ case "content_block_delta": {
4382
+ if (!completeResponse.content || completeResponse.content.length === 0) {
4383
+ completeResponse.content = [{ type: "text", text: "" }];
4384
+ }
4385
+ const targetIndex = chunk.index ?? completeResponse.content.length - 1;
4386
+ const targetBlock = completeResponse.content[targetIndex];
4387
+ if (!targetBlock) break;
4388
+ if (chunk.delta?.type === "input_json_delta" && targetBlock.type === "tool_use") {
4389
+ targetBlock.input += chunk.delta.partial_json ?? "";
4390
+ } else if (chunk.delta?.text) {
4391
+ targetBlock.text += chunk.delta.text;
4392
+ }
4393
+ break;
4394
+ }
4395
+ case "content_block_stop": {
4396
+ const blocks = completeResponse.content;
4397
+ if (blocks && blocks.length > 0) {
4398
+ const finishedBlock = blocks[blocks.length - 1];
4399
+ if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4400
+ try {
4401
+ finishedBlock.input = JSON.parse(finishedBlock.input);
4402
+ } catch {
4403
+ Logger.warn(
4404
+ "netra.instrumentation.anthropic: Failed to parse tool use input"
4138
4405
  );
4139
- span2.setStatus({ code: SpanStatusCode.OK });
4140
- span2.end();
4141
- return response;
4142
4406
  }
4143
- } catch (error) {
4144
- Logger.error("netra.instrumentation.anthropic:", error);
4145
- span2.setStatus({
4146
- code: SpanStatusCode.ERROR,
4147
- message: error instanceof Error ? error.message : String(error)
4148
- });
4149
- span2.recordException(error);
4150
- span2.end();
4151
- throw error;
4152
4407
  }
4153
4408
  }
4154
- );
4409
+ break;
4410
+ }
4411
+ case "message_delta": {
4412
+ if (chunk.delta?.stop_reason) {
4413
+ completeResponse.stop_reason = chunk.delta.stop_reason;
4414
+ }
4415
+ const usageData = chunk.usage ?? chunk.delta?.usage;
4416
+ if (usageData) {
4417
+ completeResponse.usage = {
4418
+ ...completeResponse.usage ?? {},
4419
+ ...usageData
4420
+ };
4421
+ }
4422
+ break;
4423
+ }
4424
+ case "message_stop": {
4425
+ if (chunk.usage) {
4426
+ completeResponse.usage = {
4427
+ ...completeResponse.usage ?? {},
4428
+ ...chunk.usage
4429
+ };
4430
+ }
4431
+ break;
4432
+ }
4155
4433
  }
4156
- };
4434
+ if (Logger.isDebugMode()) {
4435
+ span2.addEvent("llm.content.completion.chunk", {
4436
+ "chunk.type": chunk.type
4437
+ });
4438
+ }
4439
+ } catch (e) {
4440
+ Logger.error(
4441
+ "netra.instrumentation.anthropic: processStreamChunk error",
4442
+ e
4443
+ );
4444
+ }
4445
+ }
4446
+ function finalizeStreamSpan(span2, completeResponse, startTime, code) {
4447
+ try {
4448
+ const endTime = Date.now();
4449
+ setResponseAttributes2(span2, {
4450
+ model: completeResponse.model,
4451
+ content: completeResponse.content,
4452
+ usage: completeResponse.usage,
4453
+ stop_reason: completeResponse.stop_reason
4454
+ });
4455
+ span2.setAttribute("llm.response.duration", (endTime - startTime) / 1e3);
4456
+ span2.setStatus({ code });
4457
+ } catch (e) {
4458
+ Logger.error(
4459
+ "netra.instrumentation.anthropic: finalizeStreamSpan error",
4460
+ e
4461
+ );
4462
+ } finally {
4463
+ span2.end();
4464
+ }
4157
4465
  }
4158
- var chatWrapper = (tracer) => anthropicWrapper(tracer, CHAT_SPAN_NAME, "chat");
4159
- var betaWrapper = (tracer) => anthropicWrapper(tracer, BETA_SPAN_NAME, "beta");
4160
- var batchesWrapper = (tracer) => anthropicWrapper(tracer, BATCHES_SPAN_NAME, "batches");
4466
+ function setRequestAttributes2(span2, kwargs, requestType) {
4467
+ try {
4468
+ if (!span2.isRecording()) {
4469
+ Logger.log("Span is not recording");
4470
+ return;
4471
+ }
4472
+ setRequestAttributes(span2, kwargs, requestType, "anthropic");
4473
+ } catch (e) {
4474
+ Logger.error(
4475
+ "netra.instrumentation.anthropic: setRequestAttributes error",
4476
+ e
4477
+ );
4478
+ }
4479
+ }
4480
+ function setResponseAttributes2(span2, response) {
4481
+ try {
4482
+ if (!span2.isRecording()) {
4483
+ Logger.log("Span is not recording");
4484
+ return;
4485
+ }
4486
+ if (response?.type === "message_batch") {
4487
+ span2.setAttribute("status", response?.processing_status);
4488
+ }
4489
+ setResponseAttributes(span2, response);
4490
+ } catch (e) {
4491
+ Logger.error(
4492
+ "netra.instrumentation.anthropic: setResponseAttributes error",
4493
+ e
4494
+ );
4495
+ }
4496
+ }
4497
+
4498
+ // src/instrumentation/anthropic/wrappers.ts
4161
4499
  var WRAPPER_OWN_PROPS = /* @__PURE__ */ new Set([
4162
4500
  "span",
4163
4501
  "messageStream",
4164
4502
  "startTime",
4165
4503
  "requestKwargs",
4166
4504
  "completeResponse",
4167
- "processChunk",
4168
- "finalizeSpan",
4505
+ "finalizeSpanOnce",
4169
4506
  "processEventData",
4170
- "finalizeSpanFromMessage"
4507
+ "finalizeSpanFromMessage",
4508
+ "parentContext",
4509
+ "spanFinalized",
4510
+ "completionPending",
4511
+ "listenerMap"
4171
4512
  ]);
4172
4513
  var EVENT_EMITTER_METHODS = /* @__PURE__ */ new Set([
4173
4514
  "on",
@@ -4181,20 +4522,90 @@ var EVENT_EMITTER_METHODS = /* @__PURE__ */ new Set([
4181
4522
  "listenerCount"
4182
4523
  ]);
4183
4524
  var LISTENER_REGISTRATION_METHODS = /* @__PURE__ */ new Set(["on", "once", "addListener"]);
4525
+ var LISTENER_REMOVAL_METHODS = /* @__PURE__ */ new Set(["off", "removeListener"]);
4184
4526
  var COMPLETION_METHODS = /* @__PURE__ */ new Set(["finalMessage", "done", "finalText"]);
4185
- var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set(["message", "contentBlock", "text", "finalMessage"]);
4527
+ var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set([
4528
+ "message",
4529
+ "contentBlock",
4530
+ "text",
4531
+ "finalMessage"
4532
+ ]);
4533
+ var MAX_TOOL_ATTR_LENGTH = 4096;
4534
+ function wrapRunnableTools(tools, tracer, parentContext) {
4535
+ return tools.map((tool) => {
4536
+ if (typeof tool.run !== "function") return tool;
4537
+ const originalRun = tool.run;
4538
+ const toolName = tool.name ?? "unknown_tool";
4539
+ const wrappedRun = async function(input, runContext) {
4540
+ const toolUseId = runContext?.toolUse?.id ?? runContext?.toolUseBlock?.id;
4541
+ const traceContent = isTraceContentEnabled();
4542
+ const attrs = {
4543
+ "netra.span.type": "TOOL",
4544
+ [SpanAttributes2.LLM_REQUEST_TOOL_NAME]: toolName
4545
+ };
4546
+ if (toolUseId) attrs[SpanAttributes2.LLM_REQUEST_TOOL_ID] = toolUseId;
4547
+ if (traceContent) {
4548
+ attrs.input = safeStringify(input, MAX_TOOL_ATTR_LENGTH);
4549
+ }
4550
+ const span2 = tracer.startSpan(
4551
+ toolName,
4552
+ { kind: SpanKind.INTERNAL, attributes: attrs },
4553
+ parentContext
4554
+ );
4555
+ const spanCtx = trace.setSpan(parentContext, span2);
4556
+ try {
4557
+ const result = await context.with(
4558
+ spanCtx,
4559
+ () => originalRun.call(this, input, runContext)
4560
+ );
4561
+ if (traceContent) {
4562
+ span2.setAttribute(
4563
+ "output",
4564
+ safeStringify(result, MAX_TOOL_ATTR_LENGTH)
4565
+ );
4566
+ }
4567
+ span2.setStatus({ code: SpanStatusCode.OK });
4568
+ return result;
4569
+ } catch (error) {
4570
+ span2.setStatus({
4571
+ code: SpanStatusCode.ERROR,
4572
+ message: error instanceof Error ? error.message : String(error)
4573
+ });
4574
+ span2.recordException(error);
4575
+ throw error;
4576
+ } finally {
4577
+ span2.end();
4578
+ }
4579
+ };
4580
+ const wrapped = Object.create(
4581
+ Object.getPrototypeOf(tool),
4582
+ Object.getOwnPropertyDescriptors(tool)
4583
+ );
4584
+ wrapped.run = wrappedRun;
4585
+ return wrapped;
4586
+ });
4587
+ }
4186
4588
  var MessageStreamWrapper = class {
4187
- constructor(span2, messageStream, startTime, requestKwargs, spanContext) {
4589
+ constructor(span2, messageStream, startTime, requestKwargs, spanContext, parentContext) {
4188
4590
  this.completeResponse = {
4189
4591
  content: [],
4190
4592
  model: "",
4191
4593
  usage: {}
4192
4594
  };
4595
+ this.spanFinalized = false;
4596
+ this.completionPending = false;
4597
+ this.listenerMap = /* @__PURE__ */ new WeakMap();
4193
4598
  defineHidden(this, "span", span2);
4194
4599
  defineHidden(this, "messageStream", messageStream);
4195
4600
  defineHidden(this, "startTime", startTime);
4196
4601
  defineHidden(this, "requestKwargs", requestKwargs);
4197
- defineHidden(this, "spanContext", spanContext || trace.setSpan(context.active(), span2));
4602
+ defineHidden(
4603
+ this,
4604
+ "spanContext",
4605
+ spanContext || trace.setSpan(context.active(), span2)
4606
+ );
4607
+ defineHidden(this, "parentContext", parentContext || context.active());
4608
+ this.registerSafetyNetListeners();
4198
4609
  return new Proxy(this, {
4199
4610
  get(target, prop, receiver) {
4200
4611
  if (prop === "toJSON") {
@@ -4208,67 +4619,135 @@ var MessageStreamWrapper = class {
4208
4619
  }
4209
4620
  if (typeof prop === "string" && EVENT_EMITTER_METHODS.has(prop)) {
4210
4621
  const method = target.messageStream[prop];
4211
- if (typeof method === "function") {
4212
- if (LISTENER_REGISTRATION_METHODS.has(prop)) {
4213
- return function(event, listener) {
4214
- const wrappedListener = (...args) => {
4622
+ if (typeof method !== "function") return method;
4623
+ if (LISTENER_REGISTRATION_METHODS.has(prop)) {
4624
+ return function(event, listener) {
4625
+ const wrappedListener = (...args) => {
4626
+ try {
4215
4627
  target.span.addEvent(`messagestream.event.${event}`, {
4216
4628
  "event.type": event
4217
4629
  });
4218
- if (TRACKED_STREAM_EVENTS.has(event)) {
4219
- if (args[0]) {
4220
- target.processEventData(event, args[0]);
4221
- }
4630
+ if (TRACKED_STREAM_EVENTS.has(event) && args[0]) {
4631
+ target.processEventData(event, args[0]);
4222
4632
  }
4223
- return listener(...args);
4224
- };
4225
- return method.call(target.messageStream, event, wrappedListener);
4633
+ } catch (e) {
4634
+ Logger.error(
4635
+ "netra.instrumentation.anthropic: event tracking error",
4636
+ e
4637
+ );
4638
+ }
4639
+ return listener(...args);
4226
4640
  };
4227
- }
4228
- return method.bind(target.messageStream);
4641
+ let eventMap = target.listenerMap.get(listener);
4642
+ if (!eventMap) {
4643
+ eventMap = /* @__PURE__ */ new Map();
4644
+ target.listenerMap.set(listener, eventMap);
4645
+ }
4646
+ let wrappers = eventMap.get(event);
4647
+ if (!wrappers) {
4648
+ wrappers = [];
4649
+ eventMap.set(event, wrappers);
4650
+ }
4651
+ wrappers.push(wrappedListener);
4652
+ return method.call(target.messageStream, event, wrappedListener);
4653
+ };
4654
+ }
4655
+ if (LISTENER_REMOVAL_METHODS.has(prop)) {
4656
+ return function(event, listener) {
4657
+ const eventMap = target.listenerMap.get(listener);
4658
+ const wrappers = eventMap?.get(event);
4659
+ const wrapped = wrappers?.shift() ?? listener;
4660
+ if (wrappers && wrappers.length === 0) eventMap?.delete(event);
4661
+ return method.call(target.messageStream, event, wrapped);
4662
+ };
4663
+ }
4664
+ if (prop === "removeAllListeners") {
4665
+ return function(event) {
4666
+ target.listenerMap = /* @__PURE__ */ new WeakMap();
4667
+ return method.call(target.messageStream, event);
4668
+ };
4229
4669
  }
4230
- return method;
4670
+ return method.bind(target.messageStream);
4231
4671
  }
4232
4672
  if (typeof prop === "string" && COMPLETION_METHODS.has(prop)) {
4233
4673
  const method = target.messageStream[prop];
4234
- if (typeof method === "function") {
4235
- return async function(...args) {
4236
- try {
4237
- const result = await method.call(target.messageStream, ...args);
4238
- if (prop === "finalMessage" || prop === "done") {
4239
- target.finalizeSpanFromMessage(result);
4674
+ if (typeof method !== "function") return method;
4675
+ return async function(...args) {
4676
+ target.completionPending = true;
4677
+ try {
4678
+ const result = await method.call(target.messageStream, ...args);
4679
+ if (prop === "finalMessage" || prop === "done") {
4680
+ target.finalizeSpanFromMessage(result);
4681
+ } else if (prop === "finalText") {
4682
+ if (typeof result === "string" && result.length > 0) {
4683
+ target.completeResponse.content = [
4684
+ { type: "text", text: result }
4685
+ ];
4686
+ } else {
4687
+ target.flushCurrentText();
4240
4688
  }
4241
- return result;
4242
- } catch (error) {
4243
- target.finalizeSpan(SpanStatusCode.ERROR);
4244
- throw error;
4689
+ target.finalizeSpanOnce(SpanStatusCode.OK);
4245
4690
  }
4246
- };
4247
- }
4248
- return method;
4691
+ return result;
4692
+ } catch (error) {
4693
+ target.finalizeSpanOnce(SpanStatusCode.ERROR);
4694
+ throw error;
4695
+ }
4696
+ };
4249
4697
  }
4250
4698
  const value = target.messageStream[prop];
4251
- if (typeof value === "function") {
4699
+ if (typeof value === "function")
4252
4700
  return value.bind(target.messageStream);
4253
- }
4254
4701
  return value;
4255
4702
  }
4256
4703
  });
4257
4704
  }
4705
+ registerSafetyNetListeners() {
4706
+ try {
4707
+ if (typeof this.messageStream?.on !== "function") return;
4708
+ this.messageStream.on("end", () => {
4709
+ if (!this.completionPending) {
4710
+ this.finalizeSpanOnce(SpanStatusCode.OK);
4711
+ }
4712
+ });
4713
+ this.messageStream.on("error", (err) => {
4714
+ if (err && !this.spanFinalized) {
4715
+ this.span.setStatus({
4716
+ code: SpanStatusCode.ERROR,
4717
+ message: err instanceof Error ? err.message : String(err)
4718
+ });
4719
+ this.span.recordException(
4720
+ err instanceof Error ? err : new Error(String(err))
4721
+ );
4722
+ }
4723
+ this.finalizeSpanOnce(SpanStatusCode.ERROR);
4724
+ });
4725
+ } catch (e) {
4726
+ Logger.error(
4727
+ "netra.instrumentation.anthropic: safety net listener registration failed",
4728
+ e
4729
+ );
4730
+ }
4731
+ }
4258
4732
  toJSON() {
4259
4733
  return this.completeResponse;
4260
4734
  }
4261
4735
  async *[Symbol.asyncIterator]() {
4736
+ let errorOccurred = false;
4262
4737
  try {
4263
4738
  for await (const chunk of this.messageStream) {
4264
- this.processChunk(chunk);
4739
+ processStreamChunk(this.completeResponse, chunk, this.span);
4265
4740
  yield chunk;
4266
4741
  }
4267
- this.finalizeSpan(SpanStatusCode.OK);
4268
4742
  } catch (err) {
4743
+ errorOccurred = true;
4269
4744
  Logger.error("netra.instrumentation.anthropic: Stream error", err);
4270
- this.finalizeSpan(SpanStatusCode.ERROR);
4745
+ this.finalizeSpanOnce(SpanStatusCode.ERROR);
4271
4746
  throw err;
4747
+ } finally {
4748
+ if (!errorOccurred) {
4749
+ this.finalizeSpanOnce(SpanStatusCode.OK);
4750
+ }
4272
4751
  }
4273
4752
  }
4274
4753
  getSpanContext() {
@@ -4277,12 +4756,8 @@ var MessageStreamWrapper = class {
4277
4756
  processEventData(eventType, data) {
4278
4757
  switch (eventType) {
4279
4758
  case "message":
4280
- if (data.model) {
4281
- this.completeResponse.model = data.model;
4282
- }
4283
- if (data.usage) {
4284
- this.completeResponse.usage = data.usage;
4285
- }
4759
+ if (data.model) this.completeResponse.model = data.model;
4760
+ if (data.usage) this.completeResponse.usage = data.usage;
4286
4761
  break;
4287
4762
  case "text":
4288
4763
  if (!this.completeResponse.currentText) {
@@ -4303,250 +4778,359 @@ var MessageStreamWrapper = class {
4303
4778
  break;
4304
4779
  }
4305
4780
  }
4306
- processChunk(chunk) {
4307
- switch (chunk.type) {
4308
- case "message_start": {
4309
- if (chunk.message?.model) {
4310
- this.completeResponse.model = chunk.message.model;
4311
- }
4312
- if (chunk.message?.usage) {
4313
- this.completeResponse.usage = chunk.message.usage;
4314
- }
4315
- break;
4316
- }
4317
- case "content_block_start": {
4318
- if (!this.completeResponse.content) {
4319
- this.completeResponse.content = [];
4320
- }
4321
- const block = chunk.content_block;
4322
- if (block.type === "tool_use") {
4323
- this.completeResponse.content.push({
4324
- type: "tool_use",
4325
- id: block.id,
4326
- name: block.name,
4327
- input: ""
4328
- });
4329
- } else {
4330
- this.completeResponse.content.push({
4331
- type: block.type,
4332
- text: ""
4333
- });
4334
- }
4335
- break;
4336
- }
4337
- case "content_block_delta": {
4338
- if (!this.completeResponse.content || this.completeResponse.content.length === 0) {
4339
- this.completeResponse.content = [{ type: "text", text: "" }];
4340
- }
4341
- const lastBlock = this.completeResponse.content[this.completeResponse.content.length - 1];
4342
- if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
4343
- lastBlock.input += chunk.delta.partial_json ?? "";
4344
- } else if (lastBlock && chunk.delta?.text) {
4345
- lastBlock.text += chunk.delta.text;
4346
- }
4347
- break;
4348
- }
4349
- case "content_block_stop": {
4350
- const blocks = this.completeResponse.content;
4351
- if (blocks && blocks.length > 0) {
4352
- const finishedBlock = blocks[blocks.length - 1];
4353
- if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4354
- try {
4355
- finishedBlock.input = JSON.parse(finishedBlock.input);
4356
- } catch {
4357
- Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
4358
- }
4359
- }
4360
- }
4361
- break;
4362
- }
4363
- case "message_delta": {
4364
- if (chunk.delta?.usage) {
4365
- this.completeResponse.usage = {
4366
- ...this.completeResponse.usage,
4367
- ...chunk.delta.usage
4368
- };
4369
- }
4370
- break;
4371
- }
4372
- case "message_stop": {
4373
- if (chunk.usage) {
4374
- this.completeResponse.usage = chunk.usage;
4375
- }
4376
- break;
4377
- }
4781
+ flushCurrentText() {
4782
+ if (this.completeResponse.currentText && (!this.completeResponse.content || this.completeResponse.content.length === 0)) {
4783
+ this.completeResponse.content = [
4784
+ { type: "text", text: this.completeResponse.currentText }
4785
+ ];
4378
4786
  }
4379
- this.span.addEvent("llm.content.completion.chunk", {
4380
- "chunk.type": chunk.type
4381
- });
4382
4787
  }
4383
4788
  finalizeSpanFromMessage(message) {
4384
4789
  if (message) {
4385
4790
  if (message.model) this.completeResponse.model = message.model;
4386
4791
  if (message.content) this.completeResponse.content = message.content;
4387
4792
  if (message.usage) this.completeResponse.usage = message.usage;
4793
+ if (message.stop_reason)
4794
+ this.completeResponse.stop_reason = message.stop_reason;
4388
4795
  }
4389
- this.finalizeSpan(SpanStatusCode.OK);
4796
+ this.finalizeSpanOnce(SpanStatusCode.OK);
4390
4797
  }
4391
- finalizeSpan(code) {
4392
- const endTime = Date.now();
4393
- const duration = (endTime - this.startTime) / 1e3;
4394
- setResponseAttributes2(this.span, {
4395
- model: this.completeResponse.model,
4396
- content: this.completeResponse.content,
4397
- usage: this.completeResponse.usage
4398
- });
4399
- this.span.setAttribute("llm.response.duration", duration);
4400
- this.span.setStatus({ code });
4401
- this.span.end();
4798
+ finalizeSpanOnce(code) {
4799
+ if (this.spanFinalized) return;
4800
+ this.spanFinalized = true;
4801
+ finalizeStreamSpan(this.span, this.completeResponse, this.startTime, code);
4402
4802
  }
4403
4803
  };
4404
- var AsyncStreamingWrapper = class {
4405
- constructor(span2, response, startTime, requestKwargs, spanContext) {
4406
- this.iterator = null;
4407
- this.completeResponse = {
4408
- choices: [],
4409
- model: ""
4410
- };
4411
- defineHidden(this, "span", span2);
4412
- defineHidden(this, "response", response);
4413
- defineHidden(this, "startTime", startTime);
4414
- defineHidden(this, "requestKwargs", requestKwargs);
4415
- defineHidden(this, "spanContext", spanContext || trace.setSpan(context.active(), span2));
4416
- }
4417
- toJSON() {
4418
- return this.completeResponse;
4419
- }
4420
- [Symbol.asyncIterator]() {
4421
- return this;
4422
- }
4423
- async next() {
4424
- try {
4425
- if (!this.iterator) {
4426
- if (Symbol.asyncIterator in this.response) {
4427
- this.iterator = this.response[Symbol.asyncIterator]();
4428
- } else if (typeof this.response.next === "function") {
4429
- this.iterator = this.response;
4430
- } else {
4431
- throw new Error("Response is not iterable");
4432
- }
4433
- }
4434
- const result = await context.with(this.spanContext, () => this.iterator.next());
4435
- if (result.done) {
4436
- this.finalizeSpan(SpanStatusCode.OK);
4437
- return result;
4438
- }
4439
- this.processChunk(result.value);
4440
- return result;
4441
- } catch (error) {
4442
- this.finalizeSpan(SpanStatusCode.ERROR);
4443
- throw error;
4444
- }
4445
- }
4446
- processChunk(chunk) {
4447
- switch (chunk.type) {
4448
- case "message_start": {
4449
- if (chunk.message?.model) {
4450
- this.completeResponse.model = chunk.message.model;
4451
- }
4452
- if (chunk.message?.usage) {
4453
- this.completeResponse.usage = chunk.message.usage;
4454
- }
4455
- break;
4456
- }
4457
- case "content_block_start": {
4458
- const content = this.completeResponse.content || [];
4459
- this.completeResponse.content = content;
4460
- const block = chunk.content_block;
4461
- if (block.type === "tool_use") {
4462
- content.push({
4463
- type: "tool_use",
4464
- id: block.id,
4465
- name: block.name,
4466
- input: ""
4467
- });
4468
- } else {
4469
- content.push({
4470
- type: block.type,
4471
- text: ""
4472
- });
4473
- }
4474
- break;
4475
- }
4476
- case "content_block_delta": {
4477
- const content = this.completeResponse.content || [];
4478
- if (content.length === 0) {
4479
- content.push({ type: "text", text: "" });
4480
- this.completeResponse.content = content;
4481
- }
4482
- const lastBlock = content[content.length - 1];
4483
- if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
4484
- lastBlock.input += chunk.delta.partial_json ?? "";
4485
- } else if (lastBlock && chunk.delta?.text) {
4486
- lastBlock.text += chunk.delta.text;
4487
- }
4488
- break;
4804
+ function anthropicWrapper(tracer, spanName, requestType) {
4805
+ return function wrapper(original) {
4806
+ return function(...args) {
4807
+ if (shouldSuppressInstrumentation()) {
4808
+ return original.apply(this, args);
4489
4809
  }
4490
- case "content_block_stop": {
4491
- const content = this.completeResponse.content || [];
4492
- if (content.length > 0) {
4493
- const finishedBlock = content[content.length - 1];
4494
- if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4495
- try {
4496
- finishedBlock.input = JSON.parse(finishedBlock.input);
4497
- } catch {
4498
- Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
4810
+ const attributes = args[0] || {};
4811
+ const currentContext = context.active();
4812
+ const isStreaming = attributes.stream === true;
4813
+ const activeSpan = trace.getSpan(currentContext);
4814
+ Logger.debug(
4815
+ `Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`
4816
+ );
4817
+ return tracer.startActiveSpan(
4818
+ spanName,
4819
+ {
4820
+ kind: SpanKind.CLIENT,
4821
+ attributes: { "llm.request.type": requestType }
4822
+ },
4823
+ (span2) => {
4824
+ try {
4825
+ setRequestAttributes2(span2, attributes, requestType);
4826
+ if (isStreaming) {
4827
+ span2.setAttribute("llm.streaming", true);
4499
4828
  }
4829
+ const startTime = Date.now();
4830
+ const spanContext = trace.setSpan(currentContext, span2);
4831
+ const response = context.with(
4832
+ spanContext,
4833
+ () => original.apply(this, args)
4834
+ );
4835
+ const completeResponse = {
4836
+ content: [],
4837
+ model: "",
4838
+ usage: {}
4839
+ };
4840
+ return wrapResponse(
4841
+ response,
4842
+ {
4843
+ withContext: (fn) => context.with(spanContext, fn),
4844
+ onChunk: (chunk) => processStreamChunk(completeResponse, chunk, span2),
4845
+ onError: (error) => {
4846
+ Logger.error("netra.instrumentation.anthropic:", error);
4847
+ span2.setStatus({
4848
+ code: SpanStatusCode.ERROR,
4849
+ message: error instanceof Error ? error.message : String(error)
4850
+ });
4851
+ span2.recordException(error);
4852
+ },
4853
+ onSuccess: (value) => {
4854
+ const endTime = Date.now();
4855
+ const responseDict = modelAsDict(value);
4856
+ setResponseAttributes2(span2, responseDict);
4857
+ span2.setAttribute(
4858
+ "llm.response.duration",
4859
+ (endTime - startTime) / 1e3
4860
+ );
4861
+ },
4862
+ finalize: (status) => {
4863
+ const hasStreamData = completeResponse.content?.length || completeResponse.model || completeResponse.usage?.input_tokens !== void 0 || completeResponse.usage?.output_tokens !== void 0;
4864
+ if (status === "ok" && hasStreamData) {
4865
+ finalizeStreamSpan(
4866
+ span2,
4867
+ completeResponse,
4868
+ startTime,
4869
+ SpanStatusCode.OK
4870
+ );
4871
+ } else {
4872
+ if (status === "ok") {
4873
+ span2.setStatus({ code: SpanStatusCode.OK });
4874
+ }
4875
+ span2.end();
4876
+ }
4877
+ }
4878
+ },
4879
+ { preserveOriginal: response }
4880
+ );
4881
+ } catch (error) {
4882
+ Logger.error("netra.instrumentation.anthropic:", error);
4883
+ span2.setStatus({
4884
+ code: SpanStatusCode.ERROR,
4885
+ message: error instanceof Error ? error.message : String(error)
4886
+ });
4887
+ span2.recordException(error);
4888
+ span2.end();
4889
+ throw error;
4500
4890
  }
4501
4891
  }
4502
- break;
4892
+ );
4893
+ };
4894
+ };
4895
+ }
4896
+ function streamWrapper(tracer, spanName, requestType, originalCreate) {
4897
+ return function wrapper(original) {
4898
+ return function(...args) {
4899
+ if (shouldSuppressInstrumentation()) {
4900
+ return original.apply(this, args);
4503
4901
  }
4504
- case "message_delta": {
4505
- if (chunk.delta?.usage) {
4506
- const currentUsage = this.completeResponse.usage || {};
4507
- this.completeResponse.usage = {
4508
- ...currentUsage,
4509
- ...chunk.delta.usage
4510
- };
4902
+ const attributes = args[0] || {};
4903
+ const currentContext = context.active();
4904
+ const span2 = tracer.startSpan(
4905
+ spanName,
4906
+ {
4907
+ kind: SpanKind.CLIENT,
4908
+ attributes: {
4909
+ "llm.request.type": requestType,
4910
+ "llm.streaming": true,
4911
+ "llm.operation": "stream"
4912
+ }
4913
+ },
4914
+ currentContext
4915
+ );
4916
+ const spanContext = trace.setSpan(currentContext, span2);
4917
+ setRequestAttributes2(span2, attributes, requestType);
4918
+ const startTime = Date.now();
4919
+ const callTarget = originalCreate ? new Proxy(this, {
4920
+ get(target, prop) {
4921
+ if (prop === "create") return originalCreate.bind(target);
4922
+ const value = target[prop];
4923
+ if (typeof value === "function") return value.bind(target);
4924
+ return value;
4511
4925
  }
4512
- break;
4926
+ }) : this;
4927
+ try {
4928
+ const messageStream = context.with(
4929
+ spanContext,
4930
+ () => original.call(callTarget, ...args)
4931
+ );
4932
+ return new MessageStreamWrapper(
4933
+ span2,
4934
+ messageStream,
4935
+ startTime,
4936
+ attributes,
4937
+ spanContext,
4938
+ currentContext
4939
+ );
4940
+ } catch (error) {
4941
+ span2.setStatus({
4942
+ code: SpanStatusCode.ERROR,
4943
+ message: error instanceof Error ? error.message : String(error)
4944
+ });
4945
+ span2.recordException(error);
4946
+ span2.end();
4947
+ throw error;
4513
4948
  }
4514
- case "message_stop": {
4515
- if (chunk.usage) {
4516
- this.completeResponse.usage = chunk.usage;
4949
+ };
4950
+ };
4951
+ }
4952
+ function toolRunnerWrapper(tracer, spanName, requestType) {
4953
+ return function wrapper(original) {
4954
+ return function(...args) {
4955
+ if (shouldSuppressInstrumentation()) {
4956
+ return original.apply(this, args);
4957
+ }
4958
+ const attributes = args[0] || {};
4959
+ const currentContext = context.active();
4960
+ const span2 = tracer.startSpan(
4961
+ spanName,
4962
+ {
4963
+ kind: SpanKind.CLIENT,
4964
+ attributes: {
4965
+ "llm.request.type": requestType,
4966
+ "netra.span.type": "AGENT",
4967
+ "llm.operation": "tool.runner"
4968
+ }
4969
+ },
4970
+ currentContext
4971
+ );
4972
+ let spanEnded = false;
4973
+ const endSpanOnce = (code, error) => {
4974
+ if (spanEnded) return;
4975
+ spanEnded = true;
4976
+ if (error) {
4977
+ span2.setStatus({ code, message: error.message });
4978
+ span2.recordException(error);
4979
+ } else {
4980
+ span2.setStatus({ code });
4517
4981
  }
4518
- break;
4982
+ span2.end();
4983
+ };
4984
+ try {
4985
+ setRequestAttributes2(span2, attributes, "beta");
4986
+ const spanContext = trace.setSpan(currentContext, span2);
4987
+ const wrappedTools = Array.isArray(attributes.tools) ? wrapRunnableTools(attributes.tools, tracer, spanContext) : attributes.tools;
4988
+ const wrappedArgs = [
4989
+ { ...attributes, tools: wrappedTools },
4990
+ ...args.slice(1)
4991
+ ];
4992
+ const runner = context.with(
4993
+ spanContext,
4994
+ () => original.apply(this, wrappedArgs)
4995
+ );
4996
+ if (runner == null) {
4997
+ endSpanOnce(SpanStatusCode.OK);
4998
+ return runner;
4999
+ }
5000
+ return new Proxy(runner, {
5001
+ get(target, prop, receiver) {
5002
+ if (prop === Symbol.asyncIterator) {
5003
+ return function() {
5004
+ const originalIterator = target[Symbol.asyncIterator]();
5005
+ return {
5006
+ [Symbol.asyncIterator]() {
5007
+ return this;
5008
+ },
5009
+ async next() {
5010
+ try {
5011
+ const result = await context.with(
5012
+ spanContext,
5013
+ () => originalIterator.next()
5014
+ );
5015
+ if (result.done) endSpanOnce(SpanStatusCode.OK);
5016
+ return result;
5017
+ } catch (error) {
5018
+ endSpanOnce(SpanStatusCode.ERROR, error);
5019
+ throw error;
5020
+ }
5021
+ },
5022
+ async return(value2) {
5023
+ try {
5024
+ const result = await (originalIterator.return?.(
5025
+ value2
5026
+ ) ?? {
5027
+ done: true,
5028
+ value: value2
5029
+ });
5030
+ return result;
5031
+ } finally {
5032
+ endSpanOnce(SpanStatusCode.OK);
5033
+ }
5034
+ },
5035
+ async throw(error) {
5036
+ const err = error instanceof Error ? error : new Error(String(error));
5037
+ if (originalIterator.throw) {
5038
+ try {
5039
+ const result = await originalIterator.throw(error);
5040
+ if (result.done) {
5041
+ endSpanOnce(SpanStatusCode.ERROR, err);
5042
+ }
5043
+ return result;
5044
+ } catch (e) {
5045
+ endSpanOnce(
5046
+ SpanStatusCode.ERROR,
5047
+ e instanceof Error ? e : new Error(String(e))
5048
+ );
5049
+ throw e;
5050
+ }
5051
+ }
5052
+ endSpanOnce(SpanStatusCode.ERROR, err);
5053
+ throw error;
5054
+ }
5055
+ };
5056
+ };
5057
+ }
5058
+ if (prop === "then" || prop === "catch" || prop === "finally") {
5059
+ const originalMethod = target[prop];
5060
+ if (typeof originalMethod !== "function") return originalMethod;
5061
+ if (prop === "then") {
5062
+ return function(onFulfilled, onRejected) {
5063
+ return originalMethod.call(
5064
+ target,
5065
+ (v) => {
5066
+ endSpanOnce(SpanStatusCode.OK);
5067
+ return onFulfilled ? onFulfilled(v) : v;
5068
+ },
5069
+ (e) => {
5070
+ endSpanOnce(
5071
+ SpanStatusCode.ERROR,
5072
+ e instanceof Error ? e : new Error(String(e))
5073
+ );
5074
+ if (onRejected) return onRejected(e);
5075
+ throw e;
5076
+ }
5077
+ );
5078
+ };
5079
+ }
5080
+ if (prop === "catch") {
5081
+ return function(onRejected) {
5082
+ return receiver.then(void 0, onRejected);
5083
+ };
5084
+ }
5085
+ if (prop === "finally") {
5086
+ return function(onFinally) {
5087
+ return receiver.then(
5088
+ (v) => {
5089
+ onFinally?.();
5090
+ return v;
5091
+ },
5092
+ (e) => {
5093
+ onFinally?.();
5094
+ throw e;
5095
+ }
5096
+ );
5097
+ };
5098
+ }
5099
+ }
5100
+ const value = target[prop];
5101
+ if (typeof value === "function") return value.bind(target);
5102
+ return value;
5103
+ }
5104
+ });
5105
+ } catch (error) {
5106
+ endSpanOnce(
5107
+ SpanStatusCode.ERROR,
5108
+ error instanceof Error ? error : new Error(String(error))
5109
+ );
5110
+ throw error;
4519
5111
  }
4520
- }
4521
- this.span.addEvent("llm.content.completion.chunk", {
4522
- "chunk.type": chunk.type
4523
- });
4524
- }
4525
- finalizeSpan(code) {
4526
- const endTime = Date.now();
4527
- const duration = (endTime - this.startTime) / 1e3;
4528
- setResponseAttributes2(this.span, {
4529
- model: this.completeResponse.model,
4530
- content: this.completeResponse.content,
4531
- usage: this.completeResponse.usage
4532
- });
4533
- this.span.setAttribute("llm.response.duration", duration);
4534
- this.span.setStatus({ code });
4535
- this.span.end();
4536
- }
4537
- };
5112
+ };
5113
+ };
5114
+ }
5115
+ var chatWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.CHAT, "chat");
5116
+ var betaWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.BETA, "beta");
5117
+ var batchesWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.BATCHES, "batches");
5118
+ var chatStreamWrapper = (tracer, originalCreate) => streamWrapper(tracer, SPAN_NAMES.STREAM, "chat", originalCreate);
5119
+ var betaStreamWrapper = (tracer, originalCreate) => streamWrapper(tracer, SPAN_NAMES.BETA_STREAM, "beta", originalCreate);
5120
+ var betaToolRunnerWrapper = (tracer) => toolRunnerWrapper(tracer, SPAN_NAMES.BETA_TOOL_RUNNER, "beta");
4538
5121
 
4539
5122
  // src/instrumentation/anthropic/index.ts
4540
5123
  var INSTRUMENTATION_NAME = "netra.instrumentation.anthropic";
4541
5124
  var INSTRUMENTS = ["anthropic >= 0.71.2"];
4542
- var originalMethods = /* @__PURE__ */ new Map();
4543
5125
  var isInstrumented = false;
4544
5126
  var anthropicClasses = [];
4545
- async function resolveAnthropicAsync() {
5127
+ async function resolveAnthropic() {
4546
5128
  if (anthropicClasses.length > 0) return anthropicClasses;
4547
5129
  try {
4548
5130
  const anthropicModule = await import('@anthropic-ai/sdk');
4549
- anthropicClasses.push(anthropicModule.Anthropic || anthropicModule.default || anthropicModule);
5131
+ anthropicClasses.push(
5132
+ anthropicModule.Anthropic || anthropicModule.default || anthropicModule
5133
+ );
4550
5134
  } catch {
4551
5135
  Logger.warn("Failed to resolve Anthropic ESM module");
4552
5136
  }
@@ -4562,9 +5146,6 @@ async function resolveAnthropicAsync() {
4562
5146
  }
4563
5147
  return anthropicClasses;
4564
5148
  }
4565
- function resolveAnthropic() {
4566
- return anthropicClasses;
4567
- }
4568
5149
  var NetraAnthropicInstrumentor = class {
4569
5150
  constructor() {
4570
5151
  this.tracer = null;
@@ -4572,15 +5153,13 @@ var NetraAnthropicInstrumentor = class {
4572
5153
  instrumentationDependencies() {
4573
5154
  return INSTRUMENTS;
4574
5155
  }
4575
- async instrumentAsync(options = {}) {
5156
+ async instrument(options = {}) {
4576
5157
  if (isInstrumented) {
4577
5158
  Logger.warn("Anthropic is already instrumented");
4578
5159
  return this;
4579
5160
  }
4580
- const classes = await resolveAnthropicAsync();
4581
- if (classes.length === 0) {
4582
- return this;
4583
- }
5161
+ const classes = await resolveAnthropic();
5162
+ if (classes.length === 0) return this;
4584
5163
  try {
4585
5164
  this.tracerProvider = options.tracerProvider;
4586
5165
  if (this.tracerProvider) {
@@ -4595,10 +5174,10 @@ var NetraAnthropicInstrumentor = class {
4595
5174
  Logger.error(`Failed to initialize tracer: ${error}`);
4596
5175
  return this;
4597
5176
  }
4598
- classes.forEach((AnthropicSDK, index) => {
4599
- this._instrumentMessages(AnthropicSDK, index);
4600
- this._instrumentBetaMessages(AnthropicSDK, index);
4601
- this._instrumentBatchMessages(AnthropicSDK, index);
5177
+ classes.forEach((AnthropicSDK) => {
5178
+ this._instrumentMessages(AnthropicSDK);
5179
+ this._instrumentBetaMessages(AnthropicSDK);
5180
+ this._instrumentBatchMessages(AnthropicSDK);
4602
5181
  });
4603
5182
  isInstrumented = true;
4604
5183
  return this;
@@ -4608,185 +5187,137 @@ var NetraAnthropicInstrumentor = class {
4608
5187
  Logger.warn("Anthropic is not instrumented");
4609
5188
  return;
4610
5189
  }
4611
- const classes = resolveAnthropic();
4612
- classes.forEach((AnthropicSDK, index) => {
4613
- this._uninstrumentMessages(AnthropicSDK, index);
4614
- this._uninstrumentBetaMessages(AnthropicSDK, index);
4615
- this._uninstrumentBatchMessages(AnthropicSDK, index);
5190
+ anthropicClasses.forEach((AnthropicSDK) => {
5191
+ this._uninstrumentMessages(AnthropicSDK);
5192
+ this._uninstrumentBetaMessages(AnthropicSDK);
5193
+ this._uninstrumentBatchMessages(AnthropicSDK);
4616
5194
  });
4617
- originalMethods.clear();
4618
5195
  anthropicClasses = [];
4619
5196
  isInstrumented = false;
4620
5197
  }
4621
5198
  isInstrumented() {
4622
5199
  return isInstrumented;
4623
5200
  }
4624
- _instrumentMessages(AnthropicSDK, index) {
5201
+ _instrumentMessages(AnthropicSDK) {
4625
5202
  if (!this.tracer) {
4626
5203
  Logger.warn("Anthropic instrumentation: No tracer available");
4627
5204
  return;
4628
5205
  }
4629
5206
  try {
4630
5207
  const MessagesClass = AnthropicSDK.Messages;
4631
- if (!MessagesClass) {
5208
+ if (!MessagesClass?.prototype) {
4632
5209
  Logger.error(
4633
- "Anthropic instrumentation: Could not find Anthropic Messages class to instrument"
5210
+ "Anthropic instrumentation: Could not find Messages class"
4634
5211
  );
4635
5212
  return;
4636
5213
  }
4637
- if (MessagesClass?.prototype?.stream) {
4638
- const originalStream = MessagesClass.prototype.stream;
4639
- originalMethods.set(`messages.stream-${index}`, originalStream);
4640
- const tracer = this.tracer;
4641
- MessagesClass.prototype.stream = function(...args) {
4642
- const original = originalStream.bind(this);
4643
- const kwargs = args[0] || {};
4644
- const currentContext = context.active();
4645
- const span2 = tracer.startSpan("anthropic.stream", {
4646
- kind: SpanKind.CLIENT,
4647
- attributes: {
4648
- "llm.request.type": "chat",
4649
- "llm.streaming": true,
4650
- "llm.operation": "stream"
4651
- }
4652
- }, currentContext);
4653
- const spanContext = trace.setSpan(currentContext, span2);
4654
- setRequestAttributes2(span2, kwargs, "chat");
4655
- const startTime = Date.now();
4656
- const instrumentedCreate = this.create;
4657
- const originalCreate = originalMethods.get(`messages.create-${index}`);
4658
- if (originalCreate) {
4659
- this.create = originalCreate;
4660
- }
4661
- try {
4662
- const messageStream = context.with(spanContext, () => original(...args));
4663
- return new MessageStreamWrapper(span2, messageStream, startTime, kwargs, spanContext);
4664
- } finally {
4665
- if (originalCreate) {
4666
- this.create = instrumentedCreate;
4667
- }
4668
- }
4669
- };
5214
+ const originalCreate = MessagesClass.prototype.create;
5215
+ if (typeof MessagesClass.prototype.create === "function") {
5216
+ shimmer.wrap(
5217
+ MessagesClass.prototype,
5218
+ "create",
5219
+ chatWrapper(this.tracer)
5220
+ );
4670
5221
  }
4671
- if (MessagesClass?.prototype?.create) {
4672
- const originalCreate = MessagesClass.prototype.create;
4673
- originalMethods.set(`messages.create-${index}`, originalCreate);
4674
- const tracer = this.tracer;
4675
- const wrapper = chatWrapper(tracer);
4676
- MessagesClass.prototype.create = function(...args) {
4677
- const original = originalCreate.bind(this);
4678
- const kwargs = args[0] || {};
4679
- return wrapper(
4680
- (...a) => original(...a),
4681
- this,
4682
- args,
4683
- kwargs
4684
- );
4685
- };
5222
+ if (typeof MessagesClass.prototype.stream === "function") {
5223
+ shimmer.wrap(
5224
+ MessagesClass.prototype,
5225
+ "stream",
5226
+ chatStreamWrapper(this.tracer, originalCreate)
5227
+ );
4686
5228
  }
4687
5229
  } catch (error) {
4688
5230
  Logger.error(`Failed to instrument messages: ${error}`);
4689
5231
  }
4690
5232
  }
4691
- _instrumentBetaMessages(AnthropicSDK, index) {
5233
+ _instrumentBetaMessages(AnthropicSDK) {
4692
5234
  if (!this.tracer) {
4693
5235
  Logger.warn("Anthropic instrumentation: No tracer available");
4694
5236
  return;
4695
5237
  }
4696
5238
  try {
4697
5239
  const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
4698
- if (!BetaMessagesClass) {
5240
+ if (!BetaMessagesClass?.prototype) {
4699
5241
  Logger.error(
4700
- "Anthropic instrumentation: Could not find Anthropic Beta Messages class to instrument"
5242
+ "Anthropic instrumentation: Could not find Beta Messages class"
4701
5243
  );
4702
5244
  return;
4703
5245
  }
4704
- if (BetaMessagesClass?.prototype?.create) {
4705
- const originalCreate = BetaMessagesClass.prototype.create;
4706
- originalMethods.set(`beta.messages.create-${index}`, originalCreate);
4707
- const tracer = this.tracer;
4708
- const wrapper = betaWrapper(tracer);
4709
- BetaMessagesClass.prototype.create = function(...args) {
4710
- const original = originalCreate.bind(this);
4711
- const kwargs = args[0] || {};
4712
- return wrapper(
4713
- (...a) => original(...a),
4714
- this,
4715
- args,
4716
- kwargs
4717
- );
4718
- };
5246
+ const originalCreate = BetaMessagesClass.prototype.create;
5247
+ if (typeof BetaMessagesClass.prototype.create === "function") {
5248
+ shimmer.wrap(
5249
+ BetaMessagesClass.prototype,
5250
+ "create",
5251
+ betaWrapper(this.tracer)
5252
+ );
5253
+ }
5254
+ if (typeof BetaMessagesClass.prototype.stream === "function") {
5255
+ shimmer.wrap(
5256
+ BetaMessagesClass.prototype,
5257
+ "stream",
5258
+ betaStreamWrapper(this.tracer, originalCreate)
5259
+ );
5260
+ }
5261
+ if (typeof BetaMessagesClass.prototype.toolRunner === "function") {
5262
+ shimmer.wrap(
5263
+ BetaMessagesClass.prototype,
5264
+ "toolRunner",
5265
+ betaToolRunnerWrapper(this.tracer)
5266
+ );
4719
5267
  }
4720
5268
  } catch (error) {
4721
5269
  Logger.error(`Failed to instrument beta: ${error}`);
4722
5270
  }
4723
5271
  }
4724
- _instrumentBatchMessages(AnthropicSDK, index) {
5272
+ _instrumentBatchMessages(AnthropicSDK) {
4725
5273
  if (!this.tracer) {
4726
5274
  Logger.warn("Anthropic instrumentation: No tracer available");
4727
5275
  return;
4728
5276
  }
4729
5277
  try {
4730
5278
  const BatchMessageClass = AnthropicSDK.Messages?.Batches;
4731
- if (!BatchMessageClass) {
4732
- Logger.error(
4733
- "Anthropic instrumentation: Could not find Anthropic Batches class to instrument"
4734
- );
5279
+ if (!BatchMessageClass?.prototype) {
5280
+ Logger.error("Anthropic instrumentation: Could not find Batches class");
4735
5281
  return;
4736
5282
  }
4737
- if (BatchMessageClass?.prototype?.create) {
4738
- const originalCreate = BatchMessageClass.prototype.create;
4739
- originalMethods.set(`batch.messages.create-${index}`, originalCreate);
4740
- const tracer = this.tracer;
4741
- const wrapper = batchesWrapper(tracer);
4742
- BatchMessageClass.prototype.create = function(...args) {
4743
- const original = originalCreate.bind(this);
4744
- const kwargs = args[0] || {};
4745
- return wrapper(
4746
- (...a) => original(...a),
4747
- this,
4748
- args,
4749
- kwargs
4750
- );
4751
- };
5283
+ if (typeof BatchMessageClass.prototype.create === "function") {
5284
+ shimmer.wrap(
5285
+ BatchMessageClass.prototype,
5286
+ "create",
5287
+ batchesWrapper(this.tracer)
5288
+ );
4752
5289
  }
4753
5290
  } catch (error) {
4754
5291
  Logger.error(`Failed to instrument batches: ${error}`);
4755
5292
  }
4756
5293
  }
4757
- _uninstrumentMessages(AnthropicSDK, index) {
5294
+ _uninstrumentMessages(AnthropicSDK) {
4758
5295
  try {
4759
- const MessagesClass = AnthropicSDK.Messages;
4760
- const originalCreate = originalMethods.get(`messages.create-${index}`);
4761
- if (originalCreate && MessagesClass?.prototype) {
4762
- MessagesClass.prototype.create = originalCreate;
4763
- }
4764
- const originalStream = originalMethods.get(`messages.stream-${index}`);
4765
- if (originalStream && MessagesClass?.prototype) {
4766
- MessagesClass.prototype.stream = originalStream;
4767
- }
5296
+ const proto = AnthropicSDK.Messages?.prototype;
5297
+ if (!proto) return;
5298
+ if (typeof proto.create === "function") shimmer.unwrap(proto, "create");
5299
+ if (typeof proto.stream === "function") shimmer.unwrap(proto, "stream");
4768
5300
  } catch (error) {
4769
5301
  Logger.error(`Failed to uninstrument messages: ${error}`);
4770
5302
  }
4771
5303
  }
4772
- _uninstrumentBetaMessages(AnthropicSDK, index) {
5304
+ _uninstrumentBetaMessages(AnthropicSDK) {
4773
5305
  try {
4774
- const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
4775
- const originalCreate = originalMethods.get(`beta.messages.create-${index}`);
4776
- if (originalCreate && BetaMessagesClass?.prototype) {
4777
- BetaMessagesClass.prototype.create = originalCreate;
4778
- }
5306
+ const proto = AnthropicSDK.Beta?.Messages?.prototype;
5307
+ if (!proto) return;
5308
+ if (typeof proto.create === "function") shimmer.unwrap(proto, "create");
5309
+ if (typeof proto.stream === "function") shimmer.unwrap(proto, "stream");
5310
+ if (typeof proto.toolRunner === "function")
5311
+ shimmer.unwrap(proto, "toolRunner");
4779
5312
  } catch (error) {
4780
5313
  Logger.error(`Failed to uninstrument beta: ${error}`);
4781
5314
  }
4782
5315
  }
4783
- _uninstrumentBatchMessages(AnthropicSDK, index) {
5316
+ _uninstrumentBatchMessages(AnthropicSDK) {
4784
5317
  try {
4785
- const BatchMessagesClass = AnthropicSDK.Messages?.Batches;
4786
- const originalCreate = originalMethods.get(`batch.messages.create-${index}`);
4787
- if (originalCreate && BatchMessagesClass?.prototype) {
4788
- BatchMessagesClass.prototype.create = originalCreate;
4789
- }
5318
+ const proto = AnthropicSDK.Messages?.Batches?.prototype;
5319
+ if (!proto) return;
5320
+ if (typeof proto.create === "function") shimmer.unwrap(proto, "create");
4790
5321
  } catch (error) {
4791
5322
  Logger.error(`Failed to uninstrument batches: ${error}`);
4792
5323
  }
@@ -5202,7 +5733,7 @@ function _setEmbeddingResponseAttributes(span2, response) {
5202
5733
  }
5203
5734
 
5204
5735
  // src/instrumentation/google-genai/wrappers.ts
5205
- var CHAT_SPAN_NAME2 = "google_genai.chat";
5736
+ var CHAT_SPAN_NAME = "google_genai.chat";
5206
5737
  var EMBEDDING_SPAN_NAME = "google_genai.embedding";
5207
5738
  function googleGenAIWrapper(tracer, spanName, requestType) {
5208
5739
  return function wrapper(original) {
@@ -5481,10 +6012,10 @@ function googleGenAIStartChatWrapper(tracer, spanName, requestType) {
5481
6012
  };
5482
6013
  };
5483
6014
  }
5484
- var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME2, "chat");
6015
+ var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME, "chat");
5485
6016
  var embeddingsWrapper = (tracer) => googleGenAIWrapper(tracer, EMBEDDING_SPAN_NAME, "embedding");
5486
- var chatStreamWrapper = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5487
- var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME2, "chat");
6017
+ var chatStreamWrapper2 = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME, "chat");
6018
+ var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME, "chat");
5488
6019
  var INSTRUMENTATION_NAME2 = "netra.instrumentation.google_genai";
5489
6020
  var INSTRUMENTS2 = ["@google/genai >= 0.24.1"];
5490
6021
  var isInstrumented2 = false;
@@ -5610,7 +6141,7 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5610
6141
  shimmer.wrap(
5611
6142
  GenerativeModel.prototype,
5612
6143
  "generateContentStream",
5613
- chatStreamWrapper(tracer)
6144
+ chatStreamWrapper2(tracer)
5614
6145
  );
5615
6146
  shimmer.wrap(
5616
6147
  GenerativeModel.prototype,
@@ -5672,8 +6203,8 @@ function setResponseAttributes4(span2, response) {
5672
6203
  }
5673
6204
 
5674
6205
  // src/instrumentation/groq/wrappers.ts
5675
- var CHAT_SPAN_NAME3 = "groq.chat";
5676
- var STREAM_ENABLED_REQUESTS2 = ["chat"];
6206
+ var CHAT_SPAN_NAME2 = "groq.chat";
6207
+ var STREAM_ENABLED_REQUESTS = ["chat"];
5677
6208
  function groqWrapper(tracer, spanName, requestType) {
5678
6209
  return function wrapper(wrapped, instance, args, kwargs) {
5679
6210
  if (shouldSuppressInstrumentation()) {
@@ -5681,7 +6212,7 @@ function groqWrapper(tracer, spanName, requestType) {
5681
6212
  return isPromise(result) ? result.then((value) => value) : result;
5682
6213
  }
5683
6214
  const isStreaming = kwargs.stream === true;
5684
- if (isStreaming && STREAM_ENABLED_REQUESTS2.includes(requestType)) {
6215
+ if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
5685
6216
  const currentContext = context.active();
5686
6217
  const span2 = tracer.startSpan(
5687
6218
  spanName,
@@ -5699,7 +6230,7 @@ function groqWrapper(tracer, spanName, requestType) {
5699
6230
  return (async () => {
5700
6231
  try {
5701
6232
  const stream = await response;
5702
- return new AsyncStreamingWrapper2(span2, stream, startTime, kwargs);
6233
+ return new AsyncStreamingWrapper(span2, stream, startTime, kwargs);
5703
6234
  } catch (error) {
5704
6235
  Logger.error("netra.instrumentation.groq:", error);
5705
6236
  span2.setStatus({
@@ -5788,7 +6319,7 @@ function groqWrapper(tracer, spanName, requestType) {
5788
6319
  }
5789
6320
  };
5790
6321
  }
5791
- var chatWrapper3 = (tracer) => groqWrapper(tracer, CHAT_SPAN_NAME3, "chat");
6322
+ var chatWrapper3 = (tracer) => groqWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5792
6323
  var StreamingWrapper = class {
5793
6324
  constructor(span2, response, startTime, requestKwargs) {
5794
6325
  this.iterator = null;
@@ -5886,7 +6417,7 @@ var StreamingWrapper = class {
5886
6417
  this.span.end();
5887
6418
  }
5888
6419
  };
5889
- var AsyncStreamingWrapper2 = class {
6420
+ var AsyncStreamingWrapper = class {
5890
6421
  constructor(span2, response, startTime, requestKwargs) {
5891
6422
  this.iterator = null;
5892
6423
  this.completeResponse = {
@@ -6006,7 +6537,7 @@ var AsyncStreamingWrapper2 = class {
6006
6537
  // src/instrumentation/groq/index.ts
6007
6538
  var INSTRUMENTATION_NAME3 = "netra.instrumentation.groq";
6008
6539
  var INSTRUMENTS3 = ["groq-sdk >= 0.3.0"];
6009
- var originalMethods2 = /* @__PURE__ */ new Map();
6540
+ var originalMethods = /* @__PURE__ */ new Map();
6010
6541
  var isInstrumented3 = false;
6011
6542
  var groqClasses = [];
6012
6543
  async function resolveGroqAsync() {
@@ -6117,7 +6648,7 @@ var NetraGroqInstrumentor = class {
6117
6648
  classes.forEach((Groq, index) => {
6118
6649
  this._uninstrumentChatCompletions(Groq, index);
6119
6650
  });
6120
- originalMethods2.clear();
6651
+ originalMethods.clear();
6121
6652
  groqClasses = [];
6122
6653
  isInstrumented3 = false;
6123
6654
  }
@@ -6138,7 +6669,7 @@ var NetraGroqInstrumentor = class {
6138
6669
  return;
6139
6670
  }
6140
6671
  const originalCreate = CompletionsClass.prototype.create;
6141
- originalMethods2.set(`chat.completions.create-${index}`, originalCreate);
6672
+ originalMethods.set(`chat.completions.create-${index}`, originalCreate);
6142
6673
  const tracer = this.tracer;
6143
6674
  const wrapper = chatWrapper3(tracer);
6144
6675
  CompletionsClass.prototype.create = function(...args) {
@@ -6156,7 +6687,7 @@ var NetraGroqInstrumentor = class {
6156
6687
  _uninstrumentChatCompletions(Groq, index) {
6157
6688
  try {
6158
6689
  const CompletionsClass = Groq.Chat?.Completions;
6159
- const originalCreate = originalMethods2.get(`chat.completions.create-${index}`);
6690
+ const originalCreate = originalMethods.get(`chat.completions.create-${index}`);
6160
6691
  if (originalCreate && CompletionsClass?.prototype) {
6161
6692
  CompletionsClass.prototype.create = originalCreate;
6162
6693
  }
@@ -6995,7 +7526,7 @@ var INSTRUMENTATION_NAME4 = "netra.instrumentation.langgraph";
6995
7526
  var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
6996
7527
  var isInstrumented4 = false;
6997
7528
  var LanggraphClass = null;
6998
- var originalMethods3 = /* @__PURE__ */ new Map();
7529
+ var originalMethods2 = /* @__PURE__ */ new Map();
6999
7530
  function findModuleInCache(moduleName) {
7000
7531
  if (typeof __require !== "undefined" && __require.cache) {
7001
7532
  const cache = __require.cache;
@@ -7091,7 +7622,7 @@ var NetraLanggraphInstrumentor = class {
7091
7622
  this._uninstrumentInvoke(Langgraph);
7092
7623
  this._uninstrumentStream(Langgraph);
7093
7624
  }
7094
- originalMethods3.clear();
7625
+ originalMethods2.clear();
7095
7626
  LanggraphClass = null;
7096
7627
  isInstrumented4 = false;
7097
7628
  }
@@ -7108,8 +7639,8 @@ var NetraLanggraphInstrumentor = class {
7108
7639
  }
7109
7640
  Logger.debug(`Found invoke on prototype: ${targetProto.constructor?.name}`);
7110
7641
  const originalInvoke = targetProto.invoke;
7111
- originalMethods3.set("langgraph.graph.invoke", originalInvoke);
7112
- originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
7642
+ originalMethods2.set("langgraph.graph.invoke", originalInvoke);
7643
+ originalMethods2.set("langgraph.graph.invoke.proto", targetProto);
7113
7644
  const tracer = this.tracer;
7114
7645
  const wrapper = new LanggraphWrapper(tracer);
7115
7646
  const patchedInvoke = async function(input, config2, ...rest) {
@@ -7143,8 +7674,8 @@ var NetraLanggraphInstrumentor = class {
7143
7674
  }
7144
7675
  Logger.debug(`Found stream on prototype: ${targetProto.constructor?.name}`);
7145
7676
  const originalStream = targetProto.stream;
7146
- originalMethods3.set("langgraph.graph.stream", originalStream);
7147
- originalMethods3.set("langgraph.graph.stream.proto", targetProto);
7677
+ originalMethods2.set("langgraph.graph.stream", originalStream);
7678
+ originalMethods2.set("langgraph.graph.stream.proto", targetProto);
7148
7679
  const tracer = this.tracer;
7149
7680
  const wrapper = new LanggraphWrapper(tracer);
7150
7681
  targetProto.stream = async function(input, config2, ...rest) {
@@ -7164,8 +7695,8 @@ var NetraLanggraphInstrumentor = class {
7164
7695
  }
7165
7696
  _uninstrumentInvoke(Langgraph) {
7166
7697
  try {
7167
- const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
7168
- const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
7698
+ const originalInvoke = originalMethods2.get("langgraph.graph.invoke");
7699
+ const targetProto = originalMethods2.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
7169
7700
  if (originalInvoke && targetProto?.invoke) {
7170
7701
  targetProto.invoke = originalInvoke;
7171
7702
  }
@@ -7176,8 +7707,8 @@ var NetraLanggraphInstrumentor = class {
7176
7707
  }
7177
7708
  _uninstrumentStream(Langgraph) {
7178
7709
  try {
7179
- const originalStream = originalMethods3.get("langgraph.graph.stream");
7180
- const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
7710
+ const originalStream = originalMethods2.get("langgraph.graph.stream");
7711
+ const targetProto = originalMethods2.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
7181
7712
  if (originalStream && targetProto?.stream) {
7182
7713
  targetProto.stream = originalStream;
7183
7714
  }
@@ -7217,11 +7748,11 @@ function setResponseAttributes5(span2, response) {
7217
7748
  }
7218
7749
 
7219
7750
  // src/instrumentation/mistralai/wrappers.ts
7220
- var CHAT_SPAN_NAME4 = "mistralai.chat";
7751
+ var CHAT_SPAN_NAME3 = "mistralai.chat";
7221
7752
  var EMBEDDING_SPAN_NAME2 = "mistralai.embedding";
7222
7753
  var FIM_SPAN_NAME = "mistralai.fim";
7223
7754
  var AGENTS_SPAN_NAME = "mistralai.agents";
7224
- var CHAT_STREAM_SPAN_NAME = CHAT_SPAN_NAME4;
7755
+ var CHAT_STREAM_SPAN_NAME = CHAT_SPAN_NAME3;
7225
7756
  var FIM_STREAM_SPAN_NAME = FIM_SPAN_NAME;
7226
7757
  var AGENTS_STREAM_SPAN_NAME = AGENTS_SPAN_NAME;
7227
7758
  function mistralWrapper(tracer, spanName, requestType) {
@@ -7316,7 +7847,7 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
7316
7847
  try {
7317
7848
  const stream = await response;
7318
7849
  if (stream && typeof stream === "object" && Symbol.asyncIterator in stream) {
7319
- return new AsyncStreamingWrapper3(span2, stream, startTime, kwargs);
7850
+ return new AsyncStreamingWrapper2(span2, stream, startTime, kwargs);
7320
7851
  }
7321
7852
  return new StreamingWrapper2(span2, stream, startTime, kwargs);
7322
7853
  } catch (error) {
@@ -7332,7 +7863,7 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
7332
7863
  })();
7333
7864
  }
7334
7865
  if (response && typeof response === "object" && Symbol.asyncIterator in response) {
7335
- return new AsyncStreamingWrapper3(span2, response, startTime, kwargs);
7866
+ return new AsyncStreamingWrapper2(span2, response, startTime, kwargs);
7336
7867
  }
7337
7868
  return new StreamingWrapper2(span2, response, startTime, kwargs);
7338
7869
  } catch (error) {
@@ -7347,8 +7878,8 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
7347
7878
  }
7348
7879
  };
7349
7880
  }
7350
- var chatWrapper4 = (tracer) => mistralWrapper(tracer, CHAT_SPAN_NAME4, "chat");
7351
- var chatStreamWrapper2 = (tracer) => mistralStreamWrapper(tracer, CHAT_STREAM_SPAN_NAME, "chat");
7881
+ var chatWrapper4 = (tracer) => mistralWrapper(tracer, CHAT_SPAN_NAME3, "chat");
7882
+ var chatStreamWrapper3 = (tracer) => mistralStreamWrapper(tracer, CHAT_STREAM_SPAN_NAME, "chat");
7352
7883
  var embeddingsWrapper2 = (tracer) => mistralWrapper(tracer, EMBEDDING_SPAN_NAME2, "embedding");
7353
7884
  var fimWrapper = (tracer) => mistralWrapper(tracer, FIM_SPAN_NAME, "fim");
7354
7885
  var fimStreamWrapper = (tracer) => mistralStreamWrapper(tracer, FIM_STREAM_SPAN_NAME, "fim");
@@ -7499,7 +8030,7 @@ var StreamingWrapper2 = class {
7499
8030
  this.span.end();
7500
8031
  }
7501
8032
  };
7502
- var AsyncStreamingWrapper3 = class {
8033
+ var AsyncStreamingWrapper2 = class {
7503
8034
  constructor(span2, response, startTime, requestKwargs) {
7504
8035
  this.iterator = null;
7505
8036
  defineHidden(this, "span", span2);
@@ -7649,7 +8180,7 @@ var AsyncStreamingWrapper3 = class {
7649
8180
  // src/instrumentation/mistralai/index.ts
7650
8181
  var INSTRUMENTATION_NAME5 = "netra.instrumentation.mistral_ai";
7651
8182
  var INSTRUMENTS5 = ["@mistralai/mistralai >= 1.0.0"];
7652
- var originalMethods4 = /* @__PURE__ */ new Map();
8183
+ var originalMethods3 = /* @__PURE__ */ new Map();
7653
8184
  var isInstrumented5 = false;
7654
8185
  var mistralClasses = [];
7655
8186
  async function resolveMistralAsync() {
@@ -7798,7 +8329,7 @@ var NetraMistralAIInstrumentor = class {
7798
8329
  this._uninstrumentFIM(Mistral, index);
7799
8330
  this._uninstrumentAgents(Mistral, index);
7800
8331
  });
7801
- originalMethods4.clear();
8332
+ originalMethods3.clear();
7802
8333
  mistralClasses = [];
7803
8334
  isInstrumented5 = false;
7804
8335
  }
@@ -7844,7 +8375,7 @@ var NetraMistralAIInstrumentor = class {
7844
8375
  let didPatch = false;
7845
8376
  if (ChatClass?.prototype?.complete) {
7846
8377
  const originalComplete = ChatClass.prototype.complete;
7847
- originalMethods4.set(`chat.complete-${index}`, originalComplete);
8378
+ originalMethods3.set(`chat.complete-${index}`, originalComplete);
7848
8379
  const tracer = this.tracer;
7849
8380
  const wrapper = chatWrapper4(tracer);
7850
8381
  ChatClass.prototype.complete = function(...args) {
@@ -7861,9 +8392,9 @@ var NetraMistralAIInstrumentor = class {
7861
8392
  }
7862
8393
  if (ChatClass?.prototype?.stream) {
7863
8394
  const originalStream = ChatClass.prototype.stream;
7864
- originalMethods4.set(`chat.stream-${index}`, originalStream);
8395
+ originalMethods3.set(`chat.stream-${index}`, originalStream);
7865
8396
  const tracer = this.tracer;
7866
- const wrapper = chatStreamWrapper2(tracer);
8397
+ const wrapper = chatStreamWrapper3(tracer);
7867
8398
  ChatClass.prototype.stream = function(...args) {
7868
8399
  const original = originalStream.bind(this);
7869
8400
  const kwargs = args[0] || {};
@@ -7889,7 +8420,7 @@ var NetraMistralAIInstrumentor = class {
7889
8420
  let didPatch = false;
7890
8421
  if (EmbeddingsClass?.prototype?.create) {
7891
8422
  const originalCreate = EmbeddingsClass.prototype.create;
7892
- originalMethods4.set(`embeddings.create-${index}`, originalCreate);
8423
+ originalMethods3.set(`embeddings.create-${index}`, originalCreate);
7893
8424
  const tracer = this.tracer;
7894
8425
  const wrapper = embeddingsWrapper2(tracer);
7895
8426
  EmbeddingsClass.prototype.create = function(...args) {
@@ -7917,7 +8448,7 @@ var NetraMistralAIInstrumentor = class {
7917
8448
  let didPatch = false;
7918
8449
  if (FimClass?.prototype?.complete) {
7919
8450
  const originalComplete = FimClass.prototype.complete;
7920
- originalMethods4.set(`fim.complete-${index}`, originalComplete);
8451
+ originalMethods3.set(`fim.complete-${index}`, originalComplete);
7921
8452
  const tracer = this.tracer;
7922
8453
  const wrapper = fimWrapper(tracer);
7923
8454
  FimClass.prototype.complete = function(...args) {
@@ -7934,7 +8465,7 @@ var NetraMistralAIInstrumentor = class {
7934
8465
  }
7935
8466
  if (FimClass?.prototype?.stream) {
7936
8467
  const originalStream = FimClass.prototype.stream;
7937
- originalMethods4.set(`fim.stream-${index}`, originalStream);
8468
+ originalMethods3.set(`fim.stream-${index}`, originalStream);
7938
8469
  const tracer = this.tracer;
7939
8470
  const wrapper = fimStreamWrapper(tracer);
7940
8471
  FimClass.prototype.stream = function(...args) {
@@ -7962,7 +8493,7 @@ var NetraMistralAIInstrumentor = class {
7962
8493
  let didPatch = false;
7963
8494
  if (AgentsClass?.prototype?.complete) {
7964
8495
  const originalComplete = AgentsClass.prototype.complete;
7965
- originalMethods4.set(`agents.complete-${index}`, originalComplete);
8496
+ originalMethods3.set(`agents.complete-${index}`, originalComplete);
7966
8497
  const tracer = this.tracer;
7967
8498
  const wrapper = agentsWrapper(tracer);
7968
8499
  AgentsClass.prototype.complete = function(...args) {
@@ -7979,7 +8510,7 @@ var NetraMistralAIInstrumentor = class {
7979
8510
  }
7980
8511
  if (AgentsClass?.prototype?.stream) {
7981
8512
  const originalStream = AgentsClass.prototype.stream;
7982
- originalMethods4.set(`agents.stream-${index}`, originalStream);
8513
+ originalMethods3.set(`agents.stream-${index}`, originalStream);
7983
8514
  const tracer = this.tracer;
7984
8515
  const wrapper = agentsStreamWrapper(tracer);
7985
8516
  AgentsClass.prototype.stream = function(...args) {
@@ -8003,11 +8534,11 @@ var NetraMistralAIInstrumentor = class {
8003
8534
  _uninstrumentChat(Mistral, index) {
8004
8535
  try {
8005
8536
  const ChatClass = this._getCtor(Mistral, "chat");
8006
- const originalComplete = originalMethods4.get(`chat.complete-${index}`);
8537
+ const originalComplete = originalMethods3.get(`chat.complete-${index}`);
8007
8538
  if (originalComplete && ChatClass?.prototype) {
8008
8539
  ChatClass.prototype.complete = originalComplete;
8009
8540
  }
8010
- const originalStream = originalMethods4.get(`chat.stream-${index}`);
8541
+ const originalStream = originalMethods3.get(`chat.stream-${index}`);
8011
8542
  if (originalStream && ChatClass?.prototype) {
8012
8543
  ChatClass.prototype.stream = originalStream;
8013
8544
  }
@@ -8018,7 +8549,7 @@ var NetraMistralAIInstrumentor = class {
8018
8549
  _uninstrumentEmbeddings(Mistral, index) {
8019
8550
  try {
8020
8551
  const EmbeddingsClass = this._getCtor(Mistral, "embeddings");
8021
- const originalCreate = originalMethods4.get(`embeddings.create-${index}`);
8552
+ const originalCreate = originalMethods3.get(`embeddings.create-${index}`);
8022
8553
  if (originalCreate && EmbeddingsClass?.prototype) {
8023
8554
  EmbeddingsClass.prototype.create = originalCreate;
8024
8555
  }
@@ -8029,11 +8560,11 @@ var NetraMistralAIInstrumentor = class {
8029
8560
  _uninstrumentFIM(Mistral, index) {
8030
8561
  try {
8031
8562
  const FimClass = this._getCtor(Mistral, "fim");
8032
- const originalComplete = originalMethods4.get(`fim.complete-${index}`);
8563
+ const originalComplete = originalMethods3.get(`fim.complete-${index}`);
8033
8564
  if (originalComplete && FimClass?.prototype) {
8034
8565
  FimClass.prototype.complete = originalComplete;
8035
8566
  }
8036
- const originalStream = originalMethods4.get(`fim.stream-${index}`);
8567
+ const originalStream = originalMethods3.get(`fim.stream-${index}`);
8037
8568
  if (originalStream && FimClass?.prototype) {
8038
8569
  FimClass.prototype.stream = originalStream;
8039
8570
  }
@@ -8044,11 +8575,11 @@ var NetraMistralAIInstrumentor = class {
8044
8575
  _uninstrumentAgents(Mistral, index) {
8045
8576
  try {
8046
8577
  const AgentsClass = this._getCtor(Mistral, "agents");
8047
- const originalComplete = originalMethods4.get(`agents.complete-${index}`);
8578
+ const originalComplete = originalMethods3.get(`agents.complete-${index}`);
8048
8579
  if (originalComplete && AgentsClass?.prototype) {
8049
8580
  AgentsClass.prototype.complete = originalComplete;
8050
8581
  }
8051
- const originalStream = originalMethods4.get(`agents.stream-${index}`);
8582
+ const originalStream = originalMethods3.get(`agents.stream-${index}`);
8052
8583
  if (originalStream && AgentsClass?.prototype) {
8053
8584
  AgentsClass.prototype.stream = originalStream;
8054
8585
  }
@@ -8076,7 +8607,7 @@ function setResponseAttributes6(span2, response) {
8076
8607
  }
8077
8608
 
8078
8609
  // src/instrumentation/openai/wrappers.ts
8079
- var SPAN_NAMES = {
8610
+ var SPAN_NAMES2 = {
8080
8611
  chat: "openai.chat",
8081
8612
  embedding: "openai.embedding",
8082
8613
  response: "openai.response"
@@ -8217,7 +8748,7 @@ var StreamingWrapper3 = class extends BaseStreamHandler {
8217
8748
  throw new Error("Response is not iterable");
8218
8749
  }
8219
8750
  };
8220
- var AsyncStreamingWrapper4 = class extends BaseStreamHandler {
8751
+ var AsyncStreamingWrapper3 = class extends BaseStreamHandler {
8221
8752
  constructor(span2, response, startTime, requestKwargs) {
8222
8753
  super(span2, startTime, requestKwargs);
8223
8754
  this.iterator = null;
@@ -8273,7 +8804,7 @@ function executeStreaming(span2, ctx, kwargs, requestType, call) {
8273
8804
  return (async () => {
8274
8805
  try {
8275
8806
  const stream = await response;
8276
- return new AsyncStreamingWrapper4(span2, stream, startTime, kwargs);
8807
+ return new AsyncStreamingWrapper3(span2, stream, startTime, kwargs);
8277
8808
  } catch (error) {
8278
8809
  handleSpanError(span2, error);
8279
8810
  throw error;
@@ -8311,7 +8842,7 @@ function executeNonStreaming(span2, kwargs, requestType, call) {
8311
8842
  }
8312
8843
  }
8313
8844
  function openAIWrapper(tracer, requestType) {
8314
- const spanName = SPAN_NAMES[requestType];
8845
+ const spanName = SPAN_NAMES2[requestType];
8315
8846
  const spanOpts = { kind: SpanKind.CLIENT, attributes: { "llm.request.type": requestType } };
8316
8847
  return (wrapped, instance, args, kwargs) => {
8317
8848
  if (shouldSuppressInstrumentation()) {
@@ -9537,7 +10068,7 @@ function repositoryQueryWrapper(tracer) {
9537
10068
  var __version__8 = "1.0.0";
9538
10069
  var require2 = createRequire(import.meta.url);
9539
10070
  var INSTRUMENTATION_NAME8 = "netra.instrumentation.typeorm";
9540
- var originalMethods5 = /* @__PURE__ */ new Map();
10071
+ var originalMethods4 = /* @__PURE__ */ new Map();
9541
10072
  var isInstrumented7 = false;
9542
10073
  var NetraTypeORMInstrumentor = class {
9543
10074
  constructor() {
@@ -9571,7 +10102,7 @@ var NetraTypeORMInstrumentor = class {
9571
10102
  });
9572
10103
  this._uninstrumentRepository().catch(() => {
9573
10104
  });
9574
- originalMethods5.clear();
10105
+ originalMethods4.clear();
9575
10106
  isInstrumented7 = false;
9576
10107
  }
9577
10108
  isInstrumented() {
@@ -9590,7 +10121,7 @@ var NetraTypeORMInstrumentor = class {
9590
10121
  }
9591
10122
  if (DataSource.prototype?.query) {
9592
10123
  const originalQuery = DataSource.prototype.query;
9593
- originalMethods5.set("DataSource.prototype.query", originalQuery);
10124
+ originalMethods4.set("DataSource.prototype.query", originalQuery);
9594
10125
  const tracer = this.tracer;
9595
10126
  const wrapper = queryWrapper(tracer);
9596
10127
  DataSource.prototype.query = function(...args) {
@@ -9615,7 +10146,7 @@ var NetraTypeORMInstrumentor = class {
9615
10146
  }
9616
10147
  if (EntityManager.prototype?.query) {
9617
10148
  const originalQuery = EntityManager.prototype.query;
9618
- originalMethods5.set("EntityManager.prototype.query", originalQuery);
10149
+ originalMethods4.set("EntityManager.prototype.query", originalQuery);
9619
10150
  const tracer = this.tracer;
9620
10151
  const wrapper = managerQueryWrapper(tracer);
9621
10152
  EntityManager.prototype.query = function(...args) {
@@ -9640,7 +10171,7 @@ var NetraTypeORMInstrumentor = class {
9640
10171
  }
9641
10172
  if (Repository.prototype?.query) {
9642
10173
  const originalQuery = Repository.prototype.query;
9643
- originalMethods5.set("Repository.prototype.query", originalQuery);
10174
+ originalMethods4.set("Repository.prototype.query", originalQuery);
9644
10175
  const tracer = this.tracer;
9645
10176
  const wrapper = repositoryQueryWrapper(tracer);
9646
10177
  Repository.prototype.query = function(...args) {
@@ -9656,7 +10187,7 @@ var NetraTypeORMInstrumentor = class {
9656
10187
  try {
9657
10188
  const typeorm = require2("typeorm");
9658
10189
  const DataSource = typeorm.DataSource || typeorm.default?.DataSource;
9659
- const originalQuery = originalMethods5.get("DataSource.prototype.query");
10190
+ const originalQuery = originalMethods4.get("DataSource.prototype.query");
9660
10191
  if (originalQuery && DataSource?.prototype) {
9661
10192
  DataSource.prototype.query = originalQuery;
9662
10193
  }
@@ -9668,7 +10199,7 @@ var NetraTypeORMInstrumentor = class {
9668
10199
  try {
9669
10200
  const typeorm = require2("typeorm");
9670
10201
  const EntityManager = typeorm.EntityManager || typeorm.default?.EntityManager;
9671
- const originalQuery = originalMethods5.get("EntityManager.prototype.query");
10202
+ const originalQuery = originalMethods4.get("EntityManager.prototype.query");
9672
10203
  if (originalQuery && EntityManager?.prototype) {
9673
10204
  EntityManager.prototype.query = originalQuery;
9674
10205
  }
@@ -9680,7 +10211,7 @@ var NetraTypeORMInstrumentor = class {
9680
10211
  try {
9681
10212
  const typeorm = require2("typeorm");
9682
10213
  const Repository = typeorm.Repository || typeorm.default?.Repository;
9683
- const originalQuery = originalMethods5.get("Repository.prototype.query");
10214
+ const originalQuery = originalMethods4.get("Repository.prototype.query");
9684
10215
  if (originalQuery && Repository?.prototype) {
9685
10216
  Repository.prototype.query = originalQuery;
9686
10217
  }
@@ -10333,7 +10864,7 @@ async function initCustomInstrumentationsAsync(config2, tracerProvider, customIn
10333
10864
  }
10334
10865
  if (customInstrumentModules.anthropic) {
10335
10866
  try {
10336
- await anthropicInstrumentor.instrumentAsync({ tracerProvider });
10867
+ await anthropicInstrumentor.instrument({ tracerProvider });
10337
10868
  Logger.debug("Custom Anthropic instrumentation enabled");
10338
10869
  } catch (e) {
10339
10870
  Logger.debug("Failed to initialize custom Anthropic instrumentation:", e);
@@ -10485,7 +11016,7 @@ function addCustomSpanProcessors(tracerProvider, config2, rootInstrumentNames) {
10485
11016
  }
10486
11017
  const instrumentationProcessor = new InstrumentationSpanProcessor();
10487
11018
  provider.addSpanProcessor(instrumentationProcessor);
10488
- const sessionProcessor = new SessionSpanProcessor();
11019
+ const sessionProcessor = new SessionSpanProcessor(config2.environment);
10489
11020
  provider.addSpanProcessor(sessionProcessor);
10490
11021
  const spanIOProcessor = new SpanIOProcessor();
10491
11022
  provider.addSpanProcessor(spanIOProcessor);
@@ -10497,6 +11028,10 @@ function addCustomSpanProcessors(tracerProvider, config2, rootInstrumentNames) {
10497
11028
  const scrubbingProcessor = new ScrubbingSpanProcessor();
10498
11029
  provider.addSpanProcessor(scrubbingProcessor);
10499
11030
  }
11031
+ const sizeLimitProcessor = new AttributeSizeLimitProcessor(
11032
+ Config.SPAN_ATTRIBUTE_MAX_SIZE
11033
+ );
11034
+ provider.addSpanProcessor(sizeLimitProcessor);
10500
11035
  Logger.debug("Custom span processors registered successfully");
10501
11036
  return provider;
10502
11037
  } catch (e) {
@@ -11145,33 +11680,6 @@ var Tracer17 = class {
11145
11680
  }
11146
11681
  }
11147
11682
  };
11148
- function safeStringify3(value, maxLen = 1e3) {
11149
- const seen = /* @__PURE__ */ new WeakSet();
11150
- try {
11151
- return JSON.stringify(value, (_key, val) => {
11152
- if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
11153
- if (typeof val === "symbol") return val.toString();
11154
- if (typeof val === "bigint") return val.toString();
11155
- if (val !== null && typeof val === "object") {
11156
- if (seen.has(val)) return "[Circular]";
11157
- seen.add(val);
11158
- const name = val.constructor?.name;
11159
- if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
11160
- return `[${name}]`;
11161
- }
11162
- }
11163
- return val;
11164
- }).substring(0, maxLen);
11165
- } catch {
11166
- return value?.constructor?.name ? `[${value.constructor.name}]` : String(typeof value);
11167
- }
11168
- }
11169
- function serializeValue2(value) {
11170
- if (value === null || value === void 0) return String(value);
11171
- const t = typeof value;
11172
- if (t === "string" || t === "number" || t === "boolean") return String(value);
11173
- return safeStringify3(value);
11174
- }
11175
11683
  function spanHasOutput(span2) {
11176
11684
  try {
11177
11685
  for (const field of ["attributes", "_attributes"]) {
@@ -11186,13 +11694,13 @@ function spanHasOutput(span2) {
11186
11694
  function addInputAttributes(span2, args, entityType) {
11187
11695
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.type`, entityType);
11188
11696
  if (args.length > 0) {
11189
- span2.setAttribute("input", safeStringify3(args));
11697
+ span2.setAttribute("input", safeStringify(args, Config.ATTRIBUTE_MAX_LEN));
11190
11698
  }
11191
11699
  }
11192
11700
  function addOutputAttributes(span2, result) {
11193
11701
  if (spanHasOutput(span2)) return;
11194
11702
  try {
11195
- span2.setAttribute("output", serializeValue2(result));
11703
+ span2.setAttribute("output", serializeValue(result, Config.ATTRIBUTE_MAX_LEN));
11196
11704
  } catch (e) {
11197
11705
  span2.setAttribute("output_error", String(e));
11198
11706
  }
@@ -11212,69 +11720,63 @@ function createFunctionWrapper(func, entityType, name, asType = "SPAN" /* SPAN *
11212
11720
  span2.setAttribute("netra.span.type", asType);
11213
11721
  SessionManager.registerSpan(spanName, span2);
11214
11722
  };
11215
- const handleError = (span2, e) => {
11723
+ const recordError = (span2, e) => {
11216
11724
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.error`, String(e));
11217
11725
  span2.setStatus({
11218
11726
  code: SpanStatusCode.ERROR,
11219
11727
  message: e instanceof Error ? e.message : String(e)
11220
11728
  });
11221
11729
  span2.recordException(e);
11222
- throw e;
11223
11730
  };
11224
11731
  const cleanup = (span2) => {
11225
11732
  span2.end();
11226
11733
  SessionManager.unregisterSpan(spanName, span2);
11227
11734
  SessionManager.popEntity(entityType);
11228
11735
  };
11229
- if (isAsync) {
11230
- const wrapper = async function(...args) {
11231
- SessionManager.pushEntity(entityType, spanName);
11232
- const tracer = trace.getTracer(moduleName);
11233
- return tracer.startActiveSpan(spanName, async (span2) => {
11234
- try {
11235
- initSpan(span2);
11236
- addInputAttributes(span2, args, entityType);
11237
- const result = await func.call(this, ...args);
11238
- addOutputAttributes(span2, result);
11239
- return result;
11240
- } catch (e) {
11241
- handleError(span2, e);
11242
- } finally {
11243
- cleanup(span2);
11244
- }
11245
- });
11246
- };
11247
- return wrapper;
11248
- } else {
11249
- const wrapper = function(...args) {
11250
- SessionManager.pushEntity(entityType, spanName);
11251
- const tracer = trace.getTracer(moduleName);
11252
- return tracer.startActiveSpan(spanName, (span2) => {
11253
- let returnedPromise = false;
11254
- try {
11255
- initSpan(span2);
11256
- addInputAttributes(span2, args, entityType);
11257
- const result = func.call(this, ...args);
11258
- if (result != null && typeof result.then === "function") {
11259
- returnedPromise = true;
11260
- return result.then((resolved) => {
11261
- addOutputAttributes(span2, resolved);
11262
- return resolved;
11263
- }).catch((e) => handleError(span2, e)).finally(() => cleanup(span2));
11264
- }
11265
- addOutputAttributes(span2, result);
11266
- return result;
11267
- } catch (e) {
11268
- handleError(span2, e);
11269
- } finally {
11270
- if (!returnedPromise) {
11271
- cleanup(span2);
11272
- }
11273
- }
11274
- });
11275
- };
11276
- return wrapper;
11277
- }
11736
+ const wrapperFn = isAsync ? async function(...args) {
11737
+ SessionManager.pushEntity(entityType, spanName);
11738
+ const tracer = trace.getTracer(moduleName);
11739
+ return tracer.startActiveSpan(spanName, async (span2) => {
11740
+ try {
11741
+ initSpan(span2);
11742
+ addInputAttributes(span2, args, entityType);
11743
+ const result = await func.call(this, ...args);
11744
+ const spanCtx = trace.setSpan(context.active(), span2);
11745
+ return wrapResponse(result, {
11746
+ withContext: (fn) => context.with(spanCtx, fn),
11747
+ onError: (e) => recordError(span2, e),
11748
+ onSuccess: (value) => addOutputAttributes(span2, value),
11749
+ finalize: () => cleanup(span2)
11750
+ });
11751
+ } catch (e) {
11752
+ recordError(span2, e);
11753
+ cleanup(span2);
11754
+ throw e;
11755
+ }
11756
+ });
11757
+ } : function(...args) {
11758
+ SessionManager.pushEntity(entityType, spanName);
11759
+ const tracer = trace.getTracer(moduleName);
11760
+ return tracer.startActiveSpan(spanName, (span2) => {
11761
+ try {
11762
+ initSpan(span2);
11763
+ addInputAttributes(span2, args, entityType);
11764
+ const result = func.call(this, ...args);
11765
+ const spanCtx = trace.setSpan(context.active(), span2);
11766
+ return wrapResponse(result, {
11767
+ withContext: (fn) => context.with(spanCtx, fn),
11768
+ onError: (e) => recordError(span2, e),
11769
+ onSuccess: (value) => addOutputAttributes(span2, value),
11770
+ finalize: () => cleanup(span2)
11771
+ });
11772
+ } catch (e) {
11773
+ recordError(span2, e);
11774
+ cleanup(span2);
11775
+ throw e;
11776
+ }
11777
+ });
11778
+ };
11779
+ return wrapperFn;
11278
11780
  }
11279
11781
  var SKIP_STATIC_PROPS = /* @__PURE__ */ new Set([
11280
11782
  "length",
@@ -11661,14 +12163,11 @@ Received ${signal}. Shutting down Netra SDK...`);
11661
12163
  spanWrapper.end();
11662
12164
  throw e;
11663
12165
  }
11664
- if (result instanceof Promise) {
11665
- return result.catch((e) => {
11666
- spanWrapper.setError(e instanceof Error ? e.message : String(e));
11667
- throw e;
11668
- }).finally(() => spanWrapper.end());
11669
- }
11670
- spanWrapper.end();
11671
- return result;
12166
+ return wrapResponse(result, {
12167
+ withContext: (fn2) => spanWrapper.withActive(fn2),
12168
+ onError: (e) => spanWrapper.setError(e instanceof Error ? e.message : String(e)),
12169
+ finalize: () => spanWrapper.end()
12170
+ });
11672
12171
  });
11673
12172
  }
11674
12173
  };
@@ -11678,6 +12177,6 @@ Netra._metricsEnabled = false;
11678
12177
  Netra.withBlockedSpansLocal = withBlockedSpansLocal;
11679
12178
  var index_default = Netra;
11680
12179
 
11681
- export { Aggregation, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, netraExpressMiddleware, openaiAgentsInstrumentor, runWithExtractedContext, span, task, workflow };
12180
+ export { Aggregation, AttributeSizeLimitProcessor, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, netraExpressMiddleware, openaiAgentsInstrumentor, runWithExtractedContext, span, task, workflow };
11682
12181
  //# sourceMappingURL=index.js.map
11683
12182
  //# sourceMappingURL=index.js.map