# CKEditor AI On-Premises observability

See what your CKEditor AI On-Premises deployment does at runtime: which requests it serves, how long the database takes, which model it called, and how many tokens the call cost.

CKEditor AI On-Premises uses [OpenTelemetry](https://opentelemetry.io/). Traces cover incoming HTTP requests, database queries, and outgoing calls to LLM providers and to the other services you connect. Turn on [AI spans](#recording-ai-spans), and traces also cover the models, the tools, the token usage, and the content of each call.

CKEditor AI On-Premises has two independent exports. They do not carry the same data, so enable either one on its own, or both:

* **OTLP** – everything CKEditor AI On-Premises records: HTTP requests, database queries, and, when you turn on AI spans, the AI operations too. Send it to any OTLP-compatible backend, for example Jaeger, Grafana Tempo, or Datadog.
* **[Langfuse](https://langfuse.com/)** – AI operations only. CKEditor AI On-Premises drops everything else. Langfuse shows dashboards for AI interactions, token usage, and costs.

This article connects those traces to your tracing backend, to Langfuse, or to both. For raw log output and log shipping, see [Logs](logs.md).

> **Note**
>
> If you use an AI observability platform other than Langfuse, [contact us](https://ckeditor.com/contact/). We can add support for it.

<a id="configuration">

## Configuration

CKEditor AI On-Premises reads the `OTEL_` and `LANGFUSE_` variables below from the process environment when it starts. Pass them as environment variables, even when the rest of the settings come from a `CS_CONFIG_PATH` file. `LLM_TELEMETRY_ENABLED` is an ordinary option, so it can come from either source. [Required configuration](configuration.md) covers the two sources.

<a id="recording-ai-spans">

### Recording AI spans

AI spans are off by default, and you turn them on separately from the exporters. Turn them on first. Without them, the OTLP export carries HTTP and database spans only, and Langfuse receives nothing.

An AI span records the full call: the prompt, including the document and any context, the reply, and the model’s reasoning text when the model reasons. The API never returns that reasoning text, so a trace is the only place to read it when you debug an unexpected answer. It also means your tracing backend receives your users’ documents. Pick a backend and a retention period with that in mind.

```bash
LLM_TELEMETRY_ENABLED=[true|false]
```

Where:

* `LLM_TELEMETRY_ENABLED` (optional, default: `false`) – set to `true` to record spans for AI operations: the models used, the tools called, token usage, and the prompt, reply, and reasoning text of each call. In a `CS_CONFIG_PATH` file the option name is `llm_telemetry_enabled`.

<a id="otlp-exporter">

### OTLP exporter

The following environment variables control the OTLP trace export:

```bash
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=[OTLP_TRACES_ENDPOINT_URL]
OTEL_TRACES_SAMPLER_ARG=[SAMPLING_RATE]
OTEL_DEBUG=[true|false]
```

Where:

* `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` (required for OTLP export) – the endpoint that receives the traces, for example `http://jaeger:4318/v1/traces`. The export uses OTLP over HTTP, so include the full path.
* `OTEL_TRACES_SAMPLER_ARG` (optional, default: `1.0`) – the sampling rate as a float between `0.0` and `1.0`. `1.0` captures every trace. `0.5` captures about half of them. CKEditor AI On-Premises decides sampling per trace, not per span.
* `OTEL_DEBUG` (optional) – set it to any non-empty value, and CKEditor AI On-Premises writes OpenTelemetry diagnostics to the container logs. If traces do not reach your collector, set it.

<a id="langfuse">

### Langfuse

[Langfuse](https://langfuse.com/) is an open-source LLM observability platform. CKEditor AI On-Premises sends spans to Langfuse directly, with no collector in between.

Set both `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` to enable the export:

```bash
LANGFUSE_PUBLIC_KEY=[YOUR_LANGFUSE_PUBLIC_KEY]
LANGFUSE_SECRET_KEY=[YOUR_LANGFUSE_SECRET_KEY]
LANGFUSE_BASE_URL=[LANGFUSE_URL]
LANGFUSE_DEBUG=[true|false]
```

Where:

* `LANGFUSE_PUBLIC_KEY` (required) – the public API key from your Langfuse project.
* `LANGFUSE_SECRET_KEY` (required) – the secret API key from your Langfuse project.
* `LANGFUSE_BASE_URL` (optional, default: `https://cloud.langfuse.com`) – the base URL of your Langfuse instance. If you self-host Langfuse, set it.
* `LANGFUSE_DEBUG` (optional) – set to `true` to write verbose Langfuse SDK diagnostics to the container logs. `OTEL_DEBUG` does not cover them.

> **Note**
>
> The Langfuse export does not need `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`. Langfuse receives the spans directly.

<a id="docker-example">

## Docker example

This example records AI spans, exports to an OTLP collector, and connects to Langfuse Cloud. Add the four telemetry variables to the command from [Deployment](deployment.md):

```bash
docker run --init -p 8000:8000 \
	[Your config here] \
	-e LLM_TELEMETRY_ENABLED="true" \
	-e OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://your-otlp-collector:4318/v1/traces" \
	-e LANGFUSE_PUBLIC_KEY="pk-lf-..." \
	-e LANGFUSE_SECRET_KEY="sk-lf-..." \
	docker.cke-cs.com/ai-service:[version]
```

---

Full index of the Cloud Services documentation: [llms.txt](../../../llms.txt)
