FluxMeter Python SDK
Send AI token usage events to FluxMeter for real-time aggregation and billing.
Website: fluxmeter.dev · GitHub · API reference
Install
pip install fluxmeter
Quick Start (3 lines)
from fluxmeter import FluxMeter
# Lite (HTTP) — no Kafka
meter = FluxMeter(api_url="http://localhost:8000")
meter.track("cust_123", "gpt-4o", input_tokens=500, output_tokens=150)
# Full (Kafka + WAL)
meter = FluxMeter(kafka_brokers="localhost:9094")
Wrap (path activation)
from openai import OpenAI
from fluxmeter import FluxMeter, wrap, BudgetExceededError, StreamKilledError
meter = FluxMeter(api_url="http://localhost:8000")
client = wrap(OpenAI(), meter, customer_id="cust_123", fail_open=True)
try:
client.chat.completions.create(model="gpt-4o-mini", messages=[...])
except BudgetExceededError:
pass # provider never called
# stream=True → StreamKilledError if est cost exceeds reserve
Gateway (zero-code ingest)
Point OpenAI base_url at FluxMeter Gateway (http://localhost:8080/v1) with header X-FluxMeter-Customer-Id — no SDK track_* needed. See docs/gateway.md.
OpenAI Integration
import time
from openai import OpenAI
from fluxmeter import FluxMeter
client = OpenAI()
meter = FluxMeter(kafka_brokers="localhost:9094", environment="production")
start = time.time()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
)
latency = int((time.time() - start) * 1000)
# One line to meter the usage
meter.track_openai("cust_123", response, latency_ms=latency)
Anthropic Integration
import anthropic
from fluxmeter import FluxMeter
client = anthropic.Anthropic()
meter = FluxMeter(kafka_brokers="localhost:9094")
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
meter.track_anthropic("cust_123", response)
Manual Tracking (any provider)
meter.track(
customer_id="cust_123",
model_id="gemini-1.5-pro",
provider="google",
input_tokens=2000,
output_tokens=500,
request_id="req_abc123",
span_id="span_7f3a", # link to your tracing
session_id="sess_456", # group by conversation
latency_ms=890,
environment="production",
metadata={"feature": "code-review", "team": "platform"},
)
Query usage (HTTP API)
Metering is ingest-only in the SDK. Read usage via the FluxMeter API (see API reference):
import httpx
API = "http://localhost:8000"
headers = {"X-API-Key": "your-key"}
# Lifetime cumulative
httpx.get(f"{API}/usage/customer/cust_123", headers=headers).json()
# Monthly / daily (UTC calendar buckets)
httpx.get(f"{API}/usage/customer/cust_123/period/2026-07", headers=headers).json()
httpx.get(f"{API}/usage/customer/cust_123/day/2026-07-05", headers=headers).json()
# Agent task (set parent_span_id on track)
httpx.get(f"{API}/usage/span/span_agent_42", headers=headers).json()
# Project / conversation (set session_id; lite HTTP ingest path)
httpx.get(f"{API}/usage/session/sess_456", headers=headers).json()
Configuration
meter = FluxMeter(
kafka_brokers="kafka1:9092,kafka2:9092", # Kafka cluster
topic="token-events", # Topic name (default)
environment="production", # Applied to all events
producer_config={ # Extra Kafka producer config
"security.protocol": "SASL_SSL",
"sasl.mechanisms": "PLAIN",
"sasl.username": "...",
"sasl.password": "...",
},
)
How It Works
Your App → meter.track(...) → Kafka → Flink (real-time aggregation) → Redis
↓
Grafana / API
Events are batched and compressed (lz4) before sending. The SDK flushes automatically on process exit.
Requirements
- Python 3.9+
confluent-kafka(librdkafka-based, high performance)- FluxMeter infrastructure running (Kafka + Flink + Redis)
Metadata
Release files for fluxmeter 1.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fluxmeter-1.5.0.tar.gz | 14.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fluxmeter-1.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.4 kB
Release files / fluxmeter-1.5.0.tar.gz
| Download URL | fluxmeter-1.5.0.tar.gz |
|---|---|
| Size | 14.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
23073b4f47353680e878f2320b6bd9506b05b78b1268a1917f47cfe8e96c4b02
|
|
BLAKE2b-256 checksum How to use checksums |
dfaab7908dbb1bca4d4e596d3a09bd852b86213470d2d20637174d8334cbd9d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.
Transparency logRelease files / fluxmeter-1.5.0-py3-none-any.whl
| Download URL | fluxmeter-1.5.0-py3-none-any.whl |
|---|---|
| Size | 15.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65086338277f5a20f5612b253b6b3d45818ef9a86fea7da247bf67ecbb4b4e1c
|
|
BLAKE2b-256 checksum How to use checksums |
bc9af9063f3b08633f718edd82cf7907d99fa6354bd0d06175787137a6c9810a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 11, 2026.
Transparency log