mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 00:13:30 +01:00
lib/protoparser/datadog: do not re-use previously parsed field values if they are missing in the currently parsed message
Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3432
This commit is contained in:
parent
87723ef0e1
commit
87390443d1
@ -15,6 +15,8 @@ The following tip changes can be tested by building VictoriaMetrics components f
|
|||||||
|
|
||||||
## tip
|
## tip
|
||||||
|
|
||||||
|
* BUGFIX: [DataDog protocol parser](https://docs.victoriametrics.com/#how-to-send-data-from-datadog-agent): do not re-use `host` and `device` fields from the previously parsed messages if these fields are missing in the currently parsed message. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3432).
|
||||||
|
|
||||||
|
|
||||||
## [v1.85.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.85.0)
|
## [v1.85.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.85.0)
|
||||||
|
|
||||||
|
@ -28,7 +28,15 @@ type Request struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (req *Request) reset() {
|
func (req *Request) reset() {
|
||||||
req.Series = req.Series[:0]
|
// recursively reset all the fields in req in order to avoid field value
|
||||||
|
// re-use in json.Unmarshal() when the corresponding field is missing
|
||||||
|
// in the unmarshaled JSON.
|
||||||
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3432
|
||||||
|
series := req.Series
|
||||||
|
for i := range series {
|
||||||
|
series[i].reset()
|
||||||
|
}
|
||||||
|
req.Series = series[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal unmarshals DataDog /api/v1/series request body from b to req.
|
// Unmarshal unmarshals DataDog /api/v1/series request body from b to req.
|
||||||
@ -59,23 +67,42 @@ func (req *Request) Unmarshal(b []byte) error {
|
|||||||
//
|
//
|
||||||
// See https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
// See https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
||||||
type Series struct {
|
type Series struct {
|
||||||
|
Metric string `json:"metric"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
|
|
||||||
// Do not decode Interval, since it isn't used by VictoriaMetrics
|
|
||||||
// Interval int64 `json:"interval"`
|
|
||||||
|
|
||||||
Metric string `json:"metric"`
|
|
||||||
Points []Point `json:"points"`
|
|
||||||
Tags []string `json:"tags"`
|
|
||||||
// The device field does not appear in the datadog docs, but datadog-agent does use it.
|
// The device field does not appear in the datadog docs, but datadog-agent does use it.
|
||||||
// Datadog agent (v7 at least), removes the tag "device" and adds it as its own field. Why? That I don't know!
|
// Datadog agent (v7 at least), removes the tag "device" and adds it as its own field. Why? That I don't know!
|
||||||
// https://github.com/DataDog/datadog-agent/blob/0ada7a97fed6727838a6f4d9c87123d2aafde735/pkg/metrics/series.go#L84-L105
|
// https://github.com/DataDog/datadog-agent/blob/0ada7a97fed6727838a6f4d9c87123d2aafde735/pkg/metrics/series.go#L84-L105
|
||||||
Device string `json:"device"`
|
Device string `json:"device"`
|
||||||
|
|
||||||
|
// Do not decode Interval, since it isn't used by VictoriaMetrics
|
||||||
|
// Interval int64 `json:"interval"`
|
||||||
|
|
||||||
|
Points []Point `json:"points"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
|
||||||
// Do not decode Type, since it isn't used by VictoriaMetrics
|
// Do not decode Type, since it isn't used by VictoriaMetrics
|
||||||
// Type string `json:"type"`
|
// Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Series) reset() {
|
||||||
|
s.Metric = ""
|
||||||
|
s.Host = ""
|
||||||
|
s.Device = ""
|
||||||
|
|
||||||
|
points := s.Points
|
||||||
|
for i := range points {
|
||||||
|
points[i] = Point{}
|
||||||
|
}
|
||||||
|
s.Points = points[:0]
|
||||||
|
|
||||||
|
tags := s.Tags
|
||||||
|
for i := range tags {
|
||||||
|
tags[i] = ""
|
||||||
|
}
|
||||||
|
s.Tags = tags[:0]
|
||||||
|
}
|
||||||
|
|
||||||
// Point represents a point from DataDog POST request to /api/v1/series
|
// Point represents a point from DataDog POST request to /api/v1/series
|
||||||
type Point [2]float64
|
type Point [2]float64
|
||||||
|
|
||||||
|
@ -22,6 +22,43 @@ func TestSplitTag(t *testing.T) {
|
|||||||
f(":bar", "", "bar")
|
f(":bar", "", "bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRequestUnmarshalMissingHost(t *testing.T) {
|
||||||
|
// This tests https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3432
|
||||||
|
req := Request{
|
||||||
|
Series: []Series{{
|
||||||
|
Host: "prev-host",
|
||||||
|
Device: "prev-device",
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
data := `
|
||||||
|
{
|
||||||
|
"series": [
|
||||||
|
{
|
||||||
|
"metric": "system.load.1",
|
||||||
|
"points": [[
|
||||||
|
1575317847,
|
||||||
|
0.5
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
if err := req.Unmarshal([]byte(data)); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
reqExpected := Request{
|
||||||
|
Series: []Series{{
|
||||||
|
Metric: "system.load.1",
|
||||||
|
Points: []Point{{
|
||||||
|
1575317847,
|
||||||
|
0.5,
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(&req, &reqExpected) {
|
||||||
|
t.Fatalf("unexpected request parsed;\ngot\n%+v\nwant\n%+v", req, reqExpected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRequestUnmarshalFailure(t *testing.T) {
|
func TestRequestUnmarshalFailure(t *testing.T) {
|
||||||
f := func(s string) {
|
f := func(s string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
Loading…
Reference in New Issue
Block a user