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",
|
||||||
"axum-test",
|
"axum-test",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"dotenvy",
|
||||||
"imphnen-entities",
|
"imphnen-entities",
|
||||||
"imphnen-libs",
|
"imphnen-libs",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
@@ -2174,6 +2175,7 @@ dependencies = [
|
|||||||
"strum_macros 0.27.1",
|
"strum_macros 0.27.1",
|
||||||
"surrealdb",
|
"surrealdb",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
"validator",
|
"validator",
|
||||||
]
|
]
|
||||||
@@ -2338,7 +2340,7 @@ dependencies = [
|
|||||||
"petgraph",
|
"petgraph",
|
||||||
"pico-args",
|
"pico-args",
|
||||||
"regex",
|
"regex",
|
||||||
"regex-syntax",
|
"regex-syntax 0.8.5",
|
||||||
"string_cache",
|
"string_cache",
|
||||||
"term",
|
"term",
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
@@ -2352,7 +2354,7 @@ version = "0.20.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553"
|
checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"regex-automata",
|
"regex-automata 0.4.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2518,6 +2520,15 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"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]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@@ -3467,8 +3478,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata 0.4.9",
|
||||||
"regex-syntax",
|
"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]]
|
[[package]]
|
||||||
@@ -3479,9 +3499,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"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]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -4907,10 +4933,14 @@ version = "0.3.19"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -19,3 +19,5 @@ strum.workspace = true
|
|||||||
strum_macros.workspace = true
|
strum_macros.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
tracing.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::engine::any;
|
||||||
use surrealdb::method::Query;
|
use surrealdb::method::Query;
|
||||||
|
|
||||||
|
/// Binds a filter value to the query under the key "filter".
|
||||||
pub fn bind_filter_value(
|
pub fn bind_filter_value(
|
||||||
query: Query<'_, any::Any>,
|
query: Query<'_, any::Any>,
|
||||||
val: String,
|
val: String,
|
||||||
) -> Query<'_, any::Any> {
|
) -> 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 crate::decode_access_token;
|
||||||
use axum::http::{HeaderMap, header::AUTHORIZATION};
|
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> {
|
pub fn extract_email(headers: &HeaderMap) -> Option<String> {
|
||||||
let auth_header = headers.get(AUTHORIZATION)?.to_str().ok()?;
|
info!(?headers, "extract_email called with headers");
|
||||||
let token = auth_header.strip_prefix("Bearer ")?;
|
let auth_header = match headers.get(AUTHORIZATION) {
|
||||||
|
Some(h) => h,
|
||||||
match decode_access_token(token) {
|
None => {
|
||||||
Ok(data) => Some(data.claims.sub),
|
error!("Authorization header missing in extract_email");
|
||||||
Err(_e) => None,
|
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> {
|
pub fn extract_email_token(token: String) -> Option<String> {
|
||||||
let token_data = decode_access_token(&token).ok()?;
|
info!(token = %token, "extract_email_token called with token");
|
||||||
Some(token_data.claims.sub)
|
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};
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
/// Returns the current UTC date/time as an RFC3339 string.
|
||||||
pub fn get_iso_date() -> String {
|
pub fn get_iso_date() -> String {
|
||||||
let now: DateTime<Utc> = Utc::now();
|
info!("get_iso_date called");
|
||||||
now.to_rfc3339()
|
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 anyhow::{Result, bail};
|
||||||
use surrealdb::sql::Thing;
|
use surrealdb::sql::Thing;
|
||||||
|
|
||||||
|
/// Extracts the table and id from a Thing, returning (&str, &str).
|
||||||
pub fn get_id(thing: &Thing) -> Result<(&str, &str)> {
|
pub fn get_id(thing: &Thing) -> Result<(&str, &str)> {
|
||||||
let table = thing.tb.as_str();
|
info!(?thing, "get_id called with argument");
|
||||||
let id = match &thing.id {
|
let table = thing.tb.as_str();
|
||||||
surrealdb::sql::Id::String(s) => s.as_str(),
|
let id = match &thing.id {
|
||||||
_ => bail!("Unsupported ID type"),
|
surrealdb::sql::Id::String(s) => {
|
||||||
};
|
info!(id = %s, "ID extracted as string in get_id");
|
||||||
Ok((table, 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 {
|
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 bind_filter;
|
||||||
pub mod extract_email;
|
pub mod extract_email;
|
||||||
pub mod generate_date;
|
pub mod generate_date;
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
//! Logger initialization using tracing, tracing-subscriber, and dotenvy.
|
|
||||||
use std::env;
|
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use tracing_subscriber::{EnvFilter, fmt};
|
use tracing_subscriber::{EnvFilter, fmt};
|
||||||
|
|
||||||
/// Initializes the logger using tracing and tracing-subscriber.
|
/// Initializes the logger using tracing and tracing-subscriber.
|
||||||
/// Loads environment variables from `.env` and sets log level from `RUST_LOG`.
|
/// Loads environment variables from `.env` and sets log level from `RUST_LOG`.
|
||||||
pub fn init_logger() {
|
pub fn init_logger() {
|
||||||
// Load .env file if present
|
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
|
|
||||||
|
|
||||||
// Set up the tracing subscriber with EnvFilter from RUST_LOG
|
// Set up the tracing subscriber with EnvFilter from RUST_LOG
|
||||||
let filter = EnvFilter::try_from_default_env()
|
let filter = EnvFilter::try_from_default_env()
|
||||||
.or_else(|_| EnvFilter::try_new("warn"))
|
.or_else(|_| EnvFilter::try_new("warn"))
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ test_server_connection() {
|
|||||||
|
|
||||||
clear_database() {
|
clear_database() {
|
||||||
write_test_log "INFO" "Membersihkan database via WebSocket..."
|
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."
|
write_test_log "ERROR" "Gagal membersihkan database."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -776,7 +776,7 @@ if [ "$START_SERVER" = true ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
printf "${YELLOW}Memulai server backend...${NC}\n"
|
printf "${YELLOW}Memulai server backend...${NC}\n"
|
||||||
cargo run --bin api &
|
RUST_LOG=debug cargo run --bin api &
|
||||||
SERVER_PID=$!
|
SERVER_PID=$!
|
||||||
|
|
||||||
printf "${YELLOW}Menunggu server siap...${NC}\n"
|
printf "${YELLOW}Menunggu server siap...${NC}\n"
|
||||||
@@ -803,7 +803,7 @@ fi
|
|||||||
clear_database
|
clear_database
|
||||||
|
|
||||||
printf "\n${CYAN}=== Menjalankan Seeders ===${NC}\n"
|
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."
|
write_test_log "ERROR" "Gagal menjalankan seeder roles permissions."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user