SNMP Metric as tag to other metrics (gnmi, ping)

Hello,

I have the following telegraf config:

[[inputs.snmp]]
agents = ['1.1.1.1', '2.2.2.2']
version = 2
community = "xxxxx"
interval = "10m"

[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.3.0"
name = "sysUptime"

[[inputs.snmp.field]]
oid = "1.3.6.1.2.1.1.6.0"
name = "location"
is_tag = true

I send this to prometheus, this results in the metric:

snmp_sysUptime{agent_host=“1.1.1.1”,host=“dashboard”,location=“1234_k1”} 1.5601714e+07
snmp_sysUptime{agent_host=“2.2.2.2”,host=“dashboard”,location=“4321_k1”} 1.5601714e+07

I also have other metrics in my telegraf config, like:

[[inputs.gnmi.subscription]]
name = "if_counters"
path = "/interfaces/interface/state/counters"
subscription_mode = "sample"
sample_interval = "10s"

and:

[[inputs.ping]]
urls = ['1.1.1.1', '2.2.2.2']
ping_interval = 10.0

This results in metrics like:
if_counters_in_broadcast_pkts{host=“dashboard”,name=“interfaceName”,path=“/interfaces”,source=“1.1.1.1”} 0
if_counters_in_broadcast_pkts{host=“dashboard”,name=“interfaceName”,path=“/interfaces”,source=“2.2.2.2”} 0

and:
ping_result_code{host=“dashboard”,url=“1.1.1.1”} 0
ping_result_code{host=“dashboard”,url=“2.2.2.2”} 0

I want to add the location, from the inputs.snmp.field, as a tag to all my other metrics based on the ip address. It should look like:
if_counters_in_broadcast_pkts{host=“dashboard”,name=“interfaceName”,path=“/interfaces”,source=“1.1.1.1”, location=“1234_k1”} 0
if_counters_in_broadcast_pkts{host=“dashboard”,name=“interfaceName”,path=“/interfaces”,source=“2.2.2.2”, location=“4321_k1”} 0
ping_result_code{host=“dashboard”,url=“1.1.1.1”, location=“1234_k1”} 0
ping_result_code{host=“dashboard”,url=“2.2.2.2”, location=“4321_k1”} 0

Is this possible?

I think you can achieve that with the starlark processor. If the incoming metric name is snmp, then store the value of location with index of value of source tag. for the other metric lookup the stored value by index with either the url or source tag and put the result in location metric. Just note that at the first collection, the location value might not be stored yet as snmp plugin take probably more time than ping plugin…

Thanks for your response!

It looks like this should work. I am trying the following starlark config:

# Globale map om locaties op te slaan
location_map = {}

# Dit is een eenvoudige oplossing voor het ophalen van de locatie in twee stappen
def apply(metric):
    # Verwerk SNMP-metrics (waar locatie wordt opgeslagen)
    if metric.name.startswith("snmp_"):
        agent_host = metric.tags.get("agent_host")
        location = metric.tags.get("location")

        # Als agent_host en location beschikbaar zijn, sla ze op in de map
        if agent_host and location:
            location_map[agent_host] = location
            metric.tags["debug_info"] = "Stored location: " + agent_host + " -> " + location
        else:
            # Als agent_host of locatie ontbreekt, log dit
            metric.tags["debug_info"] = "Missing location or agent_host for " + metric.name

    # Verwerk andere metrics (zoals cisco_allocated_power, if_counters, ping, etc.)
    elif metric.tags.get("source") or metric.tags.get("url") or metric.tags.get("agent_host"):
        # Haal de bron van de metric op (source, url, or agent_host)
        ip = ""
        if metric.tags.get("source"):
            ip = metric.tags["source"]
        elif metric.tags.get("url"):
            ip = metric.tags["url"]
        elif metric.tags.get("agent_host"):
            ip = metric.tags["agent_host"]

        # Debug: Voeg IP toe aan de debug_info om te zien welk IP wordt gebruikt
        metric.tags["debug_info"] = "Looking for location for IP: " + ip

        # Zoek locatie op in de location_map
        location = location_map.get(ip)

        # Als locatie niet wordt gevonden, wacht dan (voorbeeld van retry)
        if location:
            metric.tags["location"] = location
            metric.tags["debug_info"] = "Added location: " + location + " to metric: " + metric.name
        else:
            # Als locatie niet wordt gevonden, log dit ook en probeer een retry
            metric.tags["debug_info"] = "No location found for IP: " + ip
            # Hier zou je een retry-mechanisme kunnen toevoegen, bijvoorbeeld door de locatie later opnieuw te controleren

    return metric

However, I always get no location found, even within the snmp metric itself:
snmp_sysUptime{agent_host=“1.1.1.1”,debug_info=“No location found for IP: 1.1.1.1”,host=“dashboard”,location=“1234_k1”} 1.6130085e+07. (same for the other metrics)

Please update your post to put it in code blocks for readability.

1 Like

You made a mistake in your starlark script, the metric name doesn’t start with snmp_, the metric name IS snmp :wink:

PS: You could add conversion = "float(2)" to your sysUptime config to have a value in seconds instead of hundreds of seconds.

Thanks for the response.

I only use sysUptime to store sysLocation actually.
I still get the same output, “no location found”. I don’t see what I’m missing. I have edited the script to get even more debug info:

# Globale map om agent_host naar locatie te mappen
location_map = {}

# Functie om de locatie toe te voegen aan metrics
def apply(metric):
    # Log het type metric dat wordt verwerkt
    metric.tags["debug_step"] = "Processing metric: " + metric.name

    # Als de metric informatie over de locatie bevat
    if metric.name == "snmp":
        # Haal de noodzakelijke informatie op
        agent_host = metric.tags.get("agent_host")
        location = metric.tags.get("location")

        # Log de huidige waarden
        metric.tags["debug_agent_host"] = "Agent host: " + (agent_host or "None")
        metric.tags["debug_location"] = "Location: " + (location or "None")

        if agent_host and location:
            # Voeg de locatie toe aan de map
            location_map[agent_host] = location

            # Log de inhoud van location_map
            metric.tags["debug_location_map"] = "Location map updated: " + str(location_map)
            metric.tags["debug_info"] = "Stored location: " + agent_host + " -> " + location
        else:
            # Log wat ontbreekt
            metric.tags["debug_info"] = "Missing location or agent_host for " + metric.name

    # Voor andere metrics
    else:
        # Haal de relevante IP op
        ip = metric.tags.get("agent_host") or metric.tags.get("source") or metric.tags.get("url")
        metric.tags["debug_ip_lookup"] = "IP resolved to: " + (ip or "None")

        if ip:
            # Zoek de locatie in de map
            location = location_map.get(ip)
            metric.tags["debug_location_lookup"] = "Location lookup result: " + (location or "None")

            if location:
                # Voeg de locatie toe
                metric.tags["location"] = location
                metric.tags["debug_info"] = "Added location: " + location + " to metric: " + metric.name
            else:
                # Log dat de locatie niet is gevonden
                metric.tags["debug_info"] = "No location found for IP: " + ip
        else:
            # Log dat geen IP beschikbaar is
            metric.tags["debug_info"] = "No valid IP (agent_host/source/url) found for " + metric.name

    # Log de uiteindelijke status van de metric
    metric.tags["debug_final_status"] = "Final tags: " + str(metric.tags)

    return metric


I still get:

ping,building=‘staticTag’,debug_final_status=Final\ tags:\ {“building”:\ “staticTag”,\ “debug_info”:\ “No\ location\ found\ for\ IP:\ 1.1.1.1”,\ “debug_ip_lookup”:\ “IP\ resolved\ to:\ 1.1.1.1”,\ “debug_location_lookup”:\ “Location\ lookup\ result:\ None”,\ “debug_step”:\ “Processing\ metric:\ ping”,\ “host”:\ “dashboard”,\ “url”:\ “1.1.1.1”},debug_info=No\ location\ found\ for\ IP:\ 1.1.1.1 ,debug_ip_lookup=IP\ resolved\ to:\ 1.1.1.1 ,debug_location_lookup=Location\ lookup\ result:\ None,debug_step=Processing\ metric:\ ping,host=dashboard,url=1.1.1.1average_response_ms=2.376,maximum_response_ms=2.376,minimum_response_ms=2.376,packets_received=1i,packets_transmitted=1i,percent_packet_loss=0,result_code=0i,standard_deviation_ms=0,ttl=254i 1732302632000000000