From 33206ca0b032ea0dfdfd719ace59bcf25be49994 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 20 Nov 2015 11:18:22 +0800 Subject: [PATCH 1/5] Separate possible side effects of using root logger by using a standalone logger. Bug fixs. INFO, WARNING etc now works. Now log could be configured to be written to file as well. --- glog.py | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/glog.py b/glog.py index 6b975f4..5baae77 100644 --- a/glog.py +++ b/glog.py @@ -112,10 +112,7 @@ def format(self, record): record.getMessage = lambda: record_message return logging.Formatter.format(self, record) -logger = logging.getLogger() -handler = logging.StreamHandler() - -level = logger.level +logger = logging.getLogger("glog") def setLevel(newlevel): @@ -124,24 +121,35 @@ def setLevel(newlevel): logger.debug('Log level set to %s', newlevel) -def init(): +def init(filename=None): + logger.propagate = False + if filename is None: + handler = logging.StreamHandler() + else: + handler = logging.FileHandler(filename) + + handler.setFormatter(GlogFormatter()) + logger.addHandler(handler) setLevel(FLAGS.verbosity) -debug = logging.debug -info = logging.info -warning = logging.warning -warn = logging.warning -error = logging.error -exception = logging.exception -fatal = logging.fatal -log = logging.log - -DEBUG = logging.DEBUG -INFO = logging.INFO -WARNING = logging.WARNING -WARN = logging.WARN -ERROR = logging.ERROR -FATAL = logging.FATAL +debug = logger.debug +info = logger.info +warning = logger.warning +warn = logger.warning +error = logger.error +exception = logger.exception +fatal = logger.fatal +log = logger.log + + +DEBUG = logger.debug +INFO = logger.info +WARNING = logger.warning +WARN = logger.warning +ERROR = logger.error +FATAL = logger.fatal + +# basicConfig = logger.basicConfig _level_names = { DEBUG: 'DEBUG', @@ -166,6 +174,4 @@ def init(): """) % ''.join(_level_letters) """Regex you can use to parse glog line prefixes.""" -handler.setFormatter(GlogFormatter()) -logger.addHandler(handler) -setLevel(FLAGS.verbosity) +init() From fb0501c164011077f31d187d37959c3a23c71cbc Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 20 Nov 2015 11:23:19 +0800 Subject: [PATCH 2/5] Updated doc. --- README.rst | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 1fb8095..06a1b98 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,8 @@ that uses the standard Python logging module will play along nicely. Behaviours ---------- -- Messages are always written to stderr. +- Messages are always written to stderr by default. A copy could be saved to + file by configuration. - Lines are prefixed with a google-style log prefix, of the form @@ -76,6 +77,19 @@ parsing flags, like so: log.init() main(posargs[1:]) +To show log and save a copy to file at the same time: + +.. code:: python + + import glog as log + + log.init("example.log") + + log.info("It works.") + log.warn("Something not ideal") + log.error("Something went wrong") + log.fatal("AAAAAAAAAAAAAAA!") + Happy logging! .. _twitter.common.log: https://github.com/twitter/commons/tree/master/src/python/twitter/common/log From 1c4f0585d283d91c19067698ff32638fe01a1ad2 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 20 Nov 2015 11:51:59 +0800 Subject: [PATCH 3/5] Cancel the INFO change due to misunderstanding. --- glog.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/glog.py b/glog.py index 5baae77..599fc93 100644 --- a/glog.py +++ b/glog.py @@ -142,12 +142,12 @@ def init(filename=None): log = logger.log -DEBUG = logger.debug -INFO = logger.info -WARNING = logger.warning -WARN = logger.warning -ERROR = logger.error -FATAL = logger.fatal +DEBUG = logging.DEBUG +INFO = logging.INFO +WARNING = logging.WARNING +WARN = logging.WARN +ERROR = logging.ERROR +FATAL = logging.FATAL # basicConfig = logger.basicConfig From c4cc685dc14b68c903c2f1fd12611751edfb440c Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Fri, 11 Mar 2016 21:59:23 +0800 Subject: [PATCH 4/5] * Changed the default behavior to write log to stdout, since most time INFO level logging is used and is expected in stdout. * Program now could handle file object output. --- README.rst | 4 ++-- glog.py | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 06a1b98..1309363 100644 --- a/README.rst +++ b/README.rst @@ -30,8 +30,8 @@ that uses the standard Python logging module will play along nicely. Behaviours ---------- -- Messages are always written to stderr by default. A copy could be saved to - file by configuration. +- Messages are always written to stdout by default. A copy could be saved to + file by configuration. - Lines are prefixed with a google-style log prefix, of the form diff --git a/glog.py b/glog.py index 599fc93..22de107 100644 --- a/glog.py +++ b/glog.py @@ -64,6 +64,7 @@ def main(): Happy logging! """ +import sys import logging import time @@ -121,12 +122,17 @@ def setLevel(newlevel): logger.debug('Log level set to %s', newlevel) -def init(filename=None): +def init(destiny=None): logger.propagate = False - if filename is None: + destiny_type = type(destiny) + if destiny is None: handler = logging.StreamHandler() + elif destiny_type is file: + handler = logging.StreamHandler(destiny) + elif destiny_type is str: + handler = logging.FileHandler(destiny) else: - handler = logging.FileHandler(filename) + print("Cannot handle type {} destiny.".format(destiny_type)) handler.setFormatter(GlogFormatter()) logger.addHandler(handler) @@ -174,4 +180,4 @@ def init(filename=None): """) % ''.join(_level_letters) """Regex you can use to parse glog line prefixes.""" -init() +init(sys.stdout) From 8a9be0072a3dc5eb3fddac632692b11c2abb0d50 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Sat, 26 Mar 2016 15:35:44 +0800 Subject: [PATCH 5/5] Repeated calling init will not have any side effect now. --- README.rst | 12 ++++++++++-- glog.py | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index 1309363..0296339 100644 --- a/README.rst +++ b/README.rst @@ -30,8 +30,16 @@ that uses the standard Python logging module will play along nicely. Behaviours ---------- -- Messages are always written to stdout by default. A copy could be saved to - file by configuration. +- Messages are always written to `stderr` if `glog` is used uninitialized. + +- By calling `glog.init(FILE_NAME)`, where FILE_NAME is a `str`, logs will be + saved to that file. Target files only need to be initialized once and could + be shared anywhere. Repeated initialization is supported, and all logs will + be added to that file only once. + +- Calling `glog.init("stderr")` or `glog.init("stdout")` will make glog log to + standard error or standard output. + - Lines are prefixed with a google-style log prefix, of the form diff --git a/glog.py b/glog.py index 22de107..e5375a4 100644 --- a/glog.py +++ b/glog.py @@ -15,12 +15,17 @@ * Your apps and scripts will all have a consistent log format, and the same predictable behaviours. -This library configures the root logger, so nearly everything you import -that uses the standard Python logging module will play along nicely. - ## Behaviours -* Messages are always written to stderr. +* Messages are always written to `stderr` if `glog` is used uninitialized. + +* By calling `glog.init(FILE_NAME)`, where FILE_NAME is a `str`, logs will be + saved to that file. Target files only need to be initialized once and could + be shared anywhere. Repeated initialization is supported, and all logs will + be added to that file only once. + +* Calling `glog.init("stderr")` or `glog.init("stdout")` will make glog log to + standard error or standard output. * Lines are prefixed with a google-style log prefix, of the form @@ -75,6 +80,8 @@ def main(): short_name='v') FLAGS = gflags.FLAGS +file_names = [] + def format_message(record): try: @@ -122,18 +129,23 @@ def setLevel(newlevel): logger.debug('Log level set to %s', newlevel) -def init(destiny=None): +def init(filename=None): logger.propagate = False - destiny_type = type(destiny) - if destiny is None: - handler = logging.StreamHandler() - elif destiny_type is file: - handler = logging.StreamHandler(destiny) - elif destiny_type is str: - handler = logging.FileHandler(destiny) + if filename is None: + if "stderr" not in file_names: + handler = logging.StreamHandler() + filename = "stderr" + elif filename in file_names: + # Do not add files that already has been added. + return + elif filename == "stderr": + handler = logging.StreamHandler(sys.stderr) + elif filename == "stdout": + handler = logging.StreamHandler(sys.stdout) else: - print("Cannot handle type {} destiny.".format(destiny_type)) + handler = logging.FileHandler(filename) + file_names.append(filename) handler.setFormatter(GlogFormatter()) logger.addHandler(handler) setLevel(FLAGS.verbosity) @@ -180,4 +192,4 @@ def init(destiny=None): """) % ''.join(_level_letters) """Regex you can use to parse glog line prefixes.""" -init(sys.stdout) +init()