telegraf.conf file
[agent]
debug = true
quiet = false
interval = “10s”
round_interval = true
metric_batch_size = 10000
metric_buffer_limit = 100000
flush_interval = “10s”
[[inputs.snmp_trap]]
service_address = “udp://:1610”
path = [“/usr/smp/snmp/mibs”]
[[processors.execd]]
command = [“/usr/bin/python3”,“/var/telegraf/alarm_script.py”]
restart_delay = “10s”
[[outputs.file]]
files = [“stdout”,“/var/log/telegraf/metrics.json”]
This is my telegraf file and when I receive a trap from any controller it comes in
sample trap:
snmp_trap,community=public,host=slp.com,mib=ALPHA-NOTIFICATION-MIB,name=alphaAlarmClearState,oid=.1.3.6.1.4.1.7.10.2,source=10.413.18.10,version=2c sysUpTime.0=586294866i,alarmActiveModelPointer=“alarmModelEntry.20004.4”,alarmModelDescription.20004.4=“DC System 48V : Output Voltage High : Major”,alarmSeverity=0i,alarmCustomDescription=“—”,alarmAdditionalInformation=“::”,alarmActiveResourceId=“componentListStaticName.1”,alarmModelState.20004.4=3i,componentListStaticName.2.1=“REWCP12WEL-HP (DC System 48V/2259)”,componentListReference.2.1=1i,controllerInfoName=" REWCP12WEL" 1746542789735623327
This is my alarm_script.py file
import sys
import re
from datetime import datetime
def escape_influx_string(value):
“”“Escape special characters for Influx Line Protocol.”“”
if value is None:
return “” # Return an empty string if the value is None
if isinstance(value, str):
return value.replace(‘"’, ‘“”’)
return value
Read metrics from STDIN
for line in sys.stdin:
try:
# Strip whitespace and skip empty lines
line = line.strip()
if not line:
continue
# Prepare the trap input
trap_input = line
# Extract and remove the last number (alarm_time_ns) from the trap input
trap_parts = trap_input.rsplit(' ', 1)
trap_body = trap_parts[0]
alarm_time_ns = trap_parts[1]
# Remove 'version=2c' from the trap body
trap_body = trap_body.replace('version=2c ', '') # Ensure only 'version=2c ' is removed
# Parse the trap body into a dictionary
trap = dict(pair.split('=', 1) for pair in trap_body.split(',') if '=' in pair)
trap["time_ns"] = alarm_time_ns
# Extract values from the trap
alarm_state = trap.get("name", "unknown")
alarm_source_ip = trap.get("source", "unknown")
alarm_oid = trap.get("oid", "unknown")
alarm_time_ns = trap.get("time_ns", "0")
# Determine alarm state
if alarm_state in ["alphaAlarmActiveState", "dcPwrSysAlarmActiveTrap"]:
alarm_state = "Active"
elif alarm_state in ["alphaAlarmClearState", "dcPwrSysAlarmClearedTrap"]:
alarm_state = "InActive"
elif alarm_state == "dcPwrSysRelayTrap":
alarm_state = "RelayTrap"
# Use regex to find alarm name field
alarm_name = None
for key in trap.keys():
if re.match("alarmModelDescription", key):
alarm_name = trap[key].strip("'")
break
elif re.match("dcPwrSysCurrAlrmStringValue", key):
alarm_name = trap[key].strip("'")
break
elif re.match("dcPwrSysRelayStringValue", key):
alarm_name = trap[key].strip("'")
break
elif re.match("dcPwrSysMiscAlrmStringValue", key):
alarm_name = trap[key].strip("'")
break
elif re.match("dcPwrSysRectAlrmStringValue", key):
alarm_name = trap[key].strip("'")
break
elif re.match("dcPwrSysBattAlrmStringValue", key):
alarm_name = trap[key].strip("'")
break
# Use regex to find alarm source CLLI field
alarm_source_clli = None
for key in trap.keys():
if re.match("controllerInfoName", key):
alarm_source_clli = trap[key].strip("'")
break
elif re.match("dcPwrSysSiteName", key):
alarm_source_clli = trap[key].strip("'")
break
# Create Influx Line Protocol output
influx_line = (
f"alarm,source_ip={alarm_source_ip},state={alarm_state} "
f"name={alarm_name},oid={alarm_oid},source_clli={alarm_source_clli} {alarm_time_ns}"
)
# Print the Influx Line Protocol to STDOUT
print(influx_line)
except Exception as e:
# Print error message to STDERR
print(f"Error processing trap: {e}", file=sys.stderr)
The Problem which I’m facing is that the traps can be printed and can also be saved to a file if the processor plugin is not used but when I use this processor plugin, traps does go into the script but it does not print anything or saves anything in the file
My end goal:
I have two types of controller this script will create one common payload regardless of the type of controller.
I also make sure that the output matches the Influx line protocol still
any help