Skip to content

Commit 1686df6

Browse files
committed
receiver/prometheusremotewritereceiver: add MetricIdentity with xxhash-based Hash method.
Creates MetricIdentity struct for uniquely identifying metrics and adds a deterministic Hash method using xxhash with proper field separation. partly fixes open-telemetry#37277.
1 parent e4559ec commit 1686df6

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

.chloggen/metric-identity-hash.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
5+
component: prometheusremotewritereciever
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: "Introduced `MetricIdentity` struct with xxhash-based hashing for uniquely identifying metrics."
9+
10+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
11+
issues: [37277]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext: |
17+
The hash method ensures consistent, deterministic identification of metrics by using
18+
proper field separation and xxhash, which is already utilized in other parts of the code.
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]

receiver/prometheusremotewritereceiver/receiver.go

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,47 @@ type prometheusRemoteWriteReceiver struct {
4949
wg sync.WaitGroup
5050
}
5151

52+
// MetricIdentity contains all the components that uniquely identify a metric
53+
// according to the OpenTelemetry Protocol data model.
54+
type MetricIdentity struct {
55+
ResourceID string
56+
ScopeName string
57+
ScopeVersion string
58+
MetricName string
59+
Unit string
60+
Type writev2.Metadata_MetricType
61+
}
62+
63+
// CreateMetricIdentity creates a MetricIdentity struct from the required components
64+
func CreateMetricIdentity(resourceID string, scopeName, scopeVersion, metricName, unit string, metricType writev2.Metadata_MetricType) MetricIdentity {
65+
return MetricIdentity{
66+
ResourceID: resourceID,
67+
ScopeName: scopeName,
68+
ScopeVersion: scopeVersion,
69+
MetricName: metricName,
70+
Unit: unit,
71+
Type: metricType,
72+
}
73+
}
74+
75+
// Hash generates a unique hash for the metric identity
76+
func (mi MetricIdentity) Hash() string {
77+
const separator = "\xff"
78+
79+
combined := strings.Join([]string{
80+
mi.ResourceID,
81+
mi.ScopeName,
82+
mi.ScopeVersion,
83+
mi.MetricName,
84+
mi.Unit,
85+
fmt.Sprintf("%d", mi.Type),
86+
}, separator)
87+
88+
hash := xxhash.Sum64String(combined)
89+
90+
return fmt.Sprintf("%x", hash)
91+
}
92+
5293
func (prw *prometheusRemoteWriteReceiver) Start(ctx context.Context, host component.Host) error {
5394
mux := http.NewServeMux()
5495
mux.HandleFunc("/api/v1/write", prw.handlePRW)
@@ -221,16 +262,17 @@ func (prw *prometheusRemoteWriteReceiver) translateV2(_ context.Context, req *wr
221262
description := req.Symbols[ts.Metadata.HelpRef]
222263

223264
resourceID := identity.OfResource(rm.Resource())
224-
// Temporary approach to generate the metric key.
225-
// TODO: Replace this with a proper hashing function.
226-
// The definition of the metric uniqueness is based on the following document. Ref: https://opentelemetry.io/docs/specs/otel/metrics/data-model/#opentelemetry-protocol-data-model
227-
metricKey := fmt.Sprintf("%s:%s:%s:%s:%s:%d",
265+
266+
metricIdentity := CreateMetricIdentity(
228267
resourceID.String(), // Resource identity
229268
scopeName, // Scope name
230269
scopeVersion, // Scope version
231270
metricName, // Metric name
232271
unit, // Unit
233-
ts.Metadata.Type) // Metric type
272+
ts.Metadata.Type, // Metric type
273+
)
274+
275+
metricKey := metricIdentity.Hash()
234276

235277
var scope pmetric.ScopeMetrics
236278
var foundScope bool

0 commit comments

Comments
 (0)