diff --git a/src/alertify.py b/src/alertify.py index d352a14..d88b5d4 100644 --- a/src/alertify.py +++ b/src/alertify.py @@ -6,6 +6,7 @@ Module to act as a bridge between Prometheus Alertmanager and Gotify import argparse import functools import json +import logging import os import sys from distutils.util import strtobool @@ -38,7 +39,7 @@ class HTTPHandler(SimpleHTTPRequestHandler): Method to handle the request for alerts """ if not healthy(self.config): - print('ERROR: Check requirements') + logging.error('Check requirements') self._respond(500, 'Server not configured correctly') return @@ -48,10 +49,13 @@ class HTTPHandler(SimpleHTTPRequestHandler): try: am_msg = json.loads(rawdata.decode()) 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}') return + logging.debug('Received from Alertmanager:\n%s', + json.dumps(am_msg, indent=2)) + gotify_client = gotify.Gotify( self.config.get('gotify_server'), self.config.get('gotify_port'), @@ -59,15 +63,11 @@ class HTTPHandler(SimpleHTTPRequestHandler): 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']: try: if alert['status'] == 'resolved': if self.config.get('disable_resolved'): - print('Ignoring resolved messages') + logging.info('Ignoring resolved messages') self._respond( 200, 'Ignored. "resolved" messages are disabled') continue @@ -77,8 +77,8 @@ class HTTPHandler(SimpleHTTPRequestHandler): if alert_id: response = gotify_client.delete(alert_id) continue - if self.config.get('verbose'): - print('DEBUG: Could not find a matching message to delete.') + logging.debug( + 'Could not find a matching message to delete.') prefix = 'Resolved' else: @@ -102,7 +102,7 @@ class HTTPHandler(SimpleHTTPRequestHandler): } } except KeyError as error: - print(f'ERROR: KeyError: {error}') + logging.error('KeyError: %s', error) self._respond(400, f'Missing field: {error}') return @@ -128,7 +128,7 @@ class HTTPHandler(SimpleHTTPRequestHandler): """ if self.path == '/healthcheck': if not healthy(self.config): - print('ERROR: Check requirements') + logging.error('Check requirements') self._respond(500, 'ERR') self._respond(200, 'OK') @@ -170,7 +170,7 @@ def parse_config(configfile): with open(configfile, 'r') as file: parsed = yaml.safe_load(file.read()) except FileNotFoundError as error: - print(f'{error}') + logging.warning('No config file found (%s)', error.filename) parsed = {} # Iterate over the DEFAULTS dictionary and check for environment variables @@ -184,11 +184,6 @@ def parse_config(configfile): else: 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 @@ -228,22 +223,33 @@ if __name__ == '__main__': """ main() """ + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) + args = parse_cli() config = parse_config(args.config) + if config.get('verbose'): + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + if args.healthcheck: # Invert the sense of 'healthy' for Unix CLI usage return not healthy(config) 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: with HTTPServer(('', listen_port), HTTPHandler) as webserver: HTTPHandler.set_config(config) webserver.serve_forever() except KeyboardInterrupt: - print('Exiting') + logging.info('Exiting') return 0 diff --git a/src/gotify.py b/src/gotify.py index 38ea564..8c472e3 100644 --- a/src/gotify.py +++ b/src/gotify.py @@ -3,13 +3,13 @@ Module to handle communication with the Gotify server """ import http.client import json +import logging class Gotify: """ Class to handle Gotify communications """ - verbose = False def __init__(self, server, port, app_key, client_key=None): self.api = http.client.HTTPConnection(server, port) @@ -30,14 +30,13 @@ class Gotify: else: headers['X-Gotify-Key'] = self.app_key - if self.verbose: - print(f'DEBUG: Sending to Gotify: {body}') + logging.debug('Sending to Gotify:\n%s', body) try: self.api.request(method, url, body=body, headers=headers) response = self.api.getresponse() except ConnectionRefusedError as error: - print(f'ERROR: {error}') + logging.error(error) return { 'status': error.errno, 'reason': error.strerror @@ -53,11 +52,10 @@ class Gotify: try: resp_obj['json'] = json.loads(rawbody.decode()) except json.decoder.JSONDecodeError as error: - print(f'ERROR: {error}') + logging.error(error) - if self.verbose: - print(f'DEBUG: Returned from Gotify: {json.dumps(resp_obj, indent=2)}') - print('DEBUG: Status: {status}, Reason: {reason}'.format(**resp_obj)) + logging.debug('Returned from Gotify:\n%s', json.dumps(resp_obj, indent=2)) + logging.debug('Status: %s, Reason: %s', resp_obj['status'], resp_obj['reason']) return resp_obj @@ -65,8 +63,7 @@ class Gotify: """ Method to delete a message from the Gotify server """ - if self.verbose: - print(f'DEBUG: Deleting message ID {msg_id}') + logging.debug('Deleting message ID: %s', msg_id) return self._call('DELETE', f'/message/{msg_id}') def find_byfingerprint(self, message): @@ -76,8 +73,7 @@ class Gotify: try: new_fingerprint = message['fingerprint'] except KeyError: - if self.verbose: - print('DEBUG: No fingerprint found in new message') + logging.debug('No fingerprint found in new message') return None for old_message in self.messages(): @@ -86,31 +82,25 @@ class Gotify: if old_fingerprint == new_fingerprint: return old_message['id'] except KeyError: - if self.verbose: - print( - f'DEBUG: No fingerprint found in message {old_message["id"]}' - ) + logging.debug('No fingerprint found in message ID: %s', old_message['id']) continue - if self.verbose: - print('DEBUG: No fingerprint matched.') + logging.debug('No fingerprint matched.') return None def messages(self): """ Method to return a list of messages from the Gotify server """ - if not self.client_key and self.verbose: - print('DEBUG: No client key is configured. No messages could be retrieved.') + if not self.client_key: + logging.debug('No client key is configured. No messages could be retrieved.') return [] - if self.verbose: - print('DEBUG: Fetching existing messages from Gotify') + logging.debug('Fetching existing messages from Gotify') return self._call('GET', '/message')['json'].get('messages', []) def send_alert(self, payload): """ Method to send a message payload to a Gotify server """ - if self.verbose: - print('DEBUG: Sending message to Gotify') + logging.debug('Sending message to Gotify') return self._call('POST', '/message', body=json.dumps(payload, indent=2))