receiver/prometheus: wire up direct pdata conversion mechanism#6421
Conversation
…thout OpenCensus Wire up and use the direct Prometheus->Pdata conversion end to end. With this change the receiver will no longer need OpenCensus. This change will involve more follow-ups that just migrate over the tests, because we don't want a super bloated/massive PR. Fixes open-telemetry#4892 Depends on PR open-telemetry/opentelemetry-collector#3694 Depends on PR open-telemetry/opentelemetry-collector#3695
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…ut-of-order exposition Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…ensus or pdata directly Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
… issues with out-of-order exposition data Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…port paths Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
… copy of opencensus translator during development Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
|
@dashpole can you take a look at this? |
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
8382077 to
598f4a2
Compare
…tor-contrib into receiver-prometheus-wireUp-roundTrip
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
|
Changes outside of |
… suite runtime Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
| BufferCount int `mapstructure:"buffer_count"` | ||
| UseStartTimeMetric bool `mapstructure:"use_start_time_metric"` | ||
| StartTimeMetricRegex string `mapstructure:"start_time_metric_regex"` | ||
| pdataDirect bool |
There was a problem hiding this comment.
It is probably simpler just to use featuregate.IsEnabled(pdataPipelineGate.ID) where it is needed, rather than store it here. Is there a way to set feature gates during a test?
There was a problem hiding this comment.
There is only a global feature gate registry, so it can't necessarily be used in tests. The feature gate registry also has a lock, so we recommend that the feature status is checked once and stored if it is needed repeatedly. There is no mechanism for operators to change feature gate statuses during program runtime, so it should be safe to read this once and re-use it.
…ing test suite runtime" This reverts commit 7e04b44.
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…tor-contrib into receiver-prometheus-wireUp-roundTrip Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…tor-contrib into receiver-prometheus-wireUp-roundTrip
|
Huh, i'm sure why my approval checkmark isn't green. I'm in the code owners entry for the prometheus receiver |
Not sure what's going on there. It doesn't look like there are any files outside In any event, this should have more eyes on it. @anuraaga and @codeboten can I get a review? |
…tor-contrib into receiver-prometheus-wireUp-roundTrip
|
@dashpole apparently to be an effective code owner for review approval purposes you must have write access to the repository:
Though that seems to be contradicted later in the same document:
v0v |
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…tor-contrib into receiver-prometheus-wireUp-roundTrip
There was a problem hiding this comment.
Intense PR did a first lightweight pass. I definitely wasn't expecting this much logic to convert between two metrics formats 😮
High level question, is this embedding functionality from cumulativetodelta? And if so, should it be?
Also, things like metrics GC feel like they'd already be in the OTel SDK. Curious if there's no way to leverage the OTel SDK to do this conversion instead of what may be a lot of similar concepts. I wouldn't imagine there to be a huge penalty in efficiency, but not sure. And also just a wild idea that came to mind, it may not be applicable at all.
| histogram.SetAggregationTemporality(pdata.MetricAggregationTemporalityCumulative) | ||
|
|
||
| destPointL := histogram.DataPoints() | ||
| // By default the AggregationTemporality is Cumulative until it'll be changed by the caller. |
There was a problem hiding this comment.
From what I can tell this is referring to line 53
There was a problem hiding this comment.
I think this comment is either a vestige of a prior pdata API or a misunderstanding by the original author. The default aggregation temporality appears to be unspecified. See https://github.com/open-telemetry/opentelemetry-collector/blob/main/model/pdata/metrics.go#L256-L261. I am removing this comment.
|
|
||
| func gaugeDistMetricPdata(name string, kvp []*kv, startTs pdata.Timestamp, points ...*pdata.HistogramDataPoint) *pdata.Metric { | ||
| hMetric := cumulativeDistMetricPdata(name, kvp, startTs, points...) | ||
| hMetric.Histogram().SetAggregationTemporality(pdata.MetricAggregationTemporalityDelta) |
There was a problem hiding this comment.
From what I understand, all prometheus data is cumulative including gauge, but am likely wrong.
Wondering if there is a reference for the mapping, I searched around and found this doc with a broken link to a design doc. Would help reviewing this PR if there's information about the mapping somewhere
There was a problem hiding this comment.
I'm not actually sure. This is inherited test helper code that seems to be used to test adjustment of gauge histograms, which should never be encountered since the appender won't build them and the metric adjuster will short circuit when encountering a distribution with other than cumulative temporality. I think this can be removed without impacting functionality or test coverage.
| // Get the timeseriesinfo for the timeseries associated with the metric and label values. | ||
| func (tsm *timeseriesMapPdata) get(metric *pdata.Metric, kv pdata.AttributeMap) *timeseriesinfoPdata { | ||
| name := metric.Name() | ||
| sig := getTimeseriesSignaturePdata(name, kv) |
There was a problem hiding this comment.
Maybe better to use a hashed object instead of string for map key
There was a problem hiding this comment.
I think the cloudwatch exporter has a pattern using a Sorted object that could work
There was a problem hiding this comment.
I'm not sure I follow. The pdata.AttributeMap isn't comparable and can't be used as a map key. Since the labels are user-provided and arbitrary I'm not sure we could create a comparable object other than a string from them.
There was a problem hiding this comment.
There's this attribute.Distinct type used here for something similar I think recommended by jmacd a while back
I figure it has at least somewhat better performance than strings
There was a problem hiding this comment.
That is from the Go SDK's attribute package, which is not in use here. These are pdata.AttributeMaps which would require similar conversion to utilize attribute.Distinct.
| tsi = ×eriesinfoPdata{} | ||
| tsm.tsiMap[sig] = tsi | ||
| } | ||
| tsm.mark = true |
There was a problem hiding this comment.
Since gc() uses a lock to access tsi, I'd expect a lock here too, or otherwise atomic write. If it's already locked at a higher level, then a comment could help
There was a problem hiding this comment.
The lock is taken in *MetricsAdjusterPdata.AdjustMetrics(), which is the first exported method encountered when walking up the call stack from all invocations of this method. This is the same as the OpenCensus-based implementation in metrics_adjuster.go that has been in use by this receiver for a long time. I expect that to be the case for most of the comments on this implementation as most of them are in repeated code.
A reworking of this implementation is probably in order, particularly given the issue noted by @dashpole regarding targets that are scraped less frequently than the fixed GC interval. That should probably be handled in a separate issue.
| jm.RLock() | ||
| defer jm.RUnlock() | ||
| if time.Since(jm.lastGC) > jm.gcInterval { | ||
| go jm.gc() |
There was a problem hiding this comment.
If get can be called from multiple threads, I think this can cause gc to be called multiple times concurrently, I suspect that's not intended. Can use a comment if this case can't happen since a simple method like get we'd generally expect to not have any threading guarantees
There was a problem hiding this comment.
The time since the last GC is checked again inside gc() once a lock is obtained. It may be triggered multiple times, but it will still only run once per interval. That's what the comments in this method and in gc() are trying to convey.
| } | ||
|
|
||
| func (jm *JobsMapPdata) get(job, instance string) *timeseriesMapPdata { | ||
| sig := job + ":" + instance |
There was a problem hiding this comment.
Notice above using printf and here using concatenation, I think most code in collector would use printf
| // Returns the total number of timeseries that had reset start times. | ||
| func (ma *MetricsAdjusterPdata) AdjustMetrics(metricL *pdata.MetricSlice) int { | ||
| resets := 0 | ||
| ma.tsm.Lock() |
There was a problem hiding this comment.
It's somewhat mysterious we're locking on tsm here but not accessing it (presumably we are accessing through adjustMetric). Maybe a comment to ensure it was intended
|
|
||
| default: | ||
| // this shouldn't happen | ||
| ma.logger.Info("Adjust - skipping unexpected point", zap.String("type", dataType.String())) |
There was a problem hiding this comment.
This is currently info in the OC metrics adjuster. If anything, since this is a situation that should never occur I might want to make this a warning.
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
…tor-contrib into receiver-prometheus-wireUp-roundTrip
…' into receiver-prometheus-wireUp-roundTrip
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
|
@open-telemetry/collector-contrib-approvers can I get some more eyes on this? We have further work that is held up behind getting these changes landed. Thanks! |
|
Given @Aneurysm9 and @dashpole are codeowners for this component, can we get this PR merged please? Can the permissions be fixed @bogdandrutu @codeboten There are other PRs (14 PRs - 9 tests and 5 bug fixes) that are blocked on this merge. |
…tor-contrib into receiver-prometheus-wireUp-roundTrip
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
anuraaga
left a comment
There was a problem hiding this comment.
I hadn't realized at first that there isn't that much new code here, a lot is copied from the old translation path to allow a feature flag deprecation. So generally good with the code as it seems to be a relatively simple change on top of that - would appreciate some more code comments to verify lock expectations though
…tor-contrib into receiver-prometheus-wireUp-roundTrip
…djuster. Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
|
Hi, thanks for the great work which possibly reduces open-telemetry memory to 50% in a testing cluster. (v0.41 v.s. v0.40) Want to cherry-pick this magic into previous versions. Do we know which small change in this PR is related to reduce agent memory? |
|
@CatherineF-dev I'm afraid this isn't an easily cherry-pickable change, as it involved refactoring the entire receiver. |
Description: Adds the remaining pieces of a direct-to-pdata mechanism for the Prometheus receiver and a feature gate that allows selecting whether to use the legacy OpenCensus translations or the new direct route.
Link to tracking Issue: #4892
Testing: Unit tests exist for new code in the
internalpackage. End-to-end tests for the receiver now run against configurations that use both the OpenCensus and pdata builders.