{"id":13501969,"url":"https://github.com/reubano/pygogo","last_synced_at":"2025-04-13T06:22:42.048Z","repository":{"id":3207171,"uuid":"48742215","full_name":"reubano/pygogo","owner":"reubano","description":"A Python logging library with superpowers","archived":false,"fork":false,"pushed_at":"2024-02-24T00:21:13.000Z","size":464,"stargazers_count":281,"open_issues_count":6,"forks_count":20,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-10-30T00:33:36.037Z","etag":null,"topics":["cli","featured","library","logger","logging","shell","structured-logging"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reubano.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-12-29T10:31:02.000Z","updated_at":"2024-02-14T03:42:12.000Z","dependencies_parsed_at":"2024-06-18T17:07:37.790Z","dependency_job_id":"030fc112-fc44-4005-818f-ee7d985ee994","html_url":"https://github.com/reubano/pygogo","commit_stats":{"total_commits":248,"total_committers":4,"mean_commits":62.0,"dds":0.03629032258064513,"last_synced_commit":"7a78062b1f996c541c5ff68ffafc231bdc07ebcf"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fpygogo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fpygogo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fpygogo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fpygogo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reubano","download_url":"https://codeload.github.com/reubano/pygogo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665752,"owners_count":21142123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","featured","library","logger","logging","shell","structured-logging"],"created_at":"2024-07-31T22:01:56.915Z","updated_at":"2025-04-13T06:22:42.007Z","avatar_url":"https://github.com/reubano.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"pygogo: a Python logger with superpowers\n========================================\n\n|travis| |versions| |pypi|\n\n.. image:: https://raw.githubusercontent.com/reubano/pygogo/master/gogo.png\n    :alt: sample pygogo usage\n    :width: 800\n    :align: center\n\nIndex\n-----\n`Introduction`_ | `Requirements`_ | `Motivation`_ | `Usage`_ | `Installation`_ |\n`Project Structure`_ | `Design Principles`_ | `Structured Logging`_ |\n`Formatters`_ | `Handlers`_ | `Scripts`_ | `Contributing`_ | `License`_\n\nIntroduction\n------------\n\npygogo is a Python logging `library`_ and `command-line interface`_ with super powers.\npygogo leverages the standard Python `logging module`_ under the hood, so there's\nno need to learn yet-another logging library. The default implementation sends\nall messages to ``stdout``, and any messages at level ``WARNING`` or above also to ``stderr``.\n\nWith pygogo, you can\n\n- Log via different handlers depending on the event severity\n- Format log messages as plain text, csv, json, and more..\n- Send logs to stdout, stderr, file, email, sockets, and more..\n- Inter-operate with the standard python logging module\n- and much more...\n\nRequirements\n------------\n\npygogo has been tested and is known to work on Python 3.7, 3.8, and 3.9; and PyPy3.7.\n\nMotivation\n----------\n\nThe standard logging module is great, but requires a ton of boilerplate before\nyou can do anything really interesting with it. I designed pygogo to provide\nmany useful logging use-cases out of the box. A reimplementation of\n`Using LoggerAdapters to impart contextual information`_ is shown below:\n\n.. _Using LoggerAdapters to impart contextual information: https://docs.python.org/2/howto/logging-cookbook.html#using-loggeradapters-to-impart-contextual-information\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    logger = gogo.Gogo(__name__).get_structured_logger(connid='1234')\n    logger.info('log message')\n\n    # Prints the following to stdout\n\n    {\"message\": \"log message\", \"connid\": \"1234\"}\n\nUsage\n-----\n\npygogo is intended to be used either directly as a Python `library`_ or from\nthe terminal via the `command-line interface`_.\n\nLibrary\n~~~~~~~\n\nExamples\n^^^^^^^^\n\n*Hello World*\n\n.. code-block:: python\n\n    from pygogo import logger\n\n    logger.debug('hello world')\n    logger.error('hello error')\n\n    # Prints the following to `stdout`\n\n    hello world\n    hello error\n\n    # Prints the following to `stderr`\n\n    hello error\n\n*Log based debugging*\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    def main(verbose=False):\n        logger = gogo.Gogo(__name__, verbose=verbose).logger\n        logger.debug('I will log to `stdout` only if `verbose` is True')\n        logger.info('I will log to `stdout` always')\n        logger.warning('I will log to both `stdout` and `stderr` always')\n\n*Disabled dual logging*\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    logger = gogo.Gogo(monolog=True).logger\n    logger.debug('debug message')\n    logger.info('info message')\n    logger.warning('warning message')\n    logger.error('error message')\n    logger.critical('critical message')\n\n    # Prints the following to `stdout.log` (all messages at level `INFO` or below):\n\n    debug message\n    info message\n\n    # Prints the following to `stderr` (messages at level `WARNING` or above):\n\n    warning message\n    error message\n    critical message\n\n*Custom formatter* [1]_\n\n.. code-block:: python\n\n    import logging\n    import pygogo as gogo\n\n    log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'\n    formatter = logging.Formatter(log_format)\n\n    logger = gogo.Gogo(\n        'examples.fmt',\n        low_hdlr=gogo.handlers.file_hdlr('custom_fmt.log'),\n        low_formatter=formatter,\n        high_level='error',\n        high_formatter=formatter).logger\n\n    # Now let's log something!\n\n    logger.debug('debug message')\n    logger.info('info message')\n    logger.warn('warn message')\n    logger.error('error message')\n    logger.critical('critical message')\n\n    # Prints the following to `custom_fmt.log` (all messages):\n\n    2015-12-18 18:51:30,416 - examples.fmt.base - DEBUG - debug message\n    2015-12-18 18:51:30,416 - examples.fmt.base - INFO - info message\n    2015-12-18 18:51:30,416 - examples.fmt.base - WARNING - warn message\n    2015-12-18 18:51:30,416 - examples.fmt.base - ERROR - error message\n    2015-12-18 18:51:30,416 - examples.fmt.base - CRITICAL - critical message\n\n    # Prints the following to `stderr` (messages at level `ERROR` or above):\n\n    2015-12-18 18:51:30,416 - examples.fmt.base - ERROR - error message\n    2015-12-18 18:51:30,416 - examples.fmt.base - CRITICAL - critical message\n\n*Structured logging* [2]_\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    formatter = gogo.formatters.structured_formatter\n    kwargs = {'low_level': 'info', 'low_formatter': formatter}\n    logger = gogo.Gogo('examples.structured', **kwargs).logger\n    extra = {'set_value': set([1, 2, 3]), 'snowman': '☃'}\n    logger.info('log message', extra=extra)  # doctest: +ELLIPSIS\n\n    # Prints the following to `stdout`:\n\n    {\"snowman\": \"\\u2603\", \"name\": \"examples.structured.base\", \"level\": \"INFO\", \"message\": \"log message\", \"time\": \"2015-12-18 18:52:39\", \"msecs\": 58.973073959350586, \"set_value\": [1, 2, 3]}\n\n*Using Filters to impart contextual information* [3]_\n\n.. code-block:: python\n\n    import logging\n    import pygogo as gogo\n\n    levels = ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')\n    log_frmt = (\n       '%(asctime)-4s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: '\n       '%(user)-8s %(message)s')\n\n    formatter = logging.Formatter(log_frmt)\n    going = gogo.Gogo('a', low_formatter=formatter)\n    a1 = going.get_logger('b.c', ip='123.231.231.123', user='fred')\n    a2 = going.get_logger('e.f', ip='192.168.0.1', user='sheila')\n\n    # Now let's log something!\n\n    a1.debug('A debug message')\n    a1.info('An info %s', 'message')\n\n    for level in [getattr(logging, l) for l in levels]:\n       name = logging.getLevelName(level)\n       a2.log(level, 'A %s msg', name)\n\n    # Prints the following to `stdout` (all messages):\n\n    2015-12-19 10:12:24,479 a.b.c DEBUG    IP: 123.231.231.123 User: fred     A debug message\n    2015-12-19 10:12:24,479 a.b.c INFO     IP: 123.231.231.123 User: fred     An info message\n    2015-12-19 10:12:24,479 a.e.f DEBUG    IP: 192.168.0.1     User: sheila   A DEBUG msg\n    2015-12-19 10:12:24,479 a.e.f INFO     IP: 192.168.0.1     User: sheila   AN INFO msg\n    2015-12-19 10:12:24,479 a.e.f WARNING  IP: 192.168.0.1     User: sheila   A WARNING msg\n    2015-12-19 10:12:24,479 a.e.f ERROR    IP: 192.168.0.1     User: sheila   AN ERROR msg\n    2015-12-19 10:12:24,479 a.e.f CRITICAL IP: 192.168.0.1     User: sheila   A CRITICAL msg\n\n    # Prints the following to `stderr` (messages at level `WARNING` or above):\n\n    2015-12-19 10:12:24,479 a.e.f WARNING  IP: 192.168.0.1     User: sheila   A WARNING msg\n    2015-12-19 10:12:24,479 a.e.f ERROR    IP: 192.168.0.1     User: sheila   AN ERROR msg\n    2015-12-19 10:12:24,479 a.e.f CRITICAL IP: 192.168.0.1     User: sheila   A CRITICAL msg\n\n*Multiple loggers* [4]_\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    going = gogo.Gogo(\n        'examples.lggrs',\n        low_hdlr=gogo.handlers.file_hdlr('multi_lggrs.log'),\n        low_formatter=gogo.formatters.fixed_formatter,\n        high_level='info',\n        high_formatter=gogo.formatters.console_formatter)\n\n    root = going.logger\n    logger1 = going.get_logger('area1')\n    logger2 = going.get_logger('area2')\n\n    # Now let's log something!\n\n    root.info('Jackdaws love my big sphinx.')\n    logger1.debug('Quick zephyrs blow, daft Jim.')\n    logger1.info('How daft jumping zebras vex.')\n    logger2.warning('Jail zesty vixen who grabbed pay.')\n    logger2.error('The five boxing wizards jump.')\n\n    # Prints the following to `multi_lggrs.log` (all messages):\n\n    2015-12-18 17:21:37.417 examples.lggrs.base INFO     Jackdaws love my big sphinx.\n    2015-12-18 17:21:37.417 examples.lggrs.area1 DEBUG    Quick zephyrs blow, daft Jim.\n    2015-12-18 17:21:37.417 examples.lggrs.area1 INFO     How daft jumping zebras vex.\n    2015-12-18 17:21:37.417 examples.lggrs.area2 WARNING  Jail zesty vixen who grabbed pay.\n    2015-12-18 17:21:37.417 examples.lggrs.area2 ERROR    The five boxing wizards jump.\n\n    # Prints the following to `stderr` (messages at level `INFO` or above):\n\n    examples.lggrs.base: INFO     Jackdaws love my big sphinx.\n    examples.lggrs.area1: INFO     How daft jumping zebras vex.\n    examples.lggrs.area2: WARNING  Jail zesty vixen who grabbed pay.\n    examples.lggrs.area2: ERROR    The five boxing wizards jump.\n\nNotes\n^^^^^\n\n.. [1] https://docs.python.org/2/howto/logging-cookbook.html#multiple-handlers-and-formatters\n.. [2] https://docs.python.org/2/howto/logging-cookbook.html#implementing-structured-logging\n.. [3] https://docs.python.org/2/howto/logging-cookbook.html#using-filters-to-impart-contextual-information\n.. [4] https://docs.python.org/2/howto/logging-cookbook.html#logging-to-multiple-destinations\n\nCommand-line Interface\n~~~~~~~~~~~~~~~~~~~~~~\n\nExamples\n^^^^^^^^\n\n*Basic Usage*\n\n.. code-block:: bash\n\n    gogo [options] \u003cmessage\u003e\n\n*show help*\n\n.. code-block:: bash\n\n    gogo -h\n\n*CLI usage*\n\n    usage: gogo [options] \u003cmessage\u003e\n\n    description: Logs a given message\n\n    positional arguments:\n      message               The message to log (defaults to reading from stdin).\n\n    optional arguments:\n      -h, --help            show this help message and exit\n      -l LEVEL, --msg-level LEVEL\n                            The level to log the message (default: info).\n                            Must be one of: critical, error, warning, info, debug.\n\n      -n NAME, --name NAME  The logger name (default: pygogo)\n      -D HANDLER, --high-hdlr HANDLER\n                            The high pass log handler (default: stderr).\n                            Must be one of: buffered, email, file, fileobj,\n                            socket, stderr, stdout, syslog, webhook.\n\n      -d HANDLER, --low-hdlr HANDLER\n                            The low pass log handler (default: stdout).\n                            Must be one of: buffered, email, file, fileobj,\n                            socket, stderr, stdout, syslog, webhook.\n\n      -L LEVEL, --high-level LEVEL\n                            Min level to log to the high pass handler\n                            (default: warning).\n                            Must be one of: buffered, email, file, fileobj,\n                            socket, stderr, stdout, syslog, webhook.\n\n      -e LEVEL, --low-level LEVEL\n                            Min level to log to the low pass handler\n                            (default: debug).\n                            Must be one of: buffered, email, file, fileobj,\n                            socket, stderr, stdout, syslog, webhook.\n\n      -F FORMAT, --high-format FORMAT\n                            High pass handler log format (default: basic).\n                            Must be one of: basic, bom, console, csv,\n                            fixed, json, structured.\n\n      -o FORMAT, --low-format FORMAT\n                            Low pass handler log format (default: basic).\n                            Must be one of: basic, bom, console, csv,\n                            fixed, json, structured.\n\n      -m, --monolog         Log high level events only to high pass handler.\n      -f FILENAME, --filename FILENAME\n                            The filename to log to.\n                            Required for the follow handlers: file.\n\n      -s SUBJECT, --subject SUBJECT\n                            The log subject (default: You've got mail).\n                            Used in the follow handlers: email.\n\n      -u URL, --url URL     The log url. Required for the follow handlers: webhook.\n      -H HOST, --host HOST  The host.\n                            Used in the follow handlers: socket and syslog.\n\n      -p NUM, --port NUM    The port number.\n                            Used in the follow handlers: socket and syslog.\n\n      -t, --tcp             Use TCP instead of UDP.\n                            Used in the follow handlers: socket and syslog.\n\n      -g, --get             Use a GET request instead of POST.\n                            Used in the follow handlers: webhook.\n\n      -v, --version         Show version and exit.\n      -V, --verbose         Increase output verbosity.\n\n*Hello World*\n\n.. code-block:: bash\n\n    gogo 'hello world'\n\n*Log based debugging*\n\n.. code-block:: bash\n\n    gogo 'default info level will log to `stdout`'\n    gogo --level=debug \"debug won't log\"\n    gogo --level=debug -V 'verbose will log to `stdout`'\n    gogo --level=info 'info will log to `stdout`'\n    gogo --level=warning 'warning will log to both `stdout` and `stderr`'\n\n    # Prints the following to `stdout`:\n\n    default info level will log to `stdout`\n    verbose will log to `stdout`\n    info will log to `stdout`\n    warning will log to both `stdout` and `stderr`\n\n    # Prints the following to `stderr`:\n\n    warning will log to both `stdout` and `stderr`\n\n*Disable dual logging*\n\n.. code-block:: bash\n\n    gogo --level=debug -V 'debug message'\n    gogo --level=info 'info message'\n    gogo --level=warning -m 'warning message'\n    gogo --level=error -m 'error message'\n    gogo --level=critical -m 'critical message'\n\n    # Prints the following to `stdout.log` (all messages at level `INFO` or below):\n\n    debug message\n    info message\n\n    # Prints the following to `stderr` (messages at level `WARNING` or above):\n\n    warning message\n    error message\n    critical message\n\n*Structured logging*\n\n.. code-block:: bash\n\n    gogo --low-format=json 'log message'\n\n    # Prints the following to `stdout`:\n\n    {\"time\": \"2015-12-19 11:26:53.776\", \"name\": \"pygogo.runner\", \"level\": \"INFO\", \"message\": \"log message\"}\n\n*Alternate handler*\n\n.. code-block:: bash\n\n    gogo --low-hdlr=file 'log message'\n\n    # Prints the following to `pygogo.log` in the current dir (assuming the current dir is named `pygogo`):\n\n    {\"time\": \"2015-12-19 11:26:53.776\", \"name\": \"pygogo.runner\", \"level\": \"INFO\", \"message\": \"log message\"}\n\nInstallation\n------------\n\n(You are using a `virtualenv`_, right?)\n\nAt the command line, install pygogo using either ``pip`` (*recommended*)\n\n.. code-block:: bash\n\n    pip install pygogo\n\nor ``easy_install``\n\n.. code-block:: bash\n\n    easy_install pygogo\n\nPlease see the `installation doc`_ for more details.\n\nProject Structure\n-----------------\n\n.. code-block:: bash\n\n    ┌── bin\n    │   └── gogo\n    ├── docs\n    │   ├── AUTHORS.rst\n    │   ├── CHANGES.rst\n    │   ├── INSTALLATION.rst\n    │   └── TODO.rst\n    ├── helpers\n    │   ├── check-stage\n    │   ├── clean\n    │   ├── pippy\n    │   ├── srcdist\n    │   └── wheel\n    ├── pygogo\n    │   ├── __init__.py\n    │   ├── formatters.py\n    │   ├── handlers.py\n    │   ├── main.py\n    │   └── utils.py\n    ├── tests\n    │   ├── __init__.py\n    │   ├── standard.rc\n    │   ├── test.py\n    │   └── test_main.py\n    ├── CONTRIBUTING.rst\n    ├── LICENSE\n    ├── MANIFEST.in\n    ├── Makefile\n    ├── README.rst\n    ├── dev-requirements.txt\n    ├── examples.py\n    ├── manage.py\n    ├── py2-requirements.txt\n    ├── setup.cfg\n    ├── setup.py\n    └── tox.ini\n\nDesign Principles\n-----------------\n\n- the built-in ``logging`` module isn't broken so don't reinvent the wheel\n- prefer functions over objects\n- keep the API as simple as possible\n\nStructured Logging\n------------------\n\nThere are severals ways to get structured (machine readable) log messages using pygogo.\nEach method makes a different customization/complexity trade-off which is\noutlined below:\n\nSetup\n~~~~~\n\nThe following methods make use of these variables.\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    kwargs = {'contextual': True}\n    extra = {'additional': True}\n\nMethods\n~~~~~~~\n\nbasic structured logger\n^^^^^^^^^^^^^^^^^^^^^^^\n\nThe simplest to use. Useful if you don’t need message metadata, i.e., log level,\nlog name, and log time.\n\n.. code-block:: python\n\n    logger = gogo.Gogo('basic').get_structured_logger('base', **kwargs)\n    logger.debug('message', extra=extra)\n\n    # Prints the following to `stdout`:\n\n    {\"additional\": true, \"contextual\": true, \"message\": \"message\"}\n\nstructured formatter\n^^^^^^^^^^^^^^^^^^^^\n\nRequires an additional step of specifying a formatter. Useful if you need\nmessage metadata, i.e., log level, log name, and log time.\n\n.. code-block:: python\n\n    formatter = gogo.formatters.structured_formatter\n    logger = gogo.Gogo('struct', low_formatter=formatter).get_logger(**kwargs)\n    logger.debug('message', extra=extra)\n\n    # Prints the following to `stdout`:\n\n     {\"additional\": true, \"contextual\": true, \"level\": \"DEBUG\", \"message\": \"message\", \"msecs\": 760.5140209197998, \"name\": \"struct.base\", \"time\": \"2015-12-19 14:25:58\"}\n\nJSON formatter\n^^^^^^^^^^^^^^\n\nRequires an additional step of specifying a formatter. Useful if you require\nmillisecond precision in the date. If you are ok with having the milliseconds\nin a separate field, consider the ``structured formatter`` since it supports\nthe ``extra`` keyword and contextual information.\n\n.. code-block:: python\n\n    formatter = gogo.formatters.json_formatter\n    logger = gogo.Gogo('json', low_formatter=formatter).get_logger(**kwargs)\n    logger.debug('message', extra=extra)\n\n    # Prints the following to `stdout`:\n\n    {\"level\": \"DEBUG\", \"message\": \"message\", \"name\": \"json.base\", \"time\": \"2015-12-19 14:25:58.760\"}\n\n    # Note that both `extra` and `kwargs` were ignored\n\ncustom logger\n^^^^^^^^^^^^^\n\nThe most complex and customizable. Useful if you need a custom\nlog or date format not provided by the above methods. However, even though this\nmethod supports the ``extra`` keyword when logging, it is static (unlike the\n``structured logger`` or ``structured formatter``). This is because the log\nformat must be specified at the time of the log's creation and therefore can't\nadapt to log messages with differing ``extra`` parameters.\n\n.. code-block:: python\n\n    logfmt = (\n        '{\"time\": \"%(asctime)s.%(msecs)d\", \"name\": \"%(name)s\", \"level\":'\n        ' \"%(levelname)s\", \"message\": \"%(message)s\", '\n        '\"contextual\": \"%(contextual)s\", \"additional\": \"%(additional)s\"}')\n\n    fmtr = logging.Formatter(logfmt, datefmt=gogo.formatters.DATEFMT)\n    logger = gogo.Gogo('custom', low_formatter=fmtr).get_logger(**kwargs)\n    logger.debug('message', extra=extra)\n\n    # Prints the following to `stdout`:\n\n    {\"additional\": \"True\", \"contextual\": \"True\", \"level\": \"DEBUG\", \"message\": \"message\", \"name\": \"custom.logger\", \"time\": \"2015-12-19 14:25:58.760\"}\n\nSummary\n~~~~~~~\n\nThe following table can help make sense of the different methods:\n\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n|                               | structured logger | structured formatter | json formatter | custom logger |\n+===============================+===================+======================+================+===============+\n| contextual information        | ✔                 | ✔                    |                | ✔             |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| ``extra`` param support       | ✔                 | ✔                    |                | ✔             |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| dynamic ``extra`` support     | ✔                 | ✔                    |                |               |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| message metadata              |                   | ✔                    | ✔              | ✔             |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| available via the command line|                   | ✔                    | ✔              |               |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| ``msecs`` field               |                   | ✔                    |                |               |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| milliseconds in time field    |                   |                      | ✔              | ✔             |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| custom date format            |                   |                      |                | ✔             |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n| custom log format             |                   |                      |                | ✔             |\n+-------------------------------+-------------------+----------------------+----------------+---------------+\n\nFormatters\n----------\n\npygogo has several builtin formatters and also supports any ``logging.Formatter``\ninstance.\n\nExamples\n~~~~~~~~\n\nbuiltin CSV format in python\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    formatter = gogo.formatters.csv_formatter\n    gogo.Gogo('csv', low_formatter=formatter).logger.debug('message')\n\n    # Prints the following to `stdout`:\n\n    2015-12-19 17:03:48.99,csv.base,DEBUG,\"message\"\n\n\n``logging.Formatter`` instance in python\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: python\n\n    import logging\n    import pygogo as gogo\n\n    datefmt = gogo.formatters.DATEFMT\n    formatter = logging.Formatter(gogo.formatters.CSV_FORMAT, datefmt=datefmt)\n    gogo.Gogo('csv', low_formatter=formatter).get_logger('custom').debug('message')\n\n    # Prints the following to `stdout`:\n\n    2015-12-19 17:03:48.99,csv.custom,DEBUG,\"message\"\n\nbuiltin CSV format via CLI\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: bash\n\n    gogo --low-format=csv 'message'\n\n    # Prints the following to `stdout`:\n\n    2015-12-19 15:51:32.16,pygogo.runner,INFO,\"message\"\n\nSummary\n~~~~~~~\n\nThe following table can help make sense of the different builtin formatters:\n\n+------------+------------------------------------------------------------------------------------------------------------------+\n| name       | message                                                                                                          |\n+============+==================================================================================================================+\n| basic      | message                                                                                                          |\n+------------+------------------------------------------------------------------------------------------------------------------+\n| bom        | message                                                                                                          |\n+------------+------------------------------------------------------------------------------------------------------------------+\n| console    | name: INFO     message                                                                                           |\n+------------+------------------------------------------------------------------------------------------------------------------+\n| csv        | 2015-12-19 15:51:32.16,name,INFO,\"message\"                                                                       |\n+------------+------------------------------------------------------------------------------------------------------------------+\n| fixed      | 2015-12-19 15:51:32.16 name INFO     message                                                                     |\n+------------+------------------------------------------------------------------------------------------------------------------+\n| json       | {\"level\": \"INFO\", \"message\": \"message\", \"name\": \"name\", \"time\": \"2015-12-19 15:51:32.16\"}                        |\n+------------+------------------------------------------------------------------------------------------------------------------+\n| structured | {\"level\": \"INFO\", \"message\": \"message\", \"msecs\": 16.5140209197998, \"name\": \"name\", \"time\": \"2015-12-19 15:51:32\"}|\n+------------+------------------------------------------------------------------------------------------------------------------+\n\nHandlers\n--------\n\npygogo has several builtin handlers and also supports any instance from the\n``logging.handlers`` module.\n\nExamples\n~~~~~~~~\n\nbuiltin stdout handler in python\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: python\n\n    import pygogo as gogo\n\n    hdlr = gogo.handlers.stdout_hdlr()\n    gogo.Gogo('stdout', low_hdlr=hdlr).logger.debug('message')\n\n    # Prints 'message' to `stdout`\n\n``logging.StreamHandler`` instance in python\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: python\n\n    import logging\n    import sys\n    import pygogo as gogo\n\n    hdlr = logging.StreamHandler(sys.stdout)\n    gogo.Gogo('stdout', low_hdlr=hdlr).get_logger('custom').debug('message')\n\n    # Prints 'message' to `stdout`\n\nbuiltin CSV format via CLI\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: bash\n\n    gogo --low-hdlr=stdout 'message'\n\n    # Prints 'message' to `stdout`\n\nSummary\n~~~~~~~\n\nThe following table can help make sense of the different builtin handlers:\n\n+------------+------------------------------------------+\n| name       | description                              |\n+============+==========================================+\n| buffered   | Holds log in memory until it reaches its |\n|            | capacity, or it logs a message with a    |\n|            | level at or above the flush level        |\n+------------+------------------------------------------+\n| email      | Emails log to a given email address      |\n+------------+------------------------------------------+\n| file       | Writes log to a given filename           |\n+------------+------------------------------------------+\n| fileobj    | Writes log to a given file-like object   |\n+------------+------------------------------------------+\n| socket     | Writes log to a given network socket     |\n+------------+------------------------------------------+\n| stderr     | Writes log to standard error             |\n+------------+------------------------------------------+\n| stdout     | Writes log to standard output            |\n+------------+------------------------------------------+\n| syslog     | Writes log to syslog                     |\n+------------+------------------------------------------+\n| webhook    | POSTs log to a url                       |\n+------------+------------------------------------------+\n\nScripts\n-------\n\npygogo comes with a built in task manager ``manage.py``\n\nSetup\n~~~~~\n\n.. code-block:: bash\n\n    pip install -r dev-requirements.txt\n\nExamples\n~~~~~~~~\n\n*Run python linter and nose tests*\n\n.. code-block:: bash\n\n    manage lint\n    manage test\n\nContributing\n------------\n\nPlease mimic the coding style/conventions used in this repo.\nIf you add new classes or functions, please add the appropriate doc blocks with\nexamples. Also, make sure the python linter and nose tests pass.\n\nPlease see the `contributing doc`_ for more details.\n\nLicense\n-------\n\npygogo is distributed under the `MIT License`_.\n\n.. |travis| image:: https://img.shields.io/travis/reubano/pygogo/master.svg\n    :target: https://app.travis-ci.com/github/reubano/pygogo\n\n.. |versions| image:: https://img.shields.io/pypi/pyversions/pygogo.svg\n    :target: https://pypi.python.org/pypi/pygogo\n\n.. |pypi| image:: https://img.shields.io/pypi/v/pygogo.svg\n    :target: https://pypi.python.org/pypi/pygogo\n\n.. _MIT License: http://opensource.org/licenses/MIT\n.. _logging module: https://docs.python.org/2/library/logging.html\n.. _virtualenv: http://www.virtualenv.org/en/latest/index.html\n.. _contributing doc: https://github.com/reubano/pygogo/blob/master/CONTRIBUTING.rst\n.. _installation doc: https://github.com/reubano/pygogo/blob/master/docs/INSTALLATION.rst\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freubano%2Fpygogo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freubano%2Fpygogo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freubano%2Fpygogo/lists"}