feat: enhance logging and dependency management with dotenvy and tracing-subscriber

This commit is contained in:
MythEclipse
2025-07-31 15:42:15 +07:00
parent 83e765f358
commit ac06224ed1
9 changed files with 123 additions and 31 deletions
Generated
+35 -5
View File
@@ -2165,6 +2165,7 @@ dependencies = [
"axum",
"axum-test",
"chrono",
"dotenvy",
"imphnen-entities",
"imphnen-libs",
"rand 0.9.1",
@@ -2174,6 +2175,7 @@ dependencies = [
"strum_macros 0.27.1",
"surrealdb",
"tracing",
"tracing-subscriber",
"uuid",
"validator",
]
@@ -2338,7 +2340,7 @@ dependencies = [
"petgraph",
"pico-args",
"regex",
"regex-syntax",
"regex-syntax 0.8.5",
"string_cache",
"term",
"tiny-keccak",
@@ -2352,7 +2354,7 @@ version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553"
dependencies = [
"regex-automata",
"regex-automata 0.4.9",
]
[[package]]
@@ -2518,6 +2520,15 @@ dependencies = [
"syn 2.0.104",
]
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "matchit"
version = "0.8.4"
@@ -3467,8 +3478,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
"regex-automata 0.4.9",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
@@ -3479,9 +3499,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"regex-syntax 0.8.5",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.5"
@@ -4907,10 +4933,14 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
+2
View File
@@ -19,3 +19,5 @@ strum.workspace = true
strum_macros.workspace = true
uuid.workspace = true
tracing.workspace = true
dotenvy = "0.15"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+6 -1
View File
@@ -1,9 +1,14 @@
use tracing::{info};
use surrealdb::engine::any;
use surrealdb::method::Query;
/// Binds a filter value to the query under the key "filter".
pub fn bind_filter_value(
query: Query<'_, any::Any>,
val: String,
) -> Query<'_, any::Any> {
query.bind(("filter", val))
info!(?val, "bind_filter_value called with arguments");
let result = query.bind(("filter", val.clone()));
info!(?val, "bind_filter_value returning query with bound filter");
result
}
+47 -9
View File
@@ -1,17 +1,55 @@
use tracing::{info, error};
use crate::decode_access_token;
use axum::http::{HeaderMap, header::AUTHORIZATION};
/// Extracts the email from the Authorization header, if present and valid.
pub fn extract_email(headers: &HeaderMap) -> Option<String> {
let auth_header = headers.get(AUTHORIZATION)?.to_str().ok()?;
let token = auth_header.strip_prefix("Bearer ")?;
match decode_access_token(token) {
Ok(data) => Some(data.claims.sub),
Err(_e) => None,
}
info!(?headers, "extract_email called with headers");
let auth_header = match headers.get(AUTHORIZATION) {
Some(h) => h,
None => {
error!("Authorization header missing in extract_email");
return None;
}
};
let auth_str = match auth_header.to_str() {
Ok(s) => s,
Err(e) => {
error!(error = ?e, "Failed to convert Authorization header to str in extract_email");
return None;
}
};
let token = match auth_str.strip_prefix("Bearer ") {
Some(t) => t,
None => {
error!(auth_str, "Authorization header does not start with 'Bearer ' in extract_email");
return None;
}
};
info!(token, "Extracted bearer token in extract_email");
match decode_access_token(token) {
Ok(data) => {
info!(email = %data.claims.sub, "Successfully decoded access token in extract_email");
Some(data.claims.sub)
}
Err(e) => {
error!(error = ?e, "Failed to decode access token in extract_email");
None
}
}
}
/// Extracts the email from a JWT token string.
pub fn extract_email_token(token: String) -> Option<String> {
let token_data = decode_access_token(&token).ok()?;
Some(token_data.claims.sub)
info!(token = %token, "extract_email_token called with token");
match decode_access_token(&token) {
Ok(data) => {
info!(email = %data.claims.sub, "Successfully decoded token in extract_email_token");
Some(data.claims.sub)
}
Err(e) => {
error!(error = ?e, "Failed to decode token in extract_email_token");
None
}
}
}
+7 -2
View File
@@ -1,6 +1,11 @@
use tracing::{info};
use chrono::{DateTime, Utc};
/// Returns the current UTC date/time as an RFC3339 string.
pub fn get_iso_date() -> String {
let now: DateTime<Utc> = Utc::now();
now.to_rfc3339()
info!("get_iso_date called");
let now: DateTime<Utc> = Utc::now();
let date_str = now.to_rfc3339();
info!(date_str = %date_str, "get_iso_date returning RFC3339 date string");
date_str
}
+21 -7
View File
@@ -1,15 +1,29 @@
use tracing::{info, error};
use anyhow::{Result, bail};
use surrealdb::sql::Thing;
/// Extracts the table and id from a Thing, returning (&str, &str).
pub fn get_id(thing: &Thing) -> Result<(&str, &str)> {
let table = thing.tb.as_str();
let id = match &thing.id {
surrealdb::sql::Id::String(s) => s.as_str(),
_ => bail!("Unsupported ID type"),
};
Ok((table, id))
info!(?thing, "get_id called with argument");
let table = thing.tb.as_str();
let id = match &thing.id {
surrealdb::sql::Id::String(s) => {
info!(id = %s, "ID extracted as string in get_id");
s.as_str()
}
other => {
error!(?other, "Unsupported ID type in get_id");
bail!("Unsupported ID type");
}
};
info!(table = %table, id = %id, "get_id returning table and id");
Ok((table, id))
}
/// Extracts the raw id string from a Thing.
pub fn extract_id(thing: &Thing) -> String {
thing.id.to_raw()
info!(?thing, "extract_id called with argument");
let raw_id = thing.id.to_raw();
info!(raw_id = %raw_id, "extract_id returning raw id string");
raw_id
}
+1 -1
View File
@@ -1,4 +1,4 @@
mod logger;
pub mod logger;
pub mod bind_filter;
pub mod extract_email;
pub mod generate_date;
+1 -3
View File
@@ -1,14 +1,12 @@
//! Logger initialization using tracing, tracing-subscriber, and dotenvy.
use std::env;
use dotenvy::dotenv;
use tracing_subscriber::{EnvFilter, fmt};
/// Initializes the logger using tracing and tracing-subscriber.
/// Loads environment variables from `.env` and sets log level from `RUST_LOG`.
pub fn init_logger() {
// Load .env file if present
dotenv().ok();
// Set up the tracing subscriber with EnvFilter from RUST_LOG
let filter = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("warn"))
+3 -3
View File
@@ -163,7 +163,7 @@ test_server_connection() {
clear_database() {
write_test_log "INFO" "Membersihkan database via WebSocket..."
if ! cargo run --bin clear_db_test --release; then
if ! RUST_LOG=debug cargo run --bin clear_db_test --release; then
write_test_log "ERROR" "Gagal membersihkan database."
exit 1
fi
@@ -776,7 +776,7 @@ if [ "$START_SERVER" = true ]; then
exit 1
fi
printf "${YELLOW}Memulai server backend...${NC}\n"
cargo run --bin api &
RUST_LOG=debug cargo run --bin api &
SERVER_PID=$!
printf "${YELLOW}Menunggu server siap...${NC}\n"
@@ -803,7 +803,7 @@ fi
clear_database
printf "\n${CYAN}=== Menjalankan Seeders ===${NC}\n"
if ! cargo run --bin seeder; then
if ! RUST_LOG=debug cargo run --bin seeder; then
write_test_log "ERROR" "Gagal menjalankan seeder roles permissions."
exit 1
fi