Skip to content

Commit 6b1021e

Browse files
committed
Add githubstatus
1 parent 7e30ddf commit 6b1021e

File tree

19 files changed

+2428
-0
lines changed

19 files changed

+2428
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Monitoring Plugins:
3636
* by-ssh
3737
* cometsystem ([PR #650](https://github.com/Linuxfabrik/monitoring-plugins/pull/650), thanks to [Dominik Riva](https://github.com/slalomsk8er))
3838
* fedora-version
39+
* githubstatus
3940
* grafana-version
4041
* mysql-version
4142
* network-io (fix [#619](https://github.com/Linuxfabrik/monitoring-plugins/issues/619))

check-plugins/githubstatus/.windows

Whitespace-only changes.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Check githubstatus
2+
==================
3+
4+
Overview
5+
--------
6+
7+
Checks the `GitHub status page <https://www.githubstatus.com>`_, including a status indicator, component statuses and unresolved incidents.
8+
9+
Links:
10+
11+
* API Documentation: https://www.githubstatus.com/api
12+
* GitHub Status Page: https://www.githubstatus.com
13+
14+
15+
Fact Sheet
16+
----------
17+
18+
.. csv-table::
19+
:widths: 30, 70
20+
21+
"Check Plugin Download", "https://github.com/Linuxfabrik/monitoring-plugins/tree/main/check-plugins/githubstatus"
22+
"Check Interval Recommendation", "Every 5 minutes"
23+
"Can be called without parameters", "Yes"
24+
"Compiled for", "Linux, Windows"
25+
26+
27+
Help
28+
----
29+
30+
.. code-block:: text
31+
32+
usage: githubstatus [-h] [-V] [--always-ok] [--test TEST]
33+
34+
Checks the GitHub status page, including a status indicator, component
35+
statuses and unresolved incidents.
36+
37+
options:
38+
-h, --help show this help message and exit
39+
-V, --version show program's version number and exit
40+
--always-ok Always returns OK.
41+
--test TEST For unit tests. Needs "path-to-stdout-file,path-to-stderr-
42+
file,expected-retc".
43+
44+
45+
Usage Examples
46+
--------------
47+
48+
.. code-block:: bash
49+
50+
./githubstatus
51+
52+
Output:
53+
54+
.. code-block:: text
55+
56+
1 incindent, 1 component affected. 2023-05-11 17:53:35, minor impact, investigating: Incident with Actions, API Requests, Codespaces, Git Operations, Issues, Pages, Pull Requests and Webhooks. We have reindexed about 20% of the pull requests missing from the /pulls and /search pages.
57+
58+
Component ! Status ! Updated (Etc/UTC)
59+
---------------+----------------+---------------------
60+
Git Operations ! operational ! 2023-05-11 14:40:16
61+
API Requests ! operational ! 2023-05-11 14:40:15
62+
Webhooks ! operational ! 2023-05-11 14:40:18
63+
Issues ! operational ! 2023-05-11 14:40:17
64+
Pull Requests ! partial_outage ! 2023-05-11 13:33:31
65+
Actions ! operational ! 2023-05-11 14:40:14
66+
Packages ! operational ! 2023-04-27 09:56:19
67+
Pages ! operational ! 2023-05-11 14:46:14
68+
Codespaces ! operational ! 2023-05-11 14:40:16
69+
Copilot ! operational ! 2023-05-04 16:18:39
70+
71+
72+
States
73+
------
74+
75+
* WARN if incidents are found
76+
* WARN if any component is not "operational"
77+
78+
79+
Perfdata / Metrics
80+
------------------
81+
82+
.. csv-table::
83+
:widths: 25, 15, 60
84+
:header-rows: 1
85+
86+
Name, Type, Description
87+
components, Number, Number of GitHub components affected.
88+
incidents, Number, Number of incidents.
89+
90+
91+
Credits, License
92+
----------------
93+
94+
* Authors: `Linuxfabrik GmbH, Zurich <https://www.linuxfabrik.ch>`_
95+
* License: The Unlicense, see `LICENSE file <https://unlicense.org/>`_.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8; py-indent-offset: 4 -*-
3+
#
4+
# Author: Linuxfabrik GmbH, Zurich, Switzerland
5+
# Contact: info (at) linuxfabrik (dot) ch
6+
# https://www.linuxfabrik.ch/
7+
# License: The Unlicense, see LICENSE file.
8+
9+
# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.rst
10+
11+
"""See the check's README for more details.
12+
"""
13+
14+
import argparse # pylint: disable=C0413
15+
import json # pylint: disable=C0413
16+
import sys # pylint: disable=C0413
17+
18+
import lib.args # pylint: disable=C0413
19+
import lib.base # pylint: disable=C0413
20+
import lib.human # pylint: disable=C0413
21+
import lib.test # pylint: disable=C0413
22+
import lib.time # pylint: disable=C0413
23+
import lib.txt # pylint: disable=C0413
24+
import lib.url # pylint: disable=C0413
25+
from lib.globals import (STATE_OK, STATE_UNKNOWN, # pylint: disable=C0413
26+
STATE_WARN)
27+
28+
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
29+
__version__ = '2023051102'
30+
31+
DESCRIPTION = """Checks the GitHub status page, including a status indicator,
32+
component statuses and unresolved incidents."""
33+
34+
35+
def parse_args():
36+
"""Parse command line arguments using argparse.
37+
"""
38+
parser = argparse.ArgumentParser(description=DESCRIPTION)
39+
40+
parser.add_argument(
41+
'-V', '--version',
42+
action='version',
43+
version='%(prog)s: v{} by {}'.format(__version__, __author__)
44+
)
45+
46+
parser.add_argument(
47+
'--always-ok',
48+
help='Always returns OK.',
49+
dest='ALWAYS_OK',
50+
action='store_true',
51+
default=False,
52+
)
53+
54+
parser.add_argument(
55+
'--test',
56+
help='For unit tests. Needs "path-to-stdout-file,path-to-stderr-file,expected-retc".',
57+
dest='TEST',
58+
type=lib.args.csv,
59+
)
60+
61+
return parser.parse_args()
62+
63+
64+
def main():
65+
"""The main function. Hier spielt die Musik.
66+
"""
67+
68+
# parse the command line, exit with UNKNOWN if it fails
69+
try:
70+
args = parse_args()
71+
except SystemExit:
72+
sys.exit(STATE_UNKNOWN)
73+
74+
# fetch data
75+
if args.TEST is None:
76+
result = lib.base.coe(
77+
lib.url.fetch_json('https://www.githubstatus.com/api/v2/summary.json'),
78+
)
79+
else:
80+
# do not call the command, put in test data
81+
stdout, stderr, retc = lib.test.test(args.TEST)
82+
result = json.loads(stdout)
83+
84+
# init some vars
85+
msg = ''
86+
state = STATE_OK
87+
perfdata = ''
88+
components, incidents = 0, 0
89+
table_data = []
90+
91+
# analyze data
92+
for incident in result.get('incidents', {}):
93+
incident['updated_at'] = incident.get('updated_at').replace('T', ' ')[:19]
94+
msg += '{}, {} impact, {}: {}. {} '.format(
95+
incident.get('updated_at'),
96+
incident.get('impact'),
97+
incident.get('status'),
98+
incident.get('name'),
99+
incident.get('incident_updates', [])[0].get('body', ''),
100+
)
101+
state = STATE_WARN
102+
incidents += 1
103+
104+
for component in result.get('components', {}):
105+
if 'githubstatus.com' in component.get('name'):
106+
# "Visit www.githubstatus.com for more information"
107+
continue
108+
component['updated_at'] = component.get('updated_at').replace('T', ' ')[:19]
109+
if component.get('status') != 'operational':
110+
state = STATE_WARN
111+
components += 1
112+
113+
table_data.append({
114+
'name': component.get('name'),
115+
'status': component.get('status'),
116+
'updated_at': component.get('updated_at'),
117+
})
118+
119+
if not result.get('incidents', {}) and not result.get('components', {}):
120+
if result.get('status', {}).get('indicator', 'none') != 'none':
121+
state = STATE_WARN
122+
msg = '{} ({})'.format(
123+
result.get('status', {}).get('description', 'none'),
124+
result.get('status', {}).get('indicator', 'none'),
125+
)
126+
127+
# build the message
128+
if state == STATE_OK:
129+
msg = 'Everything is ok.'
130+
else:
131+
msg = '{} {}, {} {} affected. {}'.format(
132+
incidents,
133+
lib.txt.pluralize('incindent', incidents),
134+
components,
135+
lib.txt.pluralize('component', components),
136+
msg,
137+
)
138+
if table_data:
139+
keys = [
140+
'name',
141+
'status',
142+
'updated_at',
143+
]
144+
headers = [
145+
'Component',
146+
'Status',
147+
'Updated ({})'.format(result['page'].get('time_zone', 'TZ n/a')),
148+
]
149+
msg += '\n\n' + lib.base.get_table(table_data, keys, header=headers)
150+
perfdata += lib.base.get_perfdata('components', components, None, None, None, 0, None)
151+
perfdata += lib.base.get_perfdata('incidents', incidents, None, None, None, 0, None)
152+
153+
# over and out
154+
lib.base.oao(msg, state, perfdata, always_ok=args.ALWAYS_OK)
155+
156+
157+
if __name__ == '__main__':
158+
try:
159+
main()
160+
except Exception: # pylint: disable=W0703
161+
lib.base.cu()

0 commit comments

Comments
 (0)