Telegraf: Statsd plugin to support multiple field values.

Created on 13 Jun 2017  路  6Comments  路  Source: influxdata/telegraf

Proposal:
Statsd plugin support multiple field values.
The ability to send multiple values through statsd.

Current behavior:
For example if I call statsd increase on this metric name:
"school.grades,name=bob grade=80,height=100"
It will translate to => "school_grades,name=bob,grade=80,height=100 value=1"
Meaning that grade and height are now tags instead of fields.
Desired behavior:
"school_grades,name=bob grade=80,height=100,value=1"
Meaning grade and height are also fields.
Use case:
I use statsd to collect several metrics with multiple tags, some with a really high range of possible values. It blows up my server memory.
I want those to be fields instead but I'm unable to do so with the current statsd plugin.

discussion

Most helpful comment

Hi,

I'm facing the same issue now where I want to send multiple values for the same measurement.
The options @danielnelson suggested won't work for me due to the following reasons:

  • Templates: Some of my field values are strings and not numeric and it seems like the templates won't allow that.
  • Sending directly to a UDP socket: My use case is that I'm reading thousands of events per second and generating metrics for them, I would like to take advantage of the statsd plugin and aggregate the counters locally before flushing them every x seconds and I would like to avoid implementing it myself

I think this could be achieved with some enhancements to the templates capabilities, for example from the top of my head, if we could use the following syntax:
templates = [
"measurement.name.field:grade.field:height"
]

For example, if I call statsd increase on this metric name: "school_grades.bob.100.80"
It would translate to: "school_grades,name=bob grade=100,height=80,value=1"

Another example that's more relative to my use case:
Call statsd increase on this metric name: 'school_grades.bob.A.tall'
would translate to: 'school_grades,name=bob grade="A",height="tall",value=1'

Does it sound reasonable?

Thanks!

All 6 comments

We can't do this directly as proposed, since it wouldn't be valid statsd format. However, you have a few options to get what you want:

  • Use the statsd templates option; more about this below.
  • Send data like this directly to a udp socket listener in line protocol.

Here is how to make this work using statsd templates. First, add something like this to your statsd config:

  ## Statsd data translation templates, more info can be read here:
  ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md#graphite
  templates = [
      "measurement.field*"
  ]

Then send three stats like this (could be in a single udp packet):

school_grades.grade,name=bob:80|g
school_grades.height,name=bob:100|g
school_grades.value,name=bob:1|g

This should result in the following point:

school_grades,name=bob,metric_type=gauge grade=80,height=100,value=1 1497380947000000000

The docs in the comment above have more info. Hope this helps!

Hi,

I'm facing the same issue now where I want to send multiple values for the same measurement.
The options @danielnelson suggested won't work for me due to the following reasons:

  • Templates: Some of my field values are strings and not numeric and it seems like the templates won't allow that.
  • Sending directly to a UDP socket: My use case is that I'm reading thousands of events per second and generating metrics for them, I would like to take advantage of the statsd plugin and aggregate the counters locally before flushing them every x seconds and I would like to avoid implementing it myself

I think this could be achieved with some enhancements to the templates capabilities, for example from the top of my head, if we could use the following syntax:
templates = [
"measurement.name.field:grade.field:height"
]

For example, if I call statsd increase on this metric name: "school_grades.bob.100.80"
It would translate to: "school_grades,name=bob grade=100,height=80,value=1"

Another example that's more relative to my use case:
Call statsd increase on this metric name: 'school_grades.bob.A.tall'
would translate to: 'school_grades,name=bob grade="A",height="tall",value=1'

Does it sound reasonable?

Thanks!

@chenl87 This is an interesting idea, one thing to consider would be how to support different field types: how will we know if the field should be an int, float, bool, or string? I suppose the obvious way would be similar to how we handle it in the logparser plugin:

templates = [
  "measurement.name:tag.grade.int:height:string"
]

There is another potential option for aggregation, and that is using the basic stats aggregator along with a udp socket listener. This solution is somewhat new and may not be as fast or feature rich, but you should take a look at it and let me know how it looks.

If you like, you can open a new feature request issue with your proposal for the template language changes.

@danielnelson thanks for the quick response.
My thought was to write the less commonly-queried fields as fields, not tags, but I wasn't aware that I can't query field values (Which I need to expose to the end users in Grafana/Chronograf).

I'm currently experimenting the InfluxDB TSI engine as I have a few tags with a very high cardinality. Hope it would do the trick.

Thanks!

Any plans to support this?

I don't think so, while it is an interesting idea I don't think it isn't very regular use of statsd. Perhaps though it would be possible to use the parser processor to encode data within a statsd packet to a similar effect?

There is an example of this in the parser processor readme using logfmt. You would need to use a statsd template to push the values into a field.

Was this page helpful?
0 / 5 - 0 ratings