crabtalk_proxy/ext/
logging.rs1use 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}