mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-29 01:42:19 +00:00
* feat(logger): add shared Rust diagnostics and Python logging bridge * feat(logger): dispatch diagnostic processing through Rust * chore: regenerate Cargo.lock after rebase Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test: allowlist bounded logging tree walkers in recursive detector Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * perf(logger): skip decoding plain access arguments * test(logger): skip embedded-python logger test when litellm deps are absent Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * style: cargo fmt Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test: expect NativeDiagnosticProcessor in the native public surface Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(stub): export NativeDiagnosticProcessor via __new__ in _native.pyi Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(tracing): rename logger crate and document host sink contract * test(logger): cover exc, stack, and nested extras in the diagnostic filter Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(logger): keep rendered redacted line when template scan flags a key pattern The blanket REDACTED for a changed msg/color template discarded lines whose rendered form was already redacted by the same pipeline, e.g. 'password=%s' became 'REDACTED' instead of 'password=REDACTED'. Only fall back to REDACTED when the rendered form did not change either, which is where interpolation can mangle the key pattern the scrub would otherwise see. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * ci(rust): install python deps so the logger bridge test runs The end-to-end bridge test skipped silently when litellm's Python deps were absent. uv sync --no-install-project installs them without a maturin build, and PYTHONPATH makes them visible to the embedded interpreter Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Yujong Lee <yujong@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
116 lines
3.6 KiB
Rust
116 lines
3.6 KiB
Rust
mod cache;
|
|
mod coercion;
|
|
mod credentials;
|
|
mod diagnostics;
|
|
mod errors;
|
|
mod http;
|
|
mod logger;
|
|
mod marshal;
|
|
mod python_settings;
|
|
mod routes;
|
|
#[allow(
|
|
dead_code,
|
|
reason = "secret-manager foundations await rollout activation"
|
|
)]
|
|
mod secrets;
|
|
mod tokenizer;
|
|
|
|
#[pymodule(gil_used = true)]
|
|
mod _native {
|
|
use crate::cache::{CacheTestHandle, CacheTestResolver, ResolvedCache};
|
|
#[cfg(feature = "panic-test")]
|
|
#[pymodule_export]
|
|
use crate::diagnostics::_panic_for_test;
|
|
#[pymodule_export]
|
|
use crate::diagnostics::{gil_stats, process_state_started, reserve_process_for_forking};
|
|
#[pymodule_export]
|
|
use crate::errors::{RustBridgeDeclined, RustUpstreamError};
|
|
#[pymodule_export]
|
|
use crate::logger::NativeDiagnosticProcessor;
|
|
#[pymodule_export]
|
|
use crate::routes::audio_transcription::{atranscription, transcription};
|
|
#[pymodule_export]
|
|
use crate::routes::chat_completions::{
|
|
achat_completions, chat_completions, chat_completions_decline,
|
|
};
|
|
#[pymodule_export]
|
|
use crate::routes::messages::{amessages, messages};
|
|
#[pymodule_export]
|
|
use crate::routes::ocr::{aocr, ocr};
|
|
#[pymodule_export]
|
|
use crate::routes::responses::ResponsesWebSocketConnection;
|
|
#[pymodule_export]
|
|
use crate::routes::token_counter::TokenCounter;
|
|
#[cfg(feature = "huggingface")]
|
|
#[pymodule_export]
|
|
use crate::tokenizer::HuggingFaceEncoding;
|
|
#[pymodule_export]
|
|
use crate::tokenizer::Tokenizer;
|
|
#[pymodule_export]
|
|
use litellm_host_python::{ForkedAfterNativeRuntimeStarted, ProcessReservedForForking};
|
|
use pyo3::{prelude::*, types::PyModule};
|
|
|
|
#[pymodule_init]
|
|
fn init(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
let py = module.py();
|
|
let dict = module.dict();
|
|
dict.set_item("_CacheTestHandle", py.get_type::<CacheTestHandle>())?;
|
|
dict.set_item("_CacheTestResolver", py.get_type::<CacheTestResolver>())?;
|
|
dict.set_item("_ResponseCacheRuntime", py.get_type::<ResolvedCache>())
|
|
}
|
|
}
|
|
|
|
use pyo3::prelude::*;
|
|
|
|
#[cfg(test)]
|
|
pub(crate) fn native_module(py: Python<'_>) -> Bound<'_, PyModule> {
|
|
pyo3::wrap_pymodule!(_native)(py).into_bound(py)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn module_registration_preserves_the_public_surface() {
|
|
Python::initialize();
|
|
Python::attach(|py| {
|
|
let mut expected = vec![
|
|
"RustBridgeDeclined",
|
|
"RustUpstreamError",
|
|
"ForkedAfterNativeRuntimeStarted",
|
|
"ProcessReservedForForking",
|
|
"ocr",
|
|
"aocr",
|
|
"transcription",
|
|
"atranscription",
|
|
"messages",
|
|
"amessages",
|
|
"chat_completions_decline",
|
|
"chat_completions",
|
|
"achat_completions",
|
|
"ResponsesWebSocketConnection",
|
|
"NativeDiagnosticProcessor",
|
|
"TokenCounter",
|
|
"Tokenizer",
|
|
"gil_stats",
|
|
"process_state_started",
|
|
"reserve_process_for_forking",
|
|
];
|
|
#[cfg(feature = "huggingface")]
|
|
expected.push("HuggingFaceEncoding");
|
|
expected.sort_unstable();
|
|
|
|
let mut public_names: Vec<String> = native_module(py)
|
|
.dict()
|
|
.keys()
|
|
.extract::<Vec<String>>()
|
|
.expect("module names should be strings")
|
|
.into_iter()
|
|
.filter(|name| !name.starts_with('_'))
|
|
.collect();
|
|
public_names.sort_unstable();
|
|
assert_eq!(public_names, expected);
|
|
});
|
|
}
|
|
}
|