mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00: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
d7d34515c5
commit
f4fcf3b572
3 changed files with 74 additions and 3 deletions
|
@ -15,6 +15,9 @@ The following tip changes can be tested by building VictoriaMetrics components f
|
|||
|
||||
## v1.79.x long-time support release (LTS)
|
||||
|
||||
* 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.79.6](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.79.6)
|
||||
|
||||
Released at 11-12-2022
|
||||
|
|
|
@ -28,7 +28,15 @@ type Request struct {
|
|||
}
|
||||
|
||||
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.
|
||||
|
@ -59,12 +67,17 @@ func (req *Request) Unmarshal(b []byte) error {
|
|||
//
|
||||
// See https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
|
||||
type Series struct {
|
||||
Host string `json:"host"`
|
||||
Metric string `json:"metric"`
|
||||
Host string `json:"host"`
|
||||
|
||||
// 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!
|
||||
// https://github.com/DataDog/datadog-agent/blob/0ada7a97fed6727838a6f4d9c87123d2aafde735/pkg/metrics/series.go#L84-L105
|
||||
Device string `json:"device"`
|
||||
|
||||
// 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"`
|
||||
|
||||
|
@ -72,6 +85,24 @@ type Series struct {
|
|||
// 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
|
||||
type Point [2]float64
|
||||
|
||||
|
|
|
@ -22,6 +22,43 @@ func TestSplitTag(t *testing.T) {
|
|||
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) {
|
||||
f := func(s string) {
|
||||
t.Helper()
|
||||
|
|
Loading…
Reference in a new issue