state_engine/common/
log_format.rs1use serde_json::Value;
6
7pub struct LogFormat;
9
10impl LogFormat {
11 pub fn method_call(class: &str, method: &str, args: &[String]) -> String {
20 let args_str = args.join(", ");
21 format!("{}::{}({})", class, method, args_str)
22 }
23
24 pub fn error(class: &str, method: &str, message: &str) -> String {
33 format!("{}::{}: {}", class, method, message)
34 }
35
36 pub fn format_arg(value: &Value) -> String {
43 match value {
44 Value::String(s) if s.len() > 50 => {
45 format!("'{}'...", &s[..47])
46 }
47 Value::String(s) => {
48 format!("'{}'", s)
49 }
50 Value::Array(arr) => {
51 if arr.is_empty() {
52 "[]".to_string()
53 } else {
54 format!("[{} items]", arr.len())
55 }
56 }
57 Value::Object(obj) => {
58 if obj.is_empty() {
59 "{}".to_string()
60 } else {
61 format!("{{{} fields}}", obj.len())
62 }
63 }
64 Value::Null => "null".to_string(),
65 Value::Bool(b) => b.to_string(),
66 Value::Number(n) => n.to_string(),
67 }
68 }
69
70 pub fn format_str_arg(s: &str) -> String {
72 if s.len() > 50 {
73 format!("'{}'...", &s[..47])
74 } else {
75 format!("'{}'", s)
76 }
77 }
78}
79
80#[macro_export]
90macro_rules! log_method {
91 ($class:expr, $method:expr $(, $arg:expr)*) => {{
92 #[cfg(feature = "logging")]
93 {
94 let args: Vec<String> = vec![
95 $(
96 $crate::common::log_format::LogFormat::format_str_arg($arg),
97 )*
98 ];
99 log::debug!("{}", $crate::common::log_format::LogFormat::method_call($class, $method, &args));
100 }
101 }};
102}
103
104#[macro_export]
114macro_rules! log_err {
115 ($class:expr, $method:expr, $msg:expr) => {{
116 #[cfg(feature = "logging")]
117 {
118 log::error!("{}", $crate::common::log_format::LogFormat::error($class, $method, $msg));
119 }
120 }};
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use serde_json::json;
127
128 #[test]
129 fn test_method_call() {
130 let result = LogFormat::method_call("State", "get", &["'cache.user'".to_string()]);
131 assert_eq!(result, "State::get('cache.user')");
132
133 let result = LogFormat::method_call("State", "get", &[
134 "'cache.user'".to_string(),
135 "null".to_string(),
136 ]);
137 assert_eq!(result, "State::get('cache.user', null)");
138 }
139
140 #[test]
141 fn test_error() {
142 let result = LogFormat::error("State", "get", "metadata not found");
143 assert_eq!(result, "State::get: metadata not found");
144 }
145
146 #[test]
147 fn test_format_arg_string() {
148 assert_eq!(LogFormat::format_arg(&json!("hello")), "'hello'");
149
150 let long_str = "a".repeat(60);
151 let result = LogFormat::format_arg(&json!(long_str));
152 assert!(result.starts_with("'aaa"));
153 assert!(result.ends_with("'..."));
154 assert_eq!(result.len(), 52); }
156
157 #[test]
158 fn test_format_arg_array() {
159 assert_eq!(LogFormat::format_arg(&json!([])), "[]");
160 assert_eq!(LogFormat::format_arg(&json!([1, 2, 3])), "[3 items]");
161 }
162
163 #[test]
164 fn test_format_arg_object() {
165 assert_eq!(LogFormat::format_arg(&json!({})), "{}");
166 assert_eq!(LogFormat::format_arg(&json!({"a": 1, "b": 2})), "{2 fields}");
167 }
168
169 #[test]
170 fn test_format_arg_primitives() {
171 assert_eq!(LogFormat::format_arg(&json!(null)), "null");
172 assert_eq!(LogFormat::format_arg(&json!(true)), "true");
173 assert_eq!(LogFormat::format_arg(&json!(false)), "false");
174 assert_eq!(LogFormat::format_arg(&json!(42)), "42");
175 assert_eq!(LogFormat::format_arg(&json!(3.14)), "3.14");
176 }
177
178 #[test]
179 fn test_format_str_arg() {
180 assert_eq!(LogFormat::format_str_arg("hello"), "'hello'");
181
182 let long_str = "a".repeat(60);
183 let result = LogFormat::format_str_arg(&long_str);
184 assert!(result.starts_with("'aaa"));
185 assert!(result.ends_with("'..."));
186 }
187}