Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timer support for statsD receiver #1335

Merged
merged 1 commit into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions receiver/statsdreceiver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ General format is:

`<name>:<value>|g|@<sample-rate>|#<tag1-key>:<tag1-value>`

<!-- ### Timer/Histogram
### Timer

`<name>:<value>|ms|@<sample-rate>|#<tag1-key>:<tag1-value>`

`<name>:<value>|<ms/h>|@<sample-rate>|#<tag1-key>:<tag1-value>` -->

## Testing

Expand Down
26 changes: 24 additions & 2 deletions receiver/statsdreceiver/protocol/statsd_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var (
)

func getSupportedTypes() []string {
return []string{"c", "g"}
return []string{"c", "g", "ms"}
}

// StatsDParser supports the Parse method for parsing StatsD messages with Tags.
Expand All @@ -41,6 +41,7 @@ type statsDMetric struct {
name string
value string
statsdMetricType string
unit string
metricType metricspb.MetricDescriptor_Type
sampleRate float64
labelKeys []*metricspb.LabelKey
Expand Down Expand Up @@ -128,7 +129,6 @@ func parseMessageToMetric(line string) (*statsDMetric, error) {
return nil, fmt.Errorf("unrecognized message part: %s", part)
}
}

return result, nil
}

Expand All @@ -147,6 +147,7 @@ func buildMetric(metric *statsDMetric, point *metricspb.Point) *metricspb.Metric
Name: metric.name,
Type: metric.metricType,
LabelKeys: metric.labelKeys,
Unit: metric.unit,
},
Timeseries: []*metricspb.TimeSeries{
{
Expand Down Expand Up @@ -181,6 +182,10 @@ func buildPoint(parsedMetric *statsDMetric) (*metricspb.Point, error) {
}
parsedMetric.metricType = metricspb.MetricDescriptor_GAUGE_INT64
})
case "ms":
return buildTimerPoint(parsedMetric, now, func(parsedMetric *statsDMetric) {
parsedMetric.metricType = metricspb.MetricDescriptor_GAUGE_DOUBLE
})
}

return nil, fmt.Errorf("unhandled metric type: %s", parsedMetric.statsdMetricType)
Expand Down Expand Up @@ -215,3 +220,20 @@ func buildGaugeOrCounterPoint(parsedMetric *statsDMetric, now *timestamppb.Times
metricTypeSetter(parsedMetric, isDouble)
return point, nil
}

func buildTimerPoint(parsedMetric *statsDMetric, now *timestamppb.Timestamp, metricTypeSetter func(parsedMetric *statsDMetric)) (*metricspb.Point, error) {
var point *metricspb.Point
gavindoudou marked this conversation as resolved.
Show resolved Hide resolved
parsedMetric.unit = "ms"
f, err := strconv.ParseFloat(parsedMetric.value, 64)
if err != nil {
return nil, fmt.Errorf("timer: failed to parse metric value to float: %s", parsedMetric.value)
}
point = &metricspb.Point{
Timestamp: now,
Value: &metricspb.Point_DoubleValue{
DoubleValue: f,
},
}
metricTypeSetter(parsedMetric)
return point, nil
}
55 changes: 55 additions & 0 deletions receiver/statsdreceiver/protocol/statsd_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func Test_StatsDParser_Parse(t *testing.T) {
metricspb.MetricDescriptor_CUMULATIVE_INT64,
nil,
nil,
"",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
Expand All @@ -83,6 +84,7 @@ func Test_StatsDParser_Parse(t *testing.T) {
metricspb.MetricDescriptor_CUMULATIVE_DOUBLE,
nil,
nil,
"",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
Expand Down Expand Up @@ -118,6 +120,7 @@ func Test_StatsDParser_Parse(t *testing.T) {
HasValue: true,
},
},
"",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
Expand All @@ -143,6 +146,7 @@ func Test_StatsDParser_Parse(t *testing.T) {
HasValue: true,
},
},
"",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
Expand All @@ -168,6 +172,7 @@ func Test_StatsDParser_Parse(t *testing.T) {
HasValue: true,
},
},
"",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
Expand All @@ -177,6 +182,54 @@ func Test_StatsDParser_Parse(t *testing.T) {
},
}),
},
{
name: "timer metric with sample rate",
input: "test.timer:42.3|ms|@0.1",
wantMetric: testMetric("test.timer",
metricspb.MetricDescriptor_GAUGE_DOUBLE,
nil,
nil,
"ms",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
},
Value: &metricspb.Point_DoubleValue{
DoubleValue: 42.3,
},
}),
},
{
name: "timer metric with sample rate and tag",
input: "test.timer:42|ms|@0.1|#key:value",
wantMetric: testMetric("test.timer",
metricspb.MetricDescriptor_GAUGE_DOUBLE,
[]*metricspb.LabelKey{
{
Key: "key",
},
},
[]*metricspb.LabelValue{
{
Value: "value",
HasValue: true,
},
},
"ms",
&metricspb.Point{
Timestamp: &timestamppb.Timestamp{
Seconds: 0,
},
Value: &metricspb.Point_DoubleValue{
DoubleValue: 42,
},
}),
},
{
name: "timer: invalid metric value",
input: "test.metric:invalidValue|ms",
err: errors.New("timer: failed to parse metric value to float: invalidValue"),
},
{
name: "invalid sample rate value",
input: "test.metric:42|c|@1.0a",
Expand Down Expand Up @@ -214,12 +267,14 @@ func testMetric(metricName string,
metricType metricspb.MetricDescriptor_Type,
lableKeys []*metricspb.LabelKey,
labelValues []*metricspb.LabelValue,
unit string,
point *metricspb.Point) *metricspb.Metric {
return &metricspb.Metric{
MetricDescriptor: &metricspb.MetricDescriptor{
Name: metricName,
Type: metricType,
LabelKeys: lableKeys,
Unit: unit,
},
Timeseries: []*metricspb.TimeSeries{
{
Expand Down