Principle:BerriAI Litellm Custom Logger Development
| Knowledge Sources | Domains | Last Updated |
|---|---|---|
| [[1]] | Observability, Extensibility | 2026-02-15 |
Overview
Custom logger development is the practice of creating new observability integrations by subclassing a base logger class that provides standardized lifecycle hooks for intercepting LLM API call events.
Description
While built-in integration handlers cover popular platforms, many organizations need to route telemetry to internal systems, proprietary dashboards, or niche monitoring tools. Rather than requiring modifications to the core logging pipeline, a well-designed system provides a base class with clearly defined hook methods that can be overridden by custom implementations.
This approach solves several problems:
- Extensibility without core changes -- New integrations are added by subclassing, not by editing the dispatch logic.
- Consistent lifecycle contract -- Every custom logger receives the same event data at the same lifecycle points, regardless of which LLM provider handled the request.
- Opt-in complexity -- The base class provides no-op defaults for every hook. Subclasses override only the hooks they need.
- Batching support -- A separate base class provides batching infrastructure (queue, flush lock, periodic flush timer) for integrations that benefit from sending multiple events in a single request.
- Message privacy control -- The base class accepts configuration flags that let the logger opt into message redaction, so sensitive content never reaches the custom handler.
Usage
Apply custom logger development when:
- You need to send LLM telemetry to an internal monitoring system not covered by built-in integrations.
- You want to implement custom business logic triggered by LLM call events (e.g., alerting on high costs, enforcing quotas).
- You need batched log export with configurable flush intervals and batch sizes.
- You want to build a guardrail or content filter that hooks into the pre-call or post-call lifecycle.
Theoretical Basis
Template Method Pattern
The custom logger follows the Template Method design pattern. The framework defines the overall algorithm (lifecycle dispatch), and subclasses fill in specific steps:
BaseLogger:
log_pre_api_call(model, messages, kwargs) -- before provider call
log_post_api_call(kwargs, response, start, end) -- after raw response
log_stream_event(kwargs, response, start, end) -- each stream chunk
log_success_event(kwargs, response, start, end) -- sync success
log_failure_event(kwargs, response, start, end) -- sync failure
async_log_pre_api_call(model, messages, kwargs) -- async before call
async_log_success_event(kwargs, response, start, end) -- async success
async_log_failure_event(kwargs, response, start, end) -- async failure
Each method has a default no-op implementation. Subclasses override only what they need.
Lifecycle Hook Sequence
1. log_pre_api_call -- called before the HTTP request to the provider
2. log_post_api_call -- called immediately after the raw response is received
3. [if streaming]
log_stream_event -- called for each streaming chunk
4. [on success]
log_success_event -- sync path
async_log_success_event -- async path
[on failure]
log_failure_event -- sync path
async_log_failure_event -- async path
Batching Extension
For high-throughput integrations, a batching base class adds queue management:
BatchLogger extends BaseLogger:
state:
log_queue: list of pending events
batch_size: max events before auto-flush
flush_interval: seconds between periodic flushes
flush_lock: concurrency control
periodic_flush():
every flush_interval seconds:
if log_queue is not empty:
acquire flush_lock
call async_send_batch(log_queue)
log_queue.clear()
release flush_lock
async_send_batch(batch):
-- subclass implements actual network send
pass
Router and Proxy Hooks
Beyond basic logging, the base class also provides hooks for the router and proxy layers:
async_pre_call_check(deployment) -- validate before calling a deployment
async_filter_deployments(deployments) -- filter available deployments
async_pre_call_deployment_hook(kwargs) -- modify request after deployment selected
async_post_call_success_deployment_hook(request, response) -- inspect/modify response
These hooks enable advanced use cases such as usage-based routing, deployment filtering, and response transformation.