Skip to main content

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.

Release License PyPI Downloads

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-pricing already 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 identifier
  • requests: number of stored usage spans
  • input: input tokens reported by gen_ai.usage.input_tokens
  • cache_read: input tokens reported by gen_ai.usage.cache_read.input_tokens
  • cache_creation: input tokens reported by gen_ai.usage.cache_creation.input_tokens
  • output: total output tokens
  • estimated_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-pricing and 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

llm_ot_cost_monitor-1.0.1.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llm_ot_cost_monitor-1.0.1-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

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

Hashes for llm_ot_cost_monitor-1.0.1.tar.gz
Algorithm Hash digest
SHA256 e1b312794cba233c80a7c8155b9f7e9e54922a9d9dd66d627bb7a3fc58ab929a
MD5 02d25e387d6c15c1809318eea61bc78c
BLAKE2b-256 b4718062d2f780b9450a2aa36ac281605ab382624da06a0312c1c9895f74df14

See more details on using hashes here.

File details

Details for the file llm_ot_cost_monitor-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for llm_ot_cost_monitor-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a537ff064e55876a0681d2f724278fa2cf5ea612900903042161b8ad3832cb53
MD5 20dda141fa5d5367bee2f8ca154c42e8
BLAKE2b-256 151c76bbc5d0b7914ae84dfc40a96268c0bd7908c0663dac3691c2e593b265cb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page