-
Notifications
You must be signed in to change notification settings - Fork 821
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
feat(sdk-metrics-base) Add pull controller #2517
Conversation
@Sobuno thanks for the contribution. I see you structured this based on a comment that I made, but I made that comment quite a while ago and the spec has changed a lot since then. Have you read the spec to ensure this change matches the latest state? Please make sure to sign the CLA |
Per https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#metricexporter regarding Pull Metric Exporters: "Implementors MAY choose the best idiomatic design for their language." - the spec generally doesn't limit the design choices for Pull Metric Exporters, so I believe it should be in-spec. I have signed the CLA now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any tests for this, nor do I see any documentation or examples of its use.
In general, I don't think it's a badly flawed idea, but I think the metric export pipeline in general would do well to have a design review while we still can and ensure it is flexible enough to meet our needs while being maintained long term. I'm not sure this is the route I would go in today. It might end up being what we do, but I think this is a good opportunity to explore other options as well.
return this.collect(); | ||
} | ||
|
||
public async collect(): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is collect
public? I don't see it called anywhere. Is it expected to be called by exporters? If so, isn't it a little odd that calling the controller causes the controller to call the exporter? Seems like an unnecessarily convoluted export chain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was to keep implementing a push-based versus pull-based exporter very similar, only difference being the added function registerPullCollector and having the exporter invoke the collect function itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you looked at implementations in other languages like python and go to see what they're doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't really looked around much as I found your comment and figured that sounded pretty simple :) I will take a look around if I find the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a look at the Go implementation (https://github.com/open-telemetry/opentelemetry-go/blob/main/sdk/metric/controller/basic/controller.go)
They have a single Controller that has (among others) Start
, Collect
and ForEach
exposed - Start
starts the periodic calling of Collect
whereas Collect
itself collects the metrics and pushes them to the exporter (if one is defined), so basically the same pattern as above. ForEach
"calls the passed function once per instrumentation library, allowing the caller to emit metrics grouped by the library that produced them."
They differ in that I do not see a way for the exporter to obtain a handle on the Collector (as I've done through the registerPullController function) - Indeed, the Go Prometheus Exporter explicitly states it does not implement the metric.Exporter interface, but instead itself creates a pull controller (https://github.com/open-telemetry/opentelemetry-go/blob/main/exporters/prometheus/prometheus.go#L41) and calls Collect, followed by ForEach whenever the HTTP endpoint is invoked.
If we were to follow their design more closely, we should have one Collector with public Start, Collect and ForEach methods. I do not see a simple way other than the aforementioned registerPullController
to expose a handle to the Collector though - What the Go Prometheus Exporter does is basically set its internal Controller as the MetricsProvider, but we do not expose that as an option in the NodeSDKConfiguration.
Regarding examples, I was considering changing the Prometheus Exporter to use this - wasn't sure if you wanted that separated into another PR. Wasn't sure on the testing policy for experimental packages - at least the linting command on the overall project (as listed in the contribution document mentioned when creating a PR) doesn't seem to run on these packages. |
Splitting the experimental packages into their own directory was done only recently so some packages could be released as 1.0. The testing and linting requirements are not changed. Thanks for letting me know the lint isnt running on the experimental packages. I'll look into it. |
In the latest spec, there is a |
Which problem is this PR solving?
Fixes #796
This PR introduces a Pull Controller. In contrast to the Push Controller which collects metrics at a fixed interval, this controller leaves the decision of when to collect to the MetricExporter. The implementation is based on @dyladan's comment here: #796 (comment). This kind of controller is great for e.g. a Prometheus exporter as Prometheus is generally pull-based (Except for their Pushgateway)
Short description of the changes
An optional function
registerPullController
can be defined on the MetricExporter. If defined, a PullController is created instead of a PushController. The MetricExporter must then itself callcollect
on the PullController to collect metrics when needed.