Open bryanlarsen opened 3 months ago
axum-prometheus 0.6.1 does not have this problem.
Don't think this is an issue with axum-prometheus. This error originates from metrics-exporter-prometheus.
0.6.1
does not have this issue, because that code I linked is a very recent change. I'm pretty sure you should file an issue for them.
The documentation for metrics-exporter-prometheus' PrometheusBuilder indicates that it opens port 9000 by default, so it's behaving as documented.
Well, axum-prometheus
is clear about using metrics-rs
and its ecosystem, so what could we possibly do in the default implementation? There're plenty of ways to work around this via lower level APIs that give you finer control.. basically just don't use pair/pair_from
and with_default_metrics
functions from this crate. BaseMetricLayer
is completely decoupled from the metric exporter initialization code, and you may perform it as you like.
I'd rather not duplicate the documentation of metrics-exporter-prometheus
in this crate either.
Ah yeah, it looks like this is a consequence of using PrometheusBuilder::build
to ensure the upkeep thread is started, but which also builds an exporter future... which will end up triggered the binding of the port. 😓
I'll have to think a little bit about what a better builder API could look like... because it seems like like this keeps coming up.
I'd rather not duplicate the documentation of
metrics-exporter-prometheus
in this crate either.
It's not documented that http-listener
feature (which overlaps the scope of axum
to me). The documentation gives an example that manually wire the rendering code into a axum
route. That makes me assume that there would be no other listener otherwise.
Could we disable this feature by default, or at least make it possible to be disabled? Downstream users can still enable it if they want (features will merge). But currently, downstream users cannot disable it because it's explicitly enabled via axum-prometheus
.
The reason why this crate changed the defaults is because the upkeep task needs to be started in metrics-exporter-prometheus
in order to prevent unbound histogram growth, see #52 . This led to an unfortunate consequence that metrics-exporter-prometheus
binds the default (or configured) HTTP port.. but that http listener is not used in any way in axum-prometheus
.
It's possible to avoid that if you reach for PrometheusMetricLayerBuilder::with_metrics_from_fn
and construct the PrometheusBuilder
yourself (you either don't care about the upkeep task, or bind a different random port, etc).
I do not intend to disable the http-listener
feature, because the crate has essentially no point if you use it with metrics-exporter-prometheus
, but you have neither http-listener
nor push-gateway
enabled. You have an option to disable the prometheus
feature, which is exactly what people should do if they don't want to work with Prometheus.
As a workaround, I could probably start the http listener explicitly on 127.0.0.1:0
, so that the operating system will choose an available random port, but I don't think that's a viable solution.. I'd rather like to have the root cause fixed.
EDIT: I'll reopen this issue for visibility.
Thanks for the explanation and with_metrics_from_fn
does work for me.
52
In my own setup, I use .build_recorder()
and manually spawn the upkeeping thread (because I want tokio tasks rather than system threads). Also, leaking threads (there is no way to stop it even though all Handle
s are dropped) in Default::default
sounds so dirty. I'd say I don't like the API design for this. If we need to spawn threads, we should use build_recorder
to avoid different behaviors depending on upstream features, and spawn our own upkeeping thread when building PrometheusMetricLayer
(if we want to).
I do not intend to disable the
http-listener
feature, because the crate has essentially no point if you use it withmetrics-exporter-prometheus
, but you have neitherhttp-listener
norpush-gateway
enabled.
Why saying "essentially no point"? I do use metrics-exporter-prometheus
with default features disabled. As mentioned above, I use .build_recorder()
, spawning my own upkeeping thread and run axum
for serving the scraping server. It runs perfectly fine and never tries to bind :9000
. Thus I don't think http-listener
is technically required when having axum
.
Why saying "essentially no point"? I do use metrics-exporter-prometheus with default features disabled. As mentioned above, I use .build_recorder(), spawning my own upkeeping thread and run axum for serving the scraping server. It runs perfectly fine and never tries to bind :9000. Thus I don't think http-listener is technically required when having axum.
Oh, maybe I'm just completely off with my mental model. Currently I don't actively use this library, and forgot some stuff. I think it's worth a try then to just disable the default features completely for metrics-exporter-prometheus
. I'm not sure when I'll have the time to really work on this, and figure out whether it is a breaking change.
Would you mind sharing your setup code you're using with axum?
How to reproduce:
netcat -l 9000
)Result:
main.rs for reference, copied from https://docs.rs/axum-prometheus/latest/axum_prometheus/index.html:
Cargo.toml: