-
Event Transforms and Examples
-
Beginner examples
-
Dropping events
-
BGP event enhancement
-
Interface High Utilization event enhancement using if, then, elif
-
Assign eventclasskey and event class to SNMP traps and syslog messages
-
Modify event down to specify which interface is down
-
Automatically clear event "Process not running" when the process is restarted
-
Event Mapping based on Interface Description
-
Change severity dependant on count
-
Make Linux Load Averages actual values instead of RAW data.
-
List all Event Transforms
- Event Transforms and Examples
- Beginner examples
- Dropping events
- BGP event enhancement
- Interface High Utilization event enhancement using if, then, elif
- Assign eventclasskey and event class to SNMP traps and syslog messages
- Modify event down to specify which interface is down
- Automatically clear event "Process not running" when the process is restarted
- Event Mapping based on Interface Description
- Change severity dependant on count
- Make Linux Load Averages actual values instead of RAW data.
- List all Event Transforms
Event Transforms and Examples
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.
Beginner examples
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."
Dropping events
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"
BGP event enhancement
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
Interface High Utilization event enhancement using if, then, elif
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
Assign eventclasskey and event class to SNMP traps and syslog messages
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"
Modify event down to specify which interface is down
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)
Automatically clear event "Process not running" when the process is restarted
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"
Event Mapping based on Interface Description
Here's how : Follow the procedure here to set up the active monitoring of interface states : http://www.zenoss.com/Members/cluther/polling-interface-status/
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.*”
Change severity dependant on count
From nyeates:
Following is a simple transform to to increase the severity of an event, as more and more counts (repeats) of the event come in.
# Create the dedup id; This is what zenoss normally does to the event to ascertain if
# it is a duplicate (another occurance) of an existing event. We are doing it in this
# transform to be able to reference the count variable, which does not come with an
# incoming event.
dedupfields = [
evt.device, evt.component, evt.eventClass, evt.eventKey, evt.severity]
if not evt.eventKey:
dedupfields += [evt.summary]
mydedupid = '|'.join(map(str, dedupfields))
# Get the event details (including count) from the existing event that is in the mysql database
em = dmd.Events.getEventManager()
em.cleanCache()
try:
ed = em.getEventDetail(dedupid=mydedupid)
mycount = ed.count
except:
mycount = 0
# Do what you like with the count;
# In this example we up the severity to CRITICAL if the count is > 3
if mycount > 3:
evt.severity = 5
Make Linux Load Averages actual values instead of RAW data.
if evt.summary.startswith('threshold of high load exceeded'):
import re
m = re.search("current value ([\d]+)", evt.summary)
if m:
currentload = float(m.group(1)) / 100
evt.summary = "threshold of high load exceeded: current value %s" % (currentload)
evt.message = "threshold of high load exceeded: current value %s" % (currentload)
List all Event Transforms
From cgriebel:
Simple script to print out all event transforms
#!/usr/bin/env python
import Globals
from Products.ZenUtils.ZenScriptBase import ZenScriptBase
dmd = ZenScriptBase(connect=True).dmd
print "The following event classes have transforms associated with them:"
for ec in [ ec for ec in dmd.Events.getSubOrganizers() if ec.transform ]:
print ec.getOrganizerName()
print ec.transform
print 'X'*80
You may also want to look at here: https://zcaportal.org/wiki/bin/view/ZCA/ZCABestPractices#Transforms