Export Metrics
Octomil supports managed metrics export integrations so teams can route operational telemetry to existing observability tools.
Supported Integrations
- Prometheus
- Datadog
- OpenTelemetry
- StatsD / DogStatsD
OTLP Collector (Recommended)
The OTLP Collector integration provides a single endpoint for both metrics and log export. Instead of configuring metrics and logs separately, point Octomil at your OpenTelemetry collector and both streams are routed automatically.
How it works
When you connect an OTLP collector, Octomil creates two integrations under the hood:
- Metrics integration — pushes to
<endpoint>/v1/metrics - Logs integration — pushes to
<endpoint>/v1/logs
Both integrations share the same endpoint, name, and authentication headers.
In addition to aggregated fleet metrics, Octomil forwards every raw SDK telemetry event to your collector in real-time. This means your backend receives per-request inference data instead of pre-bucketed summaries — you compute your own histograms, percentiles, and alerting thresholds.
What your collector receives
LogRecords (pushed to /v1/logs) — every SDK telemetry event as a structured log with all original attributes, timestamps, and trace/span IDs.
Gauge metrics (pushed to /v1/metrics) — numeric attributes extracted as named gauges:
| Metric name | Source attribute | Description |
|---|---|---|
octomil.inference.duration_ms | inference.duration_ms | End-to-end inference latency |
octomil.inference.ttft_ms | inference.ttft_ms | Time to first token |
octomil.inference.throughput_tps | inference.throughput_tps | Tokens per second |
octomil.inference.total_tokens | inference.total_tokens | Total tokens generated |
octomil.device.battery_level | battery_level | Raw battery percentage (not bucketed) |
octomil.device.memory_used_mb | memory_used_mb | Device memory usage |
Every data point carries org.id, device.id, model.id, and event.name as attributes, so you can filter and group in your backend.
Example — querying forwarded metrics in Grafana:
# p99 inference latency per model over the last hour
histogram_quantile(0.99, rate(octomil_inference_duration_ms[1h])) by (model_id)
# Devices with battery below 20%
octomil_device_battery_level < 20
Example — querying forwarded logs in Grafana Loki:
{service_name="octomil"} | json | event_name="inference.completed"
Forwarding is fire-and-forget — it never blocks or delays event ingestion. If your collector is unreachable, events are dropped silently and the circuit breaker prevents retry storms.
Setup
Dashboard: Navigate to Settings > OTLP Collector card and enter your collector URL.
CLI:
octomil integrations connect-otlp --endpoint http://otel-collector:4318
Python SDK:
api.connect_otlp_collector("Production Grafana", "http://collector:4318")
Node SDK:
await client.integrations.connectOtlpCollector({
name: "Production Grafana",
endpoint: "http://collector:4318",
});
Compatible collectors
The OTLP integration works with any collector that accepts OTLP/HTTP:
- Grafana Alloy
- Datadog Agent (with OTLP receiver)
- New Relic OTLP endpoint
- Honeycomb
- Any OpenTelemetry Collector distribution
Configure in Octomil
- Open Settings.
- Go to Metrics export.
- Click Add integration.
- Select provider and enter connection details.
- Run Test.
- Save and enable.
Configure via SDK
Manage integrations programmatically with the Python or Node SDKs.
- Python
- Node
from octomil import Octomil
api = Octomil(api_key="edg_...", org_id="your-org-id")
# List integrations
metrics_integrations = api.integrations.list_metrics_integrations()
log_integrations = api.integrations.list_log_integrations()
# Create a metrics integration
api.integrations.create_metrics_integration(
name="Prod Prometheus",
integration_type="prometheus",
config={"prefix": "octomil", "scrape_interval": 30},
)
# Test an integration
api.integrations.test_metrics_integration(integration_id)
# Delete an integration
api.integrations.delete_metrics_integration(integration_id)
import { OctomilClient } from "@octomil/sdk";
const client = new OctomilClient({ apiKey: "edg_...", orgId: "your-org-id" });
// List integrations
const metricsIntegrations = await client.integrations.listMetricsIntegrations();
const logIntegrations = await client.integrations.listLogIntegrations();
// Create a metrics integration
await client.integrations.createMetricsIntegration({
name: "Prod Prometheus",
integration_type: "prometheus",
config: { prefix: "octomil", scrape_interval: 30 },
});
// Test an integration
await client.integrations.testMetricsIntegration(integrationId);
// Delete an integration
await client.integrations.deleteMetricsIntegration(integrationId);
Configure via CLI
# List all configured integrations
octomil integrations list
# Connect OTLP collector (metrics + logs in one step)
octomil integrations connect-otlp --endpoint http://collector:4318
# Create individual integrations
octomil integrations create --kind metrics --type prometheus --name prod-prom \
--config-json '{"prefix":"octomil"}'
# Test an integration
octomil integrations test <id> --kind metrics
# Delete an integration
octomil integrations delete <id> --kind metrics
See the CLI Reference for the full list of options.
Metric Families
- SLO metrics
- Infrastructure health metrics
- Device fleet metrics
- SDK stability metrics
- Training operation metrics
Best Practices
- Use naming/tag conventions by environment (
dev,staging,prod). - Avoid high-cardinality dimensions.
- Set alert thresholds for crash rate, completion rate, and SLO attainment.
- Rotate integration credentials on a fixed schedule.
Troubleshooting
No metrics arriving
Check:
- integration is enabled
- credentials/endpoint are valid
- test action succeeds in Settings
Delayed or sparse metrics
Check:
- export cadence in your observability stack
- dashboard query windows and aggregation settings