Skip to main content

crabtalk_proxy/ext/
logging.rs

1use crabtalk_core::{
2    BoxFuture, ChatCompletionRequest, ChatCompletionResponse, Error, Prefix, RequestContext,
3};
4
5pub struct RequestLogger;
6
7impl RequestLogger {
8    pub fn new(_config: &serde_json::Value) -> Result<Self, String> {
9        Ok(Self)
10    }
11}
12
13impl crabtalk_core::Extension for RequestLogger {
14    fn name(&self) -> &str {
15        "logging"
16    }
17
18    fn prefix(&self) -> Prefix {
19        *b"logg"
20    }
21
22    fn on_response(
23        &self,
24        ctx: &RequestContext,
25        _request: &ChatCompletionRequest,
26        response: &ChatCompletionResponse,
27    ) -> BoxFuture<'_, ()> {
28        let latency = ctx.started_at.elapsed();
29        let (prompt, completion) = response
30            .usage
31            .as_ref()
32            .map(|u| (u.prompt_tokens, u.completion_tokens))
33            .unwrap_or((0, 0));
34
35        tracing::info!(
36            model = %ctx.model,
37            provider = %ctx.provider,
38            key = ctx.key_name.as_deref().unwrap_or("-"),
39            stream = ctx.is_stream,
40            latency_ms = latency.as_millis() as u64,
41            prompt_tokens = prompt,
42            completion_tokens = completion,
43            "request completed"
44        );
45
46        Box::pin(async {})
47    }
48
49    fn on_error(&self, ctx: &RequestContext, error: &Error) -> BoxFuture<'_, ()> {
50        let latency = ctx.started_at.elapsed();
51
52        tracing::warn!(
53            model = %ctx.model,
54            provider = %ctx.provider,
55            key = ctx.key_name.as_deref().unwrap_or("-"),
56            stream = ctx.is_stream,
57            latency_ms = latency.as_millis() as u64,
58            error = %error,
59            "request failed"
60        );
61
62        Box::pin(async {})
63    }
64}