Tracing
Insight Export

Insight Export

Export traces to Mantis Insight for visualization and analysis.

Overview

Mantis Insight is the observability backend for Mantis SDK. It provides:

  • Trace visualization with span hierarchy
  • LLM metrics (tokens, latency, cost)
  • User and session tracking
  • Search and filtering

OTLP export vs direct ingestion helper

Use both paths based on where your telemetry is produced:

  • OTLP export (tracing.init() + exporter): Best for automatic span export from instrumented application runtime.
  • Direct ingestion helper (InsightLangfuseCompatClient): Best for explicit trace/score submission from external pipelines or post-processing systems.

For the direct helper flow, see Insight Ingestion (SDK).

Configuration

Environment Variables

Set these environment variables to enable Insight export:

# Required
INSIGHT_HOST=https://insight.withmetis.ai
INSIGHT_PUBLIC_KEY=pk-lf-your-public-key
INSIGHT_SECRET_KEY=sk-lf-your-secret-key
 
# Optional: Custom OTLP endpoint
INSIGHT_OTLP_ENDPOINT=https://custom.endpoint/v1/traces

Auto-Detection

When you call tracing.init(), the SDK automatically detects Insight credentials:

import mantisdk.tracing as tracing
 
# Auto-detects INSIGHT_* environment variables
tracing.init()

Explicit Configuration

Create the exporter explicitly:

import mantisdk.tracing as tracing
 
tracing.init(
    exporters=[
        tracing.insight_exporter(
            host="https://insight.withmetis.ai",
            public_key="pk-lf-...",
            secret_key="sk-lf-...",
        )
    ]
)

Checking Configuration

from mantisdk.tracing.exporters.insight import is_insight_configured
 
if is_insight_configured():
    print("Insight credentials found in environment")
else:
    print("Missing INSIGHT_HOST, INSIGHT_PUBLIC_KEY, or INSIGHT_SECRET_KEY")

insight_exporter() Function

Parameters

tracing.insight_exporter(
    host=None,           # Insight host URL (or INSIGHT_HOST env var)
    public_key=None,     # Public key (or INSIGHT_PUBLIC_KEY env var)
    secret_key=None,     # Secret key (or INSIGHT_SECRET_KEY env var)
    otlp_endpoint=None,  # Custom OTLP endpoint (optional)
)

Returns

An OpenTelemetry SpanExporter configured for Insight's OTLP endpoint.

Send OTLP Traces Without MantisDK

If you already have OpenTelemetry tracing set up (e.g., via the OTel Python SDK, JS SDK, or any OTLP-compatible framework), you can send traces directly to Insight without installing MantisDK. All you need is the endpoint and auth headers.

Endpoint

POST https://insight.withmetis.ai/api/public/otel/v1/traces

Authentication

Insight uses HTTP Basic Auth with your project's API keys:

HeaderValue
AuthorizationBasic base64(publicKey:secretKey)
Content-Typeapplication/json or application/x-protobuf

You can find your public key (pk-lf-...) and secret key (sk-lf-...) in your Insight project settings under API Keys.

Python (OTel SDK)

import base64
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
 
# Your existing TracerProvider
provider = TracerProvider()
 
# Add Insight as an exporter
public_key = "pk-lf-..."
secret_key = "sk-lf-..."
credentials = base64.b64encode(f"{public_key}:{secret_key}".encode()).decode()
 
insight_exporter = OTLPSpanExporter(
    endpoint="https://insight.withmetis.ai/api/public/otel/v1/traces",
    headers={"Authorization": f"Basic {credentials}"},
)
provider.add_span_processor(BatchSpanProcessor(insight_exporter))

JavaScript / TypeScript (OTel JS SDK)

import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
 
const publicKey = "pk-lf-...";
const secretKey = "sk-lf-...";
const credentials = Buffer.from(`${publicKey}:${secretKey}`).toString("base64");
 
const insightExporter = new OTLPTraceExporter({
  url: "https://insight.withmetis.ai/api/public/otel/v1/traces",
  headers: { Authorization: `Basic ${credentials}` },
});
 
// Add to your existing provider
provider.addSpanProcessor(new BatchSpanProcessor(insightExporter));

Environment Variables (Any OTel SDK)

Most OTel SDKs support standard environment variables. Note that OTEL_EXPORTER_OTLP_ENDPOINT should be the base URL — the SDK appends /v1/traces automatically:

OTEL_EXPORTER_OTLP_ENDPOINT=https://insight.withmetis.ai/api/public/otel
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <base64(pk-lf-...:sk-lf-...)>"
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

Insight accepts both application/json and application/x-protobuf content types, and supports gzip content encoding. Most OTel SDKs default to protobuf, which works out of the box.

Dual-Write to Multiple Backends

If you're already exporting to another backend (e.g., Datadog, Grafana Tempo, Jaeger), just add a second BatchSpanProcessor for Insight. Each processor exports independently — a failure in one does not affect the other.

# Existing exporter
provider.add_span_processor(BatchSpanProcessor(your_existing_exporter))
 
# Add Insight alongside it
provider.add_span_processor(BatchSpanProcessor(insight_exporter))

Multiple Exporters

The exporters parameter accepts a list, so you can send traces to multiple backends simultaneously. Each exporter gets its own BatchSpanProcessor — they export independently and won't block each other.

Insight + Another OTEL Backend

Send traces to both Insight and a second OpenTelemetry-compatible backend (e.g., Jaeger, Grafana Tempo, Datadog, Honeycomb):

from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
import mantisdk.tracing as tracing
 
tracing.init(
    service_name="my-agent",
    exporters=[
        tracing.insight_exporter(),                                      # Insight
        OTLPSpanExporter(endpoint="https://tempo.internal/v1/traces"),   # Second backend
    ]
)

For backends that use gRPC instead of HTTP:

from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
import mantisdk.tracing as tracing
 
tracing.init(
    service_name="my-agent",
    exporters=[
        tracing.insight_exporter(),
        OTLPSpanExporter(endpoint="localhost:4317"),  # gRPC endpoint
    ]
)

Insight + Another OTLP Backend

⚠️

If your team already has a central OpenTelemetry backend, you can dual-write traces to Insight and that backend. Insight remains the LLM-specific observability surface, while your existing backend keeps its broader service tracing view.

Add your existing OTLP collector as a second exporter:

from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
import mantisdk.tracing as tracing
 
tracing.init(
    service_name="my-agent",
    exporters=[
        tracing.insight_exporter(),                   # Insight (LLM observability)
        OTLPSpanExporter(                             # Your existing OTel backend
            endpoint="otel-collector.example.com:4317",
            insecure=False,
        ),
    ]
)

Both exporters run independently with their own BatchSpanProcessor, so a failure in one does not affect the other.

Use the endpoint, TLS settings, and headers required by your own OpenTelemetry collector. Many managed collectors require authentication headers in addition to the endpoint.

Insight + Console (Debugging)

from opentelemetry.sdk.trace.export import ConsoleSpanExporter
import mantisdk.tracing as tracing
 
tracing.init(
    exporters=[
        tracing.insight_exporter(),  # Insight
        ConsoleSpanExporter(),       # Console for debugging
    ]
)

Data Sent to Insight

Trace-Level Data

  • Trace ID and name
  • Input and output (via semantic conventions)
  • User ID and session ID
  • Tags and metadata
  • Environment and version

Span-Level Data

  • Span name and kind
  • Parent-child relationships
  • Start/end timestamps
  • Attributes (including semantic conventions)
  • Events and exceptions

LLM-Specific Data (via auto-instrumentation)

  • Model name
  • Input/output token counts
  • Latency
  • Tool calls and results

Viewing Traces in Insight

After traces are exported:

  1. Log in to Mantis Insight (opens in a new tab)
  2. Navigate to your project
  3. View traces in the Traces tab
  4. Click a trace to see the span hierarchy
  5. Use filters to find specific traces:
    • By user ID
    • By session ID
    • By time range
    • By tags

Ensuring Export

Flush Before Exit

Always ensure spans are exported before your program exits:

import atexit
import mantisdk.tracing as tracing
 
tracing.init()
atexit.register(tracing.shutdown)
 
# Or use try/finally
try:
    main()
finally:
    tracing.shutdown()

Manual Flush

Force export without shutting down:

# Process batch
for item in batch:
    process_item(item)
 
# Ensure batch spans are exported
tracing.flush()
 
# Continue processing...

Troubleshooting

Traces Not Appearing

  1. Check credentials: Verify INSIGHT_HOST, INSIGHT_PUBLIC_KEY, INSIGHT_SECRET_KEY
  2. Check network: Ensure your application can reach the Insight host
  3. Check shutdown: Ensure tracing.shutdown() is called
  4. Enable debug: Add console exporter to see spans locally

Debug with Console Exporter

from opentelemetry.sdk.trace.export import ConsoleSpanExporter
import mantisdk.tracing as tracing
 
tracing.init(
    exporters=[
        tracing.insight_exporter(),
        ConsoleSpanExporter(),  # See spans in terminal
    ]
)

Check Configuration

from mantisdk.tracing.exporters.insight import is_insight_configured
import os
 
print(f"INSIGHT_HOST: {os.environ.get('INSIGHT_HOST', 'NOT SET')}")
print(f"INSIGHT_PUBLIC_KEY: {os.environ.get('INSIGHT_PUBLIC_KEY', 'NOT SET')[:10]}...")
print(f"INSIGHT_SECRET_KEY: {'SET' if os.environ.get('INSIGHT_SECRET_KEY') else 'NOT SET'}")
print(f"Is configured: {is_insight_configured()}")

Complete Example

#!/usr/bin/env python3
"""Complete Insight export example."""
 
import atexit
from dotenv import load_dotenv
load_dotenv()
 
import mantisdk.tracing as tracing
from mantisdk.tracing.exporters.insight import is_insight_configured
 
 
def setup_tracing():
    """Configure tracing with Insight export."""
    if not is_insight_configured():
        print("Warning: Insight not configured")
        print("Set INSIGHT_HOST, INSIGHT_PUBLIC_KEY, INSIGHT_SECRET_KEY")
        return False
 
    tracing.init(
        service_name="my-agent",
        exporters=[tracing.insight_exporter()],
    )
 
    atexit.register(tracing.shutdown)
    print("Tracing configured with Insight export")
    return True
 
 
def main():
    with tracing.trace("main_workflow", input="example") as span:
        span.set_attribute(tracing.semconv.USER_ID, "user-123")
        span.set_attribute(tracing.semconv.SESSION_ID, "session-456")
 
        with tracing.span("step_1"):
            print("Step 1")
 
        with tracing.span("step_2"):
            print("Step 2")
 
        span.set_attribute(tracing.semconv.TRACE_OUTPUT, "completed")
 
 
if __name__ == "__main__":
    if setup_tracing():
        main()
        print("Traces exported to Insight!")

Next Steps