diff --git a/bin/inx-chronicle/src/api/error.rs b/bin/inx-chronicle/src/api/error.rs index 60876758b..0ddffbe1c 100644 --- a/bin/inx-chronicle/src/api/error.rs +++ b/bin/inx-chronicle/src/api/error.rs @@ -7,6 +7,7 @@ use axum::{ extract::rejection::{ExtensionRejection, QueryRejection, TypedHeaderRejection}, response::IntoResponse, }; +use chronicle::runtime::ErrorLevel; use hyper::{header::InvalidHeaderValue, StatusCode}; use mongodb::bson::document::ValueAccessError; use serde::Serialize; @@ -89,6 +90,8 @@ impl ApiError { } } +impl ErrorLevel for ApiError {} + impl> From for ApiError { fn from(err: T) -> Self { ApiError::Internal(err.into()) diff --git a/bin/inx-chronicle/src/launcher.rs b/bin/inx-chronicle/src/launcher.rs index 0b5a42a39..f68fc95ee 100644 --- a/bin/inx-chronicle/src/launcher.rs +++ b/bin/inx-chronicle/src/launcher.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use chronicle::{ db::MongoDb, - runtime::{Actor, ActorContext, ActorError, HandleEvent, Report, RuntimeError}, + runtime::{Actor, ActorContext, ActorError, ErrorLevel, HandleEvent, Report, RuntimeError}, }; use clap::Parser; use thiserror::Error; @@ -26,6 +26,15 @@ pub enum LauncherError { Runtime(#[from] RuntimeError), } +impl ErrorLevel for LauncherError { + fn level(&self) -> log::Level { + match self { + LauncherError::Config(_) | LauncherError::MongoDb(_) => log::Level::Error, + LauncherError::Runtime(_) => log::Level::Warn, + } + } +} + #[derive(Debug)] /// Supervisor actor pub struct Launcher; diff --git a/bin/inx-chronicle/src/stardust_inx/error.rs b/bin/inx-chronicle/src/stardust_inx/error.rs index 8eb6aba60..16ec5203d 100644 --- a/bin/inx-chronicle/src/stardust_inx/error.rs +++ b/bin/inx-chronicle/src/stardust_inx/error.rs @@ -1,7 +1,7 @@ // Copyright 2022 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use chronicle::types::tangle::MilestoneIndex; +use chronicle::{runtime::ErrorLevel, types::tangle::MilestoneIndex}; use thiserror::Error; #[derive(Debug, Error)] @@ -27,3 +27,16 @@ pub enum InxError { #[error(transparent)] Tonic(#[from] inx::tonic::Error), } + +impl ErrorLevel for InxError { + fn level(&self) -> log::Level { + match self { + Self::InvalidAddress(_) + | Self::InxTypeConversion(_) + | Self::MongoDb(_) + | Self::NetworkChanged(_, _) + | Self::ParsingAddressFailed(_) => log::Level::Error, + _ => log::Level::Warn, + } + } +} diff --git a/src/runtime/actor/mod.rs b/src/runtime/actor/mod.rs index e47d3c74b..e961ebbe9 100644 --- a/src/runtime/actor/mod.rs +++ b/src/runtime/actor/mod.rs @@ -16,12 +16,13 @@ pub(crate) mod sender; /// Module containing utilities. pub(crate) mod util; -use std::{borrow::Cow, error::Error}; +use std::borrow::Cow; use async_trait::async_trait; use futures::StreamExt; use self::context::ActorContext; +use super::error::ErrorLevel; /// The actor trait, which defines a task that is managed by the runtime. #[async_trait] @@ -29,7 +30,7 @@ pub trait Actor: Send + Sync + Sized { /// Custom data that is passed to all actor methods. type State: Send; /// Custom error type that is returned by all actor methods. - type Error: Error + Send; + type Error: ErrorLevel + Send; /// Set this actor's name, primarily for debugging purposes. fn name(&self) -> Cow<'static, str> { diff --git a/src/runtime/error.rs b/src/runtime/error.rs index 6dd07d91d..effebf2d7 100644 --- a/src/runtime/error.rs +++ b/src/runtime/error.rs @@ -14,16 +14,24 @@ pub enum RuntimeError { AbortedScope(ScopeId), #[error("Actor exited with error: {0}")] ActorError(String), - #[error("Dependency notification canceled")] - CanceledDepNotification, - #[error("Invalid scope")] - InvalidScope, - #[error("Missing dependency: {0}")] - MissingDependency(String), #[error("Error launching scope: {0}")] ScopeLaunchError(Box), #[error(transparent)] SendError(#[from] SendError), - #[error("Task exited with error: {0}")] - TaskError(Box), } + +/// Defines an error's log level. +pub trait ErrorLevel: Error { + /// Returns the log level for this error. + fn level(&self) -> log::Level { + log::Level::Error + } +} + +impl ErrorLevel for RuntimeError { + fn level(&self) -> log::Level { + log::Level::Warn + } +} + +impl ErrorLevel for std::convert::Infallible {} diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 259e1af1f..a9c6100fa 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -36,7 +36,7 @@ pub use self::{ Actor, }, config::{ConfigureActor, SpawnConfig}, - error::RuntimeError, + error::{ErrorLevel, RuntimeError}, scope::{RuntimeScope, ScopeView}, task::{error::TaskError, report::TaskReport, Task}, }; diff --git a/src/runtime/scope.rs b/src/runtime/scope.rs index 0f78f96d0..ef5d0d380 100644 --- a/src/runtime/scope.rs +++ b/src/runtime/scope.rs @@ -30,7 +30,7 @@ use super::{ }, Sender, }; -use crate::runtime::merge::Merge; +use crate::runtime::{error::ErrorLevel, merge::Merge}; /// A view into a particular scope which provides the user-facing API. #[derive(Clone, Debug)] @@ -236,7 +236,8 @@ impl RuntimeScope { Ok(()) } Err(e) => { - log::warn!( + log::log!( + e.level(), "{} exited with error: {}", format!("Task {:x}", child_scope.id().as_fields().0), e @@ -279,7 +280,7 @@ impl RuntimeScope { Ok(()) } Err(e) => { - log::warn!("{} exited with error: {}", actor.name(), e); + log::log!(e.level(), "{} exited with error: {}", actor.name(), e); let err_str = e.to_string(); supervisor_addr.send(Report::Error(ErrorReport::new( actor, @@ -320,7 +321,7 @@ impl RuntimeScope { Ok(res) => match res { Ok(_) => Ok(()), Err(e) => { - log::warn!("{} exited with error: {}", actor.name(), e); + log::log!(e.level(), "{} exited with error: {}", actor.name(), e); Err(RuntimeError::ActorError(e.to_string())) } }, diff --git a/src/runtime/task/mod.rs b/src/runtime/task/mod.rs index 658add4fc..02c42a646 100644 --- a/src/runtime/task/mod.rs +++ b/src/runtime/task/mod.rs @@ -4,16 +4,18 @@ pub(super) mod error; pub(super) mod report; -use std::{borrow::Cow, error::Error}; +use std::borrow::Cow; use async_trait::async_trait; +use super::error::ErrorLevel; + /// The task trait, which defines a task that is managed by the runtime and requires little to no /// external comunication. #[async_trait] pub trait Task: Send + Sync + Sized { /// Custom error type that is returned by all task methods. - type Error: Error + Send; + type Error: ErrorLevel + Send; /// Set this task's name, primarily for debugging purposes. fn name(&self) -> Cow<'static, str> {