Archived community.zenoss.org | full text search
Skip navigation
Currently Being Moderated

Event Transforms & Examples

VERSION 14  Click to view document history
Created on: Sep 14, 2009 11:21 AM by Noel Brockett - Last Modified:  Oct 27, 2011 1:59 PM by jmp242

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

Comments (8)