Writing Native Plugins
While the Outlyer agent can run standard Nagios plugins and scrape Promtheus endpoints, it also supports a plugin format called
Native
which is specific to the Outlyer agent. All our standard integrations are written in this format which outputs a JSON
payload with collected metrics that the agent can forward to Outlyer.
Although Open-Source standards is at the core of our design philosophy, there is currently no Open-Source plugin standard which allows different metric types (counters, gauges) to be collected with labels alongside events, which resulted in us creating this new plugin format for Outlyer. Over time we will evolve this plugin type to support more metric types and responses that enable our standard integrations to collect more information about your services when they run.
The plugin type supports Python and inherits from the outlyer_plugin
module which will be made available as a seperate module
outside the agent runtime soon for developing Outlyer plugins outside Outlyer. If you develop plugins using our built in plugin IDE
in the Outlyer web application, they will run from the agent successfully.
The Basic Plugin Structure
At the most basic level, a plugin inherits the Plugin
class which provides utility methods to collect metrics, status, events
and logs from a plugin when it runs. It also outputs the JSON format required by the agent to parse the plugin output to forward
this information to Outlyer.
As plugins run as a subprocess scheduled by the Outlyer agent, they must contain an ___main__
function at the end so they can run as
a stand alone process when scheduled. A Status
class is also provided to output different exit status codes so the agent can tell
if the plugin ran successfully, was warning, critical or unknown, after it runs.
import sys
from outlyer_plugin import Plugin, Status
class MyPlugin(Plugin):
def collect(self, _):
return Status.OK
if __name__ == '__main__':
sys.exit(MyPlugin().run())
The code above forms the basis of the Outlyer Native plugin and at this point will simply run and return an OK status.
Available Plugin Methods
To make the plugin more useful, the following methods are available from inside your Plugin class:
Get a Check Variable
If you run the plugin as part of a check with variable settings set (i.e. port number or username) you can get these check variables as Strings using the following method:
port = self.get('port', 'default')
This will get the plugin variable ‘port’ if set on the check running the plugin, and the variable hasn’t been applied will return the default value ‘default’ instead.
Collect Metrics
Outlyer plugins can collect Counters and Gauges, with more metric types (i.e. Histograms) planned soon. A metric has a name, optional labels, a value and an optional timestamp.
A counter should be used for collected values that increase over time and don’t go up and down. You can collect a counter using the following method:
self.counter(name: str, labels: Optional[dict]) -> Counter
A gauge should be used to collect values that can go up and down over time. You can collect a gauge using the following method:
self.gauge(name: str, labels: Optional[dict]) -> Gauge
All metric classes have a set
method that allows you to set a value and an optional timestamp for the metric. If no timestamp is given
it will use the current time the plugin was run as the timestamp for the metric value.
For example, the following code will set a counter ‘sys.cpu_time’ and a gauge ‘sys.cpu_pct’ with the timestamp overriden:
self.counter('sys.cpu_time', {'process': 'mysql'}).set(1243343.00)
# Get current time in unix UTC time seconds
ts = int(datetime.utcnow() * 1000)
self.gauge('sys.cpu_pct', {'process': 'mysql'}).set(34.34, ts=ts)
Status Codes
The Status
class is provided to return standard status codes which indicate the status of a plugin:
Enumeration | Value | Description |
---|---|---|
Status.OK | 0 | Plugin exited OK without any issues |
Status.WARNING | 1 | Plugin exited with Warning, but isn’t critical yet |
Status.CRITICAL | 2 | Plugin exited with Critical, meaning there was a problem with the service its monitoring |
Status.UNKNOWN | 3 | Plugin exited with unknown status. Use this if a plugin hasn’t bee setup properly or has a code error |
When you exit the collect()
method of the plugin class, simply return one of the enumerations above to send the
plugin status code.
Further Reading
For more inspiration on how to run Outlyer Native plugins you can look through our integrations repo.