fix(outputs.nebius_cloud_monitoring): Replace reserved label names (#13597)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@me.com>
This commit is contained in:
parent
8cde34bfeb
commit
36709713e1
|
|
@ -34,3 +34,55 @@ Folder ID from instance metadata. In this plugin we use [Google Cloud notation]
|
||||||
This internal metadata endpoint is only accessible for VMs from the cloud.
|
This internal metadata endpoint is only accessible for VMs from the cloud.
|
||||||
|
|
||||||
[Google Cloud notation]: https://nebius.com/il/docs/compute/operations/vm-info/get-info#gce-metadata
|
[Google Cloud notation]: https://nebius.com/il/docs/compute/operations/vm-info/get-info#gce-metadata
|
||||||
|
|
||||||
|
### Reserved Labels
|
||||||
|
|
||||||
|
Nebius Monitoring backend using json format to receive the metrics:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "metric_name",
|
||||||
|
"labels": {
|
||||||
|
"key": "value",
|
||||||
|
"foo": "bar"
|
||||||
|
},
|
||||||
|
"ts": "2023-06-06T11:10:50Z",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
But key of label cannot be `name` because it's reserved for `metric_name`.
|
||||||
|
|
||||||
|
So this payload:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "systemd_units_load_code",
|
||||||
|
"labels": {
|
||||||
|
"active": "active",
|
||||||
|
"host": "vm",
|
||||||
|
"load": "loaded",
|
||||||
|
"name": "accounts-daemon.service",
|
||||||
|
"sub": "running"
|
||||||
|
},
|
||||||
|
"ts": "2023-06-06T11:10:50Z",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
will be replaced with:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "systemd_units_load_code",
|
||||||
|
"labels": {
|
||||||
|
"active": "active",
|
||||||
|
"host": "vm",
|
||||||
|
"load": "loaded",
|
||||||
|
"_name": "accounts-daemon.service",
|
||||||
|
"sub": "running"
|
||||||
|
},
|
||||||
|
"ts": "2023-06-06T11:10:50Z",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ func (a *NebiusCloudMonitoring) Write(metrics []telegraf.Metric) error {
|
||||||
nebiusCloudMonitoringMetrics,
|
nebiusCloudMonitoringMetrics,
|
||||||
nebiusCloudMonitoringMetric{
|
nebiusCloudMonitoringMetric{
|
||||||
Name: m.Name() + "_" + field.Key,
|
Name: m.Name() + "_" + field.Key,
|
||||||
Labels: m.Tags(),
|
Labels: replaceReservedTagNames(m.Tags()),
|
||||||
TS: m.Time().Format(time.RFC3339),
|
TS: m.Time().Format(time.RFC3339),
|
||||||
Value: value,
|
Value: value,
|
||||||
},
|
},
|
||||||
|
|
@ -242,3 +242,15 @@ func init() {
|
||||||
return &NebiusCloudMonitoring{}
|
return &NebiusCloudMonitoring{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func replaceReservedTagNames(tagNames map[string]string) map[string]string {
|
||||||
|
newTags := make(map[string]string, len(tagNames))
|
||||||
|
for tagName, tagValue := range tagNames {
|
||||||
|
if tagName == "name" {
|
||||||
|
newTags["_name"] = tagValue
|
||||||
|
} else {
|
||||||
|
newTags[tagName] = tagValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newTags
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,31 @@ func TestWrite(t *testing.T) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "label with name 'name' is replaced with '_name'",
|
||||||
|
plugin: &NebiusCloudMonitoring{},
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cluster",
|
||||||
|
map[string]string{
|
||||||
|
"name": "accounts-daemon.service",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"value": 9226,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
handler: func(t *testing.T, w http.ResponseWriter, r *http.Request) {
|
||||||
|
message, err := readBody(r)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, message.Metrics, 1)
|
||||||
|
require.Equal(t, "cluster_value", message.Metrics[0].Name)
|
||||||
|
require.Contains(t, message.Metrics[0].Labels, "_name")
|
||||||
|
require.Equal(t, float64(9226), message.Metrics[0].Value)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
@ -137,3 +162,37 @@ func TestWrite(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReplaceReservedTagNames(t *testing.T) {
|
||||||
|
tagMap := map[string]string{
|
||||||
|
"name": "value",
|
||||||
|
"other": "value",
|
||||||
|
}
|
||||||
|
wantTagMap := map[string]string{
|
||||||
|
"_name": "value",
|
||||||
|
"other": "value",
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
tagNames map[string]string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "tagReplacement",
|
||||||
|
args: args{
|
||||||
|
tagNames: tagMap,
|
||||||
|
},
|
||||||
|
want: wantTagMap,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := replaceReservedTagNames(tt.args.tagNames)
|
||||||
|
require.EqualValues(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue