Datasources in Detail¶
How to Determine what Daemon Runs a DataSource¶
The ZenPack documentation should list of daemons and datasource types. If that is not quite enough, then try this:
- First look at the collector daemon’s class, it will specify a
configurationService.
- For a custom daemon, look in the daemons folder.
- Then look at that service, to see what kinds of datasources it includes.
- For custom services, look in the services folder.
- If your datasource inherits from PythonCollector, it probably runs zenpython
How to Determine How Templates Set the DataSource¶
- Look for the sourcetypes variable in objects.xml or datasource.type in zenpack.yaml.
- Now compare that to existing datasources’ sourcetype variable.
General Questions and Answers¶
Question: What’s the difference between a datasource and a datasource plugin?
A datasource is an instance of RRDDataSource. It’s the object that’s part of a monitoring template and stored in ZODB. A datasource plugin is not a persistent ZODB object. It’s a class that is used to perform collection of a specific subclass of RRDDataSource instance: PythonDataSource.
A PythonDataSource has a plugin_classname property that must be set to the fully qualified classname of a PythonDataSourcePlugin class such as “ZenPacks.zenoss.AWS.dsplugins.S3BucketPlugin”.(edited)
Also datasource plugins are a zenpython concept. So all PythonDataSources have PythonDataSourcePlugins, but other kinds of RRDDataSources do not.
So for instance, vsphere has a datasource, but not a plugin.
PythonCollector¶
When using PythonCollector there are two ways to configure collection as described in PythonCollector’s documentation.
- Using the existing PythonDataSource. http://wiki.zenoss.org/ZenPack:PythonCollector#Using_the_Python_Data_Source_Type_Directly
- Subclassing PythonDataSource. http://wiki.zenoss.org/ZenPack:PythonCollector#Extending_the_Python_Data_Source_Type
How do you decide which method to use?
It’s pretty easy to figure out. Do you expect that a Zenoss admin would ever be adding one of your datasources to a monitoring template? If so, the answer is to subclass PythonDataSource to create your own type. If the answer is no, the answer is to not create a PythonDataSource subclass, but to just deliver your own monitoring templates that use the Python data source type with the plugin_classname populated.
Zenoss adds each PythonDataSource subclass as an option in the datasource type drop-down when creating a new datasource in a monitoring template. So don’t pollute that drop-down with things the user will never use, but don’t make the user create “Python” type datasources where they have to provide the correct value for plugin_classname.
Using the Ceph ZenPack as an example, the suggestion would be that none of the PythonDataSourcePlugins implemented therein are generic enough to deserve a PythonDataSource subclass.
Good examples of plugins that deserve a PythonDataSource subclass are “Windows Perfmon”, “Windows Event Log”, “Windows Process”.
Invalid config_keys() in Datasources: Clearing Redis¶
Sometimes if you work on datasource, you can accidentlly insert a bad entry into your config_key() method. This can get cached in redis and result your datasource using the cached value, even if you change the config_key() method later.
You may see a messages like this in your collector logs:
2017-08-17 13:12:08,839 DEBUG zen.collector.config: Fetching daemon configuration properties
Traceback (most recent call last):
File "/usr/lib64/python2.7/logging/__init__.py", line 851, in emit
msg = self.format(record)
File "/usr/lib64/python2.7/logging/__init__.py", line 724, in format
return fmt.format(record)
File "/usr/lib64/python2.7/logging/__init__.py", line 464, in format
record.message = record.getMessage()
File "/usr/lib64/python2.7/logging/__init__.py", line 328, in getMessage
msg = msg % self.args
TypeError: %d format: a number is required, not str
This probably means that the cached config_keys are not in the proper order. Ensure your config_key returns items in the following order:
* context.device().id,
* datasource.getCycleTime(context),
* <whatever>
* <whatever>
* <whatever>
You must ensure that the first and second fields are (str, int).
If you get a broken config key n collectorredis or redis, you may have to flush redis’ cache :
connect to the redis container(s)
list the contents of table 2:
(zenoss) [zenoss@6f913fd44dbb ~]$ redis-cli -n 2 --scan --pattern '*' collector_cache_zenpython-0_devices@@nutanix64 collector_cache_zenpython-0_threshold_classes collector_cache_zenpython-0_property_items collector_cache_zenpython-0_thresholds
Open up redis table 2 in redis-cli:
(zenoss) [zenoss@6f913fd44dbb ~]$ redis-cli -n 2 127.0.0.1:6379[2]> 127.0.0.1:6379[2]> del collector_cache_zenpython-0_devices@@nutanix64 (integer) 1 127.0.0.1:6379[2]> del collector_cache_zenpython-0_property_item (integer) 1 127.0.0.1:6379[2]> exit (zenoss) [zenoss@6f913fd44dbb ~]$ (zenoss) [zenoss@6f913fd44dbb ~]$ redis-cli -n 2 --scan --pattern '*'
Now retry your datasource