Skip to main content

View on npm

netra-sdk - AI observability SDK for TypeScript/JavaScript applications

Installation

npm install netra-sdk

Netra Class

The Netra class is the main entry point for all SDK operations. All methods are static and can be called directly on the class.

init

Initialize the Netra SDK with configuration options. This method is async and waits for all instrumentations to be ready before returning. Call this once at the start of your application, before importing other libraries for best results.
import { Netra, NetraInstruments } from "netra-sdk";

await Netra.init({
  appName: "my-ai-app",
  headers: `x-api-key=${process.env.NETRA_API_KEY}`,
  environment: "production",
  traceContent: true,
  instruments: new Set([NetraInstruments.OPENAI, NetraInstruments.LANGCHAIN]),
});
Always await the init() call to ensure all instrumentations (like OpenAI, Anthropic, LangGraph) are fully patched before your application starts using them. This is especially important in frameworks like NestJS where modules are loaded after initialization.
Parameters:
ParameterTypeDescription
appNamestring?Name of your application for identification in the dashboard
headersstring?Headers for API requests (e.g., x-api-key=your-key)
disableBatchboolean?Disable batch processing of spans (default: false)
traceContentboolean?Enable tracing of prompt/completion content (default: true)
resourceAttributesRecord<string, any>?Additional OpenTelemetry resource attributes
environmentstring?Application environment (e.g., “production”, “staging”)
instrumentsSet<NetraInstruments>?Set of instrumentations to enable (enables only these)
blockInstrumentsSet<NetraInstruments>?Set of instrumentations to disable
enableRootSpanboolean?Create a root span wrapping all traces
debugModeboolean?Enable debug logging
enableScrubbingboolean?Enable PII scrubbing
blockedSpansstring[]?Span names to filter out globally (supports wildcards)
Returns: Promise<void>

startSpan

Create a new span for manual tracing. Unlike Python, TypeScript requires explicit end() calls.
import { Netra, SpanType } from "netra-sdk";

// Basic usage
const span = Netra.startSpan("process-document");
try {
  const result = await processDocument(doc);
  span.setAttribute("pages", result.pageCount);
  span.setSuccess();
} catch (error) {
  span.setError(error.message);
  throw error;
} finally {
  span.end();
}

// With span type and attributes
const genSpan = Netra.startSpan("generate-response", { attributes: { model: "gpt-4" }, moduleName: "chat" }, undefined, SpanType.GENERATION);
Parameters:
ParameterTypeDescription
namestringName of the span (required)
options.asTypeSpanType?Type of span for categorization
options.attributesRecord<string, any>?Initial attributes to set
options.moduleNamestring?Module name for organization
Returns: SpanWrapper instance

setSessionId

Set the session ID for the current context. All subsequent spans will be associated with this session.
Netra.setSessionId("session-abc123");
Parameters:
ParameterTypeDescription
sessionIdstringUnique identifier for the session
Returns: void

setUserId

Set the user ID for the current context.
Netra.setUserId("user-456");
Parameters:
ParameterTypeDescription
userIdstringUnique identifier for the user
Returns: void

setTenantId

Set the tenant ID for multi-tenant applications.
Netra.setTenantId("tenant-org-789");
Parameters:
ParameterTypeDescription
tenantIdstringUnique identifier for the tenant
Returns: void

setCustomAttributes

Add custom key-value attributes to the current context.
Netra.setCustomAttributes({ key: "customer_tier", value: "premium" });
Netra.setCustomAttributes({ key: "region", value: "us-east" });
Parameters:
ParameterTypeDescription
options.keystringAttribute key
options.valueanyAttribute value
Returns: void

setCustomEvent

Record a custom event in the current context.
Netra.setCustomEvent({
  event_name: "user_feedback",
  attributes: {
    rating: 5,
    comment: "Great response!",
    category: "positive",
  },
});
Parameters:
ParameterTypeDescription
options.event_namestringName of the event
options.attributesRecord<string, any>Event attributes
Returns: void

shutdown

Gracefully shutdown the SDK, flushing any pending spans.
await Netra.shutdown();
Returns: Promise<void>

SpanWrapper Class

The SpanWrapper class provides methods for enriching spans with additional context. It’s returned by Netra.startSpan() and supports method chaining.

setAttribute

Add a custom attribute to the span.
span.setAttribute("query", userQuery);
span.setAttribute("results.count", results.length);
Parameters:
ParameterTypeDescription
keystringAttribute key
valueanyAttribute value
Returns: SpanWrapper (for chaining)

addEvent

Record a timestamped event within the span.
span.addEvent("validation-started");
span.addEvent("validation-completed", { valid: true, errors: 0 });
Parameters:
ParameterTypeDescription
namestringEvent name
attributesRecord<string, any>?Event attributes
Returns: SpanWrapper (for chaining)

setPrompt

Set the input prompt for LLM spans.
span.setPrompt("Summarize this article: ...");
Parameters:
ParameterTypeDescription
promptstringThe prompt text
Returns: SpanWrapper (for chaining)

setNegativePrompt

Set the negative prompt (commonly used for image generation).
span.setNegativePrompt("blurry, low quality, distorted");
Parameters:
ParameterTypeDescription
promptstringThe negative prompt text
Returns: SpanWrapper (for chaining)

setModel

Set the model name used in the operation.
span.setModel("gpt-4-turbo");
Parameters:
ParameterTypeDescription
modelstringModel name
Returns: SpanWrapper (for chaining)

setLlmSystem

Set the LLM provider/system name.
span.setLlmSystem("openai");
Parameters:
ParameterTypeDescription
systemstringLLM system name
Returns: SpanWrapper (for chaining)

setUsage

Record token usage and cost metrics.
span.setUsage([
  {
    model: "gpt-4",
    costInUsd: 0.006,
    usageType: "chat",
    unitsUsed: 1,
  },
]);
Parameters:
ParameterTypeDescription
usageDataUsageModel[]List of usage records
Returns: SpanWrapper (for chaining)

setAction

Track actions or tool calls within the span.
span.setAction([
  {
    action: "DB",
    actionType: "INSERT",
    affectedRecords: [{ recordId: "123", recordType: "user" }],
    metadata: { table: "users" },
    success: true,
  },
]);
Parameters:
ParameterTypeDescription
actionsActionModel[]List of action records
Returns: SpanWrapper (for chaining)

setSuccess

Mark the span as successful.
span.setSuccess();
Returns: SpanWrapper (for chaining)

setError

Mark the span as failed with an error message.
span.setError("Failed to connect to database");
Parameters:
ParameterTypeDescription
messagestringError message
Returns: SpanWrapper (for chaining)

end

End the span. Required in TypeScript - spans won’t be exported until end() is called.
span.end();
Returns: void
Always call span.end() in TypeScript, preferably in a finally block to ensure spans are closed even when errors occur.

Types and Interfaces

SpanType

Enum for categorizing spans.
import { SpanType } from "netra-sdk";

SpanType.SPAN;       // General operations (default)
SpanType.GENERATION; // LLM completions, image generation
SpanType.EMBEDDING;  // Vector embedding operations
SpanType.TOOL;       // Function calls, API requests
SpanType.AGENT;      // AI agent operations

UsageModel

Interface for tracking token usage and costs.
interface UsageModel {
  model: string;
  costInUsd?: number;
  usageType?: string;
  unitsUsed?: number;
}
Example:
const usage: UsageModel = {
  model: "gpt-4",
  costInUsd: 0.0045,
  usageType: "chat",
  unitsUsed: 1,
};

ActionModel

Interface for tracking actions and tool calls.
interface ActionModel {
  action: string;
  actionType: string;
  affectedRecords?: Array<{
    recordId: string;
    recordType: string;
  }>;
  metadata?: Record<string, string>;
  success: boolean;
}
Example:
const action: ActionModel = {
  action: "API",
  actionType: "CALL",
  affectedRecords: [{ recordId: "order-123", recordType: "order" }],
  metadata: {
    endpoint: "/api/orders",
    method: "POST",
    statusCode: "201",
  },
  success: true,
};

Decorators

TypeScript decorators for easy function instrumentation.
TypeScript decorators require "experimentalDecorators": true in your tsconfig.json.

@agent

Mark a function or class as an AI agent.
import { agent } from "netra-sdk/decorators";

@agent
async function researchAgent(query: string) {
  return await performResearch(query);
}

@agent({ name: "customer-support" })
async function supportAgent(request: Request) {
  return await handleRequest(request);
}

@task

Mark a function as a task or tool.
import { task } from "netra-sdk/decorators";

@task
async function fetchData(query: string) {
  return await database.query(query);
}

@task({ name: "web-search" })
async function searchWeb(query: string) {
  return await searchApi.search(query);
}

@workflow

Mark a function as a workflow.
import { workflow } from "netra-sdk/decorators";

@workflow
async function processOrder(order: Order) {
  await validateOrder(order);
  await processPayment(order);
  await fulfillOrder(order);
}

Instruments

Available instrumentations for auto-tracing.
import { NetraInstruments } from "netra-sdk";

// LLM Providers
NetraInstruments.OPENAI;
NetraInstruments.GOOGLE_GENAI;
NetraInstruments.MISTRAL;
NetraInstruments.GROQ;
NetraInstruments.VERTEX_AI;
NetraInstruments.TOGETHER;

// AI Frameworks
NetraInstruments.LANGCHAIN;
NetraInstruments.LANGGRAPH;
NetraInstruments.LLAMAINDEX;

// Vector Databases
NetraInstruments.PINECONE;
NetraInstruments.QDRANT;
NetraInstruments.CHROMADB;

// HTTP Clients
NetraInstruments.HTTP;
NetraInstruments.HTTPS;
NetraInstruments.FETCH;

// Web Frameworks
NetraInstruments.EXPRESS;
NetraInstruments.FASTIFY;
NetraInstruments.NESTJS;

// Databases
NetraInstruments.PRISMA;
NetraInstruments.TYPEORM;
NetraInstruments.MONGODB;
NetraInstruments.POSTGRES;
NetraInstruments.MYSQL;
NetraInstruments.REDIS;

// Message Queues
NetraInstruments.KAFKA;
NetraInstruments.RABBITMQ;

Complete Example

import { Netra, SpanType, NetraInstruments } from "netra-sdk";
import OpenAI from "openai";

// Initialize SDK (must await to ensure instrumentations are ready)
await Netra.init({
  appName: "my-ai-app",
  headers: `x-api-key=${process.env.NETRA_API_KEY}`,
  environment: "production",
  instruments: new Set([NetraInstruments.OPENAI]),
});

// Set context
Netra.setUserId("user-123");
Netra.setSessionId("session-abc");

// Create a traced operation
async function chatWithAI(userMessage: string): Promise<string> {
  const span = Netra.startSpan("chat-completion", {}, undefined, SpanType.GENERATION);

  span.setPrompt(userMessage);
  span.setModel("gpt-4");
  span.setLlmSystem("openai");

  try {
    const client = new OpenAI();
    const response = await client.chat.completions.create({
      model: "gpt-4",
      messages: [{ role: "user", content: userMessage }],
    });

    // Calculate cost based on token usage
    const promptCost = ((response.usage?.prompt_tokens || 0) / 1000) * 0.03;
    const completionCost = ((response.usage?.completion_tokens || 0) / 1000) * 0.06;
    const totalCost = promptCost + completionCost;

    span.setUsage([
      {
        model: "gpt-4",
        costInUsd: totalCost,
        usageType: "chat",
        unitsUsed: 1,
      },
    ]);

    span.setSuccess();
    return response.choices[0].message.content || "";
  } catch (error: any) {
    span.setError(error.message);
    throw error;
  } finally {
    span.end();
  }
}

// Use the function
const result = await chatWithAI("What is the capital of France?");
console.log(result);

// Shutdown gracefully
await Netra.shutdown();

Express.js Integration

Example of integrating Netra with Express.js:
import express from "express";
import { Netra, NetraInstruments } from "netra-sdk";

async function main() {
  // Initialize before creating the app (must await)
  await Netra.init({
    appName: "my-api",
    headers: `x-api-key=${process.env.NETRA_API_KEY}`,
    instruments: new Set([NetraInstruments.EXPRESS, NetraInstruments.OPENAI]),
  });

  const app = express();

  // Middleware to set user context
  app.use((req, res, next) => {
    if (req.headers["x-user-id"]) {
      Netra.setUserId(req.headers["x-user-id"] as string);
    }
    if (req.headers["x-session-id"]) {
      Netra.setSessionId(req.headers["x-session-id"] as string);
    }
    next();
  });

  app.post("/api/chat", async (req, res) => {
    const span = Netra.startSpan("handle-chat-request");

    try {
      const { message } = req.body;
      span.setAttribute("input.length", message.length);

      const response = await processMessage(message);

      span.setSuccess();
      res.json({ response });
    } catch (error: any) {
      span.setError(error.message);
      res.status(500).json({ error: error.message });
    } finally {
      span.end();
    }
  });

  // Graceful shutdown
  process.on("SIGTERM", async () => {
    await Netra.shutdown();
    process.exit(0);
  });

  app.listen(3000);
}

main();

Key Differences from Python SDK

FeaturePythonTypeScript
InitializationNetra.init() (sync)await Netra.init() (async, waits for instrumentations)
Span lifecycleContext manager (with statement)Manual end() call required
Naming conventionsnake_casecamelCase
Instruments enumInstrumentsNetraInstruments
ShutdownNetra.shutdown()await Netra.shutdown()
AsyncContext managers work with sync/asyncAlways use async/await

Next Steps

Last modified on January 30, 2026