Centralized Claude Code OTel collection

Centralized collection routes Claude Code telemetry through a customer-managed OpenTelemetry (OTel) collector or gateway before forwarding it to DX. Use this architecture to keep the DX ingest token off developer workstations and apply enterprise authentication and identity controls at a central point.

Note: Create a Claude Code (OTel) connection before using this guide. The connection provides your customer-specific DX endpoint and ingest token.

Centralized collection use cases

  • Keep DX credentials centralized. Store the DX ingest token in one customer-managed gateway instead of distributing the same credential across developer machines.
  • Send telemetry to multiple destinations. Point Claude Code at one gateway, then fan out the unchanged telemetry to DX and other OTLP destinations.

Before you begin

  • Customer-managed endpoint that accepts OTLP HTTP/JSON metrics and logs from Claude Code clients.
  • Per-user or per-device authentication between each client and the customer-managed endpoint.
  • Corporate identity mapping that maps the authenticated principal to a verified email address.

Centralized collection flow

  1. Claude Code sends its native OTLP HTTP/JSON telemetry to the customer-managed collector or gateway. The workstation does not store the DX ingest token.
  2. The collector authenticates each user or device with a unique credential and maps that principal to a corporate identity.
  3. The collector removes untrusted identity values and adds the verified user.email to the forwarded telemetry.
  4. The collector forwards the metrics and logs to DX without changing their structure. It adds the DX ingest token to the Authorization header.

The client-to-collector authentication method is customer controlled. DX does not prescribe how to implement it.

The DX ingest token authenticates the connection, not an individual developer. DX trusts the identity attributes in the forwarded payload, so the collector must prevent client-supplied values from overriding the verified identity. Remove or overwrite user.email, user, user.account_id, and user.id at the resource, data-point, and log-record levels before forwarding.

Forward telemetry to DX

DX accepts OTLP HTTP/JSON. It does not accept OTLP over gRPC or protobuf for this connector.

  • Send metrics to POST /api/otel/v1/metrics.
  • Send logs to POST /api/otel/v1/logs.
  • Set Content-Type: application/json.
  • Set Authorization: Bearer <DX ingest token>.
  • Send metrics with delta temporality: aggregationTemporality: 1.
  • Preserve the native Claude Code payload on the DX-bound copy. Do not aggregate it or apply transformations intended for another observability destination.

Use the host from the OTEL_EXPORTER_OTLP_ENDPOINT value generated on the Claude Code (OTel) connection page.

Metrics request

This minimal request records one Claude Code session for a verified user:

POST /api/otel/v1/metrics HTTP/1.1
Host: <your-datacloud-host>
Authorization: Bearer <DX ingest token>
Content-Type: application/json

{
  "resourceMetrics": [
    {
      "resource": {
        "attributes": [
          {
            "key": "user.email",
            "value": { "stringValue": "developer@example.com" }
          }
        ]
      },
      "scopeMetrics": [
        {
          "metrics": [
            {
              "name": "claude_code.session.count",
              "sum": {
                "aggregationTemporality": 1,
                "isMonotonic": true,
                "dataPoints": [
                  {
                    "timeUnixNano": "1784145600000000000",
                    "asInt": "1"
                  }
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}

All supported metrics use sum.dataPoints. Put metric-specific attributes on each data point.

  • claude_code.session.count — No required attributes. The value is the session count.
  • claude_code.lines_of_code.count — Set type to added or removed. The value is the line count.
  • claude_code.commit.count — No required attributes. The value is the commit count.
  • claude_code.pull_request.count — No required attributes. The value is the pull request count.
  • claude_code.token.usage — Set model and set type to input, output, cacheRead, or cacheCreation. The value is the token count.
  • claude_code.cost.usage — Set model. The value is the cost in USD.
  • claude_code.code_edit_tool.decision — Set tool_name to Edit, MultiEdit, Write, or NotebookEdit, and set decision to accept or reject. The value is the decision count.

Include timeUnixNano and either asInt or asDouble on each data point. If the timestamp is absent, DX uses the request receipt date. If the value is absent, DX records zero.

Logs request

Logs are required only for skill usage tracking. This minimal request records one skill activation:

POST /api/otel/v1/logs HTTP/1.1
Host: <your-datacloud-host>
Authorization: Bearer <DX ingest token>
Content-Type: application/json

{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          {
            "key": "user.email",
            "value": { "stringValue": "developer@example.com" }
          }
        ]
      },
      "scopeLogs": [
        {
          "logRecords": [
            {
              "timeUnixNano": "1784145600000000000",
              "body": { "stringValue": "claude_code.tool_result" },
              "attributes": [
                {
                  "key": "tool_name",
                  "value": { "stringValue": "Skill" }
                },
                {
                  "key": "tool_parameters",
                  "value": {
                    "stringValue": "{\"skill_name\":\"review-pr\"}"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

DX also accepts the skill name in tool_input instead of tool_parameters, and as skill instead of skill_name.

Identity attributes

DX uses user.email as the preferred identity. It also recognizes user as an email and uses user.account_id or user.id when an email is unavailable. user.name, organization.id, and terminal.type are optional.

Identity attributes can appear on the resource or individual data point or log record. Record-level attributes take precedence, so the collector must remove or overwrite untrusted identity attributes at every level.

If the gateway relies on identity attributes from Claude Code, add OTEL_RESOURCE_ATTRIBUTES under env in the managed or local Claude Code settings:

{
  "env": {
    "OTEL_RESOURCE_ATTRIBUTES": "user.email=alice@example.com,user.name=Alice%20Smith"
  }
}

Encode spaces as %20. If the gateway derives identity from its client authentication, omit these client-side identity attributes and add the verified values at the gateway instead.

Note: Keep custom resource attributes to the minimum needed by the gateway. Claude Code repeats them across metric data points, so directory fields such as user.department or user.title can significantly increase payload size. DX does not use those fields for metric aggregation.

Validate the connection

Send telemetry for one user before rolling out the configuration:

  • 200 confirms that DX received the request for asynchronous processing. It does not confirm that every field passed semantic validation.
  • 401 indicates a missing or invalid ingest token, or that no active Claude Code (OTel) connection exists.
  • 415 indicates that Content-Type is not application/json.
  • 422 indicates invalid JSON or a malformed gzip body.
  • If DX returns 200 but no data appears, confirm that the payload includes an identity, uses delta temporality, and preserves the native Claude Code structure.

Next steps

After validating one user, distribute the customer-managed endpoint through Claude Code managed settings, MDM, or your configuration management system. Keep the DX ingest token only in the collector or gateway; when the token changes, update it there rather than on each workstation.