File: munin.py

package info (click to toggle)
munin 2.0.76-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,064 kB
  • sloc: perl: 11,684; java: 1,924; sh: 1,632; makefile: 636; javascript: 365; python: 267
file content (177 lines) | stat: -rwxr-xr-x 4,796 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env python

"""
Makes it easy to create munin plugins...

    http://munin-monitoring.org/wiki/protocol-config

Morten Siebuhr
sbhr@sbhr.dk
12/12 2008
"""


def getOptionOrDefault(option, default=None):  # noqa: N802
    from os import environ
    return environ.setdefault(option, default)


class DataSource(object):
    """Represents a single data source.

    This class should not be directly created by the user - this is done
    transparently by the Plugin-class."""

    __slots__ = ['label', 'cdef', 'draw', 'graph', 'info', 'extinfo', 'max',
                 'min', 'negative', 'type', 'warning', 'critical', 'colour',
                 'skipdraw', 'sum', 'stack', 'line', 'value']

    # Allowed draw modes
    _draw_modes = ['AREA', 'STACK',
                   'LINE1', 'LINE2', 'LINE3',
                   'LINESTACK1', 'LINESTACK2', 'LINESTACK3',
                   'AREASTACK']

    def get_config(self):
        if hasattr(self, "draw"):
            assert self.draw in self._draw_modes

        data = dict()

        for attr in self.__slots__:
            if attr == 'value':
                continue
            if hasattr(self, attr):
                data[attr] = self.__getattribute__(attr)

        return data

    def get_value(self, data_source_name):
        assert hasattr(self, "value")

        if callable(self.value):
            return self.value(data_source_name)

        return self.value


class Plugin(object):
    """Facilitates OO creation of Munin plugins.

    #!/usr/bin/env python
    from munin import Plugin

    p = Plugin("Test measurement", "test/second", category="junk")
    p.autoconf = False

    for name, value in {'a': 1, 'b': 2}:
        p[name].label = name
        p[name].value = value

    p.run()

    (It will itself detect how the script is called and create the proper
    output.)

     * If 'autoconf' is a callable, it will be called when running autoconf.

    """

    def __init__(self, title, vlabel, category="misc", info="", args="",
                 scale=True):
        """Sets up the plugin; title, vertical label, category -- all things
        that are global for the plugin.
        """

        self.title = title
        self.vlabel = vlabel
        self.category = category
        self.info = info
        self.args = args
        self.scale = scale

        self._values = dict()

        assert type(title) is str
        assert type(vlabel) is str
        assert type(category) is str

    def __getitem__(self, key):
        if key not in self._values:
            self._values[key] = DataSource()
        return self._values[key]

    def __setitem__(self, key, value):
        self._values[key] = value

    def __delitem__(self, key):
        if key in self._values:
            del self._values[key]

    def __contains__(self, key):
        return key in self._values

    def _print_values(self):
        """Print the values for all registered data sources.

        Similar to running with "values"-argument."""
        for prefix, line in self._values.items():
            value = line.get_value(prefix)
            assert isinstance(value, int)
            print("%s.value %s" % (prefix, value))

    def _print_config(self):
        """Print the output needed for setting up the graph - i.e. when the
        plugin is run with "config"-argument."""
        # Print graph_-variables

        for prop in ['title', 'category', 'vlabel', 'info', 'args', 'draw']:
            if prop not in self.__dict__:
                continue
            if not self.__dict__[prop]:
                continue
            print("graph_%s %s" % (prop, self.__dict__[prop]))

        # Print setup for individual lines
        for prefix, line in self._values.items():

            # The "label" attribute MUST be defined
            assert "label" in line.get_config().keys(), "No 'label' defined."

            for attr, value in line.get_config().items():
                print("%s.%s %s" % (prefix, attr, value))

    def _print_autoconf(self):
        """Running autoconf-mode."""
        aconf = False

        if hasattr(self, "autoconf"):
            if callable(self.autoconf):
                aconf = self.autoconf()
            else:
                aconf = self.autoconf

        if aconf:
            print("yes")
        else:
            print("no")

    def run(self, force_mode=None):
        """Run the plugin and "do the right thing"^(TM)."""

        mode = force_mode

        if mode is None:
            import sys
            if len(sys.argv) == 2:
                mode = sys.argv[1]

        if mode == "autoconf":
            self._print_autoconf()
            return

        if mode == "config":
            self._print_config()
            return

        self._print_values()