Skip to main content

scirs2_core/observability/audit/
utils.rs

1//! Utility functions for the audit logging system
2
3/// Get thread ID as a numeric value
4#[must_use]
5#[allow(dead_code)]
6pub fn get_thread_id() -> u64 {
7    use std::thread;
8    // This is a simplified implementation
9    // In production, you'd use proper thread ID detection
10    format!("{:?}", thread::current().id())
11        .chars()
12        .filter_map(|c| c.to_digit(10))
13        .map(|d| d as u64)
14        .fold(0, |acc, d| acc * 10 + d)
15}
16
17/// Get hostname from environment variables
18#[must_use]
19#[allow(dead_code)]
20pub fn get_hostname() -> String {
21    std::env::var("HOSTNAME")
22        .or_else(|_| std::env::var("COMPUTERNAME"))
23        .unwrap_or_else(|_| "unknown".to_string())
24}
25
26/// Get local IP address
27#[must_use]
28#[allow(dead_code)]
29pub fn get_local_ip() -> Option<String> {
30    // Try to get the actual local IP address
31    #[cfg(feature = "sysinfo")]
32    {
33        use std::net::UdpSocket;
34
35        // Determine the local IP via a UDP "connect": for a datagram socket
36        // this only asks the OS routing table which local interface/address
37        // would be used to reach the given destination -- no handshake and no
38        // packet is ever actually sent on the wire, so it resolves instantly
39        // regardless of network reachability.
40        //
41        // NOTE: this previously used `TcpStream::connect("8.8.8.8:80")`,
42        // which performs a real SYN and blocks for the platform's full TCP
43        // connect timeout (~75s observed on macOS) whenever the destination
44        // is unreachable -- e.g. in firewalled/air-gapped/network-restricted
45        // deployments. Because `include_system_context` defaults to `true`,
46        // that made every default-configured audit-logged event pay a ~75s
47        // stall in exactly the kind of environment audit logging is normally
48        // deployed into. The UDP-based lookup below cannot block on the
49        // network at all.
50        if let Ok(socket) = UdpSocket::bind("0.0.0.0:0") {
51            if socket.connect("8.8.8.8:80").is_ok() {
52                if let Ok(local_addr) = socket.local_addr() {
53                    return Some(local_addr.ip().to_string());
54                }
55            }
56        }
57
58        // Fallback: try to get from network interfaces
59        // This would require additional network interface detection
60        // For now, return a reasonable default
61        Some("127.0.0.1".to_string())
62    }
63
64    #[cfg(not(feature = "sysinfo"))]
65    {
66        // Simple fallback without network detection
67        use std::env;
68
69        // Check for common environment variables that might contain IP
70        if let Ok(ip) = env::var("HOST_IP") {
71            return Some(ip);
72        }
73
74        if let Ok(ip) = env::var("LOCAL_IP") {
75            return Some(ip);
76        }
77
78        // Default fallback
79        Some("127.0.0.1".to_string())
80    }
81}
82
83/// Get simplified stack trace
84#[must_use]
85#[allow(dead_code)]
86pub fn get_stack_trace() -> String {
87    // Simplified stack trace implementation for compatibility
88    let mut result = String::new();
89    result.push_str("Stack trace (simplified):\n");
90
91    // Get current thread and function info
92    if let Some(name) = std::thread::current().name() {
93        result.push_str(&format!("  Thread: {name}\n"));
94    } else {
95        result.push_str("  Thread: <unnamed>\n");
96    }
97
98    // Add caller information (simplified)
99    result.push_str(&format!(
100        "  Location: {}:{}:{}\n",
101        file!(),
102        line!(),
103        column!()
104    ));
105
106    result
107}