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/tracesAuto-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/tracesAuthentication
Insight uses HTTP Basic Auth with your project's API keys:
| Header | Value |
|---|---|
Authorization | Basic base64(publicKey:secretKey) |
Content-Type | application/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/protobufInsight 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:
- Log in to Mantis Insight (opens in a new tab)
- Navigate to your project
- View traces in the Traces tab
- Click a trace to see the span hierarchy
- 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
- Check credentials: Verify
INSIGHT_HOST,INSIGHT_PUBLIC_KEY,INSIGHT_SECRET_KEY - Check network: Ensure your application can reach the Insight host
- Check shutdown: Ensure
tracing.shutdown()is called - 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
- Insight REST API - Fetch traces back from Insight via the REST API
- Quickstart - Get started with tracing
- Integrations - Framework-specific examples