1.. highlight:: shell 2.. _index: 3 4=================================== 5`logzero`: Python logging made easy 6=================================== 7 8Robust and effective logging for Python 2 and 3. 9 10.. image:: _static/demo-output-with-beaver.png 11 :alt: Logo 12 13**Features** 14 15* Easy logging to console and/or (rotating) file. 16* Provides a fully configured `Python logger object <https://docs.python.org/2/library/logging.html#module-level-functions>`_. 17* Pretty formatting, including level-specific colors in the console. 18* JSON logging support (with integrated `python-json-logger <https://github.com/madzak/python-json-logger>`_) 19* Windows color output supported by `colorama`_ 20* Robust against str/bytes encoding problems, works with all kinds of character encodings and special characters. 21* Multiple loggers can write to the same logfile (also works across multiple Python files). 22* Global default logger with `logzero.logger <#i-logzero-logger>`_ and custom loggers with `logzero.setup_logger(..) <#i-logzero-setup-logger>`_. 23* Compatible with Python 2 and 3. 24* All contained in a `single file`_. 25* Licensed under the MIT license. 26* Heavily inspired by the `Tornado web framework`_. 27* Hosted on GitHub: https://github.com/metachris/logzero 28 29 30Installation 31============ 32 33Install `logzero` with `pip`_: 34 35.. code-block:: console 36 37 $ pip install -U logzero 38 39If you don't have `pip`_ installed, this `Python installation guide`_ can guide 40you through the process. 41 42You can also install `logzero` from the public `Github repo`_: 43 44.. code-block:: console 45 46 $ git clone https://github.com/metachris/logzero.git 47 $ cd logzero 48 $ python setup.py install 49 50.. _pip: https://pip.pypa.io 51.. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/ 52.. _Github repo: https://github.com/metachris/logzero 53.. _tarball: https://github.com/metachris/logzero/tarball/master 54.. _single file: https://github.com/metachris/logzero/blob/master/logzero/__init__.py 55.. _Tornado web framework: https://github.com/tornadoweb/tornado 56.. _colorama: https://github.com/tartley/colorama 57 58 59Example usage 60============= 61 62You can use `logzero` like this (logs only to the console by default): 63 64.. code-block:: python 65 66 from logzero import logger 67 68 logger.debug("hello") 69 logger.info("info") 70 logger.warning("warn") 71 logger.error("error") 72 73 # This is how you'd log an exception 74 try: 75 raise Exception("this is a demo exception") 76 except Exception as e: 77 logger.exception(e) 78 79 # JSON logging 80 import logzero 81 logzero.json() 82 83 logger.info("JSON test") 84 85 # Start writing into a logfile 86 logzero.logfile("/tmp/logzero-demo.log") 87 88If this was a file called ``demo.py``, the output will look like this: 89 90.. image:: _static/demo-output-json.png 91 :alt: Demo output in color 92 93Logging to files 94---------------- 95 96You can add logging to a (rotating) logfile like this: 97 98.. code-block:: python 99 100 import logzero 101 from logzero import logger 102 103 # non-rotating logfile 104 logzero.logfile("/tmp/logfile.log") 105 106 # rotating logfile 107 logzero.logfile("/tmp/rotating-logfile.log", maxBytes=1e6, backupCount=3) 108 109 # log messages 110 logger.info("This log message goes to the console and the logfile") 111 112 113JSON logging 114------------ 115 116JSON logging can be enabled for the default logger with `logzero.json()`, or with `setup_logger(json=True)` for custom loggers: 117 118.. code-block:: python 119 120 # Configure the default logger to output JSON 121 >>> logzero.json() 122 >>> logger.info("test") 123 {"asctime": "2020-10-21 10:42:45,808", "filename": "<stdin>", "funcName": "<module>", "levelname": "INFO", "levelno": 20, "lineno": 1, "module": "<stdin>", "message": "test", "name": "logzero_default", "pathname": "<stdin>", "process": 76179, "processName": "MainProcess", "threadName": "MainThread"} 124 125 # Configure a custom logger to output JSON 126 >>> my_logger = setup_logger(json=True) 127 >>> my_logger.info("test") 128 {"asctime": "2020-10-21 10:42:45,808", "filename": "<stdin>", "funcName": "<module>", "levelname": "INFO", "levelno": 20, "lineno": 1, "module": "<stdin>", "message": "test", "name": "logzero_default", "pathname": "<stdin>", "process": 76179, "processName": "MainProcess", "threadName": "MainThread"} 129 130The logged JSON object has these fields: 131 132.. code-block:: json 133 134 { 135 "asctime": "2020-10-21 10:43:40,765", 136 "filename": "test.py", 137 "funcName": "test_this", 138 "levelname": "INFO", 139 "levelno": 20, 140 "lineno": 9, 141 "module": "test", 142 "message": "info", 143 "name": "logzero", 144 "pathname": "_tests/test.py", 145 "process": 76204, 146 "processName": "MainProcess", 147 "threadName": "MainThread" 148 } 149 150An exception logged with `logger.exception(e)` has these: 151 152.. code-block:: json 153 154 { 155 "asctime": "2020-10-21 10:43:25,193", 156 "filename": "test.py", 157 "funcName": "test_this", 158 "levelname": "ERROR", 159 "levelno": 40, 160 "lineno": 17, 161 "module": "test", 162 "message": "this is a demo exception", 163 "name": "logzero", 164 "pathname": "_tests/test.py", 165 "process": 76192, 166 "processName": "MainProcess", 167 "threadName": "MainThread", 168 "exc_info": "Traceback (most recent call last):\n File \"_tests/test.py\", line 15, in test_this\n raise Exception(\"this is a demo exception\")\nException: this is a demo exception" 169 } 170 171 172Advanced usage examples 173----------------------- 174 175Here are more examples which show how to use logfiles, custom formatters 176and setting a minimum loglevel. 177 178+-----------------------------------------+--------------------------------------------------+ 179| Outcome | Method | 180+=========================================+==================================================+ 181| Set a minimum log level | `logzero.loglevel(..) <#i-logzero-loglevel>`_ | 182+-----------------------------------------+--------------------------------------------------+ 183| Add logging to a logfile | `logzero.logfile(..) <#i-logzero-logfile>`_ | 184+-----------------------------------------+--------------------------------------------------+ 185| Setup a rotating logfile | `logzero.logfile(..) <#i-logzero-logfile>`_ | 186+-----------------------------------------+--------------------------------------------------+ 187| Disable logging to a logfile | `logzero.logfile(None) <#i-logzero-logfile>`_ | 188+-----------------------------------------+--------------------------------------------------+ 189| JSON logging | `logzero.json(...) <#json-logging>`_ | 190+-----------------------------------------+--------------------------------------------------+ 191| Log to syslog | `logzero.syslog(...) <#i-logzero-logfile>`_ | 192+-----------------------------------------+--------------------------------------------------+ 193| Use a custom formatter | `logzero.formatter(..) <#i-logzero-formatter>`_ | 194+-----------------------------------------+--------------------------------------------------+ 195 196 197.. code-block:: python 198 199 import logging 200 import logzero 201 from logzero import logger 202 203 # This log message goes to the console 204 logger.debug("hello") 205 206 # Set a minimum log level 207 logzero.loglevel(logzero.INFO) 208 209 # Set a logfile (all future log messages are also saved there) 210 logzero.logfile("/tmp/logfile.log") 211 212 # Set a logfile (all future log messages are also saved there), but disable the default stderr logging 213 logzero.logfile("/tmp/logfile.log", disableStderrLogger=True) 214 215 # You can also set a different loglevel for the file handler 216 logzero.logfile("/tmp/logfile.log", loglevel=logzero.ERROR) 217 218 # Set a rotating logfile (replaces the previous logfile handler) 219 logzero.logfile("/tmp/rotating-logfile.log", maxBytes=1000000, backupCount=3) 220 221 # Disable logging to a file 222 logzero.logfile(None) 223 224 # Enable JSON log format 225 logzero.json() 226 227 # Disable JSON log format 228 logzero.json(False) 229 230 # Log to syslog, using default logzero logger and 'user' syslog facility 231 logzero.syslog() 232 233 # Log to syslog, using default logzero logger and 'local0' syslog facility 234 logzero.syslog(facility=SysLogHandler.LOG_LOCAL0) 235 236 # Set a custom formatter 237 formatter = logging.Formatter('%(name)s - %(asctime)-15s - %(levelname)s: %(message)s'); 238 logzero.formatter(formatter) 239 240 # Log some variables 241 logger.info("var1: %s, var2: %s", var1, var2) 242 243Custom logger instances 244----------------------- 245 246Instead of using the default logger you can also setup specific logger instances with `logzero.setup_logger(..) <#i-logzero-setup-logger>`_: 247 248.. code-block:: python 249 250 from logzero import setup_logger 251 logger1 = setup_logger(name="mylogger1") 252 logger2 = setup_logger(name="mylogger2", logfile="/tmp/test-logger2.log", level=logzero.INFO) 253 logger3 = setup_logger(name="mylogger3", logfile="/tmp/test-logger3.log", level=logzero.INFO, disableStderrLogger=True) 254 255 # Log something: 256 logger1.info("info for logger 1") 257 logger2.info("info for logger 2") 258 259 # log to a file only, excluding the default stderr logger 260 logger3.info("info for logger 3") 261 262 # JSON logging in a custom logger 263 jsonLogger = setup_logger(name="jsonLogger", json=True) 264 jsonLogger.info("info in json") 265 266 267 268Adding custom handlers (eg. SocketHandler) 269------------------------------------------ 270 271Since `logzero` uses the standard `Python logger object <https://docs.python.org/2/library/logging.html#module-level-functions>`_, 272you can attach any `Python logging handlers <https://docs.python.org/2/library/logging.handlers.html>`_ you can imagine! 273 274This is how you add a `SocketHandler <https://docs.python.org/2/library/logging.handlers.html#sockethandler>`_: 275 276.. code-block:: python 277 278 import logzero 279 import logging 280 from logging.handlers import SocketHandler 281 282 # Setup the SocketHandler 283 socket_handler = SocketHandler(address=('localhost', logging.DEFAULT_TCP_LOGGING_PORT)) 284 socket_handler.setLevel(logging.DEBUG) 285 socket_handler.setFormatter(logzero.LogFormatter(color=False)) 286 287 # Attach it to the logzero default logger 288 logzero.logger.addHandler(socket_handler) 289 290 # Log messages 291 logzero.logger.info("this is a test") 292 293 294Documentation 295============= 296 297.. _i-logzero-logger: 298 299`logzero.logger` 300---------------- 301 302`logzero.logger` is an already set up standard `Python logger instance <https://docs.python.org/2/library/logging.html#module-level-functions>`_ for your convenience. You can use it from all your 303files and modules directly like this: 304 305.. code-block:: python 306 307 from logzero import logger 308 309 logger.debug("hello") 310 logger.info("info") 311 logger.warning("warning") 312 logger.error("error") 313 314You can reconfigure the default logger globally with `logzero.setup_default_logger(..) <#i-logzero-setup-default-logger>`_. 315 316See the documentation for the `Python logger instance <https://docs.python.org/2/library/logging.html#module-level-functions>`_ for more information about how you can use it. 317 318 319.. _i-logzero-loglevel: 320 321`logzero.loglevel(..)` 322-------------------------- 323 324.. autofunction:: logzero.loglevel 325 326 327.. _i-logzero-logfile: 328 329`logzero.logfile(..)` 330-------------------------- 331 332.. autofunction:: logzero.logfile 333 334 335.. _i-logzero-formatter: 336 337`logzero.formatter(..)` 338-------------------------- 339 340.. autofunction:: logzero.formatter 341 342 343.. _i-logzero-setup-logger: 344 345`logzero.setup_logger(..)` 346-------------------------- 347 348.. autofunction:: logzero.setup_logger 349 350.. _i-logzero-setup-default-logger: 351 352 353Default Log Format 354------------------ 355 356This is the default log format string: 357 358.. code-block:: python 359 360 DEFAULT_FORMAT = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s' 361 362See also the `Python LogRecord attributes <https://docs.python.org/2/library/logging.html#logrecord-attributes>`_ you can use. 363 364 365Custom Formatting 366----------------- 367 368It is easy to use a custom formatter / a custom log format string: 369 370* Define your log format string (you can use any of the `LogRecord attributes <https://docs.python.org/2/library/logging.html#logrecord-attributes>`_). 371* Create a `Formatter object <https://docs.python.org/2/library/logging.html#formatter-objects>`_ (based on `logzero.LogFormatter` to get all the encoding helpers). 372* Supply the formatter object to the `formatter` argument in the `setup_logger(..)` method. 373 374This is a working example on how to setup logging with a custom format: 375 376.. code-block:: python 377 378 import logzero 379 380 log_format = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s' 381 formatter = logzero.LogFormatter(fmt=log_format) 382 logzero.setup_default_logger(formatter=formatter) 383 384 385Issues, Feedback & Contributions 386================================ 387 388All kinds of feedback and contributions are welcome. 389 390* `Create an issue <https://github.com/metachris/logzero/issues/new>`_ 391* Create a pull request 392* https://github.com/metachris/logzero 393* chris@linuxuser.at // `@metachris <https://twitter.com/metachris>`_ 394