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 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,9 +6101,13 @@ 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
  }
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
+ }
6093
6111
  const span2 = this.tracer.startSpan(
6094
6112
  this.spanName,
6095
6113
  {
@@ -6097,7 +6115,16 @@ var LanggraphWrapper = class {
6097
6115
  },
6098
6116
  api.context.active()
6099
6117
  );
6100
- return api.context.with(api.trace.setSpan(api.context.active(), span2), async () => {
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
+ }
6101
6128
  try {
6102
6129
  setGraphInputAttributes(span2, input);
6103
6130
  const updatedConfig = this.getUpdatedConfig(config2, span2);
@@ -6118,9 +6145,15 @@ var LanggraphWrapper = class {
6118
6145
  });
6119
6146
  }
6120
6147
  async stream(originalFunc, instance, input, config2, ...rest) {
6121
- 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
+ }
6122
6152
  return await originalFunc.call(instance, input, config2, ...rest);
6123
6153
  }
6154
+ if (process.env.NETRA_DEBUG_LOGS) {
6155
+ console.log("[Netra Debug] LangGraph stream starting instrumentation");
6156
+ }
6124
6157
  const span2 = this.tracer.startSpan(
6125
6158
  this.spanName,
6126
6159
  {
@@ -6146,22 +6179,71 @@ var LanggraphWrapper = class {
6146
6179
  }
6147
6180
  };
6148
6181
 
6149
- // src/instrumentation/langgraph/version.ts
6150
- var __version__4 = "1.0.0";
6151
-
6152
6182
  // src/instrumentation/langgraph/index.ts
6153
6183
  var INSTRUMENTATION_NAME4 = "netra.instrumentation.langchain";
6154
6184
  var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
6155
6185
  var isInstrumented4 = false;
6156
6186
  var LanggraphClass = null;
6157
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
+ }
6158
6208
  async function resolveLanggraph() {
6159
6209
  if (LanggraphClass) return LanggraphClass;
6160
6210
  try {
6161
- const langgraphModule = await import('@langchain/langgraph');
6162
- 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
+ }
6163
6244
  return LanggraphClass;
6164
- } catch {
6245
+ } catch (e) {
6246
+ console.error("Failed to resolve LangGraph:", e);
6165
6247
  return null;
6166
6248
  }
6167
6249
  }
@@ -6182,6 +6264,7 @@ var NetraLanggraphInstrumentor = class {
6182
6264
  }
6183
6265
  const Langgraph = await resolveLanggraph();
6184
6266
  if (!Langgraph) {
6267
+ if (process.env.NETRA_DEBUG_LOGS) console.warn("LangGraph class not found, skipping instrumentation");
6185
6268
  return this;
6186
6269
  }
6187
6270
  try {
@@ -6191,17 +6274,19 @@ var NetraLanggraphInstrumentor = class {
6191
6274
  console.error(`Failed to initialize tracer: ${error}`);
6192
6275
  return this;
6193
6276
  }
6277
+ this._instrumentInvoke(Langgraph);
6194
6278
  this._instrumentStream(Langgraph);
6195
6279
  isInstrumented4 = true;
6196
6280
  return this;
6197
6281
  }
6198
6282
  async uninstrument() {
6199
6283
  if (!isInstrumented4) {
6200
- console.warn("OpenAI is not instrumented");
6284
+ console.warn("LangGraph is not instrumented");
6201
6285
  return;
6202
6286
  }
6203
6287
  const Langgraph = await resolveLanggraph();
6204
6288
  if (Langgraph) {
6289
+ this._uninstrumentInvoke(Langgraph);
6205
6290
  this._uninstrumentStream(Langgraph);
6206
6291
  }
6207
6292
  originalMethods3.clear();
@@ -6210,15 +6295,26 @@ var NetraLanggraphInstrumentor = class {
6210
6295
  _instrumentInvoke(Langgraph) {
6211
6296
  if (!this.tracer) return;
6212
6297
  try {
6213
- 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) {
6214
6303
  console.error("Failed to find langgraph invoke function to instrument");
6215
6304
  return;
6216
6305
  }
6217
- 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;
6218
6310
  originalMethods3.set("langgraph.graph.invoke", originalInvoke);
6311
+ originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
6219
6312
  const tracer = this.tracer;
6220
6313
  const wrapper = new LanggraphWrapper(tracer);
6221
- 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
+ }
6222
6318
  return await wrapper.invoke(
6223
6319
  originalInvoke,
6224
6320
  this,
@@ -6227,6 +6323,12 @@ var NetraLanggraphInstrumentor = class {
6227
6323
  ...rest
6228
6324
  );
6229
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
+ }
6230
6332
  } catch (error) {
6231
6333
  console.error(`Failed to instrument langgraph invoke: ${error}`);
6232
6334
  }
@@ -6234,15 +6336,26 @@ var NetraLanggraphInstrumentor = class {
6234
6336
  _instrumentStream(Langgraph) {
6235
6337
  if (!this.tracer) return;
6236
6338
  try {
6237
- 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) {
6238
6344
  console.error("Failed to find langgraph stream function to instrument");
6239
6345
  return;
6240
6346
  }
6241
- 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;
6242
6351
  originalMethods3.set("langgraph.graph.stream", originalStream);
6352
+ originalMethods3.set("langgraph.graph.stream.proto", targetProto);
6243
6353
  const tracer = this.tracer;
6244
6354
  const wrapper = new LanggraphWrapper(tracer);
6245
- 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
+ }
6246
6359
  return await wrapper.stream(
6247
6360
  originalStream,
6248
6361
  this,
@@ -6251,6 +6364,9 @@ var NetraLanggraphInstrumentor = class {
6251
6364
  ...rest
6252
6365
  );
6253
6366
  };
6367
+ if (process.env.NETRA_DEBUG_LOGS) {
6368
+ console.log(`Successfully instrumented LangGraph stream method on ${targetProto.constructor?.name}`);
6369
+ }
6254
6370
  } catch (error) {
6255
6371
  console.error(`Failed to instrument langgraph stream: ${error}`);
6256
6372
  }
@@ -6258,8 +6374,9 @@ var NetraLanggraphInstrumentor = class {
6258
6374
  _uninstrumentInvoke(Langgraph) {
6259
6375
  try {
6260
6376
  const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
6261
- if (originalInvoke && Langgraph?.prototype?.invoke) {
6262
- Langgraph.prototype.invoke = originalInvoke;
6377
+ const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
6378
+ if (originalInvoke && targetProto?.invoke) {
6379
+ targetProto.invoke = originalInvoke;
6263
6380
  }
6264
6381
  } catch (error) {
6265
6382
  console.error(`Failed to uninstrument langgraph invoke: ${error}`);
@@ -6269,8 +6386,9 @@ var NetraLanggraphInstrumentor = class {
6269
6386
  _uninstrumentStream(Langgraph) {
6270
6387
  try {
6271
6388
  const originalStream = originalMethods3.get("langgraph.graph.stream");
6272
- if (originalStream && Langgraph?.prototype?.stream) {
6273
- Langgraph.prototype.stream = originalStream;
6389
+ const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
6390
+ if (originalStream && targetProto?.stream) {
6391
+ targetProto.stream = originalStream;
6274
6392
  }
6275
6393
  } catch (error) {
6276
6394
  console.error(`Failed to uninstrument langgraph stream: ${error}`);
@@ -8959,11 +9077,16 @@ var Netra = class {
8959
9077
  }
8960
9078
  /**
8961
9079
  * Initialize the Netra SDK
8962
- * Note: Custom instrumentations (OpenAI, Groq, MistralAI) are initialized
8963
- * asynchronously. Use initAsync() or await Netra.ready() to ensure
8964
- * 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();
8965
9088
  */
8966
- static init(config2 = {}) {
9089
+ static async init(config2 = {}) {
8967
9090
  if (this._initialized) {
8968
9091
  console.warn(
8969
9092
  "Netra.init() called more than once; ignoring subsequent calls."
@@ -8993,11 +9116,9 @@ var Netra = class {
8993
9116
  this.dashboard = new Dashboard(cfg);
8994
9117
  this._initialized = true;
8995
9118
  console.info("Netra successfully initialized.");
8996
- this._initialized = true;
8997
- console.info("Netra successfully initialized.");
8998
9119
  const handleSignal = async (signal) => {
8999
9120
  console.log(`
9000
- Recepived ${signal}. Shutting down Netra SDK...`);
9121
+ Received ${signal}. Shutting down Netra SDK...`);
9001
9122
  await this.shutdown();
9002
9123
  process.exit(0);
9003
9124
  };
@@ -9039,30 +9160,22 @@ Recepived ${signal}. Shutting down Netra SDK...`);
9039
9160
  );
9040
9161
  }
9041
9162
  }
9163
+ await instrumentationsReady;
9042
9164
  }
9043
9165
  /**
9044
- * Initialize the Netra SDK and wait for all instrumentations to be ready.
9045
- * This is the recommended way to initialize Netra when using ES modules,
9046
- * as it ensures all async instrumentations (OpenAI, Groq, MistralAI) are
9047
- * complete before the application starts using the instrumented modules.
9166
+ * @deprecated Use `Netra.init()` instead. The init method is now async by default.
9048
9167
  *
9049
- * @example
9050
- * await Netra.initAsync({ appName: 'my-app', instruments: new Set([NetraInstruments.OPENAI]) });
9051
- * // Now OpenAI is fully instrumented
9052
- * 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.
9053
9170
  */
9054
9171
  static async initAsync(config2 = {}) {
9055
- this.init(config2);
9056
- await instrumentationsReady;
9172
+ await this.init(config2);
9057
9173
  }
9058
9174
  /**
9059
- * Returns a promise that resolves when all async instrumentations are ready.
9060
- * 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.
9061
9177
  *
9062
- * @example
9063
- * Netra.init({ appName: 'my-app' });
9064
- * await Netra.ready();
9065
- * // Now all instrumentations are complete
9178
+ * Returns a promise that resolves when all async instrumentations are ready.
9066
9179
  */
9067
9180
  static async ready() {
9068
9181
  await instrumentationsReady;