LLM Open Telemetry Cost Monitor
A small local collector for token usage emitted by GitHub Copilot through OpenTelemetry. It accepts OTLP/HTTP trace protobuf and JSON, stores token usage metadata in SQLite, and estimates cost with genai-pricing.
The monitor stores trace ID, span ID, timestamp, model, input tokens, cache-read input tokens, cache-creation input tokens, and output tokens. It does not capture prompts or responses.
Requirements
- Python 3.10 or newer
- VS Code and a Copilot Chat version that supports OpenTelemetry export
- Network access for the first pricing lookup, unless
genai-pricingalready has a pricing cache
This project uses the repository-local virtual environment in venv/.
Install
Install the package into an activated virtual environment:
python -m pip install llm-ot-cost-monitor
To work from a repository checkout instead, install its dependencies:
./venv/bin/python -m pip install -r requirements.txt
The dependencies are pinned in requirements.txt.
Configure VS Code
Copilot's OpenTelemetry settings are application-scoped. Amend only ~/Library/Application Support/Code/User/settings.json; do not add them to a workspace .vscode/settings.json file:
{
"github.copilot.chat.otel.enabled": true,
"github.copilot.chat.otel.exporterType": "otlp-http",
"github.copilot.chat.otel.protocol": "http/protobuf",
"github.copilot.chat.otel.otlpEndpoint": "http://127.0.0.1:4318",
"github.copilot.chat.otel.captureContent": false
}
Reload VS Code after changing the settings, then run Copilot requests while the collector is running.
Do not enable content capture unless you explicitly want prompts, responses, or source code included in telemetry. This collector does not require content capture.
Start the collector
Start the local OTLP/HTTP receiver:
llm-monitor serve --db usage.db
The llm-monitor command is installed with the package. From a repository checkout,
you can instead run ./venv/bin/python monitor.py serve --db usage.db.
The receiver listens on 127.0.0.1:4318 and accepts trace exports at:
http://127.0.0.1:4318/v1/traces
To use another database, pass a different path:
llm-monitor serve --db data/usage.db
To change the listening address or port:
llm-monitor serve --host 127.0.0.1 --port 4318 --db usage.db
Keep the collector process running while using Copilot.
View usage and estimated cost
After running Copilot requests, stop or leave the collector running and execute:
llm-monitor summary --db usage.db
The output contains:
model: reported model identifierrequests: number of stored usage spansinput: input tokens reported bygen_ai.usage.input_tokenscache_read: input tokens reported bygen_ai.usage.cache_read.input_tokenscache_creation: input tokens reported bygen_ai.usage.cache_creation.input_tokensoutput: total output tokensestimated_cost_usd: estimated cost in US dollars
Example:
model | requests | input | cache_read | cache_creation | output | estimated_cost_usd
------------+----------+-------+------------+----------------+--------+--------------------
gpt-4o-mini | 2 | 1200 | 800 | 100 | 340 | 0.000248
Costs are calculated by genai-pricing using its pricing table, including provider-specific cache-read and cache-creation rates when available. Unknown models or unavailable prices are shown as n/a; the monitor does not guess rates.
genai-pricing treats input as the total prompt token count and subtracts the two cached-token counts before applying the regular input rate. This matches telemetry payloads where gen_ai.usage.input_tokens includes cached tokens. If an extension emits only non-cached tokens in that attribute, its estimate may undercount regular input because the semantic convention permits either payload interpretation.
Data and duplicate handling
The default database is usage.db in the repository root. SQLite creates it automatically when the collector starts.
Each record is keyed by trace ID and span ID. Repeated exports of the same span are ignored, preventing duplicate cost totals.
The database may contain sensitive operational metadata such as model names and usage volume. Keep it local and do not commit usage.db to source control.
Test
Run the unit tests with the local virtual environment:
env -u PYTHONHOME -u PYTHONPATH ./venv/bin/python -m unittest -v
The tests cover OTLP usage extraction, duplicate span handling, and the genai-pricing API call.
Limitations
- Exact usage depends on Copilot emitting the relevant
gen_ai.usage.*token attributes. - Missing token attributes cannot be reconstructed from trace metadata alone.
- Costs are estimates based on the pricing data available to
genai-pricingand may not match account-specific billing, discounts, or included usage. - The receiver is intentionally local and minimal; it does not provide authentication, a web dashboard, or remote storage.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_ot_cost_monitor-1.0.1.tar.gz.
File metadata
- Download URL: llm_ot_cost_monitor-1.0.1.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1b312794cba233c80a7c8155b9f7e9e54922a9d9dd66d627bb7a3fc58ab929a
|
|
| MD5 |
02d25e387d6c15c1809318eea61bc78c
|
|
| BLAKE2b-256 |
b4718062d2f780b9450a2aa36ac281605ab382624da06a0312c1c9895f74df14
|
File details
Details for the file llm_ot_cost_monitor-1.0.1-py3-none-any.whl.
File metadata
- Download URL: llm_ot_cost_monitor-1.0.1-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a537ff064e55876a0681d2f724278fa2cf5ea612900903042161b8ad3832cb53
|
|
| MD5 |
20dda141fa5d5367bee2f8ca154c42e8
|
|
| BLAKE2b-256 |
151c76bbc5d0b7914ae84dfc40a96268c0bd7908c0663dac3691c2e593b265cb
|