aboutsummaryrefslogtreecommitdiffstats
path: root/app/utils/logging
diff options
context:
space:
mode:
Diffstat (limited to 'app/utils/logging')
-rw-r--r--app/utils/logging/__init__.py10
-rw-r--r--app/utils/logging/console_logger.py21
-rw-r--r--app/utils/logging/file_logger.py23
-rw-r--r--app/utils/logging/full_logger.py47
-rw-r--r--app/utils/logging/logger.py99
-rw-r--r--app/utils/logging/message_logger.py21
-rw-r--r--app/utils/logging/mongo_logging_handler.py53
7 files changed, 274 insertions, 0 deletions
diff --git a/app/utils/logging/__init__.py b/app/utils/logging/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/utils/logging/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/utils/logging/console_logger.py b/app/utils/logging/console_logger.py
new file mode 100644
index 0000000..bb8b2ed
--- /dev/null
+++ b/app/utils/logging/console_logger.py
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import logging
+
+from utils.logging.logger import Logger
+
+
+class ConsoleLogger(Logger):
+
+ def __init__(self, level: str = Logger.default_level):
+ super().__init__(logger_name="{}-Console".format(self.PROJECT_NAME),
+ level=level)
+ self.add_handler(logging.StreamHandler())
+
diff --git a/app/utils/logging/file_logger.py b/app/utils/logging/file_logger.py
new file mode 100644
index 0000000..e205bc3
--- /dev/null
+++ b/app/utils/logging/file_logger.py
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import logging.handlers
+
+from utils.logging.logger import Logger
+
+
+class FileLogger(Logger):
+
+ LOG_DIRECTORY = "/local_dir/log/calipso/"
+
+ def __init__(self, log_file: str, level: str = Logger.default_level):
+ super().__init__(logger_name="{}-File".format(self.PROJECT_NAME),
+ level=level)
+ self.add_handler(logging.handlers.WatchedFileHandler(log_file))
+
diff --git a/app/utils/logging/full_logger.py b/app/utils/logging/full_logger.py
new file mode 100644
index 0000000..a88f00e
--- /dev/null
+++ b/app/utils/logging/full_logger.py
@@ -0,0 +1,47 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import logging
+import logging.handlers
+
+from utils.logging.logger import Logger
+from utils.logging.mongo_logging_handler import MongoLoggingHandler
+
+
+class FullLogger(Logger):
+
+ def __init__(self, env: str = None, log_file: str = None,
+ level: str = Logger.default_level):
+ super().__init__(logger_name="{}-Full".format(self.PROJECT_NAME),
+ level=level)
+
+ # Console handler
+ self.add_handler(logging.StreamHandler())
+
+ # Message handler
+ self.add_handler(MongoLoggingHandler(env, self.level))
+
+ # File handler
+ if log_file:
+ self.add_handler(logging.handlers.WatchedFileHandler(log_file))
+
+ # Make sure we update MessageHandler with new env
+ def set_env(self, env):
+ super().set_env(env)
+
+ defined_handler = next(
+ filter(
+ lambda handler: handler.__class__ == MongoLoggingHandler.__class__,
+ self.log.handlers
+ ), None)
+
+ if defined_handler:
+ defined_handler.env = env
+ else:
+ self.add_handler(MongoLoggingHandler(env, self.level))
diff --git a/app/utils/logging/logger.py b/app/utils/logging/logger.py
new file mode 100644
index 0000000..bcf8287
--- /dev/null
+++ b/app/utils/logging/logger.py
@@ -0,0 +1,99 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import logging
+from abc import ABC
+
+
+class Logger(ABC):
+ DEBUG = 'DEBUG'
+ INFO = 'INFO'
+ WARNING = 'WARNING'
+ ERROR = 'ERROR'
+ CRITICAL = 'CRITICAL'
+
+ PROJECT_NAME = 'CALIPSO'
+
+ levels = [DEBUG, INFO, WARNING, ERROR, CRITICAL]
+ log_format = '%(asctime)s %(levelname)s: %(message)s'
+ formatter = logging.Formatter(log_format)
+ default_level = INFO
+
+ def __init__(self, logger_name: str = PROJECT_NAME,
+ level: str = default_level):
+ super().__init__()
+ self.check_level(level)
+ self.log = logging.getLogger(logger_name)
+ logging.basicConfig(format=self.log_format,
+ level=level)
+ self.log.propagate = False
+ self.set_loglevel(level)
+ self.env = None
+ self.level = level
+
+ def set_env(self, env):
+ self.env = env
+
+ @staticmethod
+ def check_level(level):
+ if level.upper() not in Logger.levels:
+ raise ValueError('Invalid log level: {}. Supported levels: ({})'
+ .format(level, ", ".join(Logger.levels)))
+
+ @staticmethod
+ def get_numeric_level(loglevel):
+ Logger.check_level(loglevel)
+ numeric_level = getattr(logging, loglevel.upper(), Logger.default_level)
+ if not isinstance(numeric_level, int):
+ raise ValueError('Invalid log level: {}'.format(loglevel))
+ return numeric_level
+
+ def set_loglevel(self, loglevel):
+ # assuming loglevel is bound to the string value obtained from the
+ # command line argument. Convert to upper case to allow the user to
+ # specify --log=DEBUG or --log=debug
+ numeric_level = self.get_numeric_level(loglevel)
+
+ for handler in self.log.handlers:
+ handler.setLevel(numeric_level)
+ self.log.setLevel(numeric_level)
+ self.level = loglevel
+
+ def _log(self, level, message, *args, exc_info=False, **kwargs):
+ self.log.log(level, message, *args, exc_info=exc_info, **kwargs)
+
+ def debug(self, message, *args, **kwargs):
+ self._log(logging.DEBUG, message, *args, **kwargs)
+
+ def info(self, message, *args, **kwargs):
+ self._log(logging.INFO, message, *args, **kwargs)
+
+ def warning(self, message, *args, **kwargs):
+ self._log(logging.WARNING, message, *args, **kwargs)
+
+ def warn(self, message, *args, **kwargs):
+ self.warning(message, *args, **kwargs)
+
+ def error(self, message, *args, **kwargs):
+ self._log(logging.ERROR, message, *args, **kwargs)
+
+ def exception(self, message, *args, **kwargs):
+ self._log(logging.ERROR, message, exc_info=True, *args, **kwargs)
+
+ def critical(self, message, *args, **kwargs):
+ self._log(logging.CRITICAL, message, *args, **kwargs)
+
+ def add_handler(self, handler):
+ handler_defined = handler.__class__ in map(lambda h: h.__class__,
+ self.log.handlers)
+
+ if not handler_defined:
+ handler.setLevel(self.level)
+ handler.setFormatter(self.formatter)
+ self.log.addHandler(handler)
diff --git a/app/utils/logging/message_logger.py b/app/utils/logging/message_logger.py
new file mode 100644
index 0000000..02e098f
--- /dev/null
+++ b/app/utils/logging/message_logger.py
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import logging
+
+from utils.logging.logger import Logger
+from utils.logging.mongo_logging_handler import MongoLoggingHandler
+
+
+class MessageLogger(Logger):
+
+ def __init__(self, env: str = None, level: str = None):
+ super().__init__(logger_name="{}-Message".format(self.PROJECT_NAME),
+ level=level)
+ self.add_handler(MongoLoggingHandler(env, self.level))
diff --git a/app/utils/logging/mongo_logging_handler.py b/app/utils/logging/mongo_logging_handler.py
new file mode 100644
index 0000000..b69270e
--- /dev/null
+++ b/app/utils/logging/mongo_logging_handler.py
@@ -0,0 +1,53 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import datetime
+import logging
+
+from messages.message import Message
+from utils.inventory_mgr import InventoryMgr
+from utils.logging.logger import Logger
+from utils.string_utils import stringify_datetime
+
+
+class MongoLoggingHandler(logging.Handler):
+ """
+ Logging handler for MongoDB
+ """
+ SOURCE_SYSTEM = 'Calipso'
+
+ def __init__(self, env: str, level: str):
+ super().__init__(Logger.get_numeric_level(level))
+ self.str_level = level
+ self.env = env
+ self.inv = None
+
+ def emit(self, record):
+ # Try to invoke InventoryMgr for logging
+ if not self.inv:
+ try:
+ self.inv = InventoryMgr()
+ except:
+ return
+
+ # make sure we do not try to log to DB when DB is not ready
+ if not (self.inv.is_db_ready()
+ and 'messages' in self.inv.collections):
+ return
+
+ # make ID from current timestamp
+ now = datetime.datetime.utcnow()
+ d = now - datetime.datetime(1970, 1, 1)
+ ts = stringify_datetime(now)
+ timestamp_id = '{}.{}.{}'.format(d.days, d.seconds, d.microseconds)
+ source = self.SOURCE_SYSTEM
+ message = Message(msg_id=timestamp_id, env=self.env, source=source,
+ msg=Logger.formatter.format(record), ts=ts,
+ level=record.levelname)
+ self.inv.collections['messages'].insert_one(message.get()) \ No newline at end of file