OpenTelemetry (OTEL)
InfraSage is a native OpenTelemetry receiver. It accepts OTLP over HTTP for metrics, traces, and logs at 100,000+ messages per second.
Supported OTLP Endpoints
| Signal | Endpoint | Format |
|---|---|---|
| Metrics | POST /v1/metrics | OTLP JSON or protobuf |
| Traces | POST /v1/traces | OTLP JSON or protobuf |
| Logs | POST /v1/logs | OTLP JSON or protobuf |
All endpoints are served by the Ingestion Gateway on port 8080.
Option A — OTEL Collector
Configure the OpenTelemetry Collector to forward data to InfraSage:
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
send_batch_size: 10000
timeout: 5s
exporters:
otlphttp:
endpoint: http://localhost:8080
headers:
Content-Type: application/x-protobuf
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp]
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp]
Start the collector:
otelcol --config otel-collector-config.yaml
Option B — Direct SDK Integration
Go
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/sdk/metric"
)
func initMetrics(ctx context.Context) (*metric.MeterProvider, error) {
exporter, err := otlpmetrichttp.New(ctx,
otlpmetrichttp.WithEndpoint("localhost:8080"),
otlpmetrichttp.WithInsecure(),
)
if err != nil {
return nil, err
}
mp := metric.NewMeterProvider(metric.WithReader(
metric.NewPeriodicReader(exporter, metric.WithInterval(15*time.Second)),
))
otel.SetMeterProvider(mp)
return mp, nil
}
Python
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
exporter = OTLPMetricExporter(endpoint="http://localhost:8080/v1/metrics")
reader = PeriodicExportingMetricReader(exporter, export_interval_millis=15000)
provider = MeterProvider(metric_readers=[reader])
Node.js
const { OTLPMetricExporter } = require('@opentelemetry/exporter-otlp-http');
const { MeterProvider, PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const exporter = new OTLPMetricExporter({
url: 'http://localhost:8080/v1/metrics',
});
const provider = new MeterProvider({
readers: [new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 15000 })],
});
TLS Configuration
For production, enable TLS on the Ingestion Gateway:
GATEWAY_TLS_CERT=/etc/ssl/infrasage/cert.pem
GATEWAY_TLS_KEY=/etc/ssl/infrasage/key.pem
GATEWAY_TLS_ENABLED=true
Then configure your OTEL exporter to use HTTPS:
exporters:
otlphttp:
endpoint: https://ingest.mycompany.com
tls:
cert_file: /etc/ssl/client/cert.pem
key_file: /etc/ssl/client/key.pem
Trace Sampling
For high-volume trace ingestion, configure a tail-based sampler in the OTEL Collector to reduce volume before sending to InfraSage:
processors:
tail_sampling:
decision_wait: 10s
policies:
- name: error-policy
type: status_code
status_code: { status_codes: [ERROR] }
- name: slow-traces
type: latency
latency: { threshold_ms: 500 }
Verification
# Check ingestion received OTLP data
curl -s 'http://localhost:9999/api/v1/query?query=infrasage_ingestion_events_total' | \
jq '.data.result[] | select(.metric.format == "otlp")'
# Query a specific OTEL service in ClickHouse
docker exec infrasage-clickhouse clickhouse-client \
--user infrasage --password infrasage-dev \
--query "SELECT service_id, count() FROM infrasage.infrasage_raw_firehose
WHERE service_id = 'my-otel-service' GROUP BY service_id"
Performance
| Metric | Result |
|---|---|
| Max throughput (OTLP/HTTP) | 100,000+ msg/sec |
| Batch size (recommended) | 10,000 records |
| Supported formats | OTLP JSON, OTLP protobuf |
| Auth | API key (header: X-API-Key) or no-auth in dev |