ai-observer

作者 tobilg已验证

Unified local observability for AI coding assistants

269
Stars
24
Forks
Go
语言
2026/8/23
添加时间

⚠️ 第三方软件声明

本 Skill 为第三方开源软件,独立托管于 GitHub。SkillTip 仅为信息目录,不控制或维护底层仓库。所显示的安全检查为自动化且范围有限,安装前请自行审查源码。

阅读服务条款

安装

添加到你的 Claude Code skills 目录:

# Add to your Claude Code skills
git clone https://github.com/tobilg/ai-observer

快速入门

使用 ai-observer 等 Skills 的指南。

安全报告

已验证

上次扫描:—

{
  "status": "PASSED",
  "issues": []
}

README.md

AI Observer

Unified local observability for AI coding assistants

AI Observer is a self-hosted, single-binary, OpenTelemetry-compatible observability backend designed specifically for monitoring local AI coding tools like Claude Code, Gemini CLI, OpenAI Codex CLI, GitHub Copilot, and OpenCode.

Track token usage, costs, API latency, error rates, and session activity across all your AI coding assistants in one unified dashboard—with real-time updates and zero external dependencies.

Why AI Observer?

AI coding assistants are becoming essential development tools, but understanding their behavior and costs remains a challenge:

  • Visibility: See exactly how your AI tools are performing across sessions
  • Cost tracking: Monitor token usage and API calls to understand spending
  • Debugging: Trace errors and slow responses back to specific interactions
  • Privacy: Keep your telemetry data local—no third-party services required

Features

  • Multi-tool support — Works with Claude Code, Gemini CLI, OpenAI Codex CLI, GitHub Copilot, and OpenCode
  • Real-time dashboard — Live updates via WebSocket as telemetry arrives
  • Persistent dashboards — Drag-and-drop dashboard builder with saved widgets and multiple widget types
  • File watcher mode — Watch Claude, Codex, and Gemini session files in real-time, no OTLP configuration needed
  • Historical import — Import past Claude, Codex, and Gemini sessions from local JSONL/JSON files with cost calculation
  • Cost tracking — Embedded pricing data across Claude, Codex/OpenAI, Gemini, and GitHub Copilot model aliases, plus native OpenCode plugin cost metrics
  • Fast analytics — DuckDB-powered storage for instant queries on large datasets
  • Single binary — One ~54MB executable with embedded frontend—no external dependencies
  • Multi-arch Docker — Ready-to-run ~97MB images for linux/amd64 and linux/arm64
  • OTLP-native — Standard OpenTelemetry Protocol ingestion (HTTP/JSON and HTTP/Protobuf)

Documentation

  • Import Command — Import historical session data from local AI tool files
  • Export Command — Export telemetry data to Parquet files for archiving and sharing
  • Watch Command — Watch local session files and import incrementally in real-time
  • Pricing System — Cost calculation for Claude, Codex/OpenAI, Gemini, and GitHub Copilot models; OpenCode costs are ingested from the OTEL plugin

Screenshots

Dashboard

AI Observer Dashboard

Metrics View

AI Observer Metrics

Logs View

AI Observer Logs

Traces View

AI Observer traces

Quick Start

Using Docker (Recommended)

docker run -d \
  -p 8080:8080 \
  -p 4318:4318 \
  -v ai-observer-data:/app/data \
  --name ai-observer \
  tobilg/ai-observer:latest

Dashboard: http://localhost:8080

Using a local directory for data persistence:

# Create a local data directory
mkdir -p ./ai-observer-data

# Run with local volume mount
docker run -d \
  -p 8080:8080 \
  -p 4318:4318 \
  -v $(pwd)/ai-observer-data:/app/data \
  -e AI_OBSERVER_DATABASE_PATH=/app/data/ai-observer.duckdb \
  --name ai-observer \
  tobilg/ai-observer:latest

This stores the DuckDB database in your local ./ai-observer-data directory, making it easy to backup or inspect.

Using Homebrew (macOS Apple Silicon)

brew tap tobilg/ai-observer
brew install ai-observer
ai-observer

Using Binary

Download the latest release for your platform from Releases, then:

./ai-observer

Building from Source

git clone https://github.com/tobilg/ai-observer.git
cd ai-observer
make setup   # Install dependencies
make all     # Build single binary with embedded frontend
./bin/ai-observer

Configuration

Environment Variables

VariableDefaultDescription
AI_OBSERVER_API_PORT8080HTTP server port (dashboard + API)
AI_OBSERVER_OTLP_PORT4318OTLP ingestion port
AI_OBSERVER_DATABASE_PATH./data/ai-observer.duckdb (binary) or /app/data/ai-observer.duckdb (Docker)DuckDB database file path
AI_OBSERVER_FRONTEND_URLhttp://localhost:5173Allowed CORS origin (dev mode)
AI_OBSERVER_LOG_LEVELINFOLog level: DEBUG, INFO, WARN, ERROR

CORS and WebSocket origins allow AI_OBSERVER_FRONTEND_URL plus http://localhost:5173 and http://localhost:8080; set AI_OBSERVER_FRONTEND_URL when serving a custom UI origin.

CLI Options

ai-observer [command] [options]

Commands:

CommandDescription
importImport local sessions from AI tool files
exportExport telemetry data to Parquet files
deleteDelete telemetry data from database
setupShow setup instructions for AI tools
watchWatch local session files and import incrementally
serveStart the OTLP server (default if no command)

Global Options:

OptionDescription
-h, --helpShow help message and exit
-v, --versionShow version information and exit

Examples:

# Start the server (default, no command needed)
ai-observer

# Show version
ai-observer --version

# Show setup instructions for Claude Code
ai-observer setup claude-code

# Show setup instructions for GitHub Copilot
ai-observer setup github-copilot

# Show setup instructions for OpenCode
ai-observer setup opencode

# Import data from all file-backed AI tools
ai-observer import all

# Export data to Parquet files
ai-observer export all --output ./export

# Delete data in a date range
ai-observer delete all --from 2025-01-01 --to 2025-01-31

# Watch local session files for changes
ai-observer watch all

Import Command

Import historical session data from local AI coding tool files into AI Observer.

ai-observer import [claude-code|codex|gemini|all] [options]
OptionDescription
--from DATEOnly import sessions from DATE (YYYY-MM-DD)
--to DATEOnly import sessions up to DATE (YYYY-MM-DD)
--forceRe-import already imported files
--dry-runShow what would be imported without making changes
--skip-confirmSkip confirmation prompt
--purgeDelete existing data in time range before importing
--pricing-mode MODECost calculation mode for Claude: auto (default), calculate, display
--verboseShow detailed progress

File locations:

ToolDefault Location
Claude Code~/.claude/projects/**/*.jsonl
Codex CLI~/.codex/sessions/*.jsonl
Gemini CLI~/.gemini/tmp/**/session-*.json

Override with environment variables: AI_OBSERVER_CLAUDE_PATH, AI_OBSERVER_CODEX_PATH, AI_OBSERVER_GEMINI_PATH

Examples:

# Import from all file-backed tools
ai-observer import all

# Import Claude data from specific date range
ai-observer import claude-code --from 2025-01-01 --to 2025-12-31

# Dry run to see what would be imported
ai-observer import all --dry-run

# Force re-import and recalculate costs
ai-observer import claude-code --force --pricing-mode calculate

See docs/import.md for detailed documentation and docs/pricing.md for pricing calculation details.

Watch Command

Watch local session files in real-time and import new data incrementally as it's written. This is an alternative to configuring OTLP exporters for Claude Code, Codex CLI, and Gemini CLI — just start the watcher and it picks up data from those tools' native log files.

ai-observer watch [claude-code|codex|gemini|all] [options]
OptionDescription
--backfillOn first start, load all existing session data before watching

How it works:

  • First start (default): Records the current position in each file without importing historical data. Only data written after startup is imported.
  • First start with --backfill: Loads all existing session data, then watches for new changes.
  • Restart: Resumes from where it left off, importing any data written while the watcher was stopped.

At startup, the watcher detects which tools are installed and reports their status:

File watcher starting...
  [claude-code] Watching ~/.claude/projects/ (2 directories)
  [codex]       Watching ~/.codex/sessions/ (1 directory)
  [gemini]      ~/.gemini/tmp/ not found — will poll for directory creation

Directories that don't exist yet are polled every 30 seconds and automatically added when they appear.

File locations are the same as the import command — override with AI_OBSERVER_CLAUDE_PATH, AI_OBSERVER_CODEX_PATH, AI_OBSERVER_GEMINI_PATH.

Note: Watch mode and OTLP ingestion (serve) are mutually exclusive. Running both simultaneously would produce duplicate data. Use watch for file-based ingestion or serve for OTLP — not both. GitHub Copilot and OpenCode are OTLP-only in AI Observer; use serve and the OTLP setup settings below.

Examples:

# Watch all file-backed tools for new data
ai-observer watch all

# Watch only Claude Code sessions
ai-observer watch claude-code

# First run: load all historical data, then watch
ai-observer watch all --backfill

# Watch Gemini CLI only
ai-observer watch gemini

Export Command

Export telemetry data to portable Parquet files with an optional DuckDB views database.

ai-observer export [claude-code|codex|gemini|opencode|copilot-chat|github-copilot|all] --output <directory> [options]
OptionDescription
--output DIROutput directory (required)
--from DATEStart date filter (YYYY-MM-DD)
--to DATEEnd date filter (YYYY-MM-DD)
--from-filesRead from raw JSON/JSONL files instead of database
--zipCreate single ZIP archive of exported files
--dry-runPreview what would be exported
--verboseShow detailed progress
--yesSkip confirmation prompt

Output files:

  • traces.parquet — All trace/span data
  • logs.parquet — All log records
  • metrics.parquet — All metric data points
  • ai-observer-export-{SOURCE}-{RANGE}.duckdb — Views database with relative paths

Examples:

# Export all data from database
ai-observer export all --output ./export

# Export Claude data with date filter
ai-observer export claude-code --output ./export --from 2025-01-01 --to 2025-01-15

# Export GitHub Copilot VS Code Extension telemetry
ai-observer export copilot-chat --output ./export

# Export OpenCode telemetry
ai-observer export opencode --output ./export

# Export to ZIP archive
ai-observer export all --output ./export --zip

# Export directly from raw files (without prior import)
ai-observer export claude-code --output ./export --from-files

# Dry run to preview export
ai-observer export all --output ./export --dry-run

--from-files is only available for local file sources (claude-code, codex, gemini, all). GitHub Copilot and OpenCode are OTLP-only and export from the DuckDB database.

See docs/export.md for detailed documentation.

Delete Command

Delete telemetry data from the database by time range.

ai-observer delete [logs|metrics|traces|all] --from DATE --to DATE [options]
OptionDescription
--from DATEStart date (YYYY-MM-DD, required)
--to DATEEnd date (YYYY-MM-DD, required)
--service NAMEOnly delete data for specific service
--yesSkip confirmation prompt

Examples:

# Delete all data in a date range
ai-observer delete all --from 2025-01-01 --to 2025-01-31

# Delete only logs in a date range
ai-observer delete logs --from 2025-01-01 --to 2025-01-31

# Delete only Claude Code data
ai-observer delete all --from 2025-01-01 --to 2025-01-31 --service claude-code

# Skip confirmation prompt
ai-observer delete all --from 2025-01-01 --to 2025-01-31 --yes

AI Tool Setup

Claude Code

Configure the following environment variables:

# Enable telemetry (required)
export CLAUDE_CODE_ENABLE_TELEMETRY=1

# Configure exporters
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp

# Set OTLP endpoint (HTTP)
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

# Set shorter intervals
export OTEL_METRIC_EXPORT_INTERVAL=10000  # 10 seconds (default: 60000ms)
export OTEL_LOGS_EXPORT_INTERVAL=5000     # 5 seconds (default: 5000ms)

Add these to your ~/.bashrc, ~/.zshrc, or shell profile to persist across sessions.

Claude Code will then automatically send metrics and events to AI Observer.

Gemini CLI We assume you have at least Gemini CLI in version `v0.34.0` because all version before had a bug regarding OTLP publishing.

Add to ~/.gemini/settings.json:

{
  "telemetry": {
    "enabled": true,
    "target": "local",
    "useCollector": true,
    "otlpEndpoint": "http://localhost:4318",
    "otlpProtocol": "http",
    "logPrompts": true
  }
}

Required environment variables (workaround for Gemini CLI timing issues):

export OTEL_METRIC_EXPORT_TIMEOUT=10000
export OTEL_LOGS_EXPORT_TIMEOUT=5000
OpenAI Codex CLI

Add to ~/.codex/config.toml:

[otel]
log_user_prompt = true  # set to false to redact prompts
exporter = { otlp-http = { endpoint = "http://localhost:4318/v1/logs", protocol = "binary" } }
trace_exporter = { otlp-http = { endpoint = "http://localhost:4318/v1/traces", protocol = "binary" } }

Note: Codex CLI exports logs and traces (no metrics). The trace_exporter option is undocumented but available—if omitted, traces are sent to the same endpoint as logs.

OpenCode

OpenCode telemetry is available through the third-party @devtheops/opencode-plugin-otel plugin. AI Observer receives it through OTLP HTTP on port 4318.

Add to ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@devtheops/opencode-plugin-otel"]
}

Add to your ~/.bashrc, ~/.zshrc, or shell profile:

export OPENCODE_ENABLE_TELEMETRY=1
export OPENCODE_OTLP_ENDPOINT=http://localhost:4318
export OPENCODE_OTLP_PROTOCOL=http/protobuf

The plugin defaults to OTLP/gRPC on port 4317. AI Observer receives OTLP over HTTP on port 4318, so set OPENCODE_OTLP_PROTOCOL=http/protobuf and use the base endpoint above.

GitHub Copilot

GitHub Copilot can export OTLP telemetry from the VS Code extension and CLI. AI Observer stores the raw telemetry and derives token and cost metrics from chat spans.

VS Code settings:

{
  "github.copilot.chat.otel.enabled": true,
  "github.copilot.chat.otel.exporterType": "otlp-http",
  "github.copilot.chat.otel.otlpEndpoint": "http://localhost:4318",
  "github.copilot.chat.otel.captureContent": true
}

Environment variables:

export COPILOT_OTEL_ENABLED=true
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export COPILOT_OTEL_CAPTURE_CONTENT=true

Service names:

ServiceSource
copilot-chatGitHub Copilot VS Code Extension
github-copilotGitHub Copilot CLI

Content capture can include prompts, code, tool arguments, and tool results. Only enable it in trusted local environments.

Architecture

OTLP mode (ai-observer or ai-observer serve):

flowchart TB
    claude[Claude Code<br/>traces, metrics, logs]
    gemini[Gemini CLI<br/>traces, metrics, logs]
    codex[OpenAI Codex CLI<br/>logs, traces]
    copilot[GitHub Copilot<br/>VS Code + CLI<br/>traces, metrics, logs]
    opencode[OpenCode<br/>OTEL plugin<br/>traces, metrics, logs]

    subgraph observer[AI Observer]
        ingest[OTLP Ingestion<br/>HTTP/JSON + HTTP/Protobuf<br/>Port 4318]
        derived[Derived Metrics<br/>tokens, costs, deltas]
        db[(DuckDB<br/>local analytics)]
        api[REST API + WebSocket Hub<br/>Port 8080]
        ui[React Dashboard<br/>embedded frontend]
    end

    claude -->|OTLP/HTTP| ingest
    gemini -->|OTLP/HTTP| ingest
    codex -->|OTLP/HTTP| ingest
    copilot -->|OTLP/HTTP| ingest
    opencode -->|OTLP/HTTP| ingest
    ingest --> derived
    ingest --> db
    derived --> db
    db --> api
    api --> ui

File watcher mode (ai-observer watch all):

flowchart TB
    claudeFiles[Claude Code<br/>~/.claude/projects/**/*.jsonl]
    geminiFiles[Gemini CLI<br/>~/.gemini/tmp/**/session-*.json]
    codexFiles[OpenAI Codex CLI<br/>~/.codex/sessions/*.jsonl]

    subgraph observer[AI Observer]
        watcher[File Watcher<br/>fsnotify + polling<br/>incremental parsing]
        db[(DuckDB<br/>local analytics)]
        api[REST API + WebSocket Hub<br/>Port 8080]
        ui[React Dashboard<br/>embedded frontend]
    end

    claudeFiles -->|file changes| watcher
    geminiFiles -->|file changes| watcher
    codexFiles -->|file changes| watcher
    watcher --> db
    db --> api
    api --> ui

GitHub Copilot and OpenCode are not shown in watcher mode because AI Observer currently receives their telemetry through OTLP only.

Tech Stack:

  • Backend: Go 1.26+, chi router, DuckDB 1.5.3, gorilla/websocket
  • Frontend: React 19, TypeScript, Vite, Tailwind CSS v4, Zustand, Recharts

API Reference

AI Observer exposes two HTTP servers:

OTLP Ingestion (Port 4318)

Standard OpenTelemetry Protocol endpoints for receiving telemetry data.

  • Transport is HTTP/1.1 + h2c (no gRPC listener exposed); Content-Encoding: gzip is supported for compressed payloads.
MethodEndpointDescription
POST/v1/tracesIngest trace spans (protobuf or JSON)
POST/v1/metricsIngest metrics (protobuf or JSON)
POST/v1/logsIngest logs (protobuf or JSON)
GET/healthHealth check

Query API (Port 8080)

REST API for querying stored telemetry data. Unless otherwise specified, from/to default to the last 24 hours.

Traces
MethodEndpointDescription
GET/api/tracesList traces with filtering and pagination
GET/api/traces/recentGet most recent traces
GET/api/traces/{id}?kind={kind}Get spans for a trace row
GET/api/traces/{id}/spans?kind={kind}Get all spans for a trace row

Query parameters for /api/traces:

  • service — Filter by service name
  • search — Full-text search
  • from, to — Time range (ISO 8601)
  • limit, offset — Pagination

Trace list rows include id, kind, traceId, and rootSpanId. Use the id and kind values from a trace row when requesting details. Most rows, including GitHub Copilot and raw Codex session traces, use kind=otel_trace with id set to the OTLP trace ID. Codex operation rows, where present, use kind=codex_operation with id/rootSpanId set to the operation root span ID.

Metrics
MethodEndpointDescription
GET/api/metricsList metrics with filtering
GET/api/metrics/namesList all metric names
GET/api/metrics/seriesGet time series data for a metric
POST/api/metrics/batch-seriesGet multiple time series in one request

Query parameters for /api/metrics/series:

  • name — Metric name (required)
  • service — Filter by service
  • from, to — Time range (ISO 8601)
  • interval — Aggregation interval (e.g., 1 minute, 1 hour)
  • aggregate — Aggregate all series into one (default: false)

Batch series (POST /api/metrics/batch-series) request body:

  • Each query requires id and name; optional service, aggregate, interval.
  • Maximum 50 queries per request.
  • from/to in the body also default to the last 24 hours if omitted.
Logs
MethodEndpointDescription
GET/api/logsList logs with filtering and pagination
GET/api/logs/levelsGet log counts by severity level

Query parameters for /api/logs:

  • service — Filter by service name
  • severity — Filter by severity (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
  • traceId — Filter logs linked to a specific trace
  • search — Full-text search
  • from, to — Time range (ISO 8601)
  • limit, offset — Pagination
Dashboards
MethodEndpointDescription
GET/api/dashboardsList all dashboards
POST/api/dashboardsCreate a new dashboard
GET/api/dashboards/defaultGet the default dashboard with widgets
GET/api/dashboards/{id}Get a dashboard by ID
PUT/api/dashboards/{id}Update a dashboard
DELETE/api/dashboards/{id}Delete a dashboard
PUT/api/dashboards/{id}/defaultSet as default dashboard
POST/api/dashboards/{id}/widgetsAdd a widget
PUT/api/dashboards/{id}/widgets/positionsUpdate widget positions
PUT/api/dashboards/{id}/widgets/{widgetId}Update a widget
DELETE/api/dashboards/{id}/widgets/{widgetId}Delete a widget
Other
MethodEndpointDescription
GET/api/servicesList all services sending telemetry
GET/api/statsGet aggregate statistics
GET/wsWebSocket for real-time updates
GET/healthHealth check

Data Collected

AI Observer receives standard OpenTelemetry data:

SignalDescriptionExample Data
TracesDistributed tracing spansAPI calls, tool executions, session timelines
MetricsNumeric measurementsToken counts, latency histograms, request rates
LogsStructured log recordsErrors, prompts (if enabled), system events

All data is stored locally in DuckDB. Nothing is sent to external services.

Telemetry Reference

Each AI coding tool exports different telemetry signals. Here's what you can observe:

Claude Code Metrics & Events

Metrics

MetricDisplay NameTypeDescription
claude_code.session.countSessionsCounterCLI sessions started
claude_code.token.usageToken UsageCounterTokens used (by type: input/output/cache)
claude_code.cost.usageCostCounterSession cost in USD
claude_code.lines_of_code.countLines of CodeCounterLines of code modified (added/removed)
claude_code.pull_request.countPull RequestsCounterPull requests created
claude_code.commit.countCommitsCounterGit commits created
claude_code.code_edit_tool.decisionEdit DecisionsCounterTool permission decisions (accept/reject)
claude_code.active_time.totalActive TimeCounterActive time in seconds

Common attributes: session.id, organization.id, user.account_uuid, terminal.type, model

Derived Metrics

AI Observer computes user-facing metrics that filter out tool-routing API calls (which have no cache tokens). These metrics match the token counts shown by tools like ccusage:

MetricDisplay NameDescription
claude_code.token.usage_user_facingToken Usage (User-Facing)Tokens from user-facing API calls only (excludes tool-routing)
claude_code.cost.usage_user_facingCost (User-Facing)Cost from user-facing API calls only (excludes tool-routing)

Note: Claude Code makes internal API calls for tool routing that don't involve user interaction. These calls have no cache tokens. The user-facing metrics exclude these calls to provide counts that match what users see in their billing and usage reports.

Events (Logs)

EventDisplay NameDescriptionKey Attributes
claude_code.user_promptUser PromptUser submits a promptprompt_length, prompt (if enabled)
claude_code.api_requestAPI RequestAPI request to Claudemodel, cost_usd, duration_ms, input_tokens, output_tokens
claude_code.api_errorAPI ErrorFailed API requesterror, status_code, attempt
claude_code.tool_resultTool ResultTool execution completestool_name, success, duration_ms, decision
claude_code.tool_decisionTool DecisionPermission decision madetool_name, decision, source
Gemini CLI Metrics & Logs

Metrics

MetricDisplay NameTypeDescription
gemini_cli.session.countSessions (Cumulative)CounterSessions started (cumulative)
gemini_cli.token.usageToken Usage (Cumulative)CounterTokens by type (cumulative)
gemini_cli.cost.usageCostCounterSession cost in USD
gemini_cli.api.request.countAPI Requests (Cumulative)CounterAPI requests by model and status (cumulative)
gemini_cli.api.request.latencyAPI LatencyHistogramAPI request duration (ms)
gemini_cli.api.request.breakdownAPI Request BreakdownHistogramRequest phase analysis (ms)
gemini_cli.tool.call.countTool CallsCounterTool invocations with success/decision
gemini_cli.tool.call.latencyTool LatencyHistogramTool execution duration (ms)
gemini_cli.tool.queue.depthTool Queue DepthHistogramNumber of pending tools in queue
gemini_cli.tool.execution.breakdownTool Execution BreakdownHistogramPhase-level tool execution durations (ms)
gemini_cli.file.operation.countFile Operations (Cumulative)CounterFile operations by type and language (cumulative)
gemini_cli.lines.changedLines ChangedCounterLines added/removed
gemini_cli.agent.run.countAgent RunsCounterAgent executions
gemini_cli.agent.durationAgent DurationHistogramAgent run duration (ms)
gemini_cli.agent.turnsAgent TurnsHistogramInteraction iterations per agent run
gemini_cli.startup.durationStartup DurationHistogramInitialization time by phase (ms)
gemini_cli.memory.usageMemory UsageHistogramMemory consumption (bytes)
gemini_cli.cpu.usageCPU UsageHistogramProcessor utilization (%)
gemini_cli.chat_compressionChat CompressionCounterContext compression events
gemini_cli.chat.invalid_chunk.countInvalid ChunksCounterMalformed stream data count
gemini_cli.chat.content_retry.countContent RetriesCounterRecovery attempt count
gemini_cli.chat.content_retry_failure.countRetry FailuresCounterExhausted retry attempts count
gemini_cli.slash_command.model.call_countModel CommandsCounterModel selections via slash commands
gemini_cli.model_routing.latencyRouting LatencyHistogramRouter decision timing (ms)
gemini_cli.model_routing.failure.countRouting FailuresCounterModel routing failure count
gemini_cli.ui.flicker.countUI FlickerCounterRendering instability events
gemini_cli.token.efficiencyToken EfficiencyHistogramOutput quality metrics ratio
gemini_cli.performance.scorePerformance ScoreHistogramComposite performance benchmark
gemini_cli.performance.regressionPerformance RegressionsCounterPerformance degradation count
gemini_cli.performance.regression.percentage_changeRegression PercentageHistogramPerformance variance magnitude (%)
gemini_cli.performance.baseline.comparisonBaseline ComparisonHistogramPerformance baseline drift (%)
gen_ai.client.token.usageGenAI Token Usage (Cumulative)HistogramToken consumption (OTel semantic convention)
gen_ai.client.operation.durationGenAI Operation DurationHistogramOperation timing in seconds (OTel semantic convention)

Derived Metrics

AI Observer computes delta metrics from cumulative counters to show per-interval changes:

MetricDisplay NameDescription
gemini_cli.session.count.deltaSessionsSessions per interval
gemini_cli.token.usage.deltaToken UsageTokens consumed per interval
gemini_cli.api.request.count.deltaAPI RequestsAPI requests per interval
gemini_cli.file.operation.count.deltaFile OperationsFile operations per interval
gen_ai.client.token.usage.deltaGenAI Token UsageToken consumption per interval (OTel semantic convention)

Logs

LogDisplay NameDescription
gemini_cli.configConfigStartup configuration (model, sandbox, tools, extensions)
gemini_cli.user_promptUser PromptUser prompt with length and auth type
gemini_cli.api_requestAPI RequestAPI request details
gemini_cli.api_responseAPI ResponseResponse with token counts and finish reason
gemini_cli.api_errorAPI ErrorFailed requests with error details
gemini_cli.tool_callTool CallTool execution with duration and arguments
gemini_cli.file_operationFile OperationFile create/read/update operations
gemini_cli.agent.start / agent.finishAgent Start/FinishAgent lifecycle events
gemini_cli.model_routingModel RoutingRouting decisions with latency
gemini_cli.chat_compressionChat CompressionContext compression events
gemini_cli.conversation_finishedConversation FinishedSession completion with turn count
GitHub Copilot Metrics, Logs & Traces

GitHub Copilot exports OTLP telemetry from the VS Code extension and CLI. AI Observer stores the raw telemetry and derives token and cost metrics from GenAI chat spans.

Services

Service NameDisplay Name
copilot-chatGitHub Copilot VS Code Extension
github-copilotGitHub Copilot CLI

These are stored as separate services for filtering and exports. In the frontend metric catalog they are grouped under the GitHub Copilot provider because they share metric metadata and pricing logic.

Derived Metrics

MetricDisplay NameTypeDescription
github_copilot.token.usageToken UsageCounterTokens by type and model (input, output, cache_read, cache_creation, reasoning)
github_copilot.cost.usageCostCounterEstimated cost in USD by model

Cost derivation uses GitHub Copilot pricing data plus aliases generated from the GitHub Models catalog snapshot. If a model cannot be matched to known pricing, AI Observer still stores token usage but does not emit a cost row for that span.

Native Metrics

MetricDisplay NameTypeDescription
gen_ai.client.token.usageGenAI Token UsageHistogramGeneric token usage from the OpenTelemetry semantic convention
gen_ai.client.operation.durationGenAI Operation DurationHistogramGeneric GenAI operation duration
copilot_chat.tool.call.countTool CallsCounterTool call count by tool and status
copilot_chat.tool.call.durationTool DurationHistogramTool call execution time
copilot_chat.agent.invocation.durationAgent Invocation DurationHistogramAgent invocation execution time
copilot_chat.agent.turn.countAgent TurnsCounterAgent turn count
copilot_chat.session.countSessionsCounterCopilot chat session count
copilot_chat.time_to_first_tokenTime to First TokenHistogramTime until the first response token
copilot_chat.edit.acceptance.countEdit AcceptanceCounterAccepted or rejected edits
copilot_chat.chat_edit.outcome.countChat Edit OutcomesCounterChat edit outcomes
copilot_chat.lines_of_code.countLines of CodeCounterLines of code changed
copilot_chat.edit.survival.four_gramEdit Survival (Four-Gram)GaugeEdit survival ratio using four-gram matching
copilot_chat.edit.survival.no_revertEdit Survival (No Revert)GaugeEdit survival ratio based on non-reverted edits
copilot_chat.user.action.countUser ActionsCounterUser action count
copilot_chat.user.feedback.countUser FeedbackCounterUser feedback count
copilot_chat.agent.edit_response.countAgent Edit ResponsesCounterAgent edit response count
copilot_chat.agent.summarization.countAgent SummarizationsCounterAgent summarization count
copilot_chat.pull_request.countPull RequestsCounterPull request event count
copilot_chat.cloud.session.countCloud SessionsCounterCloud session count
copilot_chat.cloud.pr_ready.countCloud PR ReadyCounterCloud pull requests marked ready

Logs and Traces

Copilot spans are stored as normal OTLP traces and can be opened from the Traces page. When Copilot emits GenAI log records, AI Observer recognizes gen_ai.conversation.id, model attributes, tool call arguments, and tool results for session and transcript views.

OpenCode Metrics, Logs & Traces

OpenCode exports OTLP telemetry through the @devtheops/opencode-plugin-otel plugin. AI Observer stores the raw telemetry and surfaces the plugin's native token and cost metrics without deriving additional pricing rows.

Service

Service NameDisplay Name
opencodeOpenCode

Native Metrics

MetricDisplay NameTypeDescription
opencode.session.countSessionsCounterOpenCode sessions started
opencode.token.usageToken UsageCounterTokens by type (input, output, reasoning, cacheRead, cacheCreation)
opencode.cost.usageCostCounterUSD cost for completed assistant messages
opencode.lines_of_code.countLines of CodeCounterGross positive line churn by additions and deletions
opencode.lines_of_code.totalLines of Code TotalGaugeCurrent cumulative line changes for the session
opencode.commit.countCommitsCounterGit commits detected via shell tool usage
opencode.tool.durationTool DurationHistogramTool execution time in milliseconds
opencode.cache.countCache ActivityCounterCache read and cache creation activity
opencode.session.durationSession DurationHistogramSession duration from created to idle
opencode.message.countMessagesCounterCompleted assistant messages
opencode.session.token.totalSession Token TotalHistogramTotal tokens consumed per session
opencode.session.cost.totalSession Cost TotalHistogramTotal cost per session in USD
opencode.model.usageModel UsageCounterMessages by model and provider
opencode.retry.countRetriesCounterAPI retries observed from session status events

Logs and Traces

OpenCode spans are stored as normal OTLP traces. When OpenCode emits plugin log events, AI Observer recognizes session.id, model attributes, token counts, cost, tool arguments, and tool results for session and transcript views.

Recognized log events include session.created, session.idle, session.error, user_prompt, api_request, api_error, tool_result, tool_decision, and commit.

OpenAI Codex CLI Metrics & Events

Codex CLI exports logs and traces directly. AI Observer derives metrics from these log events.

Derived Metrics

AI Observer computes these metrics from Codex CLI log events:

MetricDisplay NameTypeDescription
codex_cli_rs.token.usageToken UsageCounterTokens by type (input/output/cache/reasoning/tool)
codex_cli_rs.cost.usageCostCounterSession cost in USD

Events (Logs)

EventDisplay NameDescriptionKey Attributes
codex.conversation_startsSessionsSession initializationModel, reasoning config, sandbox mode
codex.api_requestAPI RequestsAPI request to OpenAIDuration, HTTP status, token counts
codex.sse_eventSSE EventsStreamed response chunk (filtered out / not stored)Response metrics
codex.user_promptUser PromptsUser prompt submittedCharacter length (content redacted by default)
codex.tool_decisionTool DecisionsTool permission decisionApproval/denial status, decision source
codex.tool_resultTool ResultsTool execution resultDuration, success status, output preview

Note: codex.sse_event events are filtered out by AI Observer to reduce noise—these are emitted for every SSE streaming chunk from the API.

Traces

Codex CLI uses a single trace per session—all operations within a CLI session share the same trace ID with spans nested hierarchically:

flowchart TB
    trace[Trace ID<br/>session-level]
    task[run_task]
    turn1[run_sampling_request / run_turn<br/>agent turn 1]
    try1[try_run_sampling_request / try_run_turn]
    stream1[receiving_stream]
    reasoning[reasoning / function_call]
    receiving[receiving]
    turn2[run_sampling_request / run_turn<br/>agent turn 2]
    more[...]

    trace --> task
    task --> turn1
    turn1 --> try1
    turn1 --> stream1
    stream1 --> reasoning
    stream1 --> receiving
    turn1 --> more
    task --> turn2
    task --> more

This means long CLI sessions produce traces with thousands of spans spanning hours, rather than many short traces.

AI Observer Trace Handling: AI Observer lists Codex sessions as raw OTLP trace rows for fast trace queries. Trace detail can still request Codex operation grouping with kind=codex_operation: the selected operation root spanId becomes the row id, and the detail response expands to the grouped turn spans. run_sampling_request spans are preferred for current Codex versions, with legacy fallbacks such as run_turn and run_task. When a turn_id attribute is available, same-turn sibling spans and their descendants are grouped into the same operation.

Metric Availability by Ingestion Mode

Not all metrics are available in every mode. OTLP receives telemetry emitted by each tool's built-in OpenTelemetry instrumentation (in-memory counters, histograms, traces), while watch and import parse local session files which only contain conversation messages and per-response token/cost data.

Claude Code

Local JSONL files store conversation messages and API usage per response. Operational metrics (lines of code, active time, git activity) are tracked in-memory by Claude Code's OTel instrumentation and only emitted over the network — they are never written to disk.

MetricOTLP (serve)Watch (watch)Import (import)
claude_code.token.usageYesYesYes
claude_code.cost.usageYesYesYes
claude_code.token.usage_user_facingYes (derived)YesYes
claude_code.cost.usage_user_facingYes (derived)YesYes
claude_code.session.countYes
claude_code.lines_of_code.countYes
claude_code.active_time.totalYes
claude_code.pull_request.countYes
claude_code.commit.countYes
claude_code.code_edit_tool.decisionYes
Transcript logsYesYes

OpenAI Codex CLI

Local JSONL files store conversation events and cumulative token counts. The full trace/span hierarchy (session → task → turn → stream) is only available via OTLP.

MetricOTLP (serve)Watch (watch)Import (import)
codex_cli_rs.token.usageYes (derived from logs)YesYes
codex_cli_rs.cost.usageYes (derived from logs)YesYes
Traces / spansYes
Transcript logsYesYes

Gemini CLI

Local JSON session files store messages with per-response token counts. All operational metrics (API latency, tool call timing, agent duration, memory/CPU usage, and ~20 other metrics) are tracked in-memory by Gemini CLI's OTel instrumentation and only emitted over the network.

MetricOTLP (serve)Watch (watch)Import (import)
gemini_cli.token.usageYes (cumulative)YesYes
gemini_cli.cost.usageYesYesYes
gemini_cli.session.countYes (cumulative)
gemini_cli.api.request.countYes (cumulative)
gemini_cli.api.request.latencyYes
gemini_cli.tool.call.countYes
gemini_cli.tool.call.latencyYes
gemini_cli.file.operation.countYes (cumulative)
gemini_cli.agent.durationYes
All other Gemini metricsYes
Transcript logsYesYes

GitHub Copilot

GitHub Copilot telemetry is OTLP-only in AI Observer. There is no local file watcher or historical file import parser for Copilot data.

MetricOTLP (serve)Watch (watch)Import (import)
github_copilot.token.usageYes (derived from spans)
github_copilot.cost.usageYes (derived from spans)
gen_ai.client.token.usageYes
gen_ai.client.operation.durationYes
copilot_chat.tool.call.countYes
copilot_chat.tool.call.durationYes
copilot_chat.agent.invocation.durationYes
copilot_chat.agent.turn.countYes
copilot_chat.session.countYes
copilot_chat.time_to_first_tokenYes
copilot_chat.edit.acceptance.countYes
copilot_chat.chat_edit.outcome.countYes
copilot_chat.lines_of_code.countYes
copilot_chat.edit.survival.*Yes
copilot_chat.user.action.countYes
copilot_chat.user.feedback.countYes
copilot_chat.agent.edit_response.countYes
copilot_chat.agent.summarization.countYes
copilot_chat.pull_request.countYes
copilot_chat.cloud.session.countYes
copilot_chat.cloud.pr_ready.countYes
Traces / spansYes
Transcript logsYes, when emitted as OTLP logs

OpenCode

OpenCode telemetry is OTLP-only in AI Observer through the @devtheops/opencode-plugin-otel plugin. There is no local file watcher or historical file import parser for OpenCode data.

MetricOTLP (serve)Watch (watch)Import (import)
opencode.session.countYes
opencode.token.usageYes
opencode.cost.usageYes
opencode.lines_of_code.countYes
opencode.lines_of_code.totalYes
opencode.commit.countYes
opencode.tool.durationYes
opencode.cache.countYes
opencode.session.durationYes
opencode.message.countYes
opencode.session.token.totalYes
opencode.session.cost.totalYes
opencode.model.usageYes
opencode.retry.countYes
Traces / spansYes
Transcript logsYes, when emitted as OTLP logs

Summary: OTLP mode provides the richest telemetry — all metrics, traces, and events emitted by each tool's built-in or plugin instrumentation. Watch and import modes provide token usage, cost metrics, and full session transcripts parsed from local files. Operational metrics (lines of code, active time, API latency, git activity, etc.) only exist in the OTel telemetry stream and cannot be reconstructed from local files.

Understanding Token Metrics: OTLP vs Local Files

When comparing token usage from AI Observer's OTLP ingestion with tools like ccusage that parse local session files, you may notice significant differences in reported values. This is expected behavior due to different counting semantics.

Example Comparison

Here's a real comparison from a single day of Claude Code usage:

Token TypeccusageOTLPOTLP/ccusage
Input84,103681,6698.1x
Output5,073445,14387.8x
Cache Create3,856,6244,854,4561.26x
Cache Read59,803,27662,460,2041.04x
Total63,749,07668,441,4721.07x
Cost$48.35$65.941.36x

Why This Happens

The discrepancy is most pronounced for input and output tokens:

  1. Claude Code OTLP metrics appear to report tokens differently than the API response's usage object that gets written to JSONL files.

  2. Local JSONL files store the exact usage.input_tokens and usage.output_tokens values from Claude's API response, which ccusage reads directly.

  3. Cache tokens (creation and read) are much closer between the two sources, suggesting these are counted consistently.

Token Type Comparison

Token TypeOTLP vs Local File RatioNotes
Input~8x higher in OTLPLargest discrepancy
Output~80-90x higher in OTLPSignificant discrepancy
Cache Creation~1.2-1.3x (similar)Minor difference
Cache Read~1.0x (nearly identical)Consistent counting

Which Data Source Should I Use?

Use CaseRecommended Source
Billing verificationLocal files / ccusage (matches API billing)
Understanding API loadOTLP metrics (shows actual tokens transmitted)
Cost trackingEither (both calculate costs correctly)
Historical analysisImport command (ai-observer import) for ccusage-compatible data
Zero-config live monitoringWatch mode (ai-observer watch) for real-time file-based ingestion

Reconciling the Data

If you need ccusage-compatible metrics in AI Observer:

# Import from local files instead of relying on OTLP
ai-observer import claude-code --from 2025-01-01 --to 2025-12-31

Imported data uses the same token counting as ccusage and will show matching values.

Technical Details

  • OTLP metrics arrive with aggregationTemporality: 1 (DELTA), meaning each data point is a per-request value
  • The type attribute distinguishes token types: input, output, cacheCreation, cacheRead
  • Imported metrics include an import_source: local_jsonl attribute to distinguish them from OTLP data
  • Watch mode metrics include an import_source: file_watcher attribute
  • OTLP metrics have no import_source attribute (or it's null)

Development

Developer quickstart

make setup          # install Go + frontend deps
make backend-dev    # terminal 1: run API/OTLP server on 8080/4318
make frontend-dev   # terminal 2: Vite dev server on http://localhost:5173
# browse http://localhost:5173 (API + /ws proxied to :8080)

Prerequisites

  • Go 1.26+
  • Node.js 22+
  • pnpm 10+
  • Make

Commands

make setup        # Install all dependencies
make dev          # Run backend + frontend in dev mode
make test         # Run all tests
make lint         # Run linters
make clean        # Clean build artifacts

Project Structure

flowchart TB
    root[ai-observer]
    backend[backend]
    cmd[cmd/server<br/>main entry point]
    internal[internal]
    api[api<br/>API types and helpers]
    deleter[deleter<br/>data deletion logic]
    exporter[exporter<br/>Parquet export and views database]
    handlers[handlers<br/>HTTP handlers]
    importer[importer<br/>historical import for Claude, Codex, Gemini]
    otlp[otlp<br/>OTLP decoders and derived telemetry]
    pricing[pricing<br/>embedded pricing and cost calculation]
    server[server<br/>server setup and routing]
    storage[storage<br/>DuckDB storage layer]
    watcher[watcher<br/>incremental file ingestion]
    websocket[websocket<br/>real-time updates]
    compression[pkg/compression<br/>GZIP decompression]
    frontend[frontend]
    src[src]
    components[components<br/>React components]
    pages[pages<br/>page components]
    stores[stores<br/>Zustand stores]
    lib[lib<br/>utilities]
    docs[docs<br/>documentation]
    makefile[Makefile]

    root --> backend
    backend --> cmd
    backend --> internal
    internal --> api
    internal --> deleter
    internal --> exporter
    internal --> handlers
    internal --> importer
    internal --> otlp
    internal --> pricing
    internal --> server
    internal --> storage
    internal --> watcher
    internal --> websocket
    backend --> compression
    root --> frontend
    frontend --> src
    src --> components
    src --> pages
    src --> stores
    src --> lib
    root --> docs
    root --> makefile

CI/CD

GitHub Actions automatically:

TriggerActions
Push/PRRun tests (Go + frontend)
PushBuild binaries (linux/amd64, darwin/arm64, windows/amd64)
Tag v*Create GitHub Release with archives
Tag v*Push multi-arch Docker images
Release publishedUpdate Homebrew formula in ai-observer-homebrew tap

Creating a Release

git tag v1.0.0
git push origin v1.0.0

Troubleshooting

Port already in use

Change the ports using environment variables:

AI_OBSERVER_API_PORT=9090 AI_OBSERVER_OTLP_PORT=4319 ./ai-observer
No data appearing in dashboard
  1. Verify your AI tool is configured correctly
  2. Check that the OTLP endpoint is reachable: curl http://localhost:4318/health
  3. Look for errors in the AI Observer logs
CORS errors in browser console

Set the AI_OBSERVER_FRONTEND_URL environment variable to match your frontend origin:

AI_OBSERVER_FRONTEND_URL=http://localhost:3000 ./ai-observer

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

常见问题

What is ai-observer?

ai-observer is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by tobilg. Unified local observability for AI coding assistants. It has 269 GitHub stars.

Is ai-observer safe to use?

Yes. ai-observer passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.

How do I install ai-observer?

Clone the repository with "git clone https://github.com/tobilg/ai-observer" and add it to your Claude Code skills directory (see the Installation section above).

What programming language is ai-observer written in?

ai-observer is primarily written in Go. It is open-source under tobilg on GitHub, so you can review or fork the full source.

Are there alternatives to ai-observer?

Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh ai-observer against similar tools.

评论 (0)

暂无评论,成为第一个分享想法的人!

ECC

by affaan-m

10

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

242,21936,702JavaScript
AI 智能体ai-agentsanthropicclaude-code
查看详情
15

An agentic skills framework & software development methodology that works.

234,96620,863Shell
AI 智能体ai-agentsbrainstorming
查看详情

hermes-agent

by NousResearch

10

The agent that grows with you

234,43747,175Python
AI 智能体ai-agentsagent-orchestration
查看详情

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

185,94028,768JavaScript
AI 智能体ai-agentsanthropicclaude-code
查看详情

cc-switch

by farion1231

3

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

128,8688,826Rust
AI 智能体claude-codeai-tools
查看详情

claude-code

by anthropics

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

120,03119,897Shell
AI 智能体
查看详情

开发者还喜欢

基于喜欢此 Skill 的开发者投票和收藏

ECC

by affaan-m

10

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

242,21936,702JavaScript
AI 智能体ai-agentsanthropicclaude-code
查看详情
15

An agentic skills framework & software development methodology that works.

234,96620,863Shell
AI 智能体ai-agentsbrainstorming
查看详情

hermes-agent

by NousResearch

10

The agent that grows with you

234,43747,175Python
AI 智能体ai-agentsagent-orchestration
查看详情

n8n

by n8n-io

12

Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

201,88160,308TypeScript
MCP 服务器apisai-tools
查看详情

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

185,94028,768JavaScript
AI 智能体ai-agentsanthropicclaude-code
查看详情

cc-switch

by farion1231

3

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

128,8688,826Rust
AI 智能体claude-codeai-tools
查看详情