Custom trait method not executing "automatically"

Hi everyone,

I'm working on an Actix Web project and I have a custom error enum: XibendError. I don't think the error definition is important here, I will just say that it derives the Debug and thiserror::Error traits. Since I'm using Actix, I have implemented the actix_web::ResponseError for my custom error enum, like this:

impl ResponseError for XibendError {
    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code())
            .insert_header(ContentType::json())
            .json(json!({"error": format!("{}", self)}))
    }

    fn status_code(&self) -> StatusCode {
        match self {
            Self::IDNotFound
            | Self::InvalidEndpoint 
            | Self::BannerNotFound => StatusCode::NOT_FOUND,
            _ => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }
}

This implementation code runs "automatically" (meaning I never call it manually - at least as far as I'm aware) every time there is an error and handles the error properly, no problem there. However, I tried to write my own trait for logging the error using the tracing::error macro. Here is the trait and the implementation:

trait ErrorLogger: std::fmt::Debug + std::fmt::Display {
    fn log_error(&self);
}

impl ErrorLogger for XibendError {
    fn log_error(&self) {
        error!("{}", self)
    }
}

As you can see, the trait consists of a single method which should log the error. The problem is, nothing is ever logged. This might a super stupid question since I am very new to traits. Still, I can't help but wonder why the ResponseError trait code executes "automatically" but mine doesn't?

Why would you expect it to be called automatically, in the first place?

With the exception of main, no function is ever called "automatically" – something has to call them. (This hasn't got anything to do with traits.)

ResponseError's methods are called when actix-web returns a response from one of your functions. actix-web uses the Responder trait to turn the things that your request handler functions (the things you call .route(...) with) return into HTTP responses that it can send back to the clients. The docs note that

It is often not required to implement Responder for your own types due to a broad base of built-in implementations:

[...]

Meaning Responder is implemented for Results where the error inside Err implements ResponseError (and the Ok variant implements Responder). When you return an error (via Result) from a handler, actix-web uses the ResponseError trait to turn the error into a HTTP response. actix-web doesn't know anything about ErrorLogger, so it won't call its methods.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.