Skip to main content

ai_agent/services/api/
logging.rs

1// Source: /data/home/swei/claudecode/openclaudecode/src/services/api/logging.ts
2//! API logging utilities
3
4use serde::{Deserialize, Serialize};
5
6/// Log level for API logging
7#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
8#[serde(rename_all = "lowercase")]
9pub enum ApiLogLevel {
10    Debug,
11    Info,
12    Warn,
13    Error,
14}
15
16impl Default for ApiLogLevel {
17    fn default() -> Self {
18        ApiLogLevel::Info
19    }
20}
21
22/// API log entry
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ApiLogEntry {
25    pub timestamp: String,
26    pub level: ApiLogLevel,
27    pub message: String,
28    pub details: Option<serde_json::Value>,
29}
30
31impl ApiLogEntry {
32    pub fn new(level: ApiLogLevel, message: impl Into<String>) -> Self {
33        Self {
34            timestamp: chrono::Utc::now().to_rfc3339(),
35            level,
36            message: message.into(),
37            details: None,
38        }
39    }
40
41    pub fn with_details(mut self, details: serde_json::Value) -> Self {
42        self.details = Some(details);
43        self
44    }
45
46    pub fn debug(message: impl Into<String>) -> Self {
47        Self::new(ApiLogLevel::Debug, message)
48    }
49
50    pub fn info(message: impl Into<String>) -> Self {
51        Self::new(ApiLogLevel::Info, message)
52    }
53
54    pub fn warn(message: impl Into<String>) -> Self {
55        Self::new(ApiLogLevel::Warn, message)
56    }
57
58    pub fn error(message: impl Into<String>) -> Self {
59        Self::new(ApiLogLevel::Error, message)
60    }
61}
62
63/// Global API logger
64pub struct ApiLogger {
65    enabled: bool,
66    min_level: ApiLogLevel,
67}
68
69impl ApiLogger {
70    pub fn new() -> Self {
71        Self {
72            enabled: true,
73            min_level: ApiLogLevel::Info,
74        }
75    }
76
77    pub fn set_enabled(&mut self, enabled: bool) {
78        self.enabled = enabled;
79    }
80
81    pub fn set_min_level(&mut self, level: ApiLogLevel) {
82        self.min_level = level;
83    }
84
85    pub fn log(&self, entry: &ApiLogEntry) {
86        if !self.enabled {
87            return;
88        }
89
90        let level_priority = match entry.level {
91            ApiLogLevel::Debug => 0,
92            ApiLogLevel::Info => 1,
93            ApiLogLevel::Warn => 2,
94            ApiLogLevel::Error => 3,
95        };
96
97        let min_priority = match self.min_level {
98            ApiLogLevel::Debug => 0,
99            ApiLogLevel::Info => 1,
100            ApiLogLevel::Warn => 2,
101            ApiLogLevel::Error => 3,
102        };
103
104        if level_priority >= min_priority {
105            // In a real implementation, this would write to a log
106            eprintln!("[API] {:?}: {}", entry.level, entry.message);
107        }
108    }
109}
110
111impl Default for ApiLogger {
112    fn default() -> Self {
113        Self::new()
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use super::*;
120
121    #[test]
122    fn test_api_log_entry_creation() {
123        let entry = ApiLogEntry::info("test message");
124        assert_eq!(entry.level, ApiLogLevel::Info);
125        assert_eq!(entry.message, "test message");
126        assert!(entry.details.is_none());
127    }
128
129    #[test]
130    fn test_api_log_entry_with_details() {
131        let entry = ApiLogEntry::info("test").with_details(serde_json::json!({"key": "value"}));
132        assert!(entry.details.is_some());
133    }
134}