netra-sdk 1.0.0 → 1.0.2
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 +173 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -20
- package/dist/index.d.ts +17 -20
- package/dist/index.js +174 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -799,6 +799,8 @@ declare class Usage {
|
|
|
799
799
|
private mapToTraceSpan;
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
+
declare function withBlockedSpansLocal<T>(patterns: readonly string[], fn: () => Promise<T> | T): Promise<T>;
|
|
803
|
+
|
|
802
804
|
/**
|
|
803
805
|
* Session Manager for tracking user sessions and context
|
|
804
806
|
*
|
|
@@ -884,8 +886,6 @@ declare class SpanWrapper {
|
|
|
884
886
|
getCurrentSpan(): Span | undefined;
|
|
885
887
|
}
|
|
886
888
|
|
|
887
|
-
declare function withBlockedSpansLocal<T>(patterns: readonly string[], fn: () => Promise<T> | T): Promise<T>;
|
|
888
|
-
|
|
889
889
|
/**
|
|
890
890
|
* Decorators for easy instrumentation
|
|
891
891
|
*/
|
|
@@ -1140,31 +1140,28 @@ declare class Netra {
|
|
|
1140
1140
|
static isInitialized(): boolean;
|
|
1141
1141
|
/**
|
|
1142
1142
|
* Initialize the Netra SDK
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*/
|
|
1147
|
-
static init(config?: NetraConfig): void;
|
|
1148
|
-
/**
|
|
1149
|
-
* Initialize the Netra SDK and wait for all instrumentations to be ready.
|
|
1150
|
-
* This is the recommended way to initialize Netra when using ES modules,
|
|
1151
|
-
* as it ensures all async instrumentations (OpenAI, Groq, MistralAI) are
|
|
1152
|
-
* complete before the application starts using the instrumented modules.
|
|
1143
|
+
*
|
|
1144
|
+
* This method is async and must be awaited to ensure all instrumentations
|
|
1145
|
+
* are ready before your application starts using instrumented modules.
|
|
1153
1146
|
*
|
|
1154
1147
|
* @example
|
|
1155
|
-
* await Netra.
|
|
1156
|
-
* // Now
|
|
1148
|
+
* await Netra.init({ appName: 'my-app', instruments: new Set([NetraInstruments.OPENAI]) });
|
|
1149
|
+
* // Now all instrumentations are ready
|
|
1157
1150
|
* const openai = new OpenAI();
|
|
1158
1151
|
*/
|
|
1152
|
+
static init(config?: NetraConfig): Promise<void>;
|
|
1153
|
+
/**
|
|
1154
|
+
* @deprecated Use `Netra.init()` instead. The init method is now async by default.
|
|
1155
|
+
*
|
|
1156
|
+
* Initialize the Netra SDK and wait for all instrumentations to be ready.
|
|
1157
|
+
* This method is kept for backwards compatibility.
|
|
1158
|
+
*/
|
|
1159
1159
|
static initAsync(config?: NetraConfig): Promise<void>;
|
|
1160
1160
|
/**
|
|
1161
|
-
*
|
|
1162
|
-
*
|
|
1161
|
+
* @deprecated Since `Netra.init()` is now async and waits for instrumentations,
|
|
1162
|
+
* this method is no longer necessary. It's kept for backwards compatibility.
|
|
1163
1163
|
*
|
|
1164
|
-
*
|
|
1165
|
-
* Netra.init({ appName: 'my-app' });
|
|
1166
|
-
* await Netra.ready();
|
|
1167
|
-
* // Now all instrumentations are complete
|
|
1164
|
+
* Returns a promise that resolves when all async instrumentations are ready.
|
|
1168
1165
|
*/
|
|
1169
1166
|
static ready(): Promise<void>;
|
|
1170
1167
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -799,6 +799,8 @@ declare class Usage {
|
|
|
799
799
|
private mapToTraceSpan;
|
|
800
800
|
}
|
|
801
801
|
|
|
802
|
+
declare function withBlockedSpansLocal<T>(patterns: readonly string[], fn: () => Promise<T> | T): Promise<T>;
|
|
803
|
+
|
|
802
804
|
/**
|
|
803
805
|
* Session Manager for tracking user sessions and context
|
|
804
806
|
*
|
|
@@ -884,8 +886,6 @@ declare class SpanWrapper {
|
|
|
884
886
|
getCurrentSpan(): Span | undefined;
|
|
885
887
|
}
|
|
886
888
|
|
|
887
|
-
declare function withBlockedSpansLocal<T>(patterns: readonly string[], fn: () => Promise<T> | T): Promise<T>;
|
|
888
|
-
|
|
889
889
|
/**
|
|
890
890
|
* Decorators for easy instrumentation
|
|
891
891
|
*/
|
|
@@ -1140,31 +1140,28 @@ declare class Netra {
|
|
|
1140
1140
|
static isInitialized(): boolean;
|
|
1141
1141
|
/**
|
|
1142
1142
|
* Initialize the Netra SDK
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*/
|
|
1147
|
-
static init(config?: NetraConfig): void;
|
|
1148
|
-
/**
|
|
1149
|
-
* Initialize the Netra SDK and wait for all instrumentations to be ready.
|
|
1150
|
-
* This is the recommended way to initialize Netra when using ES modules,
|
|
1151
|
-
* as it ensures all async instrumentations (OpenAI, Groq, MistralAI) are
|
|
1152
|
-
* complete before the application starts using the instrumented modules.
|
|
1143
|
+
*
|
|
1144
|
+
* This method is async and must be awaited to ensure all instrumentations
|
|
1145
|
+
* are ready before your application starts using instrumented modules.
|
|
1153
1146
|
*
|
|
1154
1147
|
* @example
|
|
1155
|
-
* await Netra.
|
|
1156
|
-
* // Now
|
|
1148
|
+
* await Netra.init({ appName: 'my-app', instruments: new Set([NetraInstruments.OPENAI]) });
|
|
1149
|
+
* // Now all instrumentations are ready
|
|
1157
1150
|
* const openai = new OpenAI();
|
|
1158
1151
|
*/
|
|
1152
|
+
static init(config?: NetraConfig): Promise<void>;
|
|
1153
|
+
/**
|
|
1154
|
+
* @deprecated Use `Netra.init()` instead. The init method is now async by default.
|
|
1155
|
+
*
|
|
1156
|
+
* Initialize the Netra SDK and wait for all instrumentations to be ready.
|
|
1157
|
+
* This method is kept for backwards compatibility.
|
|
1158
|
+
*/
|
|
1159
1159
|
static initAsync(config?: NetraConfig): Promise<void>;
|
|
1160
1160
|
/**
|
|
1161
|
-
*
|
|
1162
|
-
*
|
|
1161
|
+
* @deprecated Since `Netra.init()` is now async and waits for instrumentations,
|
|
1162
|
+
* this method is no longer necessary. It's kept for backwards compatibility.
|
|
1163
1163
|
*
|
|
1164
|
-
*
|
|
1165
|
-
* Netra.init({ appName: 'my-app' });
|
|
1166
|
-
* await Netra.ready();
|
|
1167
|
-
* // Now all instrumentations are complete
|
|
1164
|
+
* Returns a promise that resolves when all async instrumentations are ready.
|
|
1168
1165
|
*/
|
|
1169
1166
|
static ready(): Promise<void>;
|
|
1170
1167
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { propagation, trace, SpanKind, context, SpanStatusCode, ROOT_CONTEXT } from '@opentelemetry/api';
|
|
1
|
+
import { createContextKey, propagation, trace, SpanKind, context, SpanStatusCode, ROOT_CONTEXT } from '@opentelemetry/api';
|
|
2
2
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
3
3
|
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
4
|
import { initialize } from '@traceloop/node-server-sdk';
|
|
@@ -18,7 +18,13 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
18
18
|
var __getProtoOf = Object.getPrototypeOf;
|
|
19
19
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
20
20
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
21
|
-
var
|
|
21
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
22
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
23
|
+
}) : x)(function(x) {
|
|
24
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
25
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
26
|
+
});
|
|
27
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
22
28
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
23
29
|
};
|
|
24
30
|
var __copyProps = (to, from, except, desc) => {
|
|
@@ -2302,8 +2308,8 @@ var Usage = class {
|
|
|
2302
2308
|
if (!page) {
|
|
2303
2309
|
break;
|
|
2304
2310
|
}
|
|
2305
|
-
for (const
|
|
2306
|
-
yield
|
|
2311
|
+
for (const trace17 of page.traces) {
|
|
2312
|
+
yield trace17;
|
|
2307
2313
|
}
|
|
2308
2314
|
if (!page.hasNextPage || !page.nextCursor) {
|
|
2309
2315
|
break;
|
|
@@ -3386,6 +3392,10 @@ function anthropicWrapper(tracer, spanName, requestType) {
|
|
|
3386
3392
|
return isPromise(result) ? result.then((value) => value) : result;
|
|
3387
3393
|
}
|
|
3388
3394
|
const isStreaming = args[0]?.stream === true;
|
|
3395
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
3396
|
+
const activeSpan = trace.getSpan(context.active());
|
|
3397
|
+
console.log(`[Netra Debug] Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
|
|
3398
|
+
}
|
|
3389
3399
|
if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
|
|
3390
3400
|
const currentContext = context.active();
|
|
3391
3401
|
const span2 = tracer.startSpan(
|
|
@@ -5320,6 +5330,9 @@ var NetraGroqInstrumentor = class {
|
|
|
5320
5330
|
};
|
|
5321
5331
|
var groqInstrumentor = new NetraGroqInstrumentor();
|
|
5322
5332
|
|
|
5333
|
+
// src/instrumentation/langgraph/version.ts
|
|
5334
|
+
var __version__4 = "1.0.0";
|
|
5335
|
+
|
|
5323
5336
|
// node_modules/@langchain/core/dist/_virtual/rolldown_runtime.js
|
|
5324
5337
|
var __defProp2 = Object.defineProperty;
|
|
5325
5338
|
var __export = (target, all) => {
|
|
@@ -5877,6 +5890,7 @@ function setLlmPrompts(span2, prompts) {
|
|
|
5877
5890
|
}
|
|
5878
5891
|
|
|
5879
5892
|
// src/instrumentation/langgraph/wrappers.ts
|
|
5893
|
+
var LANGGRAPH_INSTRUMENTATION_ACTIVE = createContextKey("netra.langgraph.active");
|
|
5880
5894
|
var NetraLanggraphCallbackHandler = class extends BaseCallbackHandler {
|
|
5881
5895
|
constructor(tracer, rootSpan) {
|
|
5882
5896
|
super();
|
|
@@ -6056,13 +6070,30 @@ var LanggraphWrapper = class {
|
|
|
6056
6070
|
return updatedConfig;
|
|
6057
6071
|
}
|
|
6058
6072
|
async invoke(originalFunc, instance, input, config2, ...rest) {
|
|
6059
|
-
if (shouldSuppressInstrumentation()) {
|
|
6073
|
+
if (shouldSuppressInstrumentation() || context.active().getValue(LANGGRAPH_INSTRUMENTATION_ACTIVE)) {
|
|
6060
6074
|
return await originalFunc.call(instance, input, config2, ...rest);
|
|
6061
6075
|
}
|
|
6062
|
-
const
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6076
|
+
const activeSpan = trace.getSpan(context.active());
|
|
6077
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6078
|
+
console.log(`[Netra Debug] LangGraph invoke start. Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
|
|
6079
|
+
}
|
|
6080
|
+
const span2 = this.tracer.startSpan(
|
|
6081
|
+
this.spanName,
|
|
6082
|
+
{
|
|
6083
|
+
kind: SpanKind.CLIENT
|
|
6084
|
+
},
|
|
6085
|
+
context.active()
|
|
6086
|
+
);
|
|
6087
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6088
|
+
console.log(`[Netra Debug] LangGraph span created. New TraceId: ${span2.spanContext().traceId}, SpanId: ${span2.spanContext().spanId}`);
|
|
6089
|
+
}
|
|
6090
|
+
const ctxWithSpan = trace.setSpan(context.active(), span2);
|
|
6091
|
+
const ctxWithFlag = ctxWithSpan.setValue(LANGGRAPH_INSTRUMENTATION_ACTIVE, true);
|
|
6092
|
+
return context.with(ctxWithFlag, async () => {
|
|
6093
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6094
|
+
const innerSpan = trace.getSpan(context.active());
|
|
6095
|
+
console.log(`[Netra Debug] Inside LangGraph context. Active TraceId: ${innerSpan?.spanContext().traceId}, SpanId: ${innerSpan?.spanContext().spanId}`);
|
|
6096
|
+
}
|
|
6066
6097
|
try {
|
|
6067
6098
|
setGraphInputAttributes(span2, input);
|
|
6068
6099
|
const updatedConfig = this.getUpdatedConfig(config2, span2);
|
|
@@ -6083,9 +6114,15 @@ var LanggraphWrapper = class {
|
|
|
6083
6114
|
});
|
|
6084
6115
|
}
|
|
6085
6116
|
async stream(originalFunc, instance, input, config2, ...rest) {
|
|
6086
|
-
if (shouldSuppressInstrumentation()) {
|
|
6117
|
+
if (shouldSuppressInstrumentation() || context.active().getValue(LANGGRAPH_INSTRUMENTATION_ACTIVE)) {
|
|
6118
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6119
|
+
console.log("[Netra Debug] LangGraph stream skipped (inside instrumented call)");
|
|
6120
|
+
}
|
|
6087
6121
|
return await originalFunc.call(instance, input, config2, ...rest);
|
|
6088
6122
|
}
|
|
6123
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6124
|
+
console.log("[Netra Debug] LangGraph stream starting instrumentation");
|
|
6125
|
+
}
|
|
6089
6126
|
const span2 = this.tracer.startSpan(
|
|
6090
6127
|
this.spanName,
|
|
6091
6128
|
{
|
|
@@ -6111,22 +6148,71 @@ var LanggraphWrapper = class {
|
|
|
6111
6148
|
}
|
|
6112
6149
|
};
|
|
6113
6150
|
|
|
6114
|
-
// src/instrumentation/langgraph/version.ts
|
|
6115
|
-
var __version__4 = "1.0.0";
|
|
6116
|
-
|
|
6117
6151
|
// src/instrumentation/langgraph/index.ts
|
|
6118
6152
|
var INSTRUMENTATION_NAME4 = "netra.instrumentation.langchain";
|
|
6119
6153
|
var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
|
|
6120
6154
|
var isInstrumented4 = false;
|
|
6121
6155
|
var LanggraphClass = null;
|
|
6122
6156
|
var originalMethods3 = /* @__PURE__ */ new Map();
|
|
6157
|
+
function findModuleInCache(moduleName) {
|
|
6158
|
+
if (typeof __require !== "undefined" && __require.cache) {
|
|
6159
|
+
const cache = __require.cache;
|
|
6160
|
+
for (const key of Object.keys(cache)) {
|
|
6161
|
+
if (key.includes(moduleName.replace(/\//g, "/")) && !key.includes("netra-sdk")) {
|
|
6162
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6163
|
+
console.log(`Found module in require.cache: ${key}`);
|
|
6164
|
+
}
|
|
6165
|
+
return cache[key]?.exports;
|
|
6166
|
+
}
|
|
6167
|
+
}
|
|
6168
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6169
|
+
console.log(
|
|
6170
|
+
`Module ${moduleName} not found in require.cache. Cache keys containing 'langgraph':`,
|
|
6171
|
+
Object.keys(cache).filter((k) => k.includes("langgraph"))
|
|
6172
|
+
);
|
|
6173
|
+
}
|
|
6174
|
+
}
|
|
6175
|
+
return null;
|
|
6176
|
+
}
|
|
6123
6177
|
async function resolveLanggraph() {
|
|
6124
6178
|
if (LanggraphClass) return LanggraphClass;
|
|
6125
6179
|
try {
|
|
6126
|
-
|
|
6127
|
-
|
|
6180
|
+
let langgraphModule = findModuleInCache("@langchain/langgraph");
|
|
6181
|
+
if (langgraphModule) {
|
|
6182
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6183
|
+
console.log("Found @langchain/langgraph in require.cache (using app's module instance)");
|
|
6184
|
+
}
|
|
6185
|
+
} else {
|
|
6186
|
+
langgraphModule = await import('@langchain/langgraph');
|
|
6187
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6188
|
+
console.log("Loaded @langchain/langgraph via dynamic import");
|
|
6189
|
+
}
|
|
6190
|
+
}
|
|
6191
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6192
|
+
console.log("LangGraph Module Exports:", Object.keys(langgraphModule));
|
|
6193
|
+
}
|
|
6194
|
+
LanggraphClass = langgraphModule.CompiledStateGraph ?? langgraphModule.StateGraph;
|
|
6195
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6196
|
+
console.log("Resolved LanggraphClass:", !!LanggraphClass);
|
|
6197
|
+
console.log("LanggraphClass name:", LanggraphClass?.name);
|
|
6198
|
+
console.log("LanggraphClass.prototype keys:", LanggraphClass?.prototype ? Object.getOwnPropertyNames(LanggraphClass.prototype) : "no prototype");
|
|
6199
|
+
console.log("Has invoke on prototype:", !!LanggraphClass?.prototype?.invoke);
|
|
6200
|
+
console.log("Has stream on prototype:", !!LanggraphClass?.prototype?.stream);
|
|
6201
|
+
console.log("Checking prototype chain for invoke location:");
|
|
6202
|
+
let proto = LanggraphClass?.prototype;
|
|
6203
|
+
while (proto) {
|
|
6204
|
+
const hasOwn = Object.getOwnPropertyNames(proto).includes("invoke");
|
|
6205
|
+
console.log(` ${proto.constructor?.name}: hasOwnProperty('invoke')=${hasOwn}`);
|
|
6206
|
+
if (hasOwn) {
|
|
6207
|
+
console.log(` -> invoke is defined on: ${proto.constructor?.name}`);
|
|
6208
|
+
break;
|
|
6209
|
+
}
|
|
6210
|
+
proto = Object.getPrototypeOf(proto);
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6128
6213
|
return LanggraphClass;
|
|
6129
|
-
} catch {
|
|
6214
|
+
} catch (e) {
|
|
6215
|
+
console.error("Failed to resolve LangGraph:", e);
|
|
6130
6216
|
return null;
|
|
6131
6217
|
}
|
|
6132
6218
|
}
|
|
@@ -6147,6 +6233,7 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6147
6233
|
}
|
|
6148
6234
|
const Langgraph = await resolveLanggraph();
|
|
6149
6235
|
if (!Langgraph) {
|
|
6236
|
+
if (process.env.NETRA_DEBUG_LOGS) console.warn("LangGraph class not found, skipping instrumentation");
|
|
6150
6237
|
return this;
|
|
6151
6238
|
}
|
|
6152
6239
|
try {
|
|
@@ -6156,17 +6243,19 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6156
6243
|
console.error(`Failed to initialize tracer: ${error}`);
|
|
6157
6244
|
return this;
|
|
6158
6245
|
}
|
|
6246
|
+
this._instrumentInvoke(Langgraph);
|
|
6159
6247
|
this._instrumentStream(Langgraph);
|
|
6160
6248
|
isInstrumented4 = true;
|
|
6161
6249
|
return this;
|
|
6162
6250
|
}
|
|
6163
6251
|
async uninstrument() {
|
|
6164
6252
|
if (!isInstrumented4) {
|
|
6165
|
-
console.warn("
|
|
6253
|
+
console.warn("LangGraph is not instrumented");
|
|
6166
6254
|
return;
|
|
6167
6255
|
}
|
|
6168
6256
|
const Langgraph = await resolveLanggraph();
|
|
6169
6257
|
if (Langgraph) {
|
|
6258
|
+
this._uninstrumentInvoke(Langgraph);
|
|
6170
6259
|
this._uninstrumentStream(Langgraph);
|
|
6171
6260
|
}
|
|
6172
6261
|
originalMethods3.clear();
|
|
@@ -6175,15 +6264,26 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6175
6264
|
_instrumentInvoke(Langgraph) {
|
|
6176
6265
|
if (!this.tracer) return;
|
|
6177
6266
|
try {
|
|
6178
|
-
|
|
6267
|
+
let targetProto = Langgraph?.prototype;
|
|
6268
|
+
while (targetProto && !Object.getOwnPropertyNames(targetProto).includes("invoke")) {
|
|
6269
|
+
targetProto = Object.getPrototypeOf(targetProto);
|
|
6270
|
+
}
|
|
6271
|
+
if (!targetProto?.invoke) {
|
|
6179
6272
|
console.error("Failed to find langgraph invoke function to instrument");
|
|
6180
6273
|
return;
|
|
6181
6274
|
}
|
|
6182
|
-
|
|
6275
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6276
|
+
console.log(`Found invoke on prototype: ${targetProto.constructor?.name}`);
|
|
6277
|
+
}
|
|
6278
|
+
const originalInvoke = targetProto.invoke;
|
|
6183
6279
|
originalMethods3.set("langgraph.graph.invoke", originalInvoke);
|
|
6280
|
+
originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
|
|
6184
6281
|
const tracer = this.tracer;
|
|
6185
6282
|
const wrapper = new LanggraphWrapper(tracer);
|
|
6186
|
-
|
|
6283
|
+
const patchedInvoke = async function(input, config2, ...rest) {
|
|
6284
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6285
|
+
console.log("[Netra Debug] LangGraph invoke intercepted!");
|
|
6286
|
+
}
|
|
6187
6287
|
return await wrapper.invoke(
|
|
6188
6288
|
originalInvoke,
|
|
6189
6289
|
this,
|
|
@@ -6192,6 +6292,12 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6192
6292
|
...rest
|
|
6193
6293
|
);
|
|
6194
6294
|
};
|
|
6295
|
+
patchedInvoke.__netra_patched = true;
|
|
6296
|
+
targetProto.invoke = patchedInvoke;
|
|
6297
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6298
|
+
console.log(`Successfully instrumented LangGraph invoke method on ${targetProto.constructor?.name}`);
|
|
6299
|
+
console.log(`Patched Pregel class identity:`, targetProto.constructor);
|
|
6300
|
+
}
|
|
6195
6301
|
} catch (error) {
|
|
6196
6302
|
console.error(`Failed to instrument langgraph invoke: ${error}`);
|
|
6197
6303
|
}
|
|
@@ -6199,15 +6305,26 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6199
6305
|
_instrumentStream(Langgraph) {
|
|
6200
6306
|
if (!this.tracer) return;
|
|
6201
6307
|
try {
|
|
6202
|
-
|
|
6308
|
+
let targetProto = Langgraph?.prototype;
|
|
6309
|
+
while (targetProto && !Object.getOwnPropertyNames(targetProto).includes("stream")) {
|
|
6310
|
+
targetProto = Object.getPrototypeOf(targetProto);
|
|
6311
|
+
}
|
|
6312
|
+
if (!targetProto?.stream) {
|
|
6203
6313
|
console.error("Failed to find langgraph stream function to instrument");
|
|
6204
6314
|
return;
|
|
6205
6315
|
}
|
|
6206
|
-
|
|
6316
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6317
|
+
console.log(`Found stream on prototype: ${targetProto.constructor?.name}`);
|
|
6318
|
+
}
|
|
6319
|
+
const originalStream = targetProto.stream;
|
|
6207
6320
|
originalMethods3.set("langgraph.graph.stream", originalStream);
|
|
6321
|
+
originalMethods3.set("langgraph.graph.stream.proto", targetProto);
|
|
6208
6322
|
const tracer = this.tracer;
|
|
6209
6323
|
const wrapper = new LanggraphWrapper(tracer);
|
|
6210
|
-
|
|
6324
|
+
targetProto.stream = async function(input, config2, ...rest) {
|
|
6325
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6326
|
+
console.log("[Netra Debug] LangGraph stream intercepted!");
|
|
6327
|
+
}
|
|
6211
6328
|
return await wrapper.stream(
|
|
6212
6329
|
originalStream,
|
|
6213
6330
|
this,
|
|
@@ -6216,6 +6333,9 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6216
6333
|
...rest
|
|
6217
6334
|
);
|
|
6218
6335
|
};
|
|
6336
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6337
|
+
console.log(`Successfully instrumented LangGraph stream method on ${targetProto.constructor?.name}`);
|
|
6338
|
+
}
|
|
6219
6339
|
} catch (error) {
|
|
6220
6340
|
console.error(`Failed to instrument langgraph stream: ${error}`);
|
|
6221
6341
|
}
|
|
@@ -6223,8 +6343,9 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6223
6343
|
_uninstrumentInvoke(Langgraph) {
|
|
6224
6344
|
try {
|
|
6225
6345
|
const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
|
|
6226
|
-
|
|
6227
|
-
|
|
6346
|
+
const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
|
|
6347
|
+
if (originalInvoke && targetProto?.invoke) {
|
|
6348
|
+
targetProto.invoke = originalInvoke;
|
|
6228
6349
|
}
|
|
6229
6350
|
} catch (error) {
|
|
6230
6351
|
console.error(`Failed to uninstrument langgraph invoke: ${error}`);
|
|
@@ -6234,8 +6355,9 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6234
6355
|
_uninstrumentStream(Langgraph) {
|
|
6235
6356
|
try {
|
|
6236
6357
|
const originalStream = originalMethods3.get("langgraph.graph.stream");
|
|
6237
|
-
|
|
6238
|
-
|
|
6358
|
+
const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
|
|
6359
|
+
if (originalStream && targetProto?.stream) {
|
|
6360
|
+
targetProto.stream = originalStream;
|
|
6239
6361
|
}
|
|
6240
6362
|
} catch (error) {
|
|
6241
6363
|
console.error(`Failed to uninstrument langgraph stream: ${error}`);
|
|
@@ -8360,6 +8482,13 @@ function initInstrumentations(config2, instruments, blockInstruments) {
|
|
|
8360
8482
|
customInstrumentModules.googleGenAI = true;
|
|
8361
8483
|
customInstrumentModules.anthropic = true;
|
|
8362
8484
|
} else if (instruments.size) {
|
|
8485
|
+
instrumentModules.google_vertexai = false;
|
|
8486
|
+
instrumentModules.langchain = false;
|
|
8487
|
+
instrumentModules.llamaIndex = false;
|
|
8488
|
+
instrumentModules.pinecone = false;
|
|
8489
|
+
instrumentModules.qdrant = false;
|
|
8490
|
+
instrumentModules.chromadb = false;
|
|
8491
|
+
instrumentModules.together = false;
|
|
8363
8492
|
if (instruments.has("openai" /* OPENAI */)) {
|
|
8364
8493
|
customInstrumentModules.openai = true;
|
|
8365
8494
|
}
|
|
@@ -8917,11 +9046,16 @@ var Netra = class {
|
|
|
8917
9046
|
}
|
|
8918
9047
|
/**
|
|
8919
9048
|
* Initialize the Netra SDK
|
|
8920
|
-
*
|
|
8921
|
-
*
|
|
8922
|
-
*
|
|
9049
|
+
*
|
|
9050
|
+
* This method is async and must be awaited to ensure all instrumentations
|
|
9051
|
+
* are ready before your application starts using instrumented modules.
|
|
9052
|
+
*
|
|
9053
|
+
* @example
|
|
9054
|
+
* await Netra.init({ appName: 'my-app', instruments: new Set([NetraInstruments.OPENAI]) });
|
|
9055
|
+
* // Now all instrumentations are ready
|
|
9056
|
+
* const openai = new OpenAI();
|
|
8923
9057
|
*/
|
|
8924
|
-
static init(config2 = {}) {
|
|
9058
|
+
static async init(config2 = {}) {
|
|
8925
9059
|
if (this._initialized) {
|
|
8926
9060
|
console.warn(
|
|
8927
9061
|
"Netra.init() called more than once; ignoring subsequent calls."
|
|
@@ -8951,11 +9085,9 @@ var Netra = class {
|
|
|
8951
9085
|
this.dashboard = new Dashboard(cfg);
|
|
8952
9086
|
this._initialized = true;
|
|
8953
9087
|
console.info("Netra successfully initialized.");
|
|
8954
|
-
this._initialized = true;
|
|
8955
|
-
console.info("Netra successfully initialized.");
|
|
8956
9088
|
const handleSignal = async (signal) => {
|
|
8957
9089
|
console.log(`
|
|
8958
|
-
|
|
9090
|
+
Received ${signal}. Shutting down Netra SDK...`);
|
|
8959
9091
|
await this.shutdown();
|
|
8960
9092
|
process.exit(0);
|
|
8961
9093
|
};
|
|
@@ -8997,30 +9129,22 @@ Recepived ${signal}. Shutting down Netra SDK...`);
|
|
|
8997
9129
|
);
|
|
8998
9130
|
}
|
|
8999
9131
|
}
|
|
9132
|
+
await instrumentationsReady;
|
|
9000
9133
|
}
|
|
9001
9134
|
/**
|
|
9002
|
-
*
|
|
9003
|
-
* This is the recommended way to initialize Netra when using ES modules,
|
|
9004
|
-
* as it ensures all async instrumentations (OpenAI, Groq, MistralAI) are
|
|
9005
|
-
* complete before the application starts using the instrumented modules.
|
|
9135
|
+
* @deprecated Use `Netra.init()` instead. The init method is now async by default.
|
|
9006
9136
|
*
|
|
9007
|
-
*
|
|
9008
|
-
*
|
|
9009
|
-
* // Now OpenAI is fully instrumented
|
|
9010
|
-
* const openai = new OpenAI();
|
|
9137
|
+
* Initialize the Netra SDK and wait for all instrumentations to be ready.
|
|
9138
|
+
* This method is kept for backwards compatibility.
|
|
9011
9139
|
*/
|
|
9012
9140
|
static async initAsync(config2 = {}) {
|
|
9013
|
-
this.init(config2);
|
|
9014
|
-
await instrumentationsReady;
|
|
9141
|
+
await this.init(config2);
|
|
9015
9142
|
}
|
|
9016
9143
|
/**
|
|
9017
|
-
*
|
|
9018
|
-
*
|
|
9144
|
+
* @deprecated Since `Netra.init()` is now async and waits for instrumentations,
|
|
9145
|
+
* this method is no longer necessary. It's kept for backwards compatibility.
|
|
9019
9146
|
*
|
|
9020
|
-
*
|
|
9021
|
-
* Netra.init({ appName: 'my-app' });
|
|
9022
|
-
* await Netra.ready();
|
|
9023
|
-
* // Now all instrumentations are complete
|
|
9147
|
+
* Returns a promise that resolves when all async instrumentations are ready.
|
|
9024
9148
|
*/
|
|
9025
9149
|
static async ready() {
|
|
9026
9150
|
await instrumentationsReady;
|