GithubHelp home page GithubHelp logo

sensu-plugins / sensu-plugin-python Goto Github PK

View Code? Open in Web Editor NEW
64.0 20.0 22.0 105 KB

A framework for writing Sensu plugins & handlers with Python.

Home Page: http://sensu-plugins.io

License: MIT License

Python 93.50% Shell 5.09% Dockerfile 1.41%
sensu sensu-plugin python monitoring library

sensu-plugin-python's Introduction

sensu

Python Sensu Plugin

This is a framework for writing your own Sensu plugins in Python. It's not required to write a plugin (most Nagios plugins will work without modification); it just makes it easier.

Build Status

Checks

To implement your own check, subclass SensuPluginCheck, like this:

from sensu_plugin import SensuPluginCheck

class MyCheck(SensuPluginCheck):
  def setup(self):
    # Setup is called with self.parser set and is responsible for setting up
    # self.options before the run method is called

    self.parser.add_argument(
      '-w',
      '--warning',
      required=True,
      type=int,
      help='Integer warning level to output'
    )
    self.parser.add_argument(
      '-m',
      '--message',
      default=None,
      help='Message to print'
    )


  def run(self):
    # this method is called to perform the actual check

    self.check_name('my_awesome_check') # defaults to class name

    if self.options.warning == 0:
      self.ok(self.options.message)
    elif self.options.warning == 1:
      self.warning(self.options.message)
    elif self.options.warning == 2:
      self.critical(self.options.message)
    else:
      self.unknown(self.options.message)

if __name__ == "__main__":
  f = MyCheck()

Remote (JIT) Checks

To submit checks on behalf of another system, import push_event:

from sensu_plugin.pushevent import push_event

Then use with:

push_event(source="a_remote_host", check_name="MyCheckName", exit_code=2, message="My check has failed")

This will submit a check result (a failure) appearing to come from the remote host 'a_remote_host', for check 'MyCheckName'.

The default assumption is that there is a local sensu client running on port 3030, but you can override this by passing in sensu_client_host and sensu_client_port parameters.

The check submits the check in json format. Arbitrary extra fields can be added, e.g.

push_event(source="a_remote_host", check_name="MyCheckName", exit_code=2, message="My check has failed", team="MyTeam")

Metrics

For a metric you can subclass one of the following;

  • SensuPluginMetricGraphite
  • SensuPluginMetricInfluxdb
  • SensuPluginMetricJSON
  • SensuPluginMetricStatsd

Graphite

from sensu_plugin import SensuPluginMetricGraphite

class MyGraphiteMetric (SensuPluginMetricGraphite):
    def run(self):
        self.ok('sensu', 1)

if __name__ == "__main__":
    metric = MyGraphiteMetric()

Influxdb

from sensu_plugin import SensuPluginMetricInfluxdb

class MyInfluxdbMetric (SensuPluginMetricInfluxdb):
    def run(self):
        self.ok('sensu', 'baz=42', 'env=prod,location=us-midwest')

if __name__ == "__main__":
    metric = MyInfluxdbMetric()

JSON

from sensu_plugin import SensuPluginMetricJSON

class MyJSONMetric(OLDSensuPluginMetricJSON):
    def run(self):
        self.ok({'foo': 1, 'bar': 'anything'})

if __name__ == "__main__":
    metric = MyJSONMetric()

StatsD

from sensu_plugin import SensuPluginMetricStatsd

class MyStatsdMetric(SensuPluginMetricStatsd):
    def run(self):
        self.ok('sensu.baz', 42, 'g')

if __name__ == "__main__":
    metric = MyStatsdMetric()

License

  • Based heavily on sensu-plugin Copyright 2011 Decklin Foster
  • Python port Copyright 2014 S. Zachariah Sprackett

Released under the same terms as Sensu (the MIT license); see LICENSE for details

sensu-plugin-python's People

Contributors

absolutejam avatar barryorourke avatar dbrgn avatar dependabot-preview[bot] avatar oboukili avatar philipharries avatar zsprackett avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sensu-plugin-python's Issues

In need of Maintainer(s)

This repository is super helpful to those who use it. @zsprackett, @nstielau and @joemiller took great care of it for quite some time, but it looks now that they could use some help.

I'd like to bring up the need to have a regular maintainer. Someone who is strong in python, knows Sensu and is willing to join a growing number of maintainers across the Sensu projects (active members include @eheydrick @majormoses @luisdavim @sstarcher @mattyjones).

If you're interested, please comment on this issue. If you're a user of this repo, please give a ๐Ÿ‘ to let us know you're using it and this is important to you.

Graphite plugin does not allow passing objects to unknown()

When using SensuPluginMetricGraphite, doing something like

try:
    some_code()
except Exception as e:
    self.unknown(e)

does not work, giving an IndexError.

The code of this class isn't terribly obvious and isn't documented, so it's hard to ascertain what the intended behavior and API are. But I'm guessing that this use case is supposed to work, based on the second if statement:

        elif isinstance(args[0], Exception) or args[1] is None:
            print(args[0])

However, it never will when called via ok(), unknown(), etc. This is because the base class forwards its arguments as a tuple, so when SensuPluginMetricGraphite gets to it, you'll have a tuple of whatever the original arguments are (for instance, a one-element tuple of an Exception).

Changing self.output(args) to self.output(*args) fixes this, but will probably break other things; I think the root of the problem is that some of the subclasses use def output(self, args), while others use def output(self, *args), making it hard to reason about how data should be passed into all of them from one place.

test coverage

Coverage is incredibly low at the moment, we should look into adding more tests to increase it.

Missing dependency: requests

Using pip install sensu-plugin will not install requests, breaking SensuPlugin import:

$ python sensu.py 
Traceback (most recent call last):
  File "sensu.py", line 2, in <module>
    from sensu_plugin import SensuPlugin
  File "/home/hukka/.pyenv/versions/browsertests/lib/python3.6/site-packages/sensu_plugin/__init__.py", line 7, in <module>
    from sensu_plugin.handler import SensuHandler
  File "/home/hukka/.pyenv/versions/browsertests/lib/python3.6/site-packages/sensu_plugin/handler.py", line 18, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

Passing arguments

Passing in any arguments into checks fails due to the the init of the Sensu Plugin class

Keep getting error: "unrecognized arguments"

Using program without the sensu plugin and it works fine.

setup.py doesn't specify the utils package

https://github.com/sensu-plugins/sensu-plugin-python/blob/master/setup.py#L8 doesn't list the utils subpackage, breaking importing SensuPlugin after pip install sensu-plugin:

$ python sensu.py 
Traceback (most recent call last):
  File "sensu.py", line 2, in <module>
    from sensu_plugin import SensuPlugin
  File "/home/hukka/.pyenv/versions/browsertests/lib/python3.6/site-packages/sensu_plugin/__init__.py", line 7, in <module>
    from sensu_plugin.handler import SensuHandler
  File "/home/hukka/.pyenv/versions/browsertests/lib/python3.6/site-packages/sensu_plugin/handler.py", line 23, in <module>
    from sensu_plugin.utils import get_settings
ModuleNotFoundError: No module named 'sensu_plugin.utils'
$ ls /home/hukka/.pyenv/versions/browsertests/lib/python3.6/site-packages/sensu_plugin
check.py   exithook.py  __init__.py  plugin.py     __pycache__
compat.py  handler.py   metric.py    pushevent.py  test

Python version support

I'd like to change the version of python supported by the module from the current;

2.7, 3.3, 3.4

to the more modern;

2.7, 3.4, 3.6

and also propose that we follow a similar support model as the ruby module, which is to support all non-EOL versions.

Looking for SGTM's from at least two of the following @luisdavim, @majormoses, @mbbroberg & @eheydrick, comments from others are very welcome :)

Document and refactor/simplify existing codebase

Work on adding missing docstrings and general documentation to existing codebase, and explain some of the design choices (Eg. use of exit hook).

This will pave the way for easier refactoring for testing and generally make the project more usable as a starting point, and for debugging.

Should exclude argparse from dependencies

argparse is included with python... unless you're using an ancient python (pre-2.7 or pre-3.2 if on 3.x). the effect of this inclusion as a dependency in sensu-plugin is that anything depending on sensu-plugin will also pull in the 3rd party argparse module, which then takes precedence over the builtin module. this is bad primarily because users of sensu-plugin are being unwittingly pinned to an ancient, unsupported version of argparse, without recent features & bugfixes. I only discovered this because some newer code (from a different 3rdparty lib) was choking with an error:

__init__() got an unexpected keyword argument 'allow_abbrev'

allow_abbrev is a valid parameter for the python's argparse.ArgumentParser, but not the 3rd party legacy version.

it seems reasonable to simply remove the dependency, and force users who are on very old versions of python to manually include the 3rd party argparse in their dependencies.

i've made the relevant 2-line fix in this fork's branch. wasn't sure what to do about changelog etc since technically this is a "breaking" change... but only for (hopefully) a tiny subset of users. for the rest of the universe, it fixes (IMHO) a serious issue.

PyPI access and housekeeping

The issue will be used to track all of the housekeeping work required to allow the new maintainers of this repo access to PyPI, so that we are able to make releases.

  • @barryorourke added to the Package Index Owners list
  • @absolutejam, @majormoses added to the Package Index Owners list
  • sensu_plugins account created on PyPI
  • sensu_plugins account added to the Package Index Owners list
  • demote everyone except sensu_plugins to maintainer.

accessing custom plugin settings

In ruby framework, I can create custom settings like,

{
  "my_custom_plugin": {
    "foo": true,
    "bar": false
  }
}

and access them in plugin,

def foo_enabled?
  settings['my_custom_plugin']['foo']
end

how can it be done in python framework?

Go Python 3!

Would be nice to work with sensu_plugin on python 3.

Mark version 0.1

Via python pip I'm able to install a "version 0.1.0", but it seems not reflected in this repos.

Unit Testing SensuPluginCheck Implementations is Difficult

The current implementation of this plugin uses the constructor to create and run the Sensu check. This makes it very difficult to implement unit tests over part of your health check. It does not appear possible to execute a test over a method inside your new class.

I would like to be able to instantiate and test a SensuPluginCheck without executing my entire health check.

For example consider this health check:

from sensu_plugin import SensuPluginCheck

class SensuHealthCheckExample(SensuPluginCheck):
    def collect_data(self):
        return "this is some data from my health check"

    def verify_data(self, data):
        return True

    def setup(self):
        self.some_argument = True

    def run(self):
        data = self.collect_data()
        if self.verify_data(data):
            self.ok("Everything is going to be alright")
        else:
            self.critical("Everything is NOT alright")

With the current implementation of this plugin calling __init__ of SensuHealthCheckExample not only creates the instance but also causes it to execute the full check. This makes it very difficult for example if I am attempting to put my verify_data function under test. I can not separate the test down to a single unit.

What is the best way to accomplish adding unit tests over these checks so that some of the more complex checks can be tested and maintained more easily?

Improve push event testing

I have added a very basic test for push events, this needs expanded upon to include testing of socket related code.

License information in classifiers

This is a pretty mundane issue. You declare the license as LICENSE.txt in setup.py. This makes this code slightly harder to import in organizations that checks licenses.

If you look at meta information on pypi.org for your package, you will see that your license is just LICENSE.txt: https://pypi.org/project/sensu_plugin/

license='LICENSE.txt',

should become

classifiers=[
        'Programming Language :: Python :: 2.7',
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
],

Even more mundane. LICENSE.txt should get renamed to just LICENSE

More about info about these changes can be found here: https://packaging.python.org/tutorials/packaging-projects

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.