I've added some of the examples from a forum thread on Event Transforms. Feel free to add your own or discuss the examples here.
One thing I've noticed that keeps tripping me up is that transforms need to be in the mapping they apply to. They usually will not work in the event class the mapping is in. So, if you have /App/Log/IN as an event mapping, putting a transform in /App/Log doesn't work - it never takes effect. You have to go into the event mapping, edit and put the transform there. One exception to this seems to be (for me) the /Perf/Filesystem event class, there it works as I would expect.
From guyverix:
Here is an example for beginners to be able to start manipulating events. The above stuff is great, but when you are starting out and dont know what is being manipulated and need somewhere to start, here you go, with some easier examples:
Basic transform:
This assumes that you want the detail oid values as your message summary.
This works well for simple transforms, but does not always work as you would think
with string data.
evt.summary = getattr(evt, "--OID# from event Details--")
If the OID value has real string data that you want to display in your summary, try this:
evt.summary = str (getattr(evt, "--OID# from event Details--"))
Now to add different OIDs into your transform, as well as your own text:
(This is a load balancer trap)
evt.summary = "IP addr " + str (getattr(evt, "snL4TrapRealServerIP")) + " Name: "
+ str (getattr(evt, "snL4TrapRealServerName")) + " Port: " + str
(getattr(evt, "snL4TrapRealServerPort")) + " real server port down."
From nyeates:
Following is a simple transform to drop all "oid XXXXXX is bad" events. This is as if the event never existed; the event is not stored in history.
if evt.message.find("Error reading value for") >= 0:
evt._action = "drop"
From gentux31:
We have a lot of customers that have a BGP session with us. When the event normally comes in you just get the message bgpBackwardTransition. So I wrote a event transform like this:
from socket import gethostbyaddr
for attr in dir(evt):
if attr.startswith('1.3.6.1.2.1.15.3.1.14.'):
evt.bgpPeerIp = attr.replace('1.3.6.1.2.1.15.3.1.14.', '')
try:
evt.bgpPeerName = gethostbyaddr(evt.bgpPeerIp)[0]
evt.summary = "bgpBackwardTransNotification from " + evt.bgpPeerIp + " (" + evt.bgpPeerName + ")"
except Exception, ex:
evt.exceptionString = str(ex)
evt.summary = "bgpBackwardTransNotification from " + evt.bgpPeerIp
From Sartuche24:
Here's what I got for an Interface Transform, seems to work for me.
import re
fs_id = device.prepId(evt.component)
for f in device.os.interfaces():
if f.id != fs_id: continue
# Extract the percent and utilization from the summary
m = re.search("threshold of [^:]+: current value ([\d\.]+)", evt.message)
if not m: continue
currentusage = (float(m.groups()[0])) * 8
p = (currentusage / f.speed) * 100
evtKey = evt.eventKey
# Whether Input or Output Traffic
if evtKey == "ifInOctets_ifInOctets|high utilization":
evtNewKey = "Input"
elif evtKey == "ifOutOctets_ifOutOctets|high utilization":
evtNewKey = "Output"
# Check the speed to determine the appropriate conversion
# Gbps utilization
if currentusage > 1000000000:
Usage = currentusage / 1000000000
evt.summary = "High " + evtNewKey + " Utilization: Currently (%3.2f Gbps) or %3.2f%% is being used." % (Usage, p)
# Mbps utilization
elif currentusage > 1000000:
Usage = currentusage / 1000000
evt.summary = "High " + evtNewKey + " Utilization: Currently (%3.2f Mbps) or %3.2f%% is being used." % (Usage, p)
# Kbps utilization
elif currentusage > 1000:
Usage = currentusage / 1000
evt.summary = "High " + evtNewKey + " Utilization: Currently (%3.2f Kbps) or %3.2f%% is being used." % (Usage, p)
# bps utilization
elif currentusage < 1000:
Usage = currentusage
evt.summary = "High " + evtNewKey + " Utilization: Currently (%3.2f bps) or %3.2f%% is being used." % (Usage, p)
break
From Webpass:
Here's some basic transforms to take syslog messages and SNMP traps from Adtran Netvanta devices and assign them an eventclasskey and an event class.. I just threw this in the /Unknown class transform.
import re
match = re.search('OPERATING_SYSTEM:SESSION[^*]', evt.message)
if match and device:
evt.severity = 1
evt.eventClassKey = "AdtranLogin"
evt.eventClass = "/Security/Auth/Login"
match = re.search('(?<=IP:DNS CLIENT)(.*)', evt.message)
if match and device:
evt.severity = 1
evt.eventClassKey = "AdtranDNSTimeout"
evt.eventClass = "/Net/NS"
evt.summary = "DNS Client "+match.group(0)
match = re.search('(?<=ETHERNET_INTERFACE:)([a-z0-9A-Z\-\/ ]*)([0-9*]\/[0-9]*)(.*)', evt.message)
if match and device:
evt.severity = 2
evt.eventClassKey = "ETHERNET_INTERFACE"
evt.eventClass = "/Net/Link"
evt.summary = match.group(0)
evt.component = match.group(1)+match.group(2)
match = re.search('(?<=ETHERNET_STATUS:)([a-z0-9A-Z\-\/ ]*)([0-9*]\/[0-9]*)(.*)', evt.message)
if match and device:
evt.severity = 2
evt.eventClassKey = "ETHERNET_STATUS"
evt.eventClass = "/Net/Link"
evt.summary = match.group(0)
evt.component = match.group(1)+match.group(2)
match = re.search('(?<=INTERFACE_STATUS:)([a-z0-9A-Z\-\/ ]*)([0-9*]\/[0-9]*)(.*)', evt.message)
if match and device:
evt.severity = 2
evt.eventClassKey = "INTERFACE_STATUS"
evt.eventClass = "/Net/Link"
evt.summary = match.group(0)
evt.component = match.group(1)+match.group(2)
match = re.search('Authentication Failure', evt.message)
if match and device:
evt.severity = 1
evt.eventClass = "/Security/Auth/Login"
From cluther:
Try using the following (or something like it) in the transform for the linkUp and linkDown event mapping transforms. Zenoss should already know the description of your interfaces. So we'll just look it up.
index = getattr(evt, 'ifIndex', 0)
descr = getattr(evt, 'ifDescr', 'Unknown Interface')
evt.component = descr
if device:
description = ''
for iface in device.os.interfaces():
if index and iface.ifindex == index:
descr = iface.description
elif descr and iface.name == descr:
descr = iface.description
evt.summary = 'Link down on %s' % (descr)
From Florian Deckert:
Here is an event transform that will automatically move to history a process restarted. when a linux process goes down, an event "Process not running" will be displayed. After the process is manually restarted, the alert is not automatically moved to history.
This is because the event triggered when a process is starting is "Process up". If the summary is being changed to "Process not running" the dedup operation will link the UP event to the DOWN event, and then you can move the event to history.
import re
sum=evt.summary
if (sum.find("Process up:") >= 0):
sum=re.sub ("Process up:", "Process not running:", sum)
evt.summary=sum
evt._action="history"
Only the Event Class Transform is different :
if evt.summary.startswith('threshold of operational status'):
fs_id = device.prepId(evt.component)
for iface in device.os.interfaces():
if iface.id == fs_id:
descr = iface.description
if descr == '':
descr = 'unknown'
# evt.severity = 2 # set the event severity to Info
# evt.eventState = 2 # suppress the event
# evt._action = 'history' # send the event to history
evt._action = 'drop' # drop the event
if evt.severity > 0:
evt.summary = 'Interface %s' % (evt.component) + ' (%s' % (descr) + '), changed state to down'
else:
evt.summary = 'Interface %s' % (evt.component) + ' (%s' % (descr) + '), changed state to up'
If the incoming event is about an interface without a description the event will be dropped. If you want to take a different action when such an event comes in just uncomment the appropriate line. Although, If there is a discription the interface it will be included in the event summary.
For example if device "rtr-test" with interface "FastEthernet0?/1" and description "switch01" goes down the event will be transformed from this :
device : rtr-test, component : FastEthernet0/1, eventClass : /Net/Link, summary : threshold of operational status exceeded : current value 2 ...
to this :
device : rtr-test, component : FastEthernet0/1, eventClass : /Net/Link, summary : Interface FastEthernet0/1 (switch01), changed state to down ...
For those who need to match only certain descriptions can use this code :
import re
if evt.summary.startswith('threshold of operational status'):
fs_id = device.prepId(evt.component)
for iface in device.os.interfaces():
if iface.id == fs_id:
descr = iface.description
match = re.search('(^switch|^ups|^tcm|^bc|server)', descr, re.I)
if not match:
# evt.severity = 2 # set the event severity to Info
# evt.eventState = 2 # suppress the event
# evt._action = 'history' # send the event to history
evt._action = 'drop' # drop the event
if evt.severity > 0:
evt.summary = 'Interface %s' % (evt.component) + ' (%s' % (descr) + '), changed state to down'
else:
evt.summary = 'Interface %s' % (evt.component) + ' (%s' % (descr) + '), changed state to up
If the interface description does not meet one of the criteria (^switch|^ups|^tcm|^bc|server) it will be dropped.
The "re.I" flag makes the search case insensitive.
In this example the description needs to start with switch, ups, tcm or bc, or contain the word server.
From StrongD Fri Jun 5 09:49:44 -0500 2009
From: StrongD
Date: Fri, 05 Jun 2009 09:49:44 -0500
Subject: 3 Solutions for Transform
Message-ID: <20090605094944-0500@www.zenoss.com>
(1) Raw data
10.10.1.240
UDP: [10.10.1.240]:51275
.1.3.6.1.2.1.1.3.0 120:2:20:30.49
.1.3.6.1.6.3.1.1.4.1.0 .1.3.6.1.6.3.1.1.5.3
.1.3.6.1.2.1.2.2.1.1.16 16
.1.3.6.1.2.1.2.2.1.2.16 FastEthernet0/16
.1.3.6.1.2.1.2.2.1.3.16 ethernetCsmacd
.1.3.6.1.4.1.9.2.2.1.1.20.16 "down"
.1.3.6.1.6.3.18.1.3.0 10.10.1.240
.1.3.6.1.6.3.18.1.4.0 "2acce55"
.1.3.6.1.6.3.1.1.4.3.0 .1.3.6.1.4.1.9.1.429
(2) Transform
---------Good---------
index = None
for key, value in evt.__dict__.items():
if key.startswith('1.3.6.1.2.1.2.2.1.1') >= 0:
index = value
break
if index is not None:
for obj in device.os.interfaces.objectItems():
if obj[1].ifindex == index:
evt.component = obj[1].id
evt.summary = "Interface " + evt.component + " is down"
break
--------Good (Recommended) --------------
evt.summary = evt.ifDescr + " is down!"
evt.component = evt.ifDescr
--------Good---------------
evt.summary = getattr(evt, "ifDescr") + " is down!"
evt.component = getattr(evt, "ifDescr")
Notice: once MIB is imported into Zenoss, “ifDescr” should be used intead of “1.3.6.1.2.1.2.2.1.2.*”
There are no comments on this document