(Pre-RFC) Add std::error::Error::identifier()

With Backtrace support on Error (finally) being implemented, there is one addition to std::error::Error I would really like to see:

a method providing an identifier for an error.

This is useful in all kinds of scenarios, but I personally want it mostly for filtering or alerting in log aggregation systems.

I know there has been some interest in this from @mitsuhiko as well, and this seems to me like a useful and rather uncontroversial change.

How do others feel about it?

pub trait Error {
    ...

    fn identifier(&self) -> Option<String> {
        None
    }
}

Questions

Return Type

  • The most conservative option would be &str, but that would also make it hard to return a computed identifier.
  • String could introduce redundant allocations (which probably wouldn't be an issue here though)
  • Cow<'static, str> allows skipping the allocation, but is a bit more complicated

Both String and Cow would prevent the method from being available in core though, if Error ever makes it there.

Default impl

There could be a default impl that returns either just the type name, or module_path::ErrorType. EG std::io::Error for the io error.

Seems like this should be doable with std::intrinsics::type_name() (and std::module_path!()).

I would find this really convenient, since it would give a unique error identifier by default.

It could be somewhat unexpected though.

Also, both variants have issues:

  • just the type name would produce a lot of noise, since a lot of errors enums are just named Error

  • Including the module path would also be confusing with re-exports coming in to the mix, since an error might live in a private module, being publicly re-exported somewhere else. Then private module paths would appear in error logs.

Skip RFC?

Does such a small change actually need the full RFC process? It could be approved by the libs team, like other small method additions are on a quite often. (Don't know if this can extend to such prominent traits though).

1 Like

How does this differ from the more general concept of a context?

I see it would be useful for Sentry, but what else?

For example, I use error identifiers to implement error localization, but that also requires arguments for the formatting string. If I have to add arguments, I may as well use another trait.

macOS (Cocoa and older) has error identifiers, but they are a pair of numeric error ID and an error domain. Rustc uses numeric identifiers too. You could encode them in the string, but would you expect to parse that string to get the original info back?

How do you ensure uniqueness? It seems that any implementation, which isn't the default type path, would have to worry about colliding. You'd need to suggest some namespacing microsyntax in there. Always the crate name? Maybe a Java-style reverse domain name?

1 Like