use actix_web::{HttpRequest, HttpResponse};
use serde_json::{Value, json};
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
use uuid::Uuid;
use crate::drivers::supabase::supabase;
use crate::api::headers::{x_company_id, x_user_id};
pub fn log_request(req: HttpRequest) -> Value {
let user_id: String = x_user_id::get_x_user_id(&req).unwrap_or_else(|| "NOT_FOUND".to_string());
let company_id: String =
x_company_id::get_x_company_id(&req).unwrap_or_else(|| "NOT_FOUND".to_string());
let request_id: String = Uuid::new_v4().to_string();
let body_json: Value = req
.match_info()
.get("body")
.and_then(|body| serde_json::from_str(body).ok())
.unwrap_or_else(|| json!({}));
let query_string: &str = req.query_string();
let query_string: String = if query_string.is_empty() {
"NOT_FOUND".to_string()
} else {
query_string.to_string()
};
let headers: HashMap<String, String> = req
.headers()
.iter()
.map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string()))
.collect::<HashMap<_, _>>();
let method: &str = req.method().as_str();
let path: &str = req.path();
let status_http_code: u16 = req
.app_data::<HttpResponse>()
.map(|resp| resp.status().as_u16())
.unwrap_or(0);
let x_real_ip: String = headers
.get("X-Real-IP")
.unwrap_or(&"NOT_FOUND".to_string())
.to_string();
let user_agent: String = req
.headers()
.get("User-Agent")
.and_then(|v| v.to_str().ok())
.unwrap_or_else(|| "NOT_FOUND")
.to_string();
if user_agent
== "Better Stack Better Uptime Bot Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
{
return json!({});
}
let time: u64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_else(|_| std::time::Duration::new(0, 0))
.as_secs();
let host: String = req
.headers()
.get("Host")
.and_then(|v| v.to_str().ok())
.unwrap_or_else(|| "NOT_FOUND")
.to_string();
let cache_control: String = req
.headers()
.get("Cache-Control")
.and_then(|v| v.to_str().ok())
.unwrap_or_else(|| "NOT_FOUND")
.to_string();
let cached: bool = if cache_control == "no-cache" {
false
} else {
true
};
let request_data: Value = json!({
"object": "request",
"request_id": request_id,
"user_id": user_id,
"company_id": company_id,
"body": body_json,
"query_string": query_string,
"headers": headers,
"method": method,
"path": path,
"http_code": status_http_code,
"ipv4": x_real_ip,
"user_agent": user_agent,
"time": time,
"host": host,
"cached": cached
});
let request_data_clone: Value = request_data.clone();
actix_web::rt::spawn(async move {
if let Ok(client) = supabase().await {
let _ = client
.insert("event_log_api", request_data_clone.clone())
.await;
}
});
request_data
}
pub fn log_event(
directive: Option<String>,
path: Option<String>,
content: Option<String>,
server: Option<String>,
api_version: Option<String>,
severity: Option<String>,
message: Option<String>,
json: Option<serde_json::Value>,
user_id: Option<String>,
company_id: Option<String>,
status: Option<String>,
) {
let time: f64 = chrono::Utc::now().timestamp() as f64;
let event_data: Value = serde_json::json!({
"directive": directive,
"time": time,
"path": path,
"content": content,
"server": server,
"api_version": api_version,
"severity": severity,
"message": message,
"json": json,
"user_id": user_id,
"company_id": company_id,
"status": status,
});
let event_data_clone: Value = event_data.clone();
actix_web::rt::spawn(async move {
if let Ok(client) = supabase().await {
let _ = client.insert("event_log", event_data_clone.clone()).await;
}
});
}
pub fn log_event_v2(
directive: Option<String>,
path: Option<String>,
severity: Option<String>,
message: Option<String>,
json: Option<serde_json::Value>,
user_id: Option<String>,
company_id: Option<String>,
status: Option<String>,
ref_id: Option<String>,
) {
let time: f64 = chrono::Utc::now().timestamp() as f64;
let package_version: String = env!("CARGO_PKG_VERSION").to_string();
let xbp_server: String = std::env::var("XBP_SERVER_HOST").unwrap_or_default();
let event_data: Value = json!({
"directive": directive,
"time": time,
"path": path,
"server": xbp_server,
"api_version": package_version,
"severity": severity,
"message": message,
"json": json,
"user_id": user_id,
"company_id": company_id,
"status": status,
"ref_id": ref_id,
});
let event_data_clone: Value = event_data.clone();
actix_web::rt::spawn(async move {
if let Ok(client) = supabase().await {
let _ = client.insert("event_log", event_data_clone.clone()).await;
}
});
}