Skip to main content
You don’t need every span. Filter out the noise and ship the useful bits. LangWatch lets you keep AI and business spans while dropping framework chatter.
Introduced in [email protected].

Defaults

By default we exclude HTTP request spans.
import { setupObservability } from "langwatch/observability/node";
import { LangWatchTraceExporter } from "langwatch";

setupObservability({
  // We are specifying a custom trace exporter, so we need to disable default
  // integration to prevent double exporting
  langwatch: "disabled",
  traceExporter: new LangWatchTraceExporter(),
});
Default is equivalent to { filters: [{ preset: "excludeHttpRequests" }] }. You can set filters: null or filters: [] to send all spans.

Quick start

new LangWatchTraceExporter({ filters: [] });

Custom filters

Use include to keep matches; use exclude to drop matches. Criteria support:
  • instrumentationScopeName
  • name
// Keep only spans from the 'ai' scope
new LangWatchTraceExporter({
  filters: [{ include: { instrumentationScopeName: [{ equals: "ai" }] } }]
});

// Drop internal spans by name prefix
new LangWatchTraceExporter({
  filters: [{ exclude: { name: [{ startsWith: "internal." }] } }]
});

Matching

Matchers are case-sensitive unless you set ignoreCase: true.
// equals (exact)
{ name: [{ equals: "chat.completion" }] }

// startsWith (prefix)
{ name: [{ startsWith: "chat." }] }

// matches (RegExp)
{ name: [{ matches: /^(GET|POST)\b/ }] }

// case-insensitive
{ name: [{ equals: "Chat.Completion", ignoreCase: true }] }

Logic

  • OR within a field: multiple matchers are alternatives
  • AND across fields: all specified fields must match
// name starts with chat. OR llm.
{ include: { name: [{ startsWith: "chat." }, { startsWith: "llm." }] } }

// scope is ai AND name starts with chat.
{ include: { instrumentationScopeName: [{ equals: "ai" }], name: [{ startsWith: "chat." }] } }

Pipelines (sequential AND)

Filters run in order; each step narrows the set.
new LangWatchTraceExporter({
  filters: [
    { include: { instrumentationScopeName: [{ equals: "ai" }] } },
    { preset: "excludeHttpRequests" },
    { exclude: { name: [{ matches: /test/ }] } }
  ]
});

Integrate with setupObservability

import { setupObservability } from "langwatch/observability/node";
import { LangWatchTraceExporter } from "langwatch";

setupObservability({
  // We are specifying a custom trace exporter, so we need to disable default
  // integration to prevent double exporting
  langwatch: "disabled",
  traceExporter: new LangWatchTraceExporter({
    filters: [{ preset: "excludeHttpRequests" }]
  })
});
Via BatchSpanProcessor
import { setupObservability } from "langwatch/observability/node";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { LangWatchTraceExporter } from "langwatch";

setupObservability({
  // We are specifying a custom trace exporter, so we need to disable default
  // integration to prevent double exporting
  langwatch: "disabled",
  spanProcessors: [
    new BatchSpanProcessor(
      new LangWatchTraceExporter({ filters: [{ preset: "vercelAIOnly" }] })
    ),
  ],
});

Troubleshooting

  • Nothing exported: try filters: [], then add rules back
  • Too much noise: apply excludeHttpRequests, add specific exclude rules
  • Case surprises: add ignoreCase: true where needed
  • Check values: log span.name and span.instrumentationScope.name in dev

Types

import type { TraceFilter, Criteria, Match } from "langwatch";
Use simple matchers (equals, startsWith) where possible; regex is powerful but slower and harder to read.