Telegraf starlark issues - multiple snmp table fields

Hello community,

I am having a heck of a time getting the starlark processor to do what I want it to do. Essentially we are feeding snmp tables/fields into telegraf/influxdb. We are using the starlark processor to manipulate some data from a specific snmp table field (conversion of mW to dBM). This conversion works, but starlark seems to just drop the other snmp table field all together instead of just passing it through.

Here is the telegraf snmp based configuration.

[[processors.starlark]]
 # Starlark processor - converts reported light levels from mW to dBm via referenced script below
 namepass = ["ASR9902 Interface Optical Measurement Table","Current Sensor Measurement"]
 script = "/usr/local/bin/mw_to_dbm.star"


[[inputs.snmp]]
  # ASR9902 - Optical Light Levels
  agents = ["my router"]
  version = 2
  community = "snmp"
  interval = "60s"

  [[inputs.snmp.field]]
    name = "ASR9902-Hostname"
    oid = "1.3.6.1.2.1.1.5.0"
    is_tag = true

  [[inputs.snmp.field]]
    name = "ASR9902-ModuleName"
    #oid = "1.3.6.1.2.1.47.1.1.1.1.7"
    oid = "ENTITY-MIB::entPhysicalName"
    is_tag = true


  [[inputs.snmp.table]]
    name = "ASR9902 Interface Optical Measurement Table"
    inherit_tags = ["ASR9902-Hostname"]
    index_as_tag = true

    [[inputs.snmp.table.field]]
      name = "Current Sensor Measurement"
      #oid = "1.3.6.1.4.1.9.9.91.1.1.1.1.4"
      oid = "CISCO-ENTITY-SENSOR-MIB::entSensorValue"

    [[inputs.snmp.table.field]]
      name = "Sensor Threshold Values"
      #oid = "1.3.6.1.4.1.9.9.91.1.2.1.1.4"
      oid = "CISCO-ENTITY-SENSOR-MIB::entSensorThresholdValue"

    [[inputs.snmp.table.field]]
      name = "ASR9902-ModuleName"
      #oid = "1.3.6.1.2.1.47.1.1.1.1.7"
      oid = "ENTITY-MIB::entPhysicalName"
      is_tag = true

The starlark script looks like this.


load('math.star', 'math')


def apply(metric):

        mW = {}
        dBm = {}

        mW = metric.fields['Current Sensor Measurement'] / 100000
        metric.fields['dBm'] = 10 * math.log(mW, 10)

        return metric

That all said, the starlark processor returns the original “Current Sensor Measurement” SNMP table field and the new “dBm” field to influxdb. It completely drops the “Sensor Threshold Values” field all together. I need to figure out how to either just have starklark multiply that field by (1) and return the original data of that field/along with the field…or just to pass anything else that was not specifically modified by starklark through without modification/drops. I read through this guide but this doesnt seem to work correctly…or I at least could not get it to work.

telegraf/plugins/processors/starlark/testdata/multiple_metrics.star at release-1.29 · influxdata/telegraf · GitHub

Anyone have any ideas?

Can you please provide an example metric you send into the processor and what you expect on the other side?

You can use the [[outputs.file]] output to print metrics in line protocol.

Hello jpowers, thanks for the reply on this thread. I do appreciate it.

Essentially, we only want to send in one of the SNMP table fields but can’t get a namepass function to do what we want…so it seems that everything in our SNMP table is being sent over.

-SNMP Table Being Sent into the processor. "name = “ASR9902 Interface Optical Measurement Table”

-We essentially have two snmp table fields in this table that (pre-processor) return an integer value based on the snmp get.
—snmp field #1: (Field we want starlark to do math on) - name = “Current Sensor Measurement”
—snmp field #2: (Field we want starlark to just pass/return) - name = “Sensor Threshold Values”

When we remove the starlark processor from the telegraf configuration, and use the influx data explorer, we can see all of our SNMP table fields show up correctly. We have an integer returned for the “Current Sensor Measurement” and the “Sensor Threshold Values” snmp fields as we expect.

When we add the starlark processor to the telegraf configuration, and use the influx data explorer, we see that from the snmp table fields…only the “Current Sensor Measurement” field and the newly created metric of “dBm” show up in the “_field” filter in the influx data explorer. Which seems to make sense as that is what is getting manipulated by “math.star” module in the starlark script I referenced in my original post.

What I need is to somehow either have the “Sensor Threshold Values” snmp field also just pass through unmolested by the starlark processor…or I can do a basic math function on that as well…like divide by 100 or 1000 to essentially “float” the value a little.

I can’t find a good example of one starlark processor script that performs multiple independent math functions on two independent snmp table fields and returns each one as their own independent metrics. I see some examples on the web where people take two snmp table fields and multiply them together to create one new metric. Not really what I am trying to do.

I hope that all made sense. I apologize for my ignorance on some of this as I am somewhat new to playing around with telegraf/influx and especially the starlark processor.

Hi,

So that helps tell me what you want to do, but it doesn’t answer my question about what your metrics look like and what you want them to look like.

What would help is to get an idea of what the metrics actually look like, for example:

metric value=42

and you want it to look like:

metric value=42000

Jpowers,

Sorry for the misunderstanding here.

This is what we are looking at.

SNMP Field: "Current Sensor Measurement"
original metric value = 74080
starklark'ed metric value = -1.3


SNMP Field: "Sensor Threshold Values"
original metric value = 218780
starklark'ed metric value = 3.3

Essentially, we are using starlark to convert the original metric value which is reported in mW (milliwatts) and converting that using the math.log10 formula to convert to dBm (decibel-milliwatts).

Is that what you are asking?

Thanks again for the assistance here, it is greatly appreciated.

I’m still not sure I’m following, but this is jist of what I think you want. Essentially, you need to check if the field exists first, and only if it exists, then do your calculation and add the dbm field:

input metric:

metric "Current\ Sensor\ Measurement"=74080,"Sensor\ Threshold\ Values"=218780
[[processors.starlark]]
  source = '''
load("math.star", "math")

def apply(metric):
  if metric.fields.get("\"Current Sensor Measurement\""):
    mW = metric.fields["\"Current Sensor Measurement\""] / 100000
    metric.fields["dBm"] = 10 * math.log(mW, 10)

  return metric
'''

Which produces:

metric "Current\ Sensor\ Measurement"=74080,"Sensor\ Threshold\ Values"=218780,dBm=-1.3029902632612207 1702999171000000000

And you can extend/duplicate the check for the other field.

1 Like

Sorry for the confusion. It is a super niche scenario as most of these things are. So, I appreciate you playing along :slight_smile: But, I believe you interpreted my word vomit correctly and nailed it.

Hmm that is interesting for sure. So, you are saying I can “extend/duplicate the check” for the other snmp field all in one starlark script…something like this would return both measurements as you were eluding to? (I created some new variables for mW and dBm as I need both the dBm for the “Current Sensor Measurement” and the thresh_dBm for the “Sensor Threshold Measurement”… I essentially need to know the values in dBm for both of these as they are mutually exclusive.

[[processors.starlark]]
  source = '''
load("math.star", "math")

def apply(metric):
  if metric.fields.get("\"Current Sensor Measurement\""):
    mW = metric.fields["\"Current Sensor Measurement\""] / 100000
    metric.fields["dBm"] = 10 * math.log(mW, 10)

  if metric.fields.get("\"Sensor Threshold Values\""):
    thresh_mW = metric.fields["\"Sensor Threshold Values\""] / 100000
    metric.fields["thresh_dBm"] = 10 * math.log(thresh_mW, 10)

  return metric

Then this would essentially return the below?

metric "Current\ Sensor\ Measurement"=74080,"Sensor\ Threshold\ Values"=218780,dBm=-1.3029902632612207,thresh_dBm=1702999171000000000

Yep, essentially that starlark script checks for the fields and only if the exist, will it attempt to do the calculation and produce the new dBm field.

Jpowers,

thank you very much for the assistance and expertise here. I truly appreciate it. I have had a really hard time tracking down good documentation/examples on the starlark processor and how the command syntax is supposed to look/feel like.

With a little modification to the original script you had provided I got it all working now as I had originally intended.

load("math.star", "math")

def apply(metric):
   if metric.fields.get("Current Sensor Measurement"):
     mW = metric.fields["Current Sensor Measurement"] / 100000
     metric.fields["dBm"] = 10 * math.log(mW, 10)

   if metric.fields.get("Sensor Threshold Values"):
     thresh_mW = metric.fields["Sensor Threshold Values"] / 100000
     metric.fields["thresh_dBm"] = 10 * math.log(thresh_mW, 10)

   return metric

Thanks again! you rock.

1 Like