Use logging to handle console messaging

This commit is contained in:
Scott Wallace 2020-10-23 14:11:32 +01:00
parent 622cb7a635
commit 8e71192d0f
2 changed files with 39 additions and 43 deletions

View file

@ -6,6 +6,7 @@ Module to act as a bridge between Prometheus Alertmanager and Gotify
import argparse import argparse
import functools import functools
import json import json
import logging
import os import os
import sys import sys
from distutils.util import strtobool from distutils.util import strtobool
@ -38,7 +39,7 @@ class HTTPHandler(SimpleHTTPRequestHandler):
Method to handle the request for alerts Method to handle the request for alerts
""" """
if not healthy(self.config): if not healthy(self.config):
print('ERROR: Check requirements') logging.error('Check requirements')
self._respond(500, 'Server not configured correctly') self._respond(500, 'Server not configured correctly')
return return
@ -48,10 +49,13 @@ class HTTPHandler(SimpleHTTPRequestHandler):
try: try:
am_msg = json.loads(rawdata.decode()) am_msg = json.loads(rawdata.decode())
except json.decoder.JSONDecodeError as error: except json.decoder.JSONDecodeError as error:
print(f'ERROR: Bad JSON: {error}') logging.error('Bad JSON: %s', error)
self._respond(400, f'Bad JSON: {error}') self._respond(400, f'Bad JSON: {error}')
return return
logging.debug('Received from Alertmanager:\n%s',
json.dumps(am_msg, indent=2))
gotify_client = gotify.Gotify( gotify_client = gotify.Gotify(
self.config.get('gotify_server'), self.config.get('gotify_server'),
self.config.get('gotify_port'), self.config.get('gotify_port'),
@ -59,15 +63,11 @@ class HTTPHandler(SimpleHTTPRequestHandler):
self.config.get('gotify_client') self.config.get('gotify_client')
) )
if self.config.get('verbose'):
gotify_client.verbose = True
print(f'DEBUG: Received from Alertmanager: {json.dumps(am_msg, indent=2)}')
for alert in am_msg['alerts']: for alert in am_msg['alerts']:
try: try:
if alert['status'] == 'resolved': if alert['status'] == 'resolved':
if self.config.get('disable_resolved'): if self.config.get('disable_resolved'):
print('Ignoring resolved messages') logging.info('Ignoring resolved messages')
self._respond( self._respond(
200, 'Ignored. "resolved" messages are disabled') 200, 'Ignored. "resolved" messages are disabled')
continue continue
@ -77,8 +77,8 @@ class HTTPHandler(SimpleHTTPRequestHandler):
if alert_id: if alert_id:
response = gotify_client.delete(alert_id) response = gotify_client.delete(alert_id)
continue continue
if self.config.get('verbose'): logging.debug(
print('DEBUG: Could not find a matching message to delete.') 'Could not find a matching message to delete.')
prefix = 'Resolved' prefix = 'Resolved'
else: else:
@ -102,7 +102,7 @@ class HTTPHandler(SimpleHTTPRequestHandler):
} }
} }
except KeyError as error: except KeyError as error:
print(f'ERROR: KeyError: {error}') logging.error('KeyError: %s', error)
self._respond(400, f'Missing field: {error}') self._respond(400, f'Missing field: {error}')
return return
@ -128,7 +128,7 @@ class HTTPHandler(SimpleHTTPRequestHandler):
""" """
if self.path == '/healthcheck': if self.path == '/healthcheck':
if not healthy(self.config): if not healthy(self.config):
print('ERROR: Check requirements') logging.error('Check requirements')
self._respond(500, 'ERR') self._respond(500, 'ERR')
self._respond(200, 'OK') self._respond(200, 'OK')
@ -170,7 +170,7 @@ def parse_config(configfile):
with open(configfile, 'r') as file: with open(configfile, 'r') as file:
parsed = yaml.safe_load(file.read()) parsed = yaml.safe_load(file.read())
except FileNotFoundError as error: except FileNotFoundError as error:
print(f'{error}') logging.warning('No config file found (%s)', error.filename)
parsed = {} parsed = {}
# Iterate over the DEFAULTS dictionary and check for environment variables # Iterate over the DEFAULTS dictionary and check for environment variables
@ -184,11 +184,6 @@ def parse_config(configfile):
else: else:
config[key] = type(val)(config[key]) config[key] = type(val)(config[key])
if config['verbose']:
print(
f'DEBUG: Config: '
f'{yaml.dump(config, explicit_start=True, default_flow_style=False)}'
)
return config return config
@ -228,22 +223,33 @@ if __name__ == '__main__':
""" """
main() main()
""" """
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
args = parse_cli() args = parse_cli()
config = parse_config(args.config) config = parse_config(args.config)
if config.get('verbose'):
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
if args.healthcheck: if args.healthcheck:
# Invert the sense of 'healthy' for Unix CLI usage # Invert the sense of 'healthy' for Unix CLI usage
return not healthy(config) return not healthy(config)
listen_port = config.get('listen_port') listen_port = config.get('listen_port')
print(f'Starting web server on port {listen_port}') logging.debug(
'Config:\n%s',
yaml.dump(config, explicit_start=True, default_flow_style=False)
)
logging.info('Starting web server on port %d', listen_port)
try: try:
with HTTPServer(('', listen_port), HTTPHandler) as webserver: with HTTPServer(('', listen_port), HTTPHandler) as webserver:
HTTPHandler.set_config(config) HTTPHandler.set_config(config)
webserver.serve_forever() webserver.serve_forever()
except KeyboardInterrupt: except KeyboardInterrupt:
print('Exiting') logging.info('Exiting')
return 0 return 0

View file

@ -3,13 +3,13 @@ Module to handle communication with the Gotify server
""" """
import http.client import http.client
import json import json
import logging
class Gotify: class Gotify:
""" """
Class to handle Gotify communications Class to handle Gotify communications
""" """
verbose = False
def __init__(self, server, port, app_key, client_key=None): def __init__(self, server, port, app_key, client_key=None):
self.api = http.client.HTTPConnection(server, port) self.api = http.client.HTTPConnection(server, port)
@ -30,14 +30,13 @@ class Gotify:
else: else:
headers['X-Gotify-Key'] = self.app_key headers['X-Gotify-Key'] = self.app_key
if self.verbose: logging.debug('Sending to Gotify:\n%s', body)
print(f'DEBUG: Sending to Gotify: {body}')
try: try:
self.api.request(method, url, body=body, headers=headers) self.api.request(method, url, body=body, headers=headers)
response = self.api.getresponse() response = self.api.getresponse()
except ConnectionRefusedError as error: except ConnectionRefusedError as error:
print(f'ERROR: {error}') logging.error(error)
return { return {
'status': error.errno, 'status': error.errno,
'reason': error.strerror 'reason': error.strerror
@ -53,11 +52,10 @@ class Gotify:
try: try:
resp_obj['json'] = json.loads(rawbody.decode()) resp_obj['json'] = json.loads(rawbody.decode())
except json.decoder.JSONDecodeError as error: except json.decoder.JSONDecodeError as error:
print(f'ERROR: {error}') logging.error(error)
if self.verbose: logging.debug('Returned from Gotify:\n%s', json.dumps(resp_obj, indent=2))
print(f'DEBUG: Returned from Gotify: {json.dumps(resp_obj, indent=2)}') logging.debug('Status: %s, Reason: %s', resp_obj['status'], resp_obj['reason'])
print('DEBUG: Status: {status}, Reason: {reason}'.format(**resp_obj))
return resp_obj return resp_obj
@ -65,8 +63,7 @@ class Gotify:
""" """
Method to delete a message from the Gotify server Method to delete a message from the Gotify server
""" """
if self.verbose: logging.debug('Deleting message ID: %s', msg_id)
print(f'DEBUG: Deleting message ID {msg_id}')
return self._call('DELETE', f'/message/{msg_id}') return self._call('DELETE', f'/message/{msg_id}')
def find_byfingerprint(self, message): def find_byfingerprint(self, message):
@ -76,8 +73,7 @@ class Gotify:
try: try:
new_fingerprint = message['fingerprint'] new_fingerprint = message['fingerprint']
except KeyError: except KeyError:
if self.verbose: logging.debug('No fingerprint found in new message')
print('DEBUG: No fingerprint found in new message')
return None return None
for old_message in self.messages(): for old_message in self.messages():
@ -86,31 +82,25 @@ class Gotify:
if old_fingerprint == new_fingerprint: if old_fingerprint == new_fingerprint:
return old_message['id'] return old_message['id']
except KeyError: except KeyError:
if self.verbose: logging.debug('No fingerprint found in message ID: %s', old_message['id'])
print(
f'DEBUG: No fingerprint found in message {old_message["id"]}'
)
continue continue
if self.verbose: logging.debug('No fingerprint matched.')
print('DEBUG: No fingerprint matched.')
return None return None
def messages(self): def messages(self):
""" """
Method to return a list of messages from the Gotify server Method to return a list of messages from the Gotify server
""" """
if not self.client_key and self.verbose: if not self.client_key:
print('DEBUG: No client key is configured. No messages could be retrieved.') logging.debug('No client key is configured. No messages could be retrieved.')
return [] return []
if self.verbose: logging.debug('Fetching existing messages from Gotify')
print('DEBUG: Fetching existing messages from Gotify')
return self._call('GET', '/message')['json'].get('messages', []) return self._call('GET', '/message')['json'].get('messages', [])
def send_alert(self, payload): def send_alert(self, payload):
""" """
Method to send a message payload to a Gotify server Method to send a message payload to a Gotify server
""" """
if self.verbose: logging.debug('Sending message to Gotify')
print('DEBUG: Sending message to Gotify')
return self._call('POST', '/message', body=json.dumps(payload, indent=2)) return self._call('POST', '/message', body=json.dumps(payload, indent=2))