Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,14 @@ usage: check_http_json.py [-h] [-d] [-s] -H HOST [-k] [-V] [--cacert CACERT]
[-y [KEY_VALUE_LIST_NOT [KEY_VALUE_LIST_NOT ...]]]
[-Y [KEY_VALUE_LIST_NOT_CRITICAL [KEY_VALUE_LIST_NOT_CRITICAL ...]]]
[-m [METRIC_LIST [METRIC_LIST ...]]]
[-M KEY=VALUE]

Check HTTP JSON Nagios Plugin

Generic Nagios plugin which checks json values from a given endpoint against
argument specified rules and determines the status and performance data for
that service.

Version: 2.2.0 (2024-05-14)

options:
-h, --help show this help message and exit
-d, --debug debug mode
Expand Down Expand Up @@ -125,7 +124,7 @@ options:
(key[>alias],value key2,value2) to determine status.
Multiple key values can be delimited with colon
(key,value1:value2). Return warning if the key is older
than the value (ex.: 30s,10m,2h,3d,...).
than the value (ex.: 30s,10m,2h,3d,...).
With at it return warning if the key is jounger
than the value (ex.: @30s,@10m,@2h,@3d,...).
With Minus you can shift the time in the future.
Expand All @@ -144,6 +143,8 @@ options:
performance data. More information about Range format and units of measure for nagios can be found at nagios-
plugins.org/doc/guidelines.html Additional formats for this parameter are: (key[>alias]),
(key[>alias],UnitOfMeasure), (key[>alias],UnitOfMeasure,WarnRange, CriticalRange).
-M KEY=VALUE Map the values of the gathered metric to the given values. This can be used to map non-numeric values to numeric values, e.g. -M
Up=1. Can used multiple times. This flag is meant to be used with the -m flag.
```

The check plugin respects the environment variables `HTTP_PROXY`, `HTTPS_PROXY`.
Expand Down Expand Up @@ -255,6 +256,28 @@ The check plugin respects the environment variables `HTTP_PROXY`, `HTTPS_PROXY`.

More info about Nagios Range format and Units of Measure can be found at [https://nagios-plugins.org/doc/guidelines.html](https://nagios-plugins.org/doc/guidelines.html).

### Performance Data Metrics

The `-m` and `-M` flags can be used to generate performance data from the JSON data.

```
check_http_json.py -H host.internal --path example-data.json -e 'service.requests' -m 'service.requests'
OK: 'service.requests'=12 Status OK. |'service.requests'=12

check_http_json.py -H host.internal --path example-data.json -e 'service.requests' -m 'service.requests>webshopRequests,c'
OK: 'webshopRequests'=12c Status OK. |'webshopRequests'=12c
```

The `-M` flag can be used to map non-numeric values to numeric values.

```
check_http_json.py -H host.internal --path example-data.json -e 'service.status' -m 'service.status'
OK: 'service.status'=Up Status OK. |'service.requests'=Up

check_http_json.py -H host.internal --path example-data.json -e 'service.status' -m 'service.status' -M Up=1
OK: 'service.status'=1 Status OK. |'service.requests'=1
```

### Timestamp

**Data**:
Expand Down
26 changes: 23 additions & 3 deletions check_http_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,12 @@ def checkMetrics(self):
Return a Nagios specific performance metrics string given keys
and parameter definitions
"""

metrics = ''
warning = ''
critical = ''

kv = dict(self.rules.metric_value_mapping) if hasattr(self.rules, 'metric_value_mapping') else {}

if self.metric_list is not None:
for metric in self.metric_list:
key = metric
Expand All @@ -461,7 +463,10 @@ def checkMetrics(self):
minimum, maximum = vals
key, alias = _getKeyAlias(key)
if self.helper.exists(key):
metrics += "'%s'=%s" % (alias, self.helper.get(key))
value = self.helper.get(key)
# Apply the value mapping if it exists
v = kv.get(str(value), value)
metrics += "'%s'=%s" % (alias, v)
if uom:
metrics += uom
if warn_range is not None:
Expand All @@ -481,7 +486,6 @@ def checkMetrics(self):
metrics += ' '
return ("%s" % metrics, warning, critical)


def parseArgs(args):
"""
CLI argument definitions and parsing
Expand Down Expand Up @@ -608,10 +612,26 @@ def parseArgs(args):
(key[>alias]), (key[>alias],UnitOfMeasure),
(key[>alias],UnitOfMeasure,WarnRange,
CriticalRange).''')
parser.add_argument('-M', dest='metric_value_mapping', metavar="KEY=VALUE",
type=key_value_pair,
action="append",
default=[],
help='''Map the values of the gathered metric to the given values.
This can be used to map non-numeric values to numeric values, e.g. -M Up=1. Can used multiple times.
This flag is meant to be used with the -m flag.''')

return parser.parse_args(args)


def key_value_pair(value):
"""
Small helper to split key=value arguments into a tuple.
"""
parts = value.split('=', 1)
if len(parts) != 2:
raise argparse.ArgumentTypeError('invalid format %s. Expected key=value' % (value))
return (parts[0], parts[1])

def debugPrint(debug_flag, message):
"""
Print debug messages if -d is set.
Expand Down
4 changes: 4 additions & 0 deletions test/test_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ def test_parser_with_separator(self):
parser = parseArgs(['-H', 'foobar', '-f', '_', '-F', '_'])
self.assertEqual(parser.separator, '_')
self.assertEqual(parser.value_separator, '_')

def test_parser_with_value_mapping(self):
parser = parseArgs(['-H', 'foobar', '-M', 'key=value'])
self.assertEqual(parser.metric_value_mapping, [('key', 'value')])
34 changes: 34 additions & 0 deletions test/test_check_http_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,40 @@ def test_critical_thresholds(self):
self.check_data(RulesHelper().dash_c(['(*).value,@1:5']),
'[{"value": 5},{"value": 1000}]', CRITICAL_CODE)

def test_metrics_value_mapping(self):
data = json.loads('{"status": "Up"}')
expected = ("'status'=0 ", '', '')

processor = JsonRuleProcessor(data, parseArgs(['-H', 'foobar', '-m', 'status', '-M', 'Up=0']))
actual = processor.checkMetrics()

self.assertEqual(actual, expected)

data = json.loads('{"status": "Down"}')
expected = ("'status'=1 ", '', '')

processor = JsonRuleProcessor(data, parseArgs(['-H', 'foobar', '-m', 'status', '-M', 'Up=0', '-M', 'Down=1']))
actual = processor.checkMetrics()

self.assertEqual(actual, expected)

def test_metrics_value_mapping_datatypes(self):
data = json.loads('{"status": "123"}')
expected = ("'status'=foo ", '', '')
# Test with string value as target
processor = JsonRuleProcessor(data, parseArgs(['-H', 'foobar', '-m', 'status', '-M', '123=foo']))
actual = processor.checkMetrics()

self.assertEqual(actual, expected)

data = json.loads('{"status": 123}')
expected = ("'status'=foo ", '', '')
# Test with string value as source and target
processor = JsonRuleProcessor(data, parseArgs(['-H', 'foobar', '-m', 'status', '-M', '123=foo']))
actual = processor.checkMetrics()

self.assertEqual(actual, expected)

def test_separator(self):
rules = RulesHelper()
rules.separator = '_'
Expand Down
Loading