feat: add tracing throughout, HTTP TraceLayer, detailed error logs

This commit is contained in:
2026-07-11 21:58:58 +02:00
parent e89cf48b34
commit 2b702d88e4
11 changed files with 60 additions and 13 deletions

View File

@@ -21,13 +21,17 @@ pub async fn execute(deps: &LoginDeps, cmd: LoginCommand) -> Result<LoginResult,
.user_repo
.find_by_email(&email)
.await?
.ok_or_else(|| DomainError::Unauthorized("invalid credentials".into()))?;
.ok_or_else(|| {
tracing::warn!(email = cmd.email, "login attempt with unknown email");
DomainError::Unauthorized("invalid credentials".into())
})?;
let valid = deps
.password_hasher
.verify(&cmd.password, user.password_hash())
.await?;
if !valid {
tracing::warn!(email = cmd.email, "login attempt with wrong password");
return Err(DomainError::Unauthorized("invalid credentials".into()));
}
@@ -44,6 +48,8 @@ pub async fn execute(deps: &LoginDeps, cmd: LoginCommand) -> Result<LoginResult,
};
deps.refresh_repo.create(&session).await?;
tracing::info!(user_id = %user.id().value(), "user logged in");
Ok(LoginResult {
access_token: generated.token,
refresh_token,

View File

@@ -4,5 +4,6 @@ use super::commands::LogoutCommand;
use super::deps::LogoutDeps;
pub async fn execute(deps: &LogoutDeps, cmd: LogoutCommand) -> Result<(), DomainError> {
tracing::debug!("user logged out");
deps.refresh_repo.revoke(&cmd.refresh_token).await
}

View File

@@ -42,6 +42,8 @@ pub async fn execute(
};
deps.refresh_repo.create(&new_session).await?;
tracing::debug!(user_id = %session.user_id.value(), "token refreshed");
Ok(RefreshResult {
access_token: generated.token,
refresh_token: new_refresh_token,

View File

@@ -7,7 +7,10 @@ use super::deps::RegisterDeps;
pub async fn execute(deps: &RegisterDeps, cmd: RegisterCommand) -> Result<(), DomainError> {
if !deps.allow_registration {
return Err(DomainError::Unauthorized("registration is disabled".into()));
tracing::warn!("registration attempt while disabled");
return Err(DomainError::Unauthorized(
"registration is disabled".into(),
));
}
let password = Password::new(&cmd.password)?;
@@ -28,6 +31,9 @@ pub async fn execute(deps: &RegisterDeps, cmd: RegisterCommand) -> Result<(), Do
let hash = deps.password_hasher.hash(password.value()).await?;
let user = User::new(email, username, hash);
tracing::info!(user_id = %user.id().value(), "new user registered");
deps.user_repo.save(&user).await?;
Ok(())

View File

@@ -4,5 +4,7 @@ use super::commands::DeleteSongCommand;
use super::deps::SongCommandDeps;
pub async fn execute(deps: &SongCommandDeps, cmd: DeleteSongCommand) -> Result<(), DomainError> {
deps.repo.delete(cmd.id).await
deps.repo.delete(cmd.id).await?;
tracing::debug!(id = %cmd.id, "song deleted");
Ok(())
}

View File

@@ -8,5 +8,8 @@ pub async fn execute(
deps: &SongCommandDeps,
cmd: SaveSongCommand,
) -> Result<StoredSong, DomainError> {
deps.repo.save(&cmd.song).await
let title = cmd.song.meta.title.clone();
let result = deps.repo.save(&cmd.song).await?;
tracing::debug!(id = %result.id, title, "song saved");
Ok(result)
}

View File

@@ -8,12 +8,15 @@ pub async fn execute(
deps: &SongCommandDeps,
cmd: UpdateSongMetaCommand,
) -> Result<SongSummary, DomainError> {
deps.repo
let result = deps
.repo
.update_meta(
cmd.id,
cmd.title.as_deref(),
cmd.artist.as_deref(),
cmd.original_key.as_deref(),
)
.await
.await?;
tracing::debug!(id = %cmd.id, "song meta updated");
Ok(result)
}

View File

@@ -9,12 +9,14 @@ use super::deps::ParseTabDeps;
pub async fn execute(deps: &ParseTabDeps, cmd: ParseTabCommand) -> Result<Song, DomainError> {
let html = if let Some(raw_html) = cmd.html {
tracing::debug!("parsing from raw HTML input");
Ok(raw_html)
} else if let Some(source) = cmd.source {
let tab_source = if source.starts_with("file://") {
let path = source.trim_start_matches("file://");
TabSource::File(PathBuf::from(path))
} else {
tracing::debug!(url = source, "fetching tab from URL");
TabSource::Url(source)
};
deps.fetcher
@@ -27,7 +29,17 @@ pub async fn execute(deps: &ParseTabDeps, cmd: ParseTabCommand) -> Result<Song,
))
}?;
deps.parser
let song = deps
.parser
.parse(&html)
.map_err(|e| DomainError::InfrastructureError(e.to_string()))
.map_err(|e| DomainError::InfrastructureError(e.to_string()))?;
tracing::debug!(
title = song.meta.title,
artist = song.meta.artist,
sections = song.sections.len(),
"tab parsed"
);
Ok(song)
}