2025-10-23 09:27:04 +08:00
# Observability with OpenTelemetry
Learn how to enable and setup OpenTelemetry for Qwen Code.
- [Observability with OpenTelemetry ](#observability-with-opentelemetry )
- [Key Benefits ](#key-benefits )
- [OpenTelemetry Integration ](#opentelemetry-integration )
- [Configuration ](#configuration )
- [Google Cloud Telemetry ](#google-cloud-telemetry )
- [Prerequisites ](#prerequisites )
- [Direct Export (Recommended) ](#direct-export-recommended )
- [Collector-Based Export (Advanced) ](#collector-based-export-advanced )
- [Local Telemetry ](#local-telemetry )
- [File-based Output (Recommended) ](#file-based-output-recommended )
- [Collector-Based Export (Advanced) ](#collector-based-export-advanced-1 )
- [Logs and Metrics ](#logs-and-metrics )
- [Logs ](#logs )
- [Metrics ](#metrics )
## Key Benefits
- **🔍 Usage Analytics**: Understand interaction patterns and feature adoption
across your team
- **⚡ Performance Monitoring**: Track response times, token consumption, and
resource utilization
- **🐛 Real-time Debugging**: Identify bottlenecks, failures, and error patterns
as they occur
- **📊 Workflow Optimization**: Make informed decisions to improve
configurations and processes
- **🏢 Enterprise Governance**: Monitor usage across teams, track costs, ensure
compliance, and integrate with existing monitoring infrastructure
## OpenTelemetry Integration
Built on ** [OpenTelemetry]** — the vendor-neutral, industry-standard
observability framework — Qwen Code's observability system provides:
- **Universal Compatibility**: Export to any OpenTelemetry backend (Google
Cloud, Jaeger, Prometheus, Datadog, etc.)
- **Standardized Data**: Use consistent formats and collection methods across
your toolchain
- **Future-Proof Integration**: Connect with existing and future observability
infrastructure
- **No Vendor Lock-in**: Switch between backends without changing your
instrumentation
2025-06-06 04:04:25 +08:00
[OpenTelemetry]: https://opentelemetry.io/
2025-10-23 09:27:04 +08:00
## Configuration
All telemetry behavior is controlled through your `.qwen/settings.json` file.
These settings can be overridden by environment variables or CLI flags.
| Setting | Environment Variable | CLI Flag | Description | Values | Default |
| -------------- | -------------------------------- | -------------------------------------------------------- | ------------------------------------------------- | ----------------- | ----------------------- |
| `enabled` | `GEMINI_TELEMETRY_ENABLED` | `--telemetry` / `--no-telemetry` | Enable or disable telemetry | `true` /`false` | `false` |
| `target` | `GEMINI_TELEMETRY_TARGET` | `--telemetry-target <local\|gcp>` | Where to send telemetry data | `"gcp"` /`"local"` | `"local"` |
| `otlpEndpoint` | `GEMINI_TELEMETRY_OTLP_ENDPOINT` | `--telemetry-otlp-endpoint <URL>` | OTLP collector endpoint | URL string | `http://localhost:4317` |
| `otlpProtocol` | `GEMINI_TELEMETRY_OTLP_PROTOCOL` | `--telemetry-otlp-protocol <grpc\|http>` | OTLP transport protocol | `"grpc"` /`"http"` | `"grpc"` |
| `outfile` | `GEMINI_TELEMETRY_OUTFILE` | `--telemetry-outfile <path>` | Save telemetry to file (overrides `otlpEndpoint` ) | file path | - |
| `logPrompts` | `GEMINI_TELEMETRY_LOG_PROMPTS` | `--telemetry-log-prompts` / `--no-telemetry-log-prompts` | Include prompts in telemetry logs | `true` /`false` | `true` |
| `useCollector` | `GEMINI_TELEMETRY_USE_COLLECTOR` | - | Use external OTLP collector (advanced) | `true` /`false` | `false` |
**Note on boolean environment variables:** For the boolean settings (`enabled`,
`logPrompts` , `useCollector` ), setting the corresponding environment variable to
`true` or `1` will enable the feature. Any other value will disable it.
For detailed information about all configuration options, see the
[Configuration Guide ](./cli/configuration.md ).
## Google Cloud Telemetry
### Prerequisites
Before using either method below, complete these steps:
1. Set your Google Cloud project ID:
- For telemetry in a separate project from inference:
```bash
export OTLP_GOOGLE_CLOUD_PROJECT="your-telemetry-project-id"
```
- For telemetry in the same project as inference:
```bash
export GOOGLE_CLOUD_PROJECT="your-project-id"
```
2. Authenticate with Google Cloud:
- If using a user account:
```bash
gcloud auth application-default login
```
- If using a service account:
```bash
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account.json"
```
3. Make sure your account or service account has these IAM roles:
- Cloud Trace Agent
- Monitoring Metric Writer
- Logs Writer
4. Enable the required Google Cloud APIs (if not already enabled):
```bash
gcloud services enable \
cloudtrace.googleapis.com \
monitoring.googleapis.com \
logging.googleapis.com \
--project="$OTLP_GOOGLE_CLOUD_PROJECT"
```
### Direct Export (Recommended)
Sends telemetry directly to Google Cloud services. No collector needed.
1. Enable telemetry in your `.qwen/settings.json` :
```json
{
"telemetry": {
"enabled": true,
"target": "gcp"
}
}
```
2. Run Qwen Code and send prompts.
3. View logs and metrics:
- Open the Google Cloud Console in your browser after sending prompts:
- Logs: https://console.cloud.google.com/logs/
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer
- Traces: https://console.cloud.google.com/traces/list
### Collector-Based Export (Advanced)
For custom processing, filtering, or routing, use an OpenTelemetry collector to
forward data to Google Cloud.
1. Configure your `.qwen/settings.json` :
```json
{
"telemetry": {
"enabled": true,
"target": "gcp",
"useCollector": true
}
}
```
2. Run the automation script:
```bash
npm run telemetry -- --target=gcp
```
This will:
- Start a local OTEL collector that forwards to Google Cloud
- Configure your workspace
- Provide links to view traces, metrics, and logs in Google Cloud Console
- Save collector logs to `~/.qwen/tmp/<projectHash>/otel/collector-gcp.log`
- Stop collector on exit (e.g. `Ctrl+C` )
3. Run Qwen Code and send prompts.
4. View logs and metrics:
- Open the Google Cloud Console in your browser after sending prompts:
- Logs: https://console.cloud.google.com/logs/
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer
- Traces: https://console.cloud.google.com/traces/list
- Open `~/.qwen/tmp/<projectHash>/otel/collector-gcp.log` to view local
collector logs.
## Local Telemetry
For local development and debugging, you can capture telemetry data locally:
### File-based Output (Recommended)
1. Enable telemetry in your `.qwen/settings.json` :
```json
{
"telemetry": {
"enabled": true,
"target": "local",
"otlpEndpoint": "",
"outfile": ".qwen/telemetry.log"
}
}
```
2. Run Qwen Code and send prompts.
3. View logs and metrics in the specified file (e.g., `.qwen/telemetry.log` ).
### Collector-Based Export (Advanced)
1. Run the automation script:
```bash
npm run telemetry -- --target=local
```
This will:
- Download and start Jaeger and OTEL collector
- Configure your workspace for local telemetry
- Provide a Jaeger UI at http://localhost:16686
- Save logs/metrics to `~/.qwen/tmp/<projectHash>/otel/collector.log`
- Stop collector on exit (e.g. `Ctrl+C` )
2. Run Qwen Code and send prompts.
3. View traces at http://localhost:16686 and logs/metrics in the collector log
file.
## Logs and Metrics
The following section describes the structure of logs and metrics generated for
Qwen Code.
2025-06-24 06:25:49 +08:00
- A `sessionId` is included as a common attribute on all logs and metrics.
2025-06-12 00:50:24 +08:00
2025-06-06 04:04:25 +08:00
### Logs
2025-08-20 15:16:45 +08:00
Logs are timestamped records of specific events. The following events are logged for Qwen Code:
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.config` : This event occurs once at startup with the CLI's configuration.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model` (string)
2025-06-12 04:15:44 +08:00
- `embedding_model` (string)
2025-06-06 04:04:25 +08:00
- `sandbox_enabled` (boolean)
- `core_tools_enabled` (string)
- `approval_mode` (string)
2025-06-12 04:15:44 +08:00
- `api_key_enabled` (boolean)
2025-06-06 04:04:25 +08:00
- `vertex_ai_enabled` (boolean)
2025-06-12 04:15:44 +08:00
- `code_assist_enabled` (boolean)
Add telemetry command and refactor telemetry settings (#1060)
#750
### Telemetry Settings
Refactors telemetry configuration to use a nested `telemetry` object in `settings.json`, for example:
```json
{
"telemetry": {
"enabled": true,
"target": "gcp"
"log-prompts": "true"
},
"sandbox": false
}
```
The above includes
- Centralized telemetry settings under a `telemetry` object in `settings.json`.
- CLI flags for the `gemini` command to override all telemetry sub-settings:
- `--telemetry` / `--no-telemetry`
- `--telemetry-target <local|gcp>`
- `--telemetry-otlp-endpoint <URL>`
- `--telemetry-log-prompts` / `--no-telemetry-log-prompts`
- Updates `packages/cli/src/config/config.ts` and `packages/core/src/config/config.ts` to read from the new settings structure and respect the new CLI flags.
- Modifies `scripts/handle-telemetry.js`, `scripts/local_telemetry.js`, and `scripts/telemetry_utils.js` to align with the new settings structure.
- Updates `docs/core/telemetry.md` to reflect the new settings structure, CLI flags, and order of precedence.
- Renames `logUserPromptsEnabled` to `logPrompts` for brevity.
### `npm run telemetry`
Add a new `npm run telemetry` command that uses `scripts/telemetry.js`, automates the entire process of setting up a local and GCP telemetry pipelines, including configuring the necessary settings in the `.gemini/settings.json` workspace file and installing required binaries (e.g. `otelcol-contrib`).
---
```shell
$ npm run telemetry -- --target=gcp
> gemini-cli@0.1.0 telemetry
> node scripts/telemetry.js --target=gcp
⚙️ Using command-line target: gcp
🚀 Running telemetry script for target: gcp.
✨ Starting Local Telemetry Exporter for Google Cloud ✨
⚙️ Enabled telemetry in workspace settings.
🔧 Set telemetry OTLP endpoint to http://localhost:4317.
🎯 Set telemetry target to gcp.
✅ Workspace settings updated.
✅ Using Google Cloud Project ID: foo-bar
🔑 Please ensure you are authenticated with Google Cloud:
- Run `gcloud auth application-default login` OR ensure `GOOGLE_APPLICATION_CREDENTIALS` environment variable points to a valid service account key.
- The account needs "Cloud Trace Agent", "Monitoring Metric Writer", and "Logs Writer" roles.
✅ otelcol-contrib already exists at /Users/jerop/github/gemini-cli/.gemini/otel/bin/otelcol-contrib
🧹 Cleaning up old processes and logs...
✅ Deleted old GCP collector log.
📄 Wrote OTEL collector config to /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.yaml
🚀 Starting OTEL collector for GCP... Logs: /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.log
⏳ Waiting for OTEL collector to start (PID: 17013)...
✅ OTEL collector started successfully on port 4317.
✨ Local OTEL collector for GCP is running.
🚀 To send telemetry, run the Gemini CLI in a separate terminal window.
📄 Collector logs are being written to: /Users/jerop/github/gemini-cli/.gemini/otel/collector-gcp.log
📊 View your telemetry data in Google Cloud Console:
- Logs: https://console.cloud.google.com/logs/query;query=logName%3D%22projects%2Ffoo-bar%2Flogs%2Fgemini_cli%22?project=foo-bar
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer?project=foo-bar
- Traces: https://console.cloud.google.com/traces/list?project=foo-bar
Press Ctrl+C to exit.
^C
👋 Shutting down...
⚙️ Disabled telemetry in workspace settings.
🔧 Cleared telemetry OTLP endpoint.
🎯 Cleared telemetry target.
✅ Workspace settings updated.
🛑 Stopping otelcol-contrib (PID: 17013)...
✅ otelcol-contrib stopped.
```
2025-06-15 12:47:32 +08:00
- `log_prompts_enabled` (boolean)
2025-06-06 04:04:25 +08:00
- `file_filtering_respect_git_ignore` (boolean)
2025-06-12 04:15:44 +08:00
- `debug_mode` (boolean)
- `mcp_servers` (string)
2025-10-23 09:27:04 +08:00
- `output_format` (string: "text" or "json")
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.user_prompt` : This event occurs when a user submits a prompt.
2025-06-06 04:04:25 +08:00
- **Attributes**:
2025-08-28 10:17:32 +08:00
- `prompt_length` (int)
- `prompt_id` (string)
2025-10-23 09:27:04 +08:00
- `prompt` (string, this attribute is excluded if `log_prompts_enabled` is
configured to be `false` )
2025-08-28 10:17:32 +08:00
- `auth_type` (string)
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.tool_call` : This event occurs for each function call.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `function_name`
- `function_args`
- `duration_ms`
- `success` (boolean)
2025-10-23 09:27:04 +08:00
- `decision` (string: "accept", "reject", "auto_accept", or "modify", if
applicable)
2025-06-24 06:25:49 +08:00
- `error` (if applicable)
- `error_type` (if applicable)
2025-10-23 09:27:04 +08:00
- `content_length` (int, if applicable)
2025-08-08 12:38:07 +08:00
- `metadata` (if applicable, dictionary of string -> any)
2025-06-06 04:04:25 +08:00
2025-10-23 09:27:04 +08:00
- `qwen-code.file_operation` : This event occurs for each file operation.
- **Attributes**:
- `tool_name` (string)
- `operation` (string: "create", "read", "update")
- `lines` (int, if applicable)
- `mimetype` (string, if applicable)
- `extension` (string, if applicable)
- `programming_language` (string, if applicable)
- `diff_stat` (json string, if applicable): A JSON string with the following members:
- `ai_added_lines` (int)
- `ai_removed_lines` (int)
- `user_added_lines` (int)
- `user_removed_lines` (int)
2025-09-12 15:27:42 +08:00
- `qwen-code.api_request` : This event occurs when making a request to Qwen API.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model`
2025-06-24 06:25:49 +08:00
- `request_text` (if applicable)
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.api_error` : This event occurs if the API request fails.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model`
- `error`
- `error_type`
- `status_code`
- `duration_ms`
2025-07-12 00:47:46 +08:00
- `auth_type`
2025-06-06 04:04:25 +08:00
2025-09-12 15:27:42 +08:00
- `qwen-code.api_response` : This event occurs upon receiving a response from Qwen API.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model`
- `status_code`
- `duration_ms`
- `error` (optional)
2025-06-13 07:36:51 +08:00
- `input_token_count`
2025-06-12 01:47:21 +08:00
- `output_token_count`
- `cached_content_token_count`
- `thoughts_token_count`
- `tool_token_count`
2025-06-24 06:25:49 +08:00
- `response_text` (if applicable)
2025-07-12 00:47:46 +08:00
- `auth_type`
2025-06-06 04:04:25 +08:00
2025-10-23 09:27:04 +08:00
- `qwen-code.tool_output_truncated` : This event occurs when the output of a tool call is too large and gets truncated.
- **Attributes**:
- `tool_name` (string)
- `original_content_length` (int)
- `truncated_content_length` (int)
- `threshold` (int)
- `lines` (int)
- `prompt_id` (string)
- `qwen-code.malformed_json_response` : This event occurs when a `generateJson` response from Qwen API cannot be parsed as a json.
- **Attributes**:
- `model`
2025-08-20 15:16:45 +08:00
- `qwen-code.flash_fallback` : This event occurs when Qwen Code switches to flash as fallback.
2025-07-12 05:10:25 +08:00
- **Attributes**:
- `auth_type`
2025-08-20 15:16:45 +08:00
- `qwen-code.slash_command` : This event occurs when a user executes a slash command.
2025-07-30 04:20:37 +08:00
- **Attributes**:
- `command` (string)
- `subcommand` (string, if applicable)
2025-10-23 09:27:04 +08:00
- `qwen-code.extension_enable` : This event occurs when an extension is enabled
- `qwen-code.extension_install` : This event occurs when an extension is installed
- **Attributes**:
- `extension_name` (string)
- `extension_version` (string)
- `extension_source` (string)
- `status` (string)
- `qwen-code.extension_uninstall` : This event occurs when an extension is uninstalled
2025-06-06 04:04:25 +08:00
### Metrics
2025-08-20 15:16:45 +08:00
Metrics are numerical measurements of behavior over time. The following metrics are collected for Qwen Code (metric names remain `qwen-code.*` for compatibility):
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.session.count` (Counter, Int): Incremented once per CLI startup.
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.tool.call.count` (Counter, Int): Counts tool calls.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `function_name`
- `success` (boolean)
2025-06-24 06:25:49 +08:00
- `decision` (string: "accept", "reject", or "modify", if applicable)
2025-09-01 14:48:55 +08:00
- `tool_type` (string: "mcp", or "native", if applicable)
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.tool.call.latency` (Histogram, ms): Measures tool call latency.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `function_name`
2025-06-24 06:25:49 +08:00
- `decision` (string: "accept", "reject", or "modify", if applicable)
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.api.request.count` (Counter, Int): Counts all API requests.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model`
- `status_code`
2025-06-24 06:25:49 +08:00
- `error_type` (if applicable)
2025-06-06 04:04:25 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.api.request.latency` (Histogram, ms): Measures API request latency.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model`
2025-08-20 15:16:45 +08:00
- `qwen-code.token.usage` (Counter, Int): Counts the number of tokens used.
2025-06-06 04:04:25 +08:00
- **Attributes**:
- `model`
2025-06-11 14:56:53 +08:00
- `type` (string: "input", "output", "thought", "cache", or "tool")
Add file operation telemetry (#1068)
Introduces telemetry for file create, read, and update operations.
This change adds the `gemini_cli.file.operation.count` metric, recorded by the `read-file`, `read-many-files`, and `write-file` tools.
The metric includes the following attributes:
- `operation` (string: `create`, `read`, `update`): The type of file operation.
- `lines` (optional, Int): Number of lines in the file.
- `mimetype` (optional, string): Mimetype of the file.
- `extension` (optional, string): File extension of the file.
Here is a stacked bar chart of file operations by extension (`js`, `ts`, `md`):

Here is a stacked bar chart of file operations by type (`create`, `read`, `update`):

#750
cc @allenhutchison as discussed
2025-06-16 04:24:53 +08:00
2025-08-20 15:16:45 +08:00
- `qwen-code.file.operation.count` (Counter, Int): Counts file operations.
Add file operation telemetry (#1068)
Introduces telemetry for file create, read, and update operations.
This change adds the `gemini_cli.file.operation.count` metric, recorded by the `read-file`, `read-many-files`, and `write-file` tools.
The metric includes the following attributes:
- `operation` (string: `create`, `read`, `update`): The type of file operation.
- `lines` (optional, Int): Number of lines in the file.
- `mimetype` (optional, string): Mimetype of the file.
- `extension` (optional, string): File extension of the file.
Here is a stacked bar chart of file operations by extension (`js`, `ts`, `md`):

Here is a stacked bar chart of file operations by type (`create`, `read`, `update`):

#750
cc @allenhutchison as discussed
2025-06-16 04:24:53 +08:00
- **Attributes**:
- `operation` (string: "create", "read", "update"): The type of file operation.
2025-06-24 06:25:49 +08:00
- `lines` (Int, if applicable): Number of lines in the file.
- `mimetype` (string, if applicable): Mimetype of the file.
- `extension` (string, if applicable): File extension of the file.
2025-10-23 09:27:04 +08:00
- `model_added_lines` (Int, if applicable): Number of lines added/changed by the model.
- `model_removed_lines` (Int, if applicable): Number of lines removed/changed by the model.
2025-08-08 12:38:07 +08:00
- `user_added_lines` (Int, if applicable): Number of lines added/changed by user in AI proposed changes.
- `user_removed_lines` (Int, if applicable): Number of lines removed/changed by user in AI proposed changes.
2025-08-22 20:17:32 +08:00
- `programming_language` (string, if applicable): The programming language of the file.
2025-09-01 14:48:55 +08:00
2025-09-12 16:01:38 +08:00
- `qwen-code.chat_compression` (Counter, Int): Counts chat compression operations
2025-09-01 14:48:55 +08:00
- **Attributes**:
- `tokens_before` : (Int): Number of tokens in context prior to compression
- `tokens_after` : (Int): Number of tokens in context after compression