-
Notifications
You must be signed in to change notification settings - Fork 31
Rethink how we handle the integrations with multiple metrics libraries #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think the choice is really between the first and second, as I really can't think of any use case where one would want to collect metrics for multiple libraries. I think the first option is good for applications which are meant to be self-hosted/used by a end-user, not the developers themselves. That would give power to the application developers to give end users the ability to switch between the metrics library used and configuring it without writing whacky code. The second option sounds also good though. In the Rust ecosystem there are a lot of crates which have mutually-exclusively feature flags, most notably sqlx. If we document this behavior correctly, we should be fine, something along the lines of: #[cfg(not(any(feature = "abc", feature = "xyz")))]
compile_error!("select either feature abc or xyz"); However, we must take care of maintaining a somehow similar API interface between the clients, else our docs will end up being really, really confusing. Option one gives us the best flexibility, but option two gives us the best API interface and thus developer usage (with the risk of having confusing documentation). Considering the prospect that Autometrics will continue to grow, I would go with the first option, as this gives us separation already early in the project (and is easier to maintain). |
Good points. Maybe we can use both the first and second ideas in the following way:
I think all of this would work. The only thing I'm doubting now is whether we want the library-specific tracker thing to be part of the crate's public API. We may have reasons to change that and we have more flexibility if we consider it part of the private API that's only meant to be used by the macro. 🤔 |
I'm always afraid of building packages that have mutually exclusive features because of feature unification but I suppose autometrics is only targetting end applications so there's probably going to be a single instance of it in the dependency tree. I don't really have an opinion on the |
That's a good point about feature unification. I guess it would still be okay as long as any libraries that include autometrics don't pick one of the metrics libraries (and we made it so it would still compile even if you don't) |
To date, we've abstracted away the differences between the underlying metrics libraries in the tracker module. We implement the
TrackMetrics
trait for each metrics library and then export the specific implementation asautometrics::__private::AutometricsTracker
(renaming it from its library-specific struct name), depending on which feature flag(s) you have enabled. Theautometrics
macro generates code that uses theAutometricsTracker
struct.This works okay as long as every library has a close enough API that we don't need to expose library-specific things. However, that changes a bit with the
prometheus-client
support (#25 and #88), because we need to expose a handle to theRegistry
. We can simply expose that as a top-level export from the crate, but it seems somewhat likely that the list of things in this category will grow.The other thing that's a bit odd with how we're currently handling things is the precedence order for the feature flags related to the metrics libraries. We currently allow multiple to be set and then use an arbitrary order for which should take precedence. It seems like this can cause somewhat unexpected behavior, because it's not obvious from the outside which library would take precedence.
Some options we have for resolving these issues:
integrations::prometheus
,integrations::prometheus_client
, etcopentelemetry
as the default and make it clear in the docs that you need to pick which underlying library it's going to use. We can have examples in the docs that use one so that would serve as an informal defaultThoughts?
The text was updated successfully, but these errors were encountered: