From def5ff5ea68d663feb7d6bb3464ea4d610e7495c Mon Sep 17 00:00:00 2001 From: luxick Date: Wed, 28 Mar 2018 22:54:02 +0200 Subject: [PATCH] Improve logging on server Log to file and std. Configured in server config file. --- dsst/dsst_server/config.py | 35 +++++++++++++++++++--- dsst/dsst_server/server.py | 61 +++++++++++++++++++++++--------------- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/dsst/dsst_server/config.py b/dsst/dsst_server/config.py index b80336e..0660537 100644 --- a/dsst/dsst_server/config.py +++ b/dsst/dsst_server/config.py @@ -1,5 +1,6 @@ # This config will be copied on first launch. # Edit the the copied file at '~/.config/dsst/server.json' before launching the server +# IMPORTANT: For a client to access the server you have to set authentication tokens in the server config DEFAULT_CONFIG = { 'database': { 'db_name': 'dsst', @@ -7,12 +8,38 @@ DEFAULT_CONFIG = { 'password': 'dsst' }, 'server': { - 'host': 'localhost', 'port': 55225, 'buffer_size': 1024 }, 'tokens': { - '': 'rw', - '': 'r' - } + 'readonly': [], + 'readwrite': [] + }, + 'logging': dict( + version=1, + disable_existing_loggers=False, + formatters={ + 'file': {'format': '[%(levelname)s] %(asctime)s - %(message)s', + 'datefmt': '%Y-%m-%d %H:%M:%S'}, + 'std': {'format': '[%(levelname)s] %(message)s'} + }, + handlers={ + 'console': { + 'class': 'logging.StreamHandler', + 'formatter': 'std', + 'level': 'INFO' + }, + 'logfile': { + 'class': 'logging.handlers.RotatingFileHandler', + 'maxBytes': 3145728, + 'backupCount': 1, + 'formatter': 'file', + 'level': 'INFO' + } + + }, + root={ + 'handlers': ['console', 'logfile'], + 'level': 'INFO' + }) } diff --git a/dsst/dsst_server/server.py b/dsst/dsst_server/server.py index ae02cf1..4a63e67 100644 --- a/dsst/dsst_server/server.py +++ b/dsst/dsst_server/server.py @@ -3,9 +3,11 @@ import pickle import socket import sys import os +import logging +from logging.config import dictConfig -from common import util, models -from dsst_server import func_read, func_write, auth +from common import util +from dsst_server import auth from dsst_server.func_proxy import FunctionProxy from dsst_server.data_access import sql, sql_func from dsst_server.config import DEFAULT_CONFIG @@ -13,54 +15,63 @@ from dsst_server.config import DEFAULT_CONFIG class DsstServer: def __init__(self, config): + # Initialize the logger + try: + logger_dict = config.get('logging') + logfile = os.path.join(os.path.expanduser("~"), '.config', 'dsst', 'server.log') + logger_dict.get('handlers').get('logfile')['filename'] = logfile + dictConfig(logger_dict) + except Exception as e: + print(e) + sys.exit(1) self.socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - print('Created socket') + logging.info('Created socket') server_conf = config.get('server') self.socket_server.bind(('', server_conf.get('port'))) - print('Bound socket to port {}'.format(server_conf.get('port'))) + logging.info('Bound socket to port {}'.format(server_conf.get('port'))) # Initialize database db_config = config.get('database') sql.db.init(db_config.get('db_name'), user=db_config.get('user'), password=db_config.get('password')) sql_func.create_tables() - print('Database initialized ({})'.format(sql.db.database)) + logging.info('Database initialized ({})'.format(sql.db.database)) # Load access tokens auth.READ_TOKENS = config.get('tokens').get('readonly') auth.WRITE_TOKENS = config.get('tokens').get('readwrite') - print('Auth tokens loaded') + logging.info('Auth tokens loaded') def run(self): self.socket_server.listen(5) - print('Socket is listening') + logging.info('Socket is listening') while True: client, address = self.socket_server.accept() try: - print('Connection from {}'.format(address)) + logging.info('Connection from {}'.format(address)) data = util.recv_msg(client) request = pickle.loads(data) - print('Request: {}'.format(request)) + logging.info('Request: {}'.format(request)) # Get requested function from function proxy action_name = request.get('action') action = getattr(FunctionProxy, action_name) - try: - value = action(request.get('auth_token'), *request.get('args')) - except auth.AuthenticationError as e: - response = e.get_response() - util.send_msg(client, pickle.dumps(response)) - raise - except Exception as e: - response = {'success': False, 'message': 'Exception was thrown on server.\n{}'.format(e)} - util.send_msg(client, pickle.dumps(response)) - raise + # Execute requested function + value = action(request.get('auth_token'), *request.get('args')) + # Send results back to client response = {'success': True, 'data': value} util.send_msg(client, pickle.dumps(response)) + logging.info('Operation executed successfully') + except auth.AuthenticationError as e: + logging.error(e.get_response()) + response = e.get_response() + util.send_msg(client, pickle.dumps(response)) except Exception as e: - print('Exception: ' + str(e)) + logging.error('Exception was thrown: ' + str(e)) + response = {'success': False, 'message': 'Exception was thrown on server.'} + util.send_msg(client, pickle.dumps(response)) finally: client.close() - print('Connection to client closed') + logging.info('Connection to client closed') def load_config(config_path: str) -> dict: @@ -80,14 +91,16 @@ def main(): config = os.path.join(os.path.expanduser('~'), '.config', 'dsst', 'server.json') if not os.path.isfile(config): save_config(DEFAULT_CONFIG, config) - print('No server config file found.\nCopied default config to "{}"\nPlease edit file before starting server.' - .format(config)) + logging.error('No server config file found.\n' + 'Copied default config to "{}"\n' + 'Please edit file before starting server.' + .format(config)) sys.exit(0) server = DsstServer(load_config(config)) try: server.run() except KeyboardInterrupt: - print('Server stopped') + logging.info('Server stopped') server.socket_server.close() try: sys.exit(0)