Ontre API / OpenTelemetry
Send OpenTelemetry to Ontre
If your services already use OpenTelemetry, point an exporter at Ontre. You keep your SDKs and Collector. Ontre reads incoming requests and named business events, and turns them into the events it measures.
All requests go to https://api.ontre.app. The OTLP path comes from the connection’s postTo field.
Overview
An admin creates an OpenTelemetry connection for a project and chooses its environment, such as production. Your exporter sends traces and logs to that connection’s URL with the connection token in a header. Ontre returns 200 once the batch is stored.
Ontre does not store full traces or log lines. From traces it keeps one event per incoming request or handled message. From logs it keeps only named events that carry an ID. Everything else is skipped.
Ontre accepts traces and logs only, over HTTP with binary Protobuf. Metrics, JSON encoding and gRPC are not supported.
Set up a connection
Project admins create the connection with POST /api/v1/projects/{projectId}/connections:
{
"displayName": "Checkout production",
"kind": "otlp",
"environment": "production"
}{
"id": "0190a0b0-6c1e-7a2b-9f3d-5e4c3b2a1908",
"displayName": "Checkout production",
"token": "8f3c0c1e9b7a4d2f8e6c5b4a39281706f5e4d3c2b1a09f8e7d6c5b4a39281706",
"postTo": "/otlp/0190a0b0-6c1e-7a2b-9f3d-5e4c3b2a1908",
"signingKey": "NOT_REQUIRED"
}The environment cannot be changed later. Use one connection per environment: a staging connection and a production connection, for example. No signing key is needed; the token authenticates every request.
Ontre stores only a hash of the token and cannot show it again. If you lose it, create a new connection.
Endpoint and headers
https://api.ontre.app/otlp/{connectionId}/v1/traceshttps://api.ontre.app/otlp/{connectionId}/v1/logsMost exporters take a base URL and add /v1/traces and /v1/logs themselves. Use https://api.ontre.app/otlp/{connectionId} as that base. When you configure a single signal’s URL directly, include the full path.
| Header | Value |
|---|---|
X-Ontre-Token | The connection token from setup. |
Content-Type | application/x-protobuf. OpenTelemetry exporters set this when the protocol is http/protobuf. |
Content-Encoding | Optional. gzip or omitted. |
Every resource must set service.name. If it also sets deployment.environment.name, the value must match the connection’s environment.
Traces
Ontre keeps server spans, one per incoming request, and consumer spans, one per handled message. Internal, client and producer spans are skipped. Each kept span becomes one event named after its operation and outcome.
| Span | Operation name | Example event |
|---|---|---|
| HTTP server | Method and http.route | POST /charge error |
| Consumer | messaging.destination.template or messaging.destination.name | process orders ok |
| Other server | The span name | ProcessRefund unknown |
HTTP server spans need http.route, the route template such as /orders/{id}. A raw path like /orders/88231 would create a new operation for every order, so spans without a route are rejected. Span and destination names that contain IDs or URLs are rejected for the same reason. Temporary queues are rejected.
Outcome
| Span status | HTTP status | Outcome |
|---|---|---|
ERROR | Any or none | error |
OK or unset | 5xx | error |
OK or unset | 2xx or 3xx | ok |
OK or unset | 4xx | unknown |
OK | None | ok |
| Unset | None | unknown |
ok means the request was not a server failure. It does not mean a payment settled or an order completed. To measure business outcomes, send log events.
The event time is the span’s end time.
Sampling changes the numbers. Counts and rates from traces describe the spans you export. If you sample, especially with tail or error-biased sampling, rates in Ontre will not match your real traffic. Export server and consumer spans unsampled to an Ontre pipeline when you want accurate rates.
Log events
Use log events for business moments such as an order being placed or a payment captured. Ontre keeps a log record when it has an event name and an ID. Ordinary log lines are skipped.
| Field | Required | Meaning |
|---|---|---|
| Event name | Yes | The log record’s event_name field, or an event.name attribute. For example order.placed. At most 128 characters, and no IDs in the name. |
event.id | Yes | An attribute unique for that service and event name, such as the order ID. Ontre uses it to store retried events once. A named event without it is rejected. |
| Timestamp | No | The record’s time, then its observed time, then the time Ontre received it. |
The same ID can appear on different event names. order.placed and order.paid for order ord_88f2 are two events.
Configuration examples
Set ONTRE_OTLP_ENDPOINT to https://api.ontre.app plus the returned postTo path, and ONTRE_TOKEN to the connection token. Send only traces and logs to Ontre.
# Works with any OpenTelemetry SDK that reads the standard variables
OTEL_SERVICE_NAME=checkout-api
OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.ontre.app/otlp/{connectionId}
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_HEADERS=X-Ontre-Token=YOUR_TOKEN
OTEL_TRACES_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_METRICS_EXPORTER=none
exporters:
otlphttp/ontre:
endpoint: ${env:ONTRE_OTLP_ENDPOINT} # https://api.ontre.app/otlp/{connectionId}
encoding: proto
compression: gzip
headers:
X-Ontre-Token: ${env:ONTRE_TOKEN}
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/ontre]
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/ontre]
# Do not add otlphttp/ontre to a metrics pipeline
// npm i @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-proto \
// @opentelemetry/exporter-logs-otlp-proto @opentelemetry/sdk-logs @opentelemetry/api-logs
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-proto';
import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';
import { logs } from '@opentelemetry/api-logs';
const endpoint = process.env.ONTRE_OTLP_ENDPOINT;
const headers = { 'X-Ontre-Token': process.env.ONTRE_TOKEN };
const sdk = new NodeSDK({
serviceName: 'checkout-api',
// Signal URLs set in code need the full path
traceExporter: new OTLPTraceExporter({ url: endpoint + '/v1/traces', headers }),
logRecordProcessors: [new BatchLogRecordProcessor(
new OTLPLogExporter({ url: endpoint + '/v1/logs', headers }))]
});
sdk.start();
// A business event: named, with an ID
logs.getLogger('checkout').emit({
body: 'order placed',
attributes: { 'event.name': 'order.placed', 'event.id': 'ord_88f2' }
});
# pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
import logging
import os
from opentelemetry import trace
from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
endpoint = os.environ["ONTRE_OTLP_ENDPOINT"]
headers = {"X-Ontre-Token": os.environ["ONTRE_TOKEN"]}
resource = Resource.create({
"service.name": "checkout-api",
"deployment.environment.name": "production",
})
# Signal URLs set in code need the full path
tracer_provider = TracerProvider(resource=resource)
tracer_provider.add_span_processor(BatchSpanProcessor(
OTLPSpanExporter(endpoint=endpoint + "/v1/traces", headers=headers)))
trace.set_tracer_provider(tracer_provider)
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(
OTLPLogExporter(endpoint=endpoint + "/v1/logs", headers=headers)))
set_logger_provider(logger_provider)
log = logging.getLogger("checkout")
log.addHandler(LoggingHandler(logger_provider=logger_provider))
log.setLevel(logging.INFO)
# A business event: named, with an ID
log.info("order placed", extra={"event.name": "order.placed", "event.id": "ord_88f2"})
Instrumentation libraries for your web framework create the server spans. Make sure they record http.route.
What Ontre keeps
Ontre keeps only the fields below. Request and response bodies, log message bodies, user attributes and all other span attributes are discarded when the batch arrives and never stored.
| From | Attributes kept |
|---|---|
| Resource | service.name, service.namespace, service.version, deployment.environment.name, cloud.region |
| Server and consumer spans | http.route, http.request.method, http.response.status_code, error.type, the trace ID, the operation and the outcome |
| Log events | The event name, event.id and error.type |
Events from different services or namespaces stay separate. Events are kept for 30 days.
Responses and retries
Ontre answers as the OTLP specification describes, so standard exporters handle retries correctly. Error responses carry a Protobuf status message with a short reason.
| Status | Meaning | What to do |
|---|---|---|
200 | Stored. If some records were rejected, partial_success gives the count and the reasons. | Nothing, unless records were rejected. Fix those at the source; resending them will not help. |
400 | The body is not a valid OTLP Protobuf request. | Check the protocol is http/protobuf. |
401 | Unknown or disabled connection, or a wrong token. | Check the URL and the X-Ontre-Token header. |
403 | The connection is paused. | Ask an admin to activate it. Data sent while paused is not stored. |
413 | Over 5 MiB, or over 1,000 spans or log records. | Send smaller batches. |
415 | Not application/x-protobuf, or an encoding other than gzip. | Use http/protobuf and gzip or no compression. |
501 | Metrics sent to /v1/metrics. | Turn off metrics export to Ontre. |
429, 503 | Temporarily unable to accept data. Nothing from the request was stored. | Your exporter retries automatically, using Retry-After when present. |
Why records are rejected
- The resource has no
service.name, or its environment differs from the connection’s. - A span has an invalid trace or span ID, no end time, or ends before it starts.
- An HTTP server span has no
http.route, or an operation or event name looks like it contains an ID or a URL. - A named log event has no
event.id. - A timestamp is more than five minutes in the future or more than 30 days old.
- A new operation or event name is over the connection’s name limit.
Retries are safe. Ontre stores each span once, by trace and span ID, and each log event once, by service, event name and event.id.
Limits
| Limit | Value |
|---|---|
| Request size | 5 MiB, before and after decompression |
| Records per request | 1,000 spans or log records |
| Operations per connection | 300 distinct operations, counted per service |
| Event names per connection | 100 distinct log event names, counted per service |
| Event age | Up to 30 days old, and no more than five minutes in the future |
Names already accepted always continue to work. Once a limit is reached, records with new names are rejected and reported in partial_success. If your services need more, contact Ontre support.
Connection lifecycle
An admin can pause or resume an OpenTelemetry connection through authenticated endpoints:
/api/v1/projects/{projectId}/connections/{connectionId}/suspend/api/v1/projects/{projectId}/connections/{connectionId}/activateBoth return 204 on success. GET /api/v1/projects/{projectId}/connections lists each connection’s status, environment and postTo path. Disabling a connection stops its token from working.
Paused connections refuse data. Requests to a paused connection return 403. Exporters do not retry a 403, so telemetry sent while paused is lost. It is not replayed after activation.