feat: enhance logging and dependency management with dotenvy and tracing-subscriber
This commit is contained in:
Generated
+35
-5
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
mod logger;
|
||||
pub mod logger;
|
||||
pub mod bind_filter;
|
||||
pub mod extract_email;
|
||||
pub mod generate_date;
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user