use std::{env, error::Error, fmt};
use backtrace;
use lambda_runtime_client::error;
use serde_json;
#[derive(Debug, Clone)]
pub struct RuntimeError {
msg: String,
stack_trace: Option<backtrace::Backtrace>,
pub(crate) request_id: Option<String>,
pub(crate) recoverable: bool,
}
impl RuntimeError {
pub(crate) fn unrecoverable(msg: &str) -> RuntimeError {
let mut new_error = RuntimeError::new(msg);
new_error.recoverable = false;
new_error
}
pub(crate) fn new(msg: &str) -> RuntimeError {
let mut trace: Option<backtrace::Backtrace> = None;
let is_backtrace = env::var("RUST_BACKTRACE");
if is_backtrace.is_ok() && is_backtrace.unwrap() == "1" {
trace!("Begin backtrace collection");
trace = Option::from(backtrace::Backtrace::new());
trace!("Completed backtrace collection");
}
RuntimeError {
msg: String::from(msg),
stack_trace: trace,
recoverable: true,
request_id: None,
}
}
}
impl error::RuntimeApiError for RuntimeError {
fn to_response(&self) -> error::ErrorResponse {
let backtrace = format!("{:?}", self.stack_trace);
error::ErrorResponse {
error_message: String::from(self.description()),
error_type: String::from(error::ERROR_TYPE_HANDLED),
stack_trace: Option::from(backtrace.lines().map(|s| s.to_string()).collect::<Vec<String>>()),
}
}
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl Error for RuntimeError {
fn description(&self) -> &str {
&self.msg
}
fn cause(&self) -> Option<&Error> {
None
}
}
impl From<env::VarError> for RuntimeError {
fn from(e: env::VarError) -> Self {
RuntimeError::unrecoverable(e.description())
}
}
impl From<serde_json::Error> for RuntimeError {
fn from(e: serde_json::Error) -> Self {
RuntimeError::unrecoverable(e.description())
}
}
impl From<error::ApiError> for RuntimeError {
fn from(e: error::ApiError) -> Self {
let mut err = RuntimeError::new(e.description());
err.recoverable = e.recoverable;
err.stack_trace = e.backtrace;
err
}
}
#[derive(Debug, Clone)]
pub struct HandlerError {
msg: String,
backtrace: Option<backtrace::Backtrace>,
}
impl fmt::Display for HandlerError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl Error for HandlerError {
fn description(&self) -> &str {
&self.msg
}
fn cause(&self) -> Option<&Error> {
None
}
}
impl HandlerError {
pub(crate) fn new(msg: &str, trace: Option<backtrace::Backtrace>) -> HandlerError {
HandlerError {
msg: msg.to_string(),
backtrace: trace,
}
}
}
impl error::RuntimeApiError for HandlerError {
fn to_response(&self) -> error::ErrorResponse {
let backtrace = format!("{:?}", self.backtrace);
error::ErrorResponse {
error_message: String::from(self.description()),
error_type: String::from(error::ERROR_TYPE_HANDLED),
stack_trace: Option::from(backtrace.lines().map(|s| s.to_string()).collect::<Vec<String>>()),
}
}
}