Mercurial > hg > Lemuriformes
diff lemuriformes/log.py @ 15:0d1b8bb1d97b
SQL + data related functionality
author | Jeff Hammel <k0scist@gmail.com> |
---|---|
date | Sun, 10 Dec 2017 17:16:52 -0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemuriformes/log.py Sun Dec 10 17:16:52 2017 -0800 @@ -0,0 +1,108 @@ +""" +ElasticSearch-style logging +""" + +import json +import sys +import time +from .cli import ConfigurationParser + +stdout = sys.stdout + +try: + # python 2 + string = (str, unicode) +except NameError: + # python 3 + string = (str, ) + + +def read_logfile(f): + """ + read a JSON-per-line log file's contents and return the value + + f -- log file pointer or name + """ + + if isinstance(f, string): + with open(f) as _f: + return read_logfile(_f) + lines = f.read().strip().splitlines() + return [json.loads(line) for line in lines] + + +class ElasticLogger(object): + """Elasticsearch-compatible log dispatcher""" + + def __init__(self, logfilepath=None, **data): + """ + logfilepath -- path to logfile + data -- data to be included with each logging event + """ + + self.logfilepath = logfilepath + self.data = data + + def write(self, f, **data): + """ + write JSON `data` to file-like object `f` + """ + + f.write(json.dumps(data, sort_keys=True) + '\n') + f.flush() + + def __call__(self, message, **kw): + + # create log data JSON blob + now = time.time() + data = self.data.copy() # shallow copy + data.update({'time': now, + 'message': message}) + data.update(kw) + + # log to stdout + self.write(stdout, **data) + + if self.logfilepath: + # log to a file + with open(self.logfilepath, 'a') as logfile: + self.write(logfile, **data) + + +class ElasticLoggerParser(ConfigurationParser): + + def add_arguments(self): + self.add_argument('-l', '--log', '--logfile', dest='logfile', + help="where to log events to in addition to stdout") + self.add_argument('--tag', dest='tags', nargs='+', default=(), + type=self.keyvalue, metavar="KEY=VALUE", + help="set of key, values to tag all log lines with") + + def logger(self): + """return elastic logger instance""" + + assert self.options is not None + return ElasticLogger(self.options.logfile, + **dict(self.options.tags)) + + +def main(args=sys.argv[1:]): + """example CLI program""" + + # parse command line + parser = ElasticLoggerParser(description="my elastic diary") + options = parser.parse_args() + + # example: timestamped diary + logger = parser.logger() + + # main loop + try: + while True: + logger(raw_input()) + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main()