Reportables: Modify what is Reported¶
Reportables allow you to control what data Analytis will extract from your zenpack. To invoke reportables you need to create a reportable.py in your zenpack toplevel directory. You can an example of this in:
- ZenPacks.zenoss.OpenStackInfrastructure
Things to consider about Reportables:¶
- Reportables are reporting on properties that come from metric data, which bogs down zenmodeletl: Sometimes this is unavoidable, but sometimes the property isn’t really that important, or worth the extra load on zenmodeletl, so it can be removed to save load.
- Datasource configs are using information from metric data, which bogs down zenperfetl: This is much more likely to be something that is a bug in the zenpack in question, as such values probably are not being propagated to the collector properly anyway, since there would be no invalidations associated with them changing- it is most, at best, a waste of time, and at worst, a bug that will bite us in subtle ways later.
Setup¶
Reportables are configured by creating a reportable.py which inherits from either:
- ZenPacks.zenoss.ZenETL.reportable.Reportable
- ZenPacks.zenoss.ZenETL.reportable.BaseReportable
In addition you will probably need to import a Factory from:
- ZenPacks.zenoss.ZenETL.reportable.BaseReportableFactory
Once you have defined a reportable class for your device or component, you will need to register it in configure.zcml or your equivalent.
Note
Many ZenPacks have a basereportable.py that defines a normalized set of properties. This basereportable is then imported into reportable.py. The purpose of this is to create a simpler reportable.py and provide a more appropriate default set of reportables.
Examples¶
Below is a simple self-contained example which modifies a PortChannel: Note the following:
- entity_class_name must be defined for each property you modify and it must be less than 28 characters long. Exceeding this created dimension (dim_*) table names that cause problems in Analytics.
- reportProperties() is the main class method that provides the change.
import logging
log = logging.getLogger("zen.CiscoMonitor.etl")
from zope.interface import implements
from zope.component import adapts
from ZenPacks.zenoss.CiscoMonitor.PortChannel import PortChannel
from Products.Zuul.interfaces import (
IReportable
)
from ZenPacks.zenoss.ZenETL.reportable import (
MARKER_LENGTH,
BaseReportableFactory,
IpInterfaceReportable,
Reportable
)
class CiscoMonitorBaseRelReportable(Reportable):
implements(IReportable)
def __init__(self, fromObject, toObject):
super(CiscoMonitorBaseRelReportable, self).__init__()
self.fromObject = fromObject
self.toObject = toObject
@property
def id(self):
return "%s__%s" % (self.fromObject.id, self.toObject.id)
@property
def uid(self):
return "%s__%s" % (self.fromObject.uid, self.toObject.uid)
@property
def sid(self):
return "%s__%s" % (IReportable(self.fromObject).sid, IReportable(self.toObject).sid)
class PortChannelReportableFactory(BaseReportableFactory):
adapts(PortChannel)
def exports(self):
# The interface as Interface
yield IpInterfaceReportable(self.context)
for child in self.context.member_interfaces():
yield PortChannelToMemberInterfaceReportable(self.context, child)
class PortChannelToMemberInterfaceReportable(CiscoMonitorBaseRelReportable):
@property
def entity_class_name(self):
return 'cisco_portchannel_interfaces'
def reportProperties(self):
return [
('portchannel_ip_interface_key', 'reference', IReportable(self.fromObject).sid, MARKER_LENGTH),
('ip_interface_key', 'reference', IReportable(self.toObject).sid, MARKER_LENGTH),
]
This is the associated ZCML entry:
<configure zcml:condition="installed ZenPacks.zenoss.ZenETL">
<adapter provides="Products.Zuul.interfaces.IReportableFactory"
for=".PortChannel.PortChannel"
factory=".reportable.PortChannelReportableFactory"
/>
</configure>