schemas_v1_api_logging_mod - OmniCloudOrg/OmniOrchestrator GitHub Wiki
Path: src/schemas/v1/api/logging/mod.rs
- enum LogLevel
- struct LogEntry
- struct LogResponse
- struct Pagination
- struct BulkLogInsert
- async fn init_clickhouse_db
- async fn list_logs
- async fn list_platform_logs
- async fn list_org_logs
- async fn list_app_logs
- async fn list_instance_logs
- async fn insert_logs
- fn routes
pub enum LogLevel {
Debug,
Info,
Warn,
Error,
Fatal,
}
pub struct LogEntry {
pub log_id: Option<String>, // Optional, will generate if missing
pub timestamp: DateTime<Utc>,
pub platform_id: String,
pub org_id: String,
pub app_id: String,
pub instance_id: String,
pub level: LogLevel,
pub message: String,
pub context: serde_json::Value, // Structured JSON context
}
pub struct LogResponse {
pub log_id: String,
pub timestamp: DateTime<Utc>,
pub platform_id: String,
pub org_id: String,
pub app_id: String,
pub instance_id: String,
pub level: String, // String for API response
pub message: String,
pub context: serde_json::Value, // Structured JSON context
}
pub struct Pagination {
pub page: i64,
pub per_page: i64,
pub total_count: i64,
pub total_pages: i64,
}
pub struct BulkLogInsert {
pub logs: Vec<LogEntry>,
}
pub async fn init_clickhouse_db(client: &Client, schema_path: &str) -> Result<(), clickhouse::error::Error> {
// Read the SQL schema file
let schema_sql = match fs::read_to_string(schema_path) {
Ok(content) => content,
Err(e) => {
eprintln!("Failed to read schema file: {}", e);
return Err(clickhouse::error::Error::Custom(format!("Failed to read schema file: {}", e)));
}
};
// Proper SQL parsing: Split by semicolons and handle each statement carefully
let statements: Vec<String> = schema_sql
.split(';')
.map(|s| s.trim())
.filter(|s| !s.is_empty() && !s.starts_with("--"))
.map(|s| s.to_string())
.collect();
println!("Found {} SQL statements to execute", statements.len());
// Execute each statement separately
// ... function definition continues
// ... function body
}
pub async fn list_logs(
page: Option<i64>,
per_page: Option<i64>,
platform_id: Option<String>,
org_id: Option<String>,
app_id: Option<String>,
instance_id: Option<String>,
level: Option<String>,
start_time: Option<String>,
end_time: Option<String>,
search: Option<String>,
clickhouse: &State<Client>,
) -> Result<Json<Value>, (Status, Json<Value>)> {
// Default pagination values
let page = page.unwrap_or(1);
let per_page = per_page.unwrap_or(50);
if page < 1 || per_page < 1 || per_page > 1000 {
return Err((
Status::BadRequest,
Json(json!({
// ... function body
}
pub async fn list_platform_logs(
platform_id: String,
page: Option<i64>,
per_page: Option<i64>,
level: Option<String>,
start_time: Option<String>,
end_time: Option<String>,
search: Option<String>,
clickhouse: &State<Client>,
) -> Result<Json<Value>, (Status, Json<Value>)> {
list_logs(
page,
per_page,
Some(platform_id),
None,
None,
None,
level,
start_time,
end_time,
search,
// ... function definition continues
// ... function body
}
pub async fn list_org_logs(
org_id: String,
page: Option<i64>,
per_page: Option<i64>,
platform_id: Option<String>,
level: Option<String>,
start_time: Option<String>,
end_time: Option<String>,
search: Option<String>,
clickhouse: &State<Client>,
) -> Result<Json<Value>, (Status, Json<Value>)> {
list_logs(
page,
per_page,
platform_id,
Some(org_id),
None,
None,
level,
start_time,
end_time,
// ... function definition continues
// ... function body
}
pub async fn list_app_logs(
app_id: String,
page: Option<i64>,
per_page: Option<i64>,
platform_id: Option<String>,
org_id: Option<String>,
level: Option<String>,
start_time: Option<String>,
end_time: Option<String>,
search: Option<String>,
clickhouse: &State<Client>,
) -> Result<Json<Value>, (Status, Json<Value>)> {
list_logs(
page,
per_page,
platform_id,
org_id,
Some(app_id),
None,
level,
start_time,
// ... function definition continues
// ... function body
}
pub async fn list_instance_logs(
instance_id: String,
page: Option<i64>,
per_page: Option<i64>,
platform_id: Option<String>,
org_id: Option<String>,
app_id: Option<String>,
level: Option<String>,
start_time: Option<String>,
end_time: Option<String>,
search: Option<String>,
clickhouse: &State<Client>,
) -> Result<Json<Value>, (Status, Json<Value>)> {
list_logs(
page,
per_page,
platform_id,
org_id,
app_id,
Some(instance_id),
level,
// ... function definition continues
// ... function body
}
pub async fn insert_logs(
log_batch: Json<BulkLogInsert>,
clickhouse: &State<Client>,
) -> Result<Json<Value>, (Status, Json<Value>)> {
let logs = log_batch.into_inner().logs;
if logs.is_empty() {
return Ok(Json(json!({
"status": "success",
"message": "No logs to insert",
"count": 0
})));
}
// FIX: Use individual inserts instead of tuples to avoid the Row trait limitation
let mut inserted_count = 0;
// Start a transaction
let _tx = clickhouse.query("BEGIN TRANSACTION").execute().await;
for mut log in logs {
// ... function body
}
pub fn routes() -> Vec<rocket::Route> {
routes![
list_logs,
list_platform_logs,
list_org_logs,
list_app_logs,
list_instance_logs,
insert_logs
]
// ... function body
}