# Cline

> Send Cline (VSCode/Cursor AI coding extension) telemetry — task turns, tokens, cost, tool calls, hooks, and AI output stats — to Last9 via OpenTelemetry.

Source: https://last9.io/docs/integrations/cline/

Cline is an AI coding extension for VSCode and Cursor. It emits structured OpenTelemetry data for every developer task: turns, tokens, cost, cache hits, tool calls, hooks, and a detailed breakdown of code Cline generated versus what the developer accepted or rejected. Routing this to Last9 lets you measure adoption, cost per developer, prompt cache efficiency, and tool reliability — within your existing observability stack.

Cline exports two OpenTelemetry signal types:

- **Logs** — structured events for prompts, tool invocations, errors, and hook executions
- **Metrics** — counters and histograms across task, cache, tools, errors, API latency, hooks, AI output, and workspace

:::note
Cline does not currently export traces. Configuration covers logs and metrics only.
:::

## What gets exported

### Logs (events)

Each Cline session emits structured log records. Filter by `service.name = cline` (or whatever you set via `OTEL_SERVICE_NAME`).

### Metrics

Cline exports 30+ metric instruments grouped by domain.

| Metric                                    | Unit      | Description                      |
| ----------------------------------------- | --------- | -------------------------------- |
| `cline.turns.total`                       | count     | Total turns across all tasks     |
| `cline.turns.per_task`                    | histogram | Turns per task                   |
| `cline.tokens.input.total`                | tokens    | Total input tokens               |
| `cline.tokens.output.total`               | tokens    | Total output tokens              |
| `cline.tokens.input.per_response`         | histogram | Input tokens per model response  |
| `cline.tokens.output.per_response`        | histogram | Output tokens per model response |
| `cline.cost.total`                        | USD       | Cumulative cost across sessions  |
| `cline.cost.per_event`                    | histogram | Cost per model call              |
| `cline.cache.write.tokens.total`          | tokens    | Cache write tokens               |
| `cline.cache.read.tokens.total`           | tokens    | Cache read tokens                |
| `cline.cache.hits.total`                  | count     | Cache hits                       |
| `cline.tool.calls.total`                  | count     | Total tool invocations           |
| `cline.tool.calls.per_task`               | histogram | Tool calls per task              |
| `cline.errors.total`                      | count     | Total errors                     |
| `cline.errors.per_task`                   | histogram | Errors per task                  |
| `cline.api.ttft.seconds`                  | histogram | Model time-to-first-token        |
| `cline.api.duration.seconds`              | histogram | Full model response duration     |
| `cline.api.throughput.tokens_per_second`  | histogram | Output token throughput          |
| `cline.hooks.executions.total`            | count     | Hook invocations                 |
| `cline.hooks.duration.seconds`            | histogram | Hook execution duration          |
| `cline.hooks.failures.total`              | count     | Hook failures                    |
| `cline.hooks.cancellations.total`         | count     | Hook cancellations               |
| `cline.hooks.context_modifications.total` | count     | Hooks that modified context      |
| `cline.hooks.cache.accesses.total`        | count     | Hook cache accesses              |
| `cline.ai_output.accepted.lines_added`    | count     | Lines added in accepted edits    |
| `cline.ai_output.accepted.lines_deleted`  | count     | Lines deleted in accepted edits  |
| `cline.ai_output.accepted.lines_changed`  | count     | Lines changed in accepted edits  |
| `cline.ai_output.accepted.files_created`  | count     | Files created in accepted edits  |
| `cline.ai_output.accepted.files_deleted`  | count     | Files deleted in accepted edits  |
| `cline.ai_output.accepted.files_moved`    | count     | Files moved in accepted edits    |
| `cline.ai_output.rejected.*`              | count     | Same set, for rejected edits     |
| `cline.workspace.active_roots`            | gauge     | Number of active workspace roots |
| `cline.grpc.response.size_bytes`          | histogram | Cline gRPC response size         |

## Prerequisites

1. **Last9 account** — Sign up at [app.last9.io](https://app.last9.io)
2. **Cline extension** — Installed in VSCode (`saoudrizwan.claude-dev`) or Cursor
3. **OTLP credentials** — Get your endpoint and auth header from [**Integrations → OpenTelemetry**](https://app.last9.io/integrations?integration=OpenTelemetry)

## Setup

Cline is configured via environment variables prefixed with `CLINE_OTEL_`. The variables must be set in the shell that launches your editor — GUI launches via Spotlight, Dock, or Finder will not pick them up.

1. **Get your Last9 OTLP credentials**

   Navigate to [**Integrations → OpenTelemetry**](https://app.last9.io/integrations?integration=OpenTelemetry) in your Last9 dashboard. Copy:

   - **OTLP Endpoint** (e.g., `https://otlp.last9.io` or `https://otlp-aps1.last9.io:443`)
   - **Authorization header** value (e.g., `Basic <base64-token>`)

2. **Add environment variables to your shell profile**

   Add the following to `~/.zshrc`, `~/.bashrc`, or equivalent:

**HTTP (recommended)**

   ```bash
   export CLINE_OTEL_TELEMETRY_ENABLED=true
   export CLINE_OTEL_METRICS_EXPORTER=otlp
   export CLINE_OTEL_LOGS_EXPORTER=otlp
   export CLINE_OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
   export CLINE_OTEL_EXPORTER_OTLP_ENDPOINT="https://<your-last9-otlp-endpoint>"
   export CLINE_OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"

   ```

**gRPC**

   ```bash
   export CLINE_OTEL_TELEMETRY_ENABLED=true
   export CLINE_OTEL_METRICS_EXPORTER=otlp
   export CLINE_OTEL_LOGS_EXPORTER=otlp
   export CLINE_OTEL_EXPORTER_OTLP_PROTOCOL=grpc
   export CLINE_OTEL_EXPORTER_OTLP_ENDPOINT="https://<your-last9-otlp-endpoint>:4317"
   export CLINE_OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <your-last9-auth-token>"

   ```

3. **Reload the shell and launch your editor from the same terminal**

   ```bash
   source ~/.zshrc
   cursor .   # or `code .` for VSCode
   ```

   Cline picks up the configuration on extension activation.

4. **Run a Cline task**

   Open the Cline panel and submit any task (e.g. _"summarize what this repo does"_).

   - Logs flush every **5 seconds**
   - Metrics flush every **60 seconds** by default

5. **Verify data is arriving**

   - **Metrics** — open **Metrics** in Last9, search for `cline_turns_total` or `cline_tokens_input_total`
   - **Logs** — open **Logs**, filter by `service.name = cline`

## Configuration reference

### Core

| Variable                       | Default | Description                                                          |
| ------------------------------ | ------- | -------------------------------------------------------------------- |
| `CLINE_OTEL_TELEMETRY_ENABLED` | `false` | Set to `true` to enable export. Overrides user telemetry preferences |
| `CLINE_OTEL_METRICS_EXPORTER`  | unset   | `otlp`, `console`, or comma-separated list                           |
| `CLINE_OTEL_LOGS_EXPORTER`     | unset   | Same as above                                                        |

### OTLP

| Variable                            | Description                                             |
| ----------------------------------- | ------------------------------------------------------- |
| `CLINE_OTEL_EXPORTER_OTLP_PROTOCOL` | `grpc`, `http/json`, or `http/protobuf`                 |
| `CLINE_OTEL_EXPORTER_OTLP_ENDPOINT` | Collector URL — applies to both metrics and logs        |
| `CLINE_OTEL_EXPORTER_OTLP_HEADERS`  | `key=value` comma-separated auth headers                |
| `CLINE_OTEL_EXPORTER_OTLP_INSECURE` | `true` to disable TLS for gRPC (local development only) |

### Per-signal endpoint override

| Variable                                    | Description           |
| ------------------------------------------- | --------------------- |
| `CLINE_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | Metrics-only endpoint |
| `CLINE_OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Metrics-only protocol |
| `CLINE_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`    | Logs-only endpoint    |
| `CLINE_OTEL_EXPORTER_OTLP_LOGS_PROTOCOL`    | Logs-only protocol    |

### Tuning

| Variable                            | Default | Description                    |
| ----------------------------------- | ------- | ------------------------------ |
| `CLINE_OTEL_METRIC_EXPORT_INTERVAL` | `60000` | Metric flush interval (ms)     |
| `CLINE_OTEL_LOG_BATCH_SIZE`         | `512`   | Max log records per batch      |
| `CLINE_OTEL_LOG_BATCH_TIMEOUT`      | `5000`  | Max wait before log flush (ms) |
| `CLINE_OTEL_LOG_MAX_QUEUE_SIZE`     | `2048`  | Max queued log records         |

:::caution
`CLINE_OTEL_TELEMETRY_ENABLED=true` exports data regardless of individual user telemetry preferences inside Cline. Use organization-wide rollouts deliberately.
:::

## What you can do in Last9

### Cost and adoption tracking (metrics)

`cline.cost.total` is a counter you can break down by `model` and `user.email` (when set via resource attributes). In Last9 Metrics, plot `rate(cline_cost_total[5m])` for spend per minute, or sum over a window for daily totals.

### Cache efficiency (metrics)

Compare `cline.cache.read.tokens.total` against `cline.tokens.input.total` to measure prompt cache hit ratio. A high ratio means lower per-interaction cost.

### Developer outcome (metrics)

`cline.ai_output.accepted.*` versus `cline.ai_output.rejected.*` tracks code Cline generated against what developers actually kept. Useful for measuring AI suggestion quality and adoption depth:

```promql
sum(rate(cline_ai_output_accepted_lines_added_total[1h]))
  /
sum(rate(cline_ai_output_accepted_lines_added_total[1h]) + rate(cline_ai_output_rejected_lines_added_total[1h]))
```

### Model latency (metrics)

`cline.api.ttft.seconds` and `cline.api.duration.seconds` show p95/p99 model performance over time. Plot per `model` to compare providers.

### Tool reliability (metrics)

`cline.tool.calls.total` and `cline.errors.total` together highlight which tools fail most. Combine with `cline.errors.per_task` to spot tasks with elevated error rates.

### Hook health (metrics)

`cline.hooks.failures.total` and `cline.hooks.cancellations.total` flag hooks that fail or block in flight. Pair with `cline.hooks.duration.seconds` to find slow hooks.

## Team-level tagging

Tag sessions by team via standard OTel resource attributes:

```bash
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production,team=platform"
```

All metrics and logs from that session carry `team` and `deployment.environment` labels, enabling per-team breakdowns in Last9.

## Debugging

Enable detailed Cline OTel diagnostic logging:

```bash
export TEL_DEBUG_DIAGNOSTICS=true
```

Diagnostic output appears in **Help → Toggle Developer Tools → Console** inside VSCode/Cursor. Includes the resolved configuration, exporters created, connection attempts, and per-export success/failure.

---

## Troubleshooting

- **No data in Last9 after running a Cline task**

  - Confirm your editor was launched from a terminal that has the `CLINE_OTEL_*` vars set. GUI launches do not inherit shell env. Run `cursor .` or `code .` from a terminal where `echo $CLINE_OTEL_TELEMETRY_ENABLED` returns `true`.
  - Check that `CLINE_OTEL_TELEMETRY_ENABLED=true` (not `True`, not `1`)
  - Wait at least 90 seconds — metrics flush every 60 seconds and may need one cycle to land

- **401 / authentication errors**

  - Cline uses comma-separated `key=value` syntax in `CLINE_OTEL_EXPORTER_OTLP_HEADERS`, not HTTP header colon syntax. The full string should be `Authorization=Basic <token>` (with `=`, not `: `)
  - Verify the token has not expired in [**Integrations → OpenTelemetry**](https://app.last9.io/integrations?integration=OpenTelemetry)

- **Logs flow but metrics are missing**

  - Cline metrics export every 60 seconds — wait at least 90 seconds. Metric names in Last9 use underscores: `cline.cost.total` becomes `cline_cost_total`

- **Per-signal endpoint customization needed**
  - Use `CLINE_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` and `CLINE_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` to point each signal at a different collector

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
