> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenTelemetry

> Forward Control Plane org logs to any OpenTelemetry-compatible collector or backend over OTLP/HTTP.

## Overview

[OpenTelemetry](https://opentelemetry.io) is a vendor-neutral standard for collecting and exporting telemetry data. Control Plane can forward all Org logs to any OpenTelemetry-compatible target — an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) or any backend that accepts logs over OTLP/HTTP — letting you route logs to a destination of your choice and fan them out from there.

Follow the steps below to configure log shipping to an OpenTelemetry target.

## Step 1 - Prerequisites

* **Endpoint**: A reachable URL for your OpenTelemetry collector or OTLP/HTTP backend (see [Endpoint Format](#endpoint-format)).
* **Authentication** (optional): Either custom [headers](#authentication) or an [Opaque Secret](/reference/secret#opaque) holding an `Authorization` header value, depending on what your target requires.

## Step 2 - Configure External Logging

External logging can be configured by using either the [UI Console](#enable-logging-using-the-ui-console) or [CLI](#enable-logging-using-the-cli).

### Enable Logging using the UI Console

1. From the Control Plane Console UI, click on `Org` in the left menu.
2. Click `External Logs` in the middle context menu.
3. Select `OpenTelemetry` and fill out the endpoint and any headers or credentials your target requires.
4. Click `Save`.
5. After the configuration is complete, log entries will begin forwarding to your OpenTelemetry target within a few minutes.

### Enable Logging using the CLI

The external logging configuration can be created / updated using the CLI's `cpln org patch ORG_NAME -f FILE.yaml` command.

Below is an example of an [Org](/reference/org) manifest (in YAML). Edit and save the YAML as a file and use it as an input to the CLI's `cpln org patch ORG_NAME -f FILE.yaml` command.

* Substitute: `ORG_NAME`, the `endpoint`, and any `headers` or `credentials` your target requires.

```yaml YAML theme={null}
kind: org
name: ORG_NAME
spec:
  logging:
    opentelemetry:
      endpoint: https://otel-collector.example.com/v1/logs
      headers:
        x-custom-header: value
      credentials: //secret/OPAQUE_SECRET
```

`headers` and `credentials` are both optional. Provide whichever your target requires (or neither for an unauthenticated endpoint).

## Endpoint Format

The `endpoint` is required. TLS and the port are derived from its format:

| Endpoint                   | TLS | Port                 | Notes                                                            |
| -------------------------- | --- | -------------------- | ---------------------------------------------------------------- |
| `https://host[:port]/path` | On  | From URL, else `443` | Recommended. The path (e.g. `/v1/logs`) is used as the logs URI. |
| `http://host[:port]/path`  | Off | From URL, else `80`  | Unencrypted; use only for in-cluster collectors.                 |
| `host:port`                | On  | As given             | TLS is always enabled for this form.                             |
| `host`                     | On  | `443`                | TLS enabled, default port.                                       |

<Tip>Use the full `https://host/v1/logs` form so the protocol, port, and logs path are explicit.</Tip>

## Authentication

Most targets require an authentication header. There are two ways to provide it:

* **`headers`** — a map of header name/value pairs sent on every export. Use this for any header your target expects, such as `api-key`, `x-…`, or `Authorization`. This is the most flexible option.
* **`credentials`** — a link to an [Opaque Secret](/reference/secret#opaque) whose value is sent as the `Authorization` header. Use this when you want to keep the credential in a secret rather than inline in the Org manifest.

<Note>When using `credentials`, store the **full `Authorization` header value, base64-encoded**, in the Opaque Secret (set the secret's `encoding` to `base64`). Control Plane base64-decodes the payload and sends the result as the `Authorization` header. A target that authenticates with a non-`Authorization` header must use `headers` instead.</Note>

## Forwarded Log Attributes

Each forwarded record carries the Control Plane log metadata as OpenTelemetry log attributes:

| Attribute  | Description                      |
| ---------- | -------------------------------- |
| `org`      | Org name                         |
| `gvc`      | GVC name                         |
| `workload` | Workload name                    |
| `version`  | Workload version                 |
| `replica`  | Replica name                     |
| `location` | Location the log originated from |
| `provider` | Cloud provider                   |
| `log`      | The log message body             |

<Note>All logs continue to remain accessible through Control Plane, adhering to the [current log retention policy](/core/logs#log-retention).</Note>
