netra-sdk 1.0.1 → 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 +159 -46
- 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 +160 -47
- 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,9 +6070,13 @@ 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
|
}
|
|
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
|
+
}
|
|
6062
6080
|
const span2 = this.tracer.startSpan(
|
|
6063
6081
|
this.spanName,
|
|
6064
6082
|
{
|
|
@@ -6066,7 +6084,16 @@ var LanggraphWrapper = class {
|
|
|
6066
6084
|
},
|
|
6067
6085
|
context.active()
|
|
6068
6086
|
);
|
|
6069
|
-
|
|
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
|
+
}
|
|
6070
6097
|
try {
|
|
6071
6098
|
setGraphInputAttributes(span2, input);
|
|
6072
6099
|
const updatedConfig = this.getUpdatedConfig(config2, span2);
|
|
@@ -6087,9 +6114,15 @@ var LanggraphWrapper = class {
|
|
|
6087
6114
|
});
|
|
6088
6115
|
}
|
|
6089
6116
|
async stream(originalFunc, instance, input, config2, ...rest) {
|
|
6090
|
-
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
|
+
}
|
|
6091
6121
|
return await originalFunc.call(instance, input, config2, ...rest);
|
|
6092
6122
|
}
|
|
6123
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6124
|
+
console.log("[Netra Debug] LangGraph stream starting instrumentation");
|
|
6125
|
+
}
|
|
6093
6126
|
const span2 = this.tracer.startSpan(
|
|
6094
6127
|
this.spanName,
|
|
6095
6128
|
{
|
|
@@ -6115,22 +6148,71 @@ var LanggraphWrapper = class {
|
|
|
6115
6148
|
}
|
|
6116
6149
|
};
|
|
6117
6150
|
|
|
6118
|
-
// src/instrumentation/langgraph/version.ts
|
|
6119
|
-
var __version__4 = "1.0.0";
|
|
6120
|
-
|
|
6121
6151
|
// src/instrumentation/langgraph/index.ts
|
|
6122
6152
|
var INSTRUMENTATION_NAME4 = "netra.instrumentation.langchain";
|
|
6123
6153
|
var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
|
|
6124
6154
|
var isInstrumented4 = false;
|
|
6125
6155
|
var LanggraphClass = null;
|
|
6126
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
|
+
}
|
|
6127
6177
|
async function resolveLanggraph() {
|
|
6128
6178
|
if (LanggraphClass) return LanggraphClass;
|
|
6129
6179
|
try {
|
|
6130
|
-
|
|
6131
|
-
|
|
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
|
+
}
|
|
6132
6213
|
return LanggraphClass;
|
|
6133
|
-
} catch {
|
|
6214
|
+
} catch (e) {
|
|
6215
|
+
console.error("Failed to resolve LangGraph:", e);
|
|
6134
6216
|
return null;
|
|
6135
6217
|
}
|
|
6136
6218
|
}
|
|
@@ -6151,6 +6233,7 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6151
6233
|
}
|
|
6152
6234
|
const Langgraph = await resolveLanggraph();
|
|
6153
6235
|
if (!Langgraph) {
|
|
6236
|
+
if (process.env.NETRA_DEBUG_LOGS) console.warn("LangGraph class not found, skipping instrumentation");
|
|
6154
6237
|
return this;
|
|
6155
6238
|
}
|
|
6156
6239
|
try {
|
|
@@ -6160,17 +6243,19 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6160
6243
|
console.error(`Failed to initialize tracer: ${error}`);
|
|
6161
6244
|
return this;
|
|
6162
6245
|
}
|
|
6246
|
+
this._instrumentInvoke(Langgraph);
|
|
6163
6247
|
this._instrumentStream(Langgraph);
|
|
6164
6248
|
isInstrumented4 = true;
|
|
6165
6249
|
return this;
|
|
6166
6250
|
}
|
|
6167
6251
|
async uninstrument() {
|
|
6168
6252
|
if (!isInstrumented4) {
|
|
6169
|
-
console.warn("
|
|
6253
|
+
console.warn("LangGraph is not instrumented");
|
|
6170
6254
|
return;
|
|
6171
6255
|
}
|
|
6172
6256
|
const Langgraph = await resolveLanggraph();
|
|
6173
6257
|
if (Langgraph) {
|
|
6258
|
+
this._uninstrumentInvoke(Langgraph);
|
|
6174
6259
|
this._uninstrumentStream(Langgraph);
|
|
6175
6260
|
}
|
|
6176
6261
|
originalMethods3.clear();
|
|
@@ -6179,15 +6264,26 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6179
6264
|
_instrumentInvoke(Langgraph) {
|
|
6180
6265
|
if (!this.tracer) return;
|
|
6181
6266
|
try {
|
|
6182
|
-
|
|
6267
|
+
let targetProto = Langgraph?.prototype;
|
|
6268
|
+
while (targetProto && !Object.getOwnPropertyNames(targetProto).includes("invoke")) {
|
|
6269
|
+
targetProto = Object.getPrototypeOf(targetProto);
|
|
6270
|
+
}
|
|
6271
|
+
if (!targetProto?.invoke) {
|
|
6183
6272
|
console.error("Failed to find langgraph invoke function to instrument");
|
|
6184
6273
|
return;
|
|
6185
6274
|
}
|
|
6186
|
-
|
|
6275
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6276
|
+
console.log(`Found invoke on prototype: ${targetProto.constructor?.name}`);
|
|
6277
|
+
}
|
|
6278
|
+
const originalInvoke = targetProto.invoke;
|
|
6187
6279
|
originalMethods3.set("langgraph.graph.invoke", originalInvoke);
|
|
6280
|
+
originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
|
|
6188
6281
|
const tracer = this.tracer;
|
|
6189
6282
|
const wrapper = new LanggraphWrapper(tracer);
|
|
6190
|
-
|
|
6283
|
+
const patchedInvoke = async function(input, config2, ...rest) {
|
|
6284
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6285
|
+
console.log("[Netra Debug] LangGraph invoke intercepted!");
|
|
6286
|
+
}
|
|
6191
6287
|
return await wrapper.invoke(
|
|
6192
6288
|
originalInvoke,
|
|
6193
6289
|
this,
|
|
@@ -6196,6 +6292,12 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6196
6292
|
...rest
|
|
6197
6293
|
);
|
|
6198
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
|
+
}
|
|
6199
6301
|
} catch (error) {
|
|
6200
6302
|
console.error(`Failed to instrument langgraph invoke: ${error}`);
|
|
6201
6303
|
}
|
|
@@ -6203,15 +6305,26 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6203
6305
|
_instrumentStream(Langgraph) {
|
|
6204
6306
|
if (!this.tracer) return;
|
|
6205
6307
|
try {
|
|
6206
|
-
|
|
6308
|
+
let targetProto = Langgraph?.prototype;
|
|
6309
|
+
while (targetProto && !Object.getOwnPropertyNames(targetProto).includes("stream")) {
|
|
6310
|
+
targetProto = Object.getPrototypeOf(targetProto);
|
|
6311
|
+
}
|
|
6312
|
+
if (!targetProto?.stream) {
|
|
6207
6313
|
console.error("Failed to find langgraph stream function to instrument");
|
|
6208
6314
|
return;
|
|
6209
6315
|
}
|
|
6210
|
-
|
|
6316
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6317
|
+
console.log(`Found stream on prototype: ${targetProto.constructor?.name}`);
|
|
6318
|
+
}
|
|
6319
|
+
const originalStream = targetProto.stream;
|
|
6211
6320
|
originalMethods3.set("langgraph.graph.stream", originalStream);
|
|
6321
|
+
originalMethods3.set("langgraph.graph.stream.proto", targetProto);
|
|
6212
6322
|
const tracer = this.tracer;
|
|
6213
6323
|
const wrapper = new LanggraphWrapper(tracer);
|
|
6214
|
-
|
|
6324
|
+
targetProto.stream = async function(input, config2, ...rest) {
|
|
6325
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6326
|
+
console.log("[Netra Debug] LangGraph stream intercepted!");
|
|
6327
|
+
}
|
|
6215
6328
|
return await wrapper.stream(
|
|
6216
6329
|
originalStream,
|
|
6217
6330
|
this,
|
|
@@ -6220,6 +6333,9 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6220
6333
|
...rest
|
|
6221
6334
|
);
|
|
6222
6335
|
};
|
|
6336
|
+
if (process.env.NETRA_DEBUG_LOGS) {
|
|
6337
|
+
console.log(`Successfully instrumented LangGraph stream method on ${targetProto.constructor?.name}`);
|
|
6338
|
+
}
|
|
6223
6339
|
} catch (error) {
|
|
6224
6340
|
console.error(`Failed to instrument langgraph stream: ${error}`);
|
|
6225
6341
|
}
|
|
@@ -6227,8 +6343,9 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6227
6343
|
_uninstrumentInvoke(Langgraph) {
|
|
6228
6344
|
try {
|
|
6229
6345
|
const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
|
|
6230
|
-
|
|
6231
|
-
|
|
6346
|
+
const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
|
|
6347
|
+
if (originalInvoke && targetProto?.invoke) {
|
|
6348
|
+
targetProto.invoke = originalInvoke;
|
|
6232
6349
|
}
|
|
6233
6350
|
} catch (error) {
|
|
6234
6351
|
console.error(`Failed to uninstrument langgraph invoke: ${error}`);
|
|
@@ -6238,8 +6355,9 @@ var NetraLanggraphInstrumentor = class {
|
|
|
6238
6355
|
_uninstrumentStream(Langgraph) {
|
|
6239
6356
|
try {
|
|
6240
6357
|
const originalStream = originalMethods3.get("langgraph.graph.stream");
|
|
6241
|
-
|
|
6242
|
-
|
|
6358
|
+
const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
|
|
6359
|
+
if (originalStream && targetProto?.stream) {
|
|
6360
|
+
targetProto.stream = originalStream;
|
|
6243
6361
|
}
|
|
6244
6362
|
} catch (error) {
|
|
6245
6363
|
console.error(`Failed to uninstrument langgraph stream: ${error}`);
|
|
@@ -8928,11 +9046,16 @@ var Netra = class {
|
|
|
8928
9046
|
}
|
|
8929
9047
|
/**
|
|
8930
9048
|
* Initialize the Netra SDK
|
|
8931
|
-
*
|
|
8932
|
-
*
|
|
8933
|
-
*
|
|
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();
|
|
8934
9057
|
*/
|
|
8935
|
-
static init(config2 = {}) {
|
|
9058
|
+
static async init(config2 = {}) {
|
|
8936
9059
|
if (this._initialized) {
|
|
8937
9060
|
console.warn(
|
|
8938
9061
|
"Netra.init() called more than once; ignoring subsequent calls."
|
|
@@ -8962,11 +9085,9 @@ var Netra = class {
|
|
|
8962
9085
|
this.dashboard = new Dashboard(cfg);
|
|
8963
9086
|
this._initialized = true;
|
|
8964
9087
|
console.info("Netra successfully initialized.");
|
|
8965
|
-
this._initialized = true;
|
|
8966
|
-
console.info("Netra successfully initialized.");
|
|
8967
9088
|
const handleSignal = async (signal) => {
|
|
8968
9089
|
console.log(`
|
|
8969
|
-
|
|
9090
|
+
Received ${signal}. Shutting down Netra SDK...`);
|
|
8970
9091
|
await this.shutdown();
|
|
8971
9092
|
process.exit(0);
|
|
8972
9093
|
};
|
|
@@ -9008,30 +9129,22 @@ Recepived ${signal}. Shutting down Netra SDK...`);
|
|
|
9008
9129
|
);
|
|
9009
9130
|
}
|
|
9010
9131
|
}
|
|
9132
|
+
await instrumentationsReady;
|
|
9011
9133
|
}
|
|
9012
9134
|
/**
|
|
9013
|
-
*
|
|
9014
|
-
* This is the recommended way to initialize Netra when using ES modules,
|
|
9015
|
-
* as it ensures all async instrumentations (OpenAI, Groq, MistralAI) are
|
|
9016
|
-
* complete before the application starts using the instrumented modules.
|
|
9135
|
+
* @deprecated Use `Netra.init()` instead. The init method is now async by default.
|
|
9017
9136
|
*
|
|
9018
|
-
*
|
|
9019
|
-
*
|
|
9020
|
-
* // Now OpenAI is fully instrumented
|
|
9021
|
-
* 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.
|
|
9022
9139
|
*/
|
|
9023
9140
|
static async initAsync(config2 = {}) {
|
|
9024
|
-
this.init(config2);
|
|
9025
|
-
await instrumentationsReady;
|
|
9141
|
+
await this.init(config2);
|
|
9026
9142
|
}
|
|
9027
9143
|
/**
|
|
9028
|
-
*
|
|
9029
|
-
*
|
|
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.
|
|
9030
9146
|
*
|
|
9031
|
-
*
|
|
9032
|
-
* Netra.init({ appName: 'my-app' });
|
|
9033
|
-
* await Netra.ready();
|
|
9034
|
-
* // Now all instrumentations are complete
|
|
9147
|
+
* Returns a promise that resolves when all async instrumentations are ready.
|
|
9035
9148
|
*/
|
|
9036
9149
|
static async ready() {
|
|
9037
9150
|
await instrumentationsReady;
|