yeah, that's annoying, but that's somewhat to be expected: rust doesn't have builtin runtime reflection by design, (think java
System.Reflection, etc), libraries have to pick some mechanism to do runtime inspection if they want to support arbitrary user defined types, and being generic isn't always feasible.
in the case of
tracing, the trade off (between usability and flexibility) is, in most common cases, you can record your custom type with the string representation through
Debug; but you still have the option to control how the inspection should behave through
Valuable if the former doesn't suit your need.
personally, I think this design is good enough, as I barely need to record very complicated states into traces, and
Valuable isn't too hard to incorporate into my own code. altough the
valuable feature is explicitly stated to be unstable API, I don't see it will be ditched very soon, after all, they need to support some form of runtime inspection anyway. yeah, visitor pattern is OO, and I don't like it, but that's what we have today.
serde is a perfectly valid option if
Display) is not suitable. and personally I would not worry about the performance in such cases.
for one thing, the
tracing crate employs many tricks to keep the overhead as low as possible, for instance, each
event!() invocation is conditional executed, guarded by looking up through a
Callsite object, and the fast path, when the callsite is disabled, is just a relaxed atomic load followed by a single branch instruction;
on the other hand, I barely instrument performance critical code paths (inside tight loops), and use mostly
TRACE level if I have to, since I like to disable
TRACE level in release builds using "release_max_level_debug" feature flag.