Skip to main content

Send Your First Telemetry

InfraSage accepts telemetry in three formats. This guide shows you how to send each type and verify the data was received.


The simplest way to send a single metric:

curl -X POST http://localhost:8080/api/v1/telemetry \
-H "Content-Type: application/json" \
-d '{
"service_id": "payment-api",
"metric_name": "request_latency_ms",
"value": 142.5,
"timestamp": "2026-04-10T12:00:00Z",
"attributes": {
"region": "us-east-1",
"env": "production",
"version": "v2.3.1"
}
}'

Batch ingestion (up to 10,000 records per request)

curl -X POST http://localhost:8080/api/v1/telemetry/batch \
-H "Content-Type: application/json" \
-d '[
{
"service_id": "payment-api",
"metric_name": "request_latency_ms",
"value": 142.5,
"timestamp": "2026-04-10T12:00:00Z"
},
{
"service_id": "payment-api",
"metric_name": "error_rate",
"value": 0.02,
"timestamp": "2026-04-10T12:00:00Z"
},
{
"service_id": "user-service",
"metric_name": "cpu_usage_percent",
"value": 72.1,
"timestamp": "2026-04-10T12:00:00Z"
}
]'

Format 2 — OpenTelemetry (OTLP)

Configure your OTEL collector to export to InfraSage:

# otel-collector-config.yaml
exporters:
otlphttp:
endpoint: http://localhost:8080
headers:
Content-Type: application/x-protobuf

service:
pipelines:
metrics:
exporters: [otlphttp]
traces:
exporters: [otlphttp]
logs:
exporters: [otlphttp]

Or send raw OTLP JSON:

curl -X POST http://localhost:8080/v1/metrics \
-H "Content-Type: application/json" \
-d '{
"resourceMetrics": [{
"resource": {
"attributes": [{"key": "service.name", "value": {"stringValue": "checkout-service"}}]
},
"scopeMetrics": [{
"metrics": [{
"name": "http.request.duration",
"gauge": {
"dataPoints": [{
"asDouble": 0.125,
"timeUnixNano": "1712750400000000000"
}]
}
}]
}]
}]
}'

Format 3 — Prometheus Remote Write

Add InfraSage as a remote-write target in your prometheus.yml:

remote_write:
- url: http://localhost:8080/api/v1/prometheus/write
queue_config:
max_samples_per_send: 10000
batch_send_deadline: 5s

Telemetry Types

InfraSage supports six telemetry types. Specify the type in the type field (defaults to metric):

TypehasValuehasBodyhasTraceUse Case
metricYesNoNoCPU, memory, latency, throughput
logNoYesNoApplication logs
traceYesNoYesDistributed tracing, spans
eventNoYesNoKubernetes events, deploys
profileYesYesNoCPU/memory profiling
sloYesNoNoSLI/SLO compliance tracking

Sending a log entry

curl -X POST http://localhost:8080/api/v1/telemetry \
-H "Content-Type: application/json" \
-d '{
"service_id": "auth-service",
"type": "log",
"body": "User login failed: invalid credentials",
"timestamp": "2026-04-10T12:00:00Z",
"attributes": {
"level": "warn",
"user_id": "u-12345"
}
}'

Sending a trace span

curl -X POST http://localhost:8080/api/v1/telemetry \
-H "Content-Type: application/json" \
-d '{
"service_id": "checkout-service",
"type": "trace",
"metric_name": "checkout.duration",
"value": 0.342,
"trace_id": "abc123def456",
"timestamp": "2026-04-10T12:00:00Z"
}'

Sending an SLO reading

curl -X POST http://localhost:8080/api/v1/telemetry \
-H "Content-Type: application/json" \
-d '{
"service_id": "api-gateway",
"type": "slo",
"metric_name": "availability",
"value": 99.97,
"timestamp": "2026-04-10T12:00:00Z"
}'

Verify Data Was Received

Check the ingestion counter

curl -s 'http://localhost:9999/api/v1/query?query=infrasage_ingestion_events_total' | \
jq '.data.result[].value[1]'

Query ClickHouse directly

docker exec infrasage-clickhouse clickhouse-client \
--user infrasage --password infrasage-dev \
--query "
SELECT
service_id,
metric_name,
count() AS events,
max(timestamp) AS last_seen
FROM infrasage.infrasage_raw_firehose
GROUP BY service_id, metric_name
ORDER BY last_seen DESC
LIMIT 20
"

List supported telemetry types via API

curl http://localhost:8080/api/v1/telemetry-types

Validation Rules

InfraSage validates every record before queueing. Records that fail validation are sent to the dead-letter queue (DLQ) — not silently dropped.

RuleDetails
service_id requiredMust be non-empty
timestamp ageMust be within ±24 hours of current time
value rangeMust be a finite float64 (no NaN, no Inf)
metric_name lengthMaximum 256 characters
type enumMust be one of: metric, log, trace, event, profile, slo

Failed records are stored in the DLQ with their original payload for manual inspection and replay:

curl http://localhost:8080/api/v1/debug/dlq-stats