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 CHANGED
@@ -49,7 +49,13 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
49
49
  var __getProtoOf = Object.getPrototypeOf;
50
50
  var __hasOwnProp = Object.prototype.hasOwnProperty;
51
51
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
52
- var __commonJS = (cb, mod) => function __require() {
52
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
53
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
54
+ }) : x)(function(x) {
55
+ if (typeof require !== "undefined") return require.apply(this, arguments);
56
+ throw Error('Dynamic require of "' + x + '" is not supported');
57
+ });
58
+ var __commonJS = (cb, mod) => function __require2() {
53
59
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
54
60
  };
55
61
  var __copyProps = (to, from, except, desc) => {
@@ -2333,8 +2339,8 @@ var Usage = class {
2333
2339
  if (!page) {
2334
2340
  break;
2335
2341
  }
2336
- for (const trace16 of page.traces) {
2337
- yield trace16;
2342
+ for (const trace17 of page.traces) {
2343
+ yield trace17;
2338
2344
  }
2339
2345
  if (!page.hasNextPage || !page.nextCursor) {
2340
2346
  break;
@@ -3417,6 +3423,10 @@ function anthropicWrapper(tracer, spanName, requestType) {
3417
3423
  return isPromise(result) ? result.then((value) => value) : result;
3418
3424
  }
3419
3425
  const isStreaming = args[0]?.stream === true;
3426
+ if (process.env.NETRA_DEBUG_LOGS) {
3427
+ const activeSpan = api.trace.getSpan(api.context.active());
3428
+ console.log(`[Netra Debug] Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
3429
+ }
3420
3430
  if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
3421
3431
  const currentContext = api.context.active();
3422
3432
  const span2 = tracer.startSpan(
@@ -5351,6 +5361,9 @@ var NetraGroqInstrumentor = class {
5351
5361
  };
5352
5362
  var groqInstrumentor = new NetraGroqInstrumentor();
5353
5363
 
5364
+ // src/instrumentation/langgraph/version.ts
5365
+ var __version__4 = "1.0.0";
5366
+
5354
5367
  // node_modules/@langchain/core/dist/_virtual/rolldown_runtime.js
5355
5368
  var __defProp2 = Object.defineProperty;
5356
5369
  var __export = (target, all) => {
@@ -5908,6 +5921,7 @@ function setLlmPrompts(span2, prompts) {
5908
5921
  }
5909
5922
 
5910
5923
  // src/instrumentation/langgraph/wrappers.ts
5924
+ var LANGGRAPH_INSTRUMENTATION_ACTIVE = api.createContextKey("netra.langgraph.active");
5911
5925
  var NetraLanggraphCallbackHandler = class extends BaseCallbackHandler {
5912
5926
  constructor(tracer, rootSpan) {
5913
5927
  super();
@@ -6087,13 +6101,30 @@ var LanggraphWrapper = class {
6087
6101
  return updatedConfig;
6088
6102
  }
6089
6103
  async invoke(originalFunc, instance, input, config2, ...rest) {
6090
- if (shouldSuppressInstrumentation()) {
6104
+ if (shouldSuppressInstrumentation() || api.context.active().getValue(LANGGRAPH_INSTRUMENTATION_ACTIVE)) {
6091
6105
  return await originalFunc.call(instance, input, config2, ...rest);
6092
6106
  }
6093
- const span2 = this.tracer.startSpan(this.spanName, {
6094
- kind: api.SpanKind.CLIENT
6095
- });
6096
- return api.context.with(api.trace.setSpan(api.context.active(), span2), async () => {
6107
+ const activeSpan = api.trace.getSpan(api.context.active());
6108
+ if (process.env.NETRA_DEBUG_LOGS) {
6109
+ console.log(`[Netra Debug] LangGraph invoke start. Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
6110
+ }
6111
+ const span2 = this.tracer.startSpan(
6112
+ this.spanName,
6113
+ {
6114
+ kind: api.SpanKind.CLIENT
6115
+ },
6116
+ api.context.active()
6117
+ );
6118
+ if (process.env.NETRA_DEBUG_LOGS) {
6119
+ console.log(`[Netra Debug] LangGraph span created. New TraceId: ${span2.spanContext().traceId}, SpanId: ${span2.spanContext().spanId}`);
6120
+ }
6121
+ const ctxWithSpan = api.trace.setSpan(api.context.active(), span2);
6122
+ const ctxWithFlag = ctxWithSpan.setValue(LANGGRAPH_INSTRUMENTATION_ACTIVE, true);
6123
+ return api.context.with(ctxWithFlag, async () => {
6124
+ if (process.env.NETRA_DEBUG_LOGS) {
6125
+ const innerSpan = api.trace.getSpan(api.context.active());
6126
+ console.log(`[Netra Debug] Inside LangGraph context. Active TraceId: ${innerSpan?.spanContext().traceId}, SpanId: ${innerSpan?.spanContext().spanId}`);
6127
+ }
6097
6128
  try {
6098
6129
  setGraphInputAttributes(span2, input);
6099
6130
  const updatedConfig = this.getUpdatedConfig(config2, span2);
@@ -6114,9 +6145,15 @@ var LanggraphWrapper = class {
6114
6145
  });
6115
6146
  }
6116
6147
  async stream(originalFunc, instance, input, config2, ...rest) {
6117
- if (shouldSuppressInstrumentation()) {
6148
+ if (shouldSuppressInstrumentation() || api.context.active().getValue(LANGGRAPH_INSTRUMENTATION_ACTIVE)) {
6149
+ if (process.env.NETRA_DEBUG_LOGS) {
6150
+ console.log("[Netra Debug] LangGraph stream skipped (inside instrumented call)");
6151
+ }
6118
6152
  return await originalFunc.call(instance, input, config2, ...rest);
6119
6153
  }
6154
+ if (process.env.NETRA_DEBUG_LOGS) {
6155
+ console.log("[Netra Debug] LangGraph stream starting instrumentation");
6156
+ }
6120
6157
  const span2 = this.tracer.startSpan(
6121
6158
  this.spanName,
6122
6159
  {
@@ -6142,22 +6179,71 @@ var LanggraphWrapper = class {
6142
6179
  }
6143
6180
  };
6144
6181
 
6145
- // src/instrumentation/langgraph/version.ts
6146
- var __version__4 = "1.0.0";
6147
-
6148
6182
  // src/instrumentation/langgraph/index.ts
6149
6183
  var INSTRUMENTATION_NAME4 = "netra.instrumentation.langchain";
6150
6184
  var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
6151
6185
  var isInstrumented4 = false;
6152
6186
  var LanggraphClass = null;
6153
6187
  var originalMethods3 = /* @__PURE__ */ new Map();
6188
+ function findModuleInCache(moduleName) {
6189
+ if (typeof __require !== "undefined" && __require.cache) {
6190
+ const cache = __require.cache;
6191
+ for (const key of Object.keys(cache)) {
6192
+ if (key.includes(moduleName.replace(/\//g, "/")) && !key.includes("netra-sdk")) {
6193
+ if (process.env.NETRA_DEBUG_LOGS) {
6194
+ console.log(`Found module in require.cache: ${key}`);
6195
+ }
6196
+ return cache[key]?.exports;
6197
+ }
6198
+ }
6199
+ if (process.env.NETRA_DEBUG_LOGS) {
6200
+ console.log(
6201
+ `Module ${moduleName} not found in require.cache. Cache keys containing 'langgraph':`,
6202
+ Object.keys(cache).filter((k) => k.includes("langgraph"))
6203
+ );
6204
+ }
6205
+ }
6206
+ return null;
6207
+ }
6154
6208
  async function resolveLanggraph() {
6155
6209
  if (LanggraphClass) return LanggraphClass;
6156
6210
  try {
6157
- const langgraphModule = await import('@langchain/langgraph');
6158
- LanggraphClass = langgraphModule.CompiledStateGraph;
6211
+ let langgraphModule = findModuleInCache("@langchain/langgraph");
6212
+ if (langgraphModule) {
6213
+ if (process.env.NETRA_DEBUG_LOGS) {
6214
+ console.log("Found @langchain/langgraph in require.cache (using app's module instance)");
6215
+ }
6216
+ } else {
6217
+ langgraphModule = await import('@langchain/langgraph');
6218
+ if (process.env.NETRA_DEBUG_LOGS) {
6219
+ console.log("Loaded @langchain/langgraph via dynamic import");
6220
+ }
6221
+ }
6222
+ if (process.env.NETRA_DEBUG_LOGS) {
6223
+ console.log("LangGraph Module Exports:", Object.keys(langgraphModule));
6224
+ }
6225
+ LanggraphClass = langgraphModule.CompiledStateGraph ?? langgraphModule.StateGraph;
6226
+ if (process.env.NETRA_DEBUG_LOGS) {
6227
+ console.log("Resolved LanggraphClass:", !!LanggraphClass);
6228
+ console.log("LanggraphClass name:", LanggraphClass?.name);
6229
+ console.log("LanggraphClass.prototype keys:", LanggraphClass?.prototype ? Object.getOwnPropertyNames(LanggraphClass.prototype) : "no prototype");
6230
+ console.log("Has invoke on prototype:", !!LanggraphClass?.prototype?.invoke);
6231
+ console.log("Has stream on prototype:", !!LanggraphClass?.prototype?.stream);
6232
+ console.log("Checking prototype chain for invoke location:");
6233
+ let proto = LanggraphClass?.prototype;
6234
+ while (proto) {
6235
+ const hasOwn = Object.getOwnPropertyNames(proto).includes("invoke");
6236
+ console.log(` ${proto.constructor?.name}: hasOwnProperty('invoke')=${hasOwn}`);
6237
+ if (hasOwn) {
6238
+ console.log(` -> invoke is defined on: ${proto.constructor?.name}`);
6239
+ break;
6240
+ }
6241
+ proto = Object.getPrototypeOf(proto);
6242
+ }
6243
+ }
6159
6244
  return LanggraphClass;
6160
- } catch {
6245
+ } catch (e) {
6246
+ console.error("Failed to resolve LangGraph:", e);
6161
6247
  return null;
6162
6248
  }
6163
6249
  }
@@ -6178,6 +6264,7 @@ var NetraLanggraphInstrumentor = class {
6178
6264
  }
6179
6265
  const Langgraph = await resolveLanggraph();
6180
6266
  if (!Langgraph) {
6267
+ if (process.env.NETRA_DEBUG_LOGS) console.warn("LangGraph class not found, skipping instrumentation");
6181
6268
  return this;
6182
6269
  }
6183
6270
  try {
@@ -6187,17 +6274,19 @@ var NetraLanggraphInstrumentor = class {
6187
6274
  console.error(`Failed to initialize tracer: ${error}`);
6188
6275
  return this;
6189
6276
  }
6277
+ this._instrumentInvoke(Langgraph);
6190
6278
  this._instrumentStream(Langgraph);
6191
6279
  isInstrumented4 = true;
6192
6280
  return this;
6193
6281
  }
6194
6282
  async uninstrument() {
6195
6283
  if (!isInstrumented4) {
6196
- console.warn("OpenAI is not instrumented");
6284
+ console.warn("LangGraph is not instrumented");
6197
6285
  return;
6198
6286
  }
6199
6287
  const Langgraph = await resolveLanggraph();
6200
6288
  if (Langgraph) {
6289
+ this._uninstrumentInvoke(Langgraph);
6201
6290
  this._uninstrumentStream(Langgraph);
6202
6291
  }
6203
6292
  originalMethods3.clear();
@@ -6206,15 +6295,26 @@ var NetraLanggraphInstrumentor = class {
6206
6295
  _instrumentInvoke(Langgraph) {
6207
6296
  if (!this.tracer) return;
6208
6297
  try {
6209
- if (!Langgraph?.prototype?.invoke) {
6298
+ let targetProto = Langgraph?.prototype;
6299
+ while (targetProto && !Object.getOwnPropertyNames(targetProto).includes("invoke")) {
6300
+ targetProto = Object.getPrototypeOf(targetProto);
6301
+ }
6302
+ if (!targetProto?.invoke) {
6210
6303
  console.error("Failed to find langgraph invoke function to instrument");
6211
6304
  return;
6212
6305
  }
6213
- const originalInvoke = Langgraph.prototype.invoke;
6306
+ if (process.env.NETRA_DEBUG_LOGS) {
6307
+ console.log(`Found invoke on prototype: ${targetProto.constructor?.name}`);
6308
+ }
6309
+ const originalInvoke = targetProto.invoke;
6214
6310
  originalMethods3.set("langgraph.graph.invoke", originalInvoke);
6311
+ originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
6215
6312
  const tracer = this.tracer;
6216
6313
  const wrapper = new LanggraphWrapper(tracer);
6217
- Langgraph.prototype.invoke = async function(input, config2, ...rest) {
6314
+ const patchedInvoke = async function(input, config2, ...rest) {
6315
+ if (process.env.NETRA_DEBUG_LOGS) {
6316
+ console.log("[Netra Debug] LangGraph invoke intercepted!");
6317
+ }
6218
6318
  return await wrapper.invoke(
6219
6319
  originalInvoke,
6220
6320
  this,
@@ -6223,6 +6323,12 @@ var NetraLanggraphInstrumentor = class {
6223
6323
  ...rest
6224
6324
  );
6225
6325
  };
6326
+ patchedInvoke.__netra_patched = true;
6327
+ targetProto.invoke = patchedInvoke;
6328
+ if (process.env.NETRA_DEBUG_LOGS) {
6329
+ console.log(`Successfully instrumented LangGraph invoke method on ${targetProto.constructor?.name}`);
6330
+ console.log(`Patched Pregel class identity:`, targetProto.constructor);
6331
+ }
6226
6332
  } catch (error) {
6227
6333
  console.error(`Failed to instrument langgraph invoke: ${error}`);
6228
6334
  }
@@ -6230,15 +6336,26 @@ var NetraLanggraphInstrumentor = class {
6230
6336
  _instrumentStream(Langgraph) {
6231
6337
  if (!this.tracer) return;
6232
6338
  try {
6233
- if (!Langgraph?.prototype?.stream) {
6339
+ let targetProto = Langgraph?.prototype;
6340
+ while (targetProto && !Object.getOwnPropertyNames(targetProto).includes("stream")) {
6341
+ targetProto = Object.getPrototypeOf(targetProto);
6342
+ }
6343
+ if (!targetProto?.stream) {
6234
6344
  console.error("Failed to find langgraph stream function to instrument");
6235
6345
  return;
6236
6346
  }
6237
- const originalStream = Langgraph.prototype.stream;
6347
+ if (process.env.NETRA_DEBUG_LOGS) {
6348
+ console.log(`Found stream on prototype: ${targetProto.constructor?.name}`);
6349
+ }
6350
+ const originalStream = targetProto.stream;
6238
6351
  originalMethods3.set("langgraph.graph.stream", originalStream);
6352
+ originalMethods3.set("langgraph.graph.stream.proto", targetProto);
6239
6353
  const tracer = this.tracer;
6240
6354
  const wrapper = new LanggraphWrapper(tracer);
6241
- Langgraph.prototype.stream = async function(input, config2, ...rest) {
6355
+ targetProto.stream = async function(input, config2, ...rest) {
6356
+ if (process.env.NETRA_DEBUG_LOGS) {
6357
+ console.log("[Netra Debug] LangGraph stream intercepted!");
6358
+ }
6242
6359
  return await wrapper.stream(
6243
6360
  originalStream,
6244
6361
  this,
@@ -6247,6 +6364,9 @@ var NetraLanggraphInstrumentor = class {
6247
6364
  ...rest
6248
6365
  );
6249
6366
  };
6367
+ if (process.env.NETRA_DEBUG_LOGS) {
6368
+ console.log(`Successfully instrumented LangGraph stream method on ${targetProto.constructor?.name}`);
6369
+ }
6250
6370
  } catch (error) {
6251
6371
  console.error(`Failed to instrument langgraph stream: ${error}`);
6252
6372
  }
@@ -6254,8 +6374,9 @@ var NetraLanggraphInstrumentor = class {
6254
6374
  _uninstrumentInvoke(Langgraph) {
6255
6375
  try {
6256
6376
  const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
6257
- if (originalInvoke && Langgraph?.prototype?.invoke) {
6258
- Langgraph.prototype.invoke = originalInvoke;
6377
+ const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
6378
+ if (originalInvoke && targetProto?.invoke) {
6379
+ targetProto.invoke = originalInvoke;
6259
6380
  }
6260
6381
  } catch (error) {
6261
6382
  console.error(`Failed to uninstrument langgraph invoke: ${error}`);
@@ -6265,8 +6386,9 @@ var NetraLanggraphInstrumentor = class {
6265
6386
  _uninstrumentStream(Langgraph) {
6266
6387
  try {
6267
6388
  const originalStream = originalMethods3.get("langgraph.graph.stream");
6268
- if (originalStream && Langgraph?.prototype?.stream) {
6269
- Langgraph.prototype.stream = originalStream;
6389
+ const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
6390
+ if (originalStream && targetProto?.stream) {
6391
+ targetProto.stream = originalStream;
6270
6392
  }
6271
6393
  } catch (error) {
6272
6394
  console.error(`Failed to uninstrument langgraph stream: ${error}`);
@@ -8391,6 +8513,13 @@ function initInstrumentations(config2, instruments, blockInstruments) {
8391
8513
  customInstrumentModules.googleGenAI = true;
8392
8514
  customInstrumentModules.anthropic = true;
8393
8515
  } else if (instruments.size) {
8516
+ instrumentModules.google_vertexai = false;
8517
+ instrumentModules.langchain = false;
8518
+ instrumentModules.llamaIndex = false;
8519
+ instrumentModules.pinecone = false;
8520
+ instrumentModules.qdrant = false;
8521
+ instrumentModules.chromadb = false;
8522
+ instrumentModules.together = false;
8394
8523
  if (instruments.has("openai" /* OPENAI */)) {
8395
8524
  customInstrumentModules.openai = true;
8396
8525
  }
@@ -8948,11 +9077,16 @@ var Netra = class {
8948
9077
  }
8949
9078
  /**
8950
9079
  * Initialize the Netra SDK
8951
- * Note: Custom instrumentations (OpenAI, Groq, MistralAI) are initialized
8952
- * asynchronously. Use initAsync() or await Netra.ready() to ensure
8953
- * instrumentations are complete before using instrumented modules.
9080
+ *
9081
+ * This method is async and must be awaited to ensure all instrumentations
9082
+ * are ready before your application starts using instrumented modules.
9083
+ *
9084
+ * @example
9085
+ * await Netra.init({ appName: 'my-app', instruments: new Set([NetraInstruments.OPENAI]) });
9086
+ * // Now all instrumentations are ready
9087
+ * const openai = new OpenAI();
8954
9088
  */
8955
- static init(config2 = {}) {
9089
+ static async init(config2 = {}) {
8956
9090
  if (this._initialized) {
8957
9091
  console.warn(
8958
9092
  "Netra.init() called more than once; ignoring subsequent calls."
@@ -8982,11 +9116,9 @@ var Netra = class {
8982
9116
  this.dashboard = new Dashboard(cfg);
8983
9117
  this._initialized = true;
8984
9118
  console.info("Netra successfully initialized.");
8985
- this._initialized = true;
8986
- console.info("Netra successfully initialized.");
8987
9119
  const handleSignal = async (signal) => {
8988
9120
  console.log(`
8989
- Recepived ${signal}. Shutting down Netra SDK...`);
9121
+ Received ${signal}. Shutting down Netra SDK...`);
8990
9122
  await this.shutdown();
8991
9123
  process.exit(0);
8992
9124
  };
@@ -9028,30 +9160,22 @@ Recepived ${signal}. Shutting down Netra SDK...`);
9028
9160
  );
9029
9161
  }
9030
9162
  }
9163
+ await instrumentationsReady;
9031
9164
  }
9032
9165
  /**
9033
- * Initialize the Netra SDK and wait for all instrumentations to be ready.
9034
- * This is the recommended way to initialize Netra when using ES modules,
9035
- * as it ensures all async instrumentations (OpenAI, Groq, MistralAI) are
9036
- * complete before the application starts using the instrumented modules.
9166
+ * @deprecated Use `Netra.init()` instead. The init method is now async by default.
9037
9167
  *
9038
- * @example
9039
- * await Netra.initAsync({ appName: 'my-app', instruments: new Set([NetraInstruments.OPENAI]) });
9040
- * // Now OpenAI is fully instrumented
9041
- * const openai = new OpenAI();
9168
+ * Initialize the Netra SDK and wait for all instrumentations to be ready.
9169
+ * This method is kept for backwards compatibility.
9042
9170
  */
9043
9171
  static async initAsync(config2 = {}) {
9044
- this.init(config2);
9045
- await instrumentationsReady;
9172
+ await this.init(config2);
9046
9173
  }
9047
9174
  /**
9048
- * Returns a promise that resolves when all async instrumentations are ready.
9049
- * Can be called after init() to wait for instrumentations.
9175
+ * @deprecated Since `Netra.init()` is now async and waits for instrumentations,
9176
+ * this method is no longer necessary. It's kept for backwards compatibility.
9050
9177
  *
9051
- * @example
9052
- * Netra.init({ appName: 'my-app' });
9053
- * await Netra.ready();
9054
- * // Now all instrumentations are complete
9178
+ * Returns a promise that resolves when all async instrumentations are ready.
9055
9179
  */
9056
9180
  static async ready() {
9057
9181
  await instrumentationsReady;