Skip to main content

moesif-litellm

PyPI version Python License

Moesif plugin for LiteLLM. Works in both SDK mode and proxy mode.

Moesif is an API analytics and governance platform. This plugin automatically captures LLM requests and responses so you can monitor usage, track costs, enforce governance rules, and analyze traffic by user or company — with no changes to your LLM calls.

What it does

  • Logging: captures every LLM request and response and sends to Moesif for analytics, cost tracking, and user insights
  • Governance: enforces block rules configured in the Moesif dashboard; requests are stopped before they reach the LLM
  • Sampling: controls what percentage of traffic is logged; sampled events are weighted so Moesif can extrapolate totals correctly
  • Identity resolution: automatically resolves user_id and company_id from multiple sources (kwargs, virtual keys, JWT, callbacks)
  • Body masking: redacts sensitive fields in request/response bodies before logging
  • Event filtering: skip_event callback to drop specific events from being logged
  • Event mutation: mask_event_model callback to transform the event before it is sent

How it works

Events are queued in memory and flushed to POST /v1/events/batch in the background. Failed batches are re-queued automatically.

Default Notes
Batch size 100 events Flush triggered early if queue hits this
Flush interval 2s Background timer
Governance rules refresh 60s Fetched from Moesif /v1/rules with ETag caching
Sampling 100% Set sample_rate=10 to capture 10%; events get weight 100/rate for extrapolation

In sync mode (litellm.completion) each event is sent immediately via a blocking HTTP call. In async mode (litellm.acompletion / proxy) events are batched and flushed on the background timer.


Prerequisites

  • Python >= 3.9
  • LiteLLM >= 1.0.0

Installation

pip install moesif-litellm

SDK Mode

Attach the handler directly to LiteLLM callbacks in your Python code.

import litellm
from moesif_litellm import MoesifHandler

litellm.callbacks = [MoesifHandler()]

litellm.completion(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
    user="alice",                          # → user_id in Moesif
    metadata={"company_id": "acme-corp"},  # → company_id in Moesif
)

Set your Moesif application ID:

export MOESIF_APPLICATION_ID=your-moesif-app-id

Or pass it directly:

MoesifHandler(application_id="your-moesif-app-id")

For custom identity resolution:

MoesifHandler(
    identify_user=lambda kwargs, payload: current_user.id,
    identify_company=lambda kwargs, payload: current_user.company_id,
)

Note: In SDK mode there is no HTTP request, so Moesif logs the request URI as litellmsdk/{call_type} (e.g. litellmsdk/completion, litellmsdk/embedding). In proxy mode the actual request path (e.g. /v1/chat/completions) is used.

See full example: examples/sdk/basic_usage.py


Proxy Mode

Run LiteLLM as a proxy server and load the plugin via a callback shim.

1. Create moesif_callback.py in the same directory as your proxy config:

from moesif_litellm import MoesifHandler
moesif_handler = MoesifHandler()

2. Reference it in proxy_config.yaml:

model_list:
  - model_name: gpt-4o
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY

litellm_settings:
  callbacks: ["moesif_callback.moesif_handler"]

3. Start the proxy:

export MOESIF_APPLICATION_ID=your-moesif-app-id
litellm --config proxy_config.yaml --port 4000

4. Make requests:

curl http://localhost:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "Hello!"}], "user": "alice", "metadata": {"company_id": "acme-corp"}}'

Virtual keys and teams (recommended for proxy)

Assign LiteLLM virtual keys to teams — the team ID maps to company_id in Moesif automatically, no metadata needed in every request.

# Create a team
curl http://localhost:4000/team/new \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -d '{"team_id": "acme-corp"}'

# Generate a virtual key for that team
curl http://localhost:4000/key/generate \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -d '{"team_id": "acme-corp"}'
# → returns "key": "sk-xxxx"

Requests using sk-xxxx automatically get company_id="acme-corp" in Moesif.

See full examples: examples/proxy/


Identity resolution

First non-None value wins.

user_id

Priority Source
1 identify_user callback
2 user_api_key_end_user_id (proxy virtual key)
3 user= kwarg
4 end_user in logging payload
5 user_api_key_user_id (proxy key owner)
6 metadata.user_id
7 JWT claim (authorization_user_id_field)

company_id

Priority Source
1 identify_company callback
2 user_api_key_team_id (proxy virtual key team)
3 requester_metadata.company_id
4 metadata.company_id
5 JWT claim (authorization_company_id_field)

JWT-based identity

MoesifHandler(
    authorization_user_id_field="sub",       # default
    authorization_company_id_field="org_id",
)

Decodes Authorization: Bearer <token> automatically — no secret key needed.


Configuration reference

Parameter Default Description
application_id $MOESIF_APPLICATION_ID Moesif Application ID (required)
batch_size 100 Events per flush
flush_interval 2 Seconds between flushes
max_queue_size 50000 Max in-memory events
capture_request_body True Log request body
capture_response_body True Log response body
request_max_body_size 100000 Max request body bytes
response_max_body_size 100000 Max response body bytes
request_body_masks [] Request body keys to null out
response_body_masks [] Response body keys to null out
request_header_masks [] Request headers to remove
response_header_masks [] Response headers to remove
identify_user None (kwargs, payload) -> str
identify_company None (kwargs, payload) -> str
authorization_user_id_field "sub" JWT claim for user ID
authorization_company_id_field None JWT claim for company ID
skip_event None (kwargs, event) -> bool — return True to drop
mask_event_model None (kwargs, event) -> event — mutate before send
sample_rate 100 0–100 percentage of events to capture
moesif_base_url https://api.moesif.net Override Moesif endpoint
debug False Print identity resolution debug info

Masking sensitive data

MoesifHandler(
    request_body_masks=["messages"],
    response_body_masks=["choices"],
    request_header_masks=["authorization"],
)

Filtering events

# Only log errors
MoesifHandler(skip_event=lambda kwargs, event: event["response"]["status"] == 200)

Sampling

MoesifHandler(sample_rate=10)  # capture 10% of traffic

Per-user and per-company sample rates can also be configured directly in the Moesif dashboard under Governance Rules.

Note: Sampling only affects whether an event is logged to Moesif — it never affects the response returned to the user. Governance rules (blocking) are independent of sampling and always enforced.


License

Apache 2.0 — see LICENSE

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

moesif_litellm-1.0.1.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

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

moesif_litellm-1.0.1-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file moesif_litellm-1.0.1.tar.gz.

File metadata

  • Download URL: moesif_litellm-1.0.1.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for moesif_litellm-1.0.1.tar.gz
Algorithm Hash digest
SHA256 9f959a4711209e358b0d16fce54fe729fbfa46304fcde9b8ad4f587759560dee
MD5 f182367f612b4c5c6a795be087a97b93
BLAKE2b-256 5b45d3ac049dab9b9623b6bcededc2c9c0a7d994c6162560550ec347eed38c2c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: moesif_litellm-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 19.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for moesif_litellm-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c565a0a73b32e365759539711f5aa505e5ca9d56cfae894b93bd1b11b83f02c6
MD5 08ad1335d91d71118acf5bcccc3243cb
BLAKE2b-256 9d75cf34bf7f01c3666a11f1f0529a41937d4589c08a8e65bfffb57f5fd24e06

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 Sentry Error logging StatusPage Status page