Skip to content

Commit a2f2b8c

Browse files
authored
metricstarttimeprocessor: Copy true reset strategy from prometheus receiver (#37855)
#### Description Copy the "metric adjuster" from the prometheus receiver to a new "true_reset_point" strategy in the metricstarttimeprocessor #### Link to tracking issue Part of #37186 #### Testing Copied unit tests #### Documentation Updated the README. #### Notes for reviewers * I would recommend reviewing commit-by-commit. The first commit is copied verbatim, with minimal changes other than splitting into multiple files. * I changed the function signature of `AdjustMetrics` to match the processMetrics function so that it doesn't need an additional wrapper layer. * I removed the MetricsAdjuster interface, since it isn't needed (we implement the processor function for metrics now). * I had to remove the validation of job + instance being present because it didn't pass generated tests. Regardless, we should not rely on those in a generic processor.
1 parent 7993c9d commit a2f2b8c

File tree

11 files changed

+1646
-44
lines changed

11 files changed

+1646
-44
lines changed
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: metricstarttimeprocessor
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: add true_reset_point strategy for setting the start timestamp of cumulative points.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [37186]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext: The implementation is copied from the Prometheus receiver.
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user, api]

processor/metricstarttimeprocessor/README.md

+42
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,45 @@
88

99
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
1010
<!-- end autogenerated section -->
11+
12+
## Description
13+
14+
The metric start time processor (`metricstarttime`) is used to set the start
15+
time for metric points with a cumulative aggregation temporality. It is
16+
commonly used with the `prometheus` receiver, which usually produces metric
17+
points without a start time.
18+
19+
## Configuration
20+
21+
Configuration allows configuring the strategy used to set the start time.
22+
23+
```yaml
24+
processors:
25+
# processor name: metricstarttime
26+
metricstarttime:
27+
28+
# specify the strategy to use for setting the start time
29+
strategy: true_reset_point
30+
```
31+
32+
### Strategy: True Reset Point
33+
34+
The `true_reset_point` strategy handles missing start times for cumulative
35+
points by producing a stream of points that starts with a
36+
[True Reset Point](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#cumulative-streams-inserting-true-reset-points).
37+
The true reset point has its start time set to its end timestamp. It is meant
38+
to indicate the absolute value of the cumulative point when the collector first
39+
observed it. Subsequent points re-use the start timestamp of the initial True
40+
Reset point.
41+
42+
Pros:
43+
44+
* The absolute value of the cumulative metric is preserved.
45+
* It is possible to calculate the correct rate between any two points since the timestamps and values are not modified.
46+
47+
Cons:
48+
49+
* This strategy is **stateful** because the initial True Reset point is necessary to properly calculate rates on subsequent points.
50+
* The True Reset point doesn't make sense semantically. It has a zero duration, but non-zero values.
51+
* Many backends reject points with equal start and end timestamps.
52+
* If the True Reset point is rejected, the next point will appear to have a very large rate.

processor/metricstarttimeprocessor/config.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,36 @@
44
package metricstarttimeprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/metricstarttimeprocessor"
55

66
import (
7+
"fmt"
8+
"time"
9+
710
"go.opentelemetry.io/collector/component"
11+
12+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/metricstarttimeprocessor/internal/truereset"
813
)
914

1015
// Config holds configuration of the metric start time processor.
11-
type Config struct{}
16+
type Config struct {
17+
Strategy string `mapstructure:"strategy"`
18+
GCInterval time.Duration `mapstructure:"gc_interval"`
19+
}
1220

1321
var _ component.Config = (*Config)(nil)
1422

23+
func createDefaultConfig() component.Config {
24+
return &Config{
25+
Strategy: truereset.Type,
26+
GCInterval: 10 * time.Minute,
27+
}
28+
}
29+
1530
// Validate checks the configuration is valid
1631
func (cfg *Config) Validate() error {
32+
if cfg.Strategy != truereset.Type {
33+
return fmt.Errorf("%v is not a valid strategy", cfg.Strategy)
34+
}
35+
if cfg.GCInterval <= 0 {
36+
return fmt.Errorf("gc_interval must be positive")
37+
}
1738
return nil
1839
}

processor/metricstarttimeprocessor/factory.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import (
99
"go.opentelemetry.io/collector/component"
1010
"go.opentelemetry.io/collector/consumer"
1111
"go.opentelemetry.io/collector/processor"
12+
"go.opentelemetry.io/collector/processor/processorhelper"
1213

1314
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/metricstarttimeprocessor/internal/metadata"
15+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/metricstarttimeprocessor/internal/truereset"
1416
)
1517

1618
// NewFactory creates a new metric start time processor factory.
@@ -21,10 +23,6 @@ func NewFactory() processor.Factory {
2123
processor.WithMetrics(createMetricsProcessor, metadata.MetricsStability))
2224
}
2325

24-
func createDefaultConfig() component.Config {
25-
return &Config{}
26-
}
27-
2826
// createMetricsProcessor creates a metrics processor based on provided config.
2927
func createMetricsProcessor(
3028
ctx context.Context,
@@ -33,5 +31,14 @@ func createMetricsProcessor(
3331
nextConsumer consumer.Metrics,
3432
) (processor.Metrics, error) {
3533
rCfg := cfg.(*Config)
36-
return newMetricStartTimeProcessor(ctx, set, nextConsumer, rCfg)
34+
35+
adjuster := truereset.NewAdjuster(set.TelemetrySettings, rCfg.GCInterval)
36+
37+
return processorhelper.NewMetrics(
38+
ctx,
39+
set,
40+
cfg,
41+
nextConsumer,
42+
adjuster.AdjustMetrics,
43+
processorhelper.WithCapabilities(consumer.Capabilities{MutatesData: true}))
3744
}

processor/metricstarttimeprocessor/go.mod

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/open-telemetry/opentelemetry-collector-contrib/processor/metri
33
go 1.23.0
44

55
require (
6+
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.120.1
67
github.com/stretchr/testify v1.10.0
78
go.opentelemetry.io/collector/component v0.120.1-0.20250226024140-8099e51f9a77
89
go.opentelemetry.io/collector/component/componenttest v0.120.1-0.20250226024140-8099e51f9a77
@@ -12,10 +13,13 @@ require (
1213
go.opentelemetry.io/collector/pdata v1.26.1-0.20250226024140-8099e51f9a77
1314
go.opentelemetry.io/collector/processor v0.120.1-0.20250226024140-8099e51f9a77
1415
go.opentelemetry.io/collector/processor/processortest v0.120.1-0.20250226024140-8099e51f9a77
16+
go.opentelemetry.io/collector/semconv v0.120.1-0.20250226024140-8099e51f9a77
1517
go.uber.org/goleak v1.3.0
18+
go.uber.org/zap v1.27.0
1619
)
1720

1821
require (
22+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
1923
github.com/davecgh/go-spew v1.1.1 // indirect
2024
github.com/go-logr/logr v1.4.2 // indirect
2125
github.com/go-logr/stdr v1.2.2 // indirect
@@ -44,7 +48,6 @@ require (
4448
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
4549
go.opentelemetry.io/otel/trace v1.34.0 // indirect
4650
go.uber.org/multierr v1.11.0 // indirect
47-
go.uber.org/zap v1.27.0 // indirect
4851
golang.org/x/net v0.33.0 // indirect
4952
golang.org/x/sys v0.29.0 // indirect
5053
golang.org/x/text v0.21.0 // indirect
@@ -59,3 +62,5 @@ replace go.opentelemetry.io/collector/extension/extensionauth => go.opentelemetr
5962
replace go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest => go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.0.0-20250226024140-8099e51f9a77
6063

6164
replace go.opentelemetry.io/collector/service/hostcapabilities => go.opentelemetry.io/collector/service/hostcapabilities v0.0.0-20250226024140-8099e51f9a77
65+
66+
replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil => ../../pkg/pdatautil

processor/metricstarttimeprocessor/go.sum

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)