Package: siftlog-py
Sift Log - JSON logging adapter for Python (now in color)FeaturesTag log statements with arbitrary values for easier grouping and analysisAdd keyword arguments that are converted to JSON valuesVariable substitutionSpecifies where log calls are made fromMeant to be used with core Python logging (formatters, handlers, etc)Colorized logs on a console (POSIX only)TRACElog level built-inExamplesA simple log messagelog.info('Hello'){"msg": "Hello", "time": "12-12-14 10:12:01 EST", "level": "INFO", "loc": "test:log_test:20"}Logging with tagslog.debug('Creating new user','MONGO','STORAGE'){"msg": "Creating new user", "time": "12-12-14 10:12:09 EST", "tags": ["MONGO", "STORAGE"], "level": "DEBUG", "loc": "test:log_test:20"}Appending more datalog.debug('Some key',is_admin=True,username='papito'){"msg": "Some key", "is_admin": true, "username": "papito", "time": "12-12-14 10:12:04 EST", "level": "DEBUG", "loc": "test:log_test:20"}String substitutionlog.debug('User "$username" admin? $is_admin',is_admin=False,username='fez'){"msg": "User \"fez\" admin? False",  "username": "fez", "is_admin": false, "time": "12-12-14 10:12:18 EST", "level": "DEBUG", "loc": "test:log_test:20"}SetupLogging to consoleimportsysimportloggingfromsiftlogimportSiftLoglogger=logging.getLogger()logger.setLevel(logging.INFO)handler=logging.StreamHandler(sys.stdout)logger.addHandler(handler)log=SiftLog(logger)In this fashion, you can direct the JSON logs toany logging handler.ColorFor enhanced flamboyancy, attach theColorStreamHandlerto your logger. The output will not have color if the logs
are being output to a file, or on systems that are not POSIX (will not work on Windows for now).fromsiftlogimportSiftLog,ColorStreamHandlerlogger=logging.getLogger()handler=ColorStreamHandler(sys.stdout)logger.addHandler(handler)log=SiftLog(logger)For development, you can opt in to useColorPlainTextStreamHandler, for logs that are easier to parse visually.PerformanceWhile the above should play, it's highly recommended that the color handler is only
attached conditionally for local development.Different colorsYou can change font background, text color, and boldness:fromsiftlogimportColorStreamHandlerhandler=ColorStreamHandler(sys.stdout)handler.set_color(logging.DEBUG,bg=handler.WHITE,fg=handler.BLUE,bold=True)Supported colorsColorStreamHandler.BLACKColorStreamHandler.REDColorStreamHandler.GREENColorStreamHandler.YELLOWColorStreamHandler.BLUEColorStreamHandler.MAGENTAColorStreamHandler.CYANColorStreamHandler.WHITEConstants (re-occurring values)You can define constants that will appear in every single log message. This is useful, for example, if you'd like to log process PID and hostname with every log message. This is done upon log adapter initialization:importosfromsiftlogimportSiftLoglog=SiftLog(logger,pid=os.getpid(),env='INTEGRATION'){"msg": "And here I am", "time": "12-12-14 11:12:24 EST", "pid": 37463, "env": "INTEGRATION", "level": "INFO"}Dynamic logging context - callbacksOften you need to add dynamic contextual data to log statements, as opposed to simple constants/literals. You can
pass methods to SiftLog on initialization that will be called on every logging call.Logging request ids or user ids are very common use cases, so to log a thread-local property with Flask, for example,
we can do the following:importflaskdefget_user_id():ifflask.has_request_context():returnflask.g.user_iduser_aware_logger=SiftLog(u_id=get_user_id)Custom time formatlog=SiftLog(logger)SiftLog.TIME_FORMAT='%Y/%m/%d%H:%M:%S.%f'Define the format as accepted bystrftime()Custom location formatlog=SiftLog(logger)SiftLog.LOCATION_FORMAT='$module:$method:$line_no'The format should be a string containing any of the following variables:$file$line_no$method$moduleCustom core key namesCore keys, such asmsgandlevelcan be overridden, if they clash with common keys you might be using.The following can be redefined:SiftLog.MESSAGE (defaultmsg)SiftLog.LEVEL (defaultlevel)SiftLog.LOCATION (defaultloc)SiftLog.TAGS (defaulttags)SiftLog.TIME (defaulttime)As in:log=SiftLog(logger)SiftLog.log.MESSAGE="MESSAGE"Development flowPoetryis used to manage the dependencies.Most things can be accessed via the Makefile, if you have Make installed.
Without Make, just inspect the Makefile for the available commands.# use the right Python
poetry use path/to/python/3.8-ish

# make sure correct Python is used
make info

# install dependencies
make install

# run tests
make test

# run visual tests (same as tests but with output)
make visual

# formatting, linting, and type checking
make lintRunning a single testIn the standard Nose tests way:poetry run nosetests siftlog/tests/test_log.py:TestLogger.test_tags