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.cjs +1257 -757
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +1250 -751
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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))
|
|
3725
|
-
|
|
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 =
|
|
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
|
-
|
|
4170
|
+
msg.role
|
|
3841
4171
|
);
|
|
3842
4172
|
span2.setAttribute(
|
|
3843
4173
|
`${SpanAttributes2.LLM_PROMPTS}.${i}.content`,
|
|
3844
|
-
|
|
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
|
-
|
|
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 (
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
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
|
|
3964
|
-
if (
|
|
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(
|
|
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/
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
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/
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
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
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
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
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
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
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
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
|
-
"
|
|
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([
|
|
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(
|
|
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
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
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
|
-
|
|
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
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
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
|
-
|
|
4242
|
-
} catch (error) {
|
|
4243
|
-
target.finalizeSpan(SpanStatusCode.ERROR);
|
|
4244
|
-
throw error;
|
|
4689
|
+
target.finalizeSpanOnce(SpanStatusCode.OK);
|
|
4245
4690
|
}
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
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.
|
|
4796
|
+
this.finalizeSpanOnce(SpanStatusCode.OK);
|
|
4390
4797
|
}
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
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
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
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
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
4599
|
-
this._instrumentMessages(AnthropicSDK
|
|
4600
|
-
this._instrumentBetaMessages(AnthropicSDK
|
|
4601
|
-
this._instrumentBatchMessages(AnthropicSDK
|
|
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
|
-
|
|
4612
|
-
|
|
4613
|
-
this.
|
|
4614
|
-
this.
|
|
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
|
|
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
|
|
5210
|
+
"Anthropic instrumentation: Could not find Messages class"
|
|
4634
5211
|
);
|
|
4635
5212
|
return;
|
|
4636
5213
|
}
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
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
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
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
|
|
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
|
|
5242
|
+
"Anthropic instrumentation: Could not find Beta Messages class"
|
|
4701
5243
|
);
|
|
4702
5244
|
return;
|
|
4703
5245
|
}
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
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
|
|
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
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
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
|
|
5294
|
+
_uninstrumentMessages(AnthropicSDK) {
|
|
4758
5295
|
try {
|
|
4759
|
-
const
|
|
4760
|
-
|
|
4761
|
-
if (
|
|
4762
|
-
|
|
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
|
|
5304
|
+
_uninstrumentBetaMessages(AnthropicSDK) {
|
|
4773
5305
|
try {
|
|
4774
|
-
const
|
|
4775
|
-
|
|
4776
|
-
if (
|
|
4777
|
-
|
|
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
|
|
5316
|
+
_uninstrumentBatchMessages(AnthropicSDK) {
|
|
4784
5317
|
try {
|
|
4785
|
-
const
|
|
4786
|
-
|
|
4787
|
-
if (
|
|
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
|
|
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,
|
|
6015
|
+
var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME, "chat");
|
|
5485
6016
|
var embeddingsWrapper = (tracer) => googleGenAIWrapper(tracer, EMBEDDING_SPAN_NAME, "embedding");
|
|
5486
|
-
var
|
|
5487
|
-
var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer,
|
|
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
|
-
|
|
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
|
|
5676
|
-
var
|
|
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 &&
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
7112
|
-
|
|
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
|
-
|
|
7147
|
-
|
|
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 =
|
|
7168
|
-
const targetProto =
|
|
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 =
|
|
7180
|
-
const targetProto =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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,
|
|
7351
|
-
var
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
8395
|
+
originalMethods3.set(`chat.stream-${index}`, originalStream);
|
|
7865
8396
|
const tracer = this.tracer;
|
|
7866
|
-
const wrapper =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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.
|
|
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",
|
|
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",
|
|
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
|
|
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
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11262
|
-
|
|
11263
|
-
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
|
|
11270
|
-
|
|
11271
|
-
|
|
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
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
|
|
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
|