OpenTelemetry Export
OpenTelemetry Export is in beta. Features and the wire surface may change before general availability.
OpenTelemetry Export streams Cursor usage data for your team to a collector you run. Cursor sends metrics (tokens, tool calls, best-effort cost) and logs (API requests, errors, corrections, skills, hooks, plugins, and cloud agent lifecycle events) to one team-managed destination. Export runs server-side.
The beta is available on the Enterprise plan. Admins configure it in Team Settings > OpenTelemetry Export.
The Wire Reference documents every metric, log event, and attribute.
Prerequisites
- An HTTPS endpoint that accepts OTLP/HTTP protobuf on
/v1/metricsand/v1/logs. Datadog Agent OTLP ingest, the OpenTelemetry Collector, and ClickHouse/ClickStack all work. - A bearer token or API key Cursor can send as a request header.
- The endpoint must be reachable from the public internet. Cursor egresses from a fixed set of source IPs.
Source IPs
Cursor delivers OTLP through a server-side egress proxy. Traffic originates from these static addresses (all /32):
| IP address | CIDR |
|---|---|
| 3.218.161.44 | /32 |
| 3.231.18.206 | /32 |
| 35.174.159.35 | /32 |
| 184.73.225.134 | /32 |
| 3.209.66.12 | /32 |
| 52.44.113.131 | /32 |
These IPs don't rotate without advance notice. Use TLS and auth as the primary control. Add IP allowlisting if your network requires it.
Collector recipes
Cursor pushes to your collector over OTLP/HTTP binary protobuf. gRPC and JSON are not supported. Enter the HTTPS base URL in Team Settings without a /v1 suffix; Cursor appends /v1/metrics and /v1/logs.
Minimal OpenTelemetry Collector
receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318processors: batch:exporters: # Swap for your sink (datadog, clickhouse, logging, etc.) logging: verbosity: basicservice: pipelines: metrics: receivers: [otlp] processors: [batch] exporters: [logging] logs: receivers: [otlp] processors: [batch] exporters: [logging]Terminate TLS in front of the collector with a load balancer, ingress, or the otelcol TLS settings. Enter https://otel.example.com in Cursor, not https://otel.example.com:4318/v1. For auth, terminate at the load balancer or configure a static header for Cursor to send, such as Authorization: Bearer <token>.
Datadog Agent (OTLP ingest)
Enable OTLP HTTP ingest and logs in the Agent, then expose the Agent (or a gateway in front of it) over HTTPS:
logs_enabled: trueotlp_config: receiver: protocols: http: endpoint: 0.0.0.0:4318 logs: enabled: trueThe env-var equivalents are DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_HTTP_ENDPOINT=0.0.0.0:4318, DD_LOGS_ENABLED=true, and DD_OTLP_CONFIG_LOGS_ENABLED=true. Expose port 4318, or terminate TLS on 443 and proxy to 4318.
In Cursor, the base URL is the public https:// endpoint in front of that listener. Add DD-API-KEY or site headers only if your gateway expects them; the Agent already has api_key configured locally.
See OTLP ingest in the Datadog Agent for Agent configuration details.
Databricks and warehouse-style sinks
For warehouse destinations like Databricks or ClickHouse, run a collector with an OTLP HTTP receiver and the vendor exporter, or forward over HTTP into your ingest pipeline. The Cursor side is the same: an HTTPS base URL serving protobuf on /v1/metrics and /v1/logs. Consume metrics as sums of deltas and dedupe logs on cursor.event.id.
Enable
In Team Settings > OpenTelemetry Export:
- Create destination with the base URL (no
/v1/...; Cursor appends the paths) and auth headers - Test connection to check the URL and auth
- Enable. Export starts within about a minute.
Each signal and telemetry family has its own toggle. New families default on unless you turn off auto_enable_new_families.
What Cursor exports
Scope: cursor.telemetry 0.1.0.
Everything below is on by default for a new destination. Turn individual families off in Team Settings.
Metrics (delta temporality)
cursor.token.usage: bycursor.token.type(input/output/cache_read/cache_creation)cursor.tool.calls: builtin and MCP (cursor.tool.kind)cursor.cost.usage: best-effort USD estimate, not an invoice
Logs
cursor.api.request: model call summarycursor.api.error: error event (no raw messages)cursor.api.correction: billing finalization; join oncursor.usage_event.idcursor.skill.activatedcursor.hook.execution_completecursor.plugin.installedcursor.cloud_agent.setup:started/completed/failedcursor.cloud_agent.artifactcursor.cloud_agent.pull_request:opened/creation_failed
Families (admin toggles; all default on)
model_usage: token and cost metrics; api.request / api.error / api.correctiontool_calls: tool.calls metricskills_hooks_plugins: skill / hook / plugin logscloud_agents: cloud_agent.* logs
Useful attributes
- Resource:
service.name=cursor,cursor.team.id, optionalcursor.user.id, surface/entrypoint - Logs:
cursor.event.id(dedupe), andcursor.request.id/cursor.conversation.id/cursor.usage_event.idwhen present
Delivery
- Metrics are at-most-once. Delta sums can have brief gaps after a failure.
- Logs are at-least-once. Dedupe on
cursor.event.idfor exactly-once views. - There is no backfill from before the destination existed.
- Editing the endpoint or credentials keeps the destination. Disabling or deleting it drops in-flight data.
Auth
Cursor stores headers encrypted. To rotate credentials, edit the destination and save. Changes take effect in about 30 seconds.
Limitations
- Cost is not billing.
cursor.cost.usageis a best-effort estimate. One series covers both included-quota drawdown and on-demand usage. For BYOK it reflects the Cursor Token Rate only, not provider spend. Use the Admin and billing APIs for invoices. - Disabling or deleting a destination drops in-flight data. Rotate credentials by editing the destination instead of deleting and re-adding it.
- Logs can arrive more than once. Delivery is at-least-once. Dedupe on
cursor.event.id. - No prompt content, no traces, and no historical backfill. Export starts when you enable the destination.
- Metric datapoints carry no correlation IDs. Use log attributes for per-conversation joins. See Joining sessions.
- Metrics are delta-only. Sum deltas per series. A strict delta-to-cumulative processor may drop end-time-inverted points.
Joining sessions
Metrics (cursor.token.usage, cursor.tool.calls, cursor.cost.usage) are aggregates. Datapoints carry no conversation.id, request.id, or usage_event.id. This keeps metric cardinality bounded. For session- or request-scoped analysis, use logs.
What each id means
cursor.conversation.idis the session key. In the IDE and CLI it's the composer chat UUID. For cloud agents it's the customer-visiblebc-...agent id. The same value appears on that run'sapi.request,api.error,skill.activated,hook.execution_complete, andcloud_agent.*logs when present.cursor.usage_event.idis the request-grain key onapi.request,api.error, andapi.correction. Use it to reconcile against Cursor usage and billing exports and to apply corrections.cursor.request.idis an optional per-call id on most logs. It never appears onapi.correctionorcloud_agent.*.cursor.event.idis a dedupe key only, not a join key across event types.
Recipe: rank sessions by tokens, then attach skills and tools
- Take
cursor.api.requestlog rows. Sumcursor.api.request.input_tokensandoutput_tokens(and the cache fields if you need them) grouped bycursor.conversation.id. This gives per-session token totals, which metrics can't provide. - Rank conversations by that sum, or by estimated cost.
- Left-join other logs on the same
cursor.conversation.id:cursor.skill.activatedshows which skills rancursor.hook.execution_completeshows hookscursor.cloud_agent.*shows setup, pull requests, and artifacts (cloud agents only)
cursor.tool.callsis metric-only, so it has no conversation id. Report org-wide tool rates from the metric. Per-session tool attribution is not on the wire yet.
cursor.cost.usage is also metric-only. To rank sessions by cost, approximate from api.request token totals and your own rates, or pull spend from the Admin and billing APIs and join on cursor.usage_event.id where available.
Recipe: apply a billing correction
- Find
cursor.api.correctionlogs. - Join on
cursor.usage_event.idto theapi.requestandapi.errorlogs sharing that id. - Treat the whole group as not billed.
Caveats
- Subagents get their own conversation id. Parent rollup is not exported yet.
- Dedupe log rows on
cursor.event.idbefore joining if you need exactly-once views.
Change policy
New metrics and events may appear as coverage expands. auto_enable_new_families controls whether they turn on automatically. Renames and removals get explicit notice. The Wire Reference documents the full attribute surface.
The OpenTelemetry Export beta is available on the Enterprise plan
Contact our team to stream Cursor usage into your observability stack.