{"id":13595439,"url":"https://github.com/severb/graypy","last_synced_at":"2026-02-21T15:06:33.660Z","repository":{"id":1398908,"uuid":"1417372","full_name":"severb/graypy","owner":"severb","description":"Python logging handler for Graylog that sends messages in GELF (Graylog Extended Log Format).","archived":false,"fork":false,"pushed_at":"2023-10-24T04:29:33.000Z","size":309,"stargazers_count":266,"open_issues_count":29,"forks_count":90,"subscribers_count":14,"default_branch":"master","last_synced_at":"2026-02-13T00:31:06.543Z","etag":null,"topics":["gelf","graylog","logging","python"],"latest_commit_sha":null,"homepage":"https://www.graylog.org/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"zilkey/active_hash","license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/severb.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"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}},"created_at":"2011-02-27T09:02:02.000Z","updated_at":"2026-01-17T15:54:23.000Z","dependencies_parsed_at":"2024-01-16T22:18:28.274Z","dependency_job_id":"ca78d1dd-8d44-4feb-91ed-e1f77a05b4c3","html_url":"https://github.com/severb/graypy","commit_stats":{"total_commits":328,"total_committers":40,"mean_commits":8.2,"dds":0.3445121951219512,"last_synced_commit":"a5a82c535002db6015473cb59a7476361060d358"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/severb/graypy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/severb%2Fgraypy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/severb%2Fgraypy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/severb%2Fgraypy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/severb%2Fgraypy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/severb","download_url":"https://codeload.github.com/severb/graypy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/severb%2Fgraypy/sbom","scorecard":{"id":813709,"data":{"date":"2025-08-11","repo":{"name":"github.com/severb/graypy","commit":"a5a82c535002db6015473cb59a7476361060d358"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":1,"reason":"Found 2/19 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T13:43:30.489Z","repository_id":1398908,"created_at":"2025-08-23T13:43:30.489Z","updated_at":"2025-08-23T13:43:30.489Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29684101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T14:31:22.911Z","status":"ssl_error","status_checked_at":"2026-02-21T14:31:22.570Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["gelf","graylog","logging","python"],"created_at":"2024-08-01T16:01:50.030Z","updated_at":"2026-02-21T15:06:33.636Z","avatar_url":"https://github.com/severb.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"######\ngraypy\n######\n\n.. image:: https://img.shields.io/pypi/v/graypy.svg\n    :target: https://pypi.python.org/pypi/graypy\n    :alt: PyPI Status\n\n.. image:: https://travis-ci.org/severb/graypy.svg?branch=master\n    :target: https://travis-ci.org/severb/graypy\n    :alt: Build Status\n\n.. image:: https://readthedocs.org/projects/graypy/badge/?version=stable\n    :target: https://graypy.readthedocs.io/en/stable/?badge=stable\n    :alt: Documentation Status\n\n.. image:: https://codecov.io/gh/severb/graypy/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/severb/graypy\n    :alt: Coverage Status\n\nDescription\n===========\n\nPython logging handlers that send log messages in the\nGraylog Extended Log Format (GELF_).\n\ngraypy supports sending GELF logs to both Graylog2 and Graylog3 servers.\n\nInstalling\n==========\n\nUsing pip\n---------\n\nInstall the basic graypy python logging handlers:\n\n.. code-block:: console\n\n    pip install graypy\n\nInstall with requirements for ``GELFRabbitHandler``:\n\n.. code-block:: console\n\n    pip install graypy[amqp]\n\nUsing easy_install\n------------------\n\nInstall the basic graypy python logging handlers:\n\n.. code-block:: console\n\n    easy_install graypy\n\nInstall with requirements for ``GELFRabbitHandler``:\n\n.. code-block:: console\n\n    easy_install graypy[amqp]\n\nUsage\n=====\n\ngraypy sends GELF logs to a Graylog server via subclasses of the python\n`logging.Handler`_ class.\n\nBelow is the list of ready to run GELF logging handlers defined by graypy:\n\n* ``GELFUDPHandler`` - UDP log forwarding\n* ``GELFTCPHandler`` - TCP log forwarding\n* ``GELFTLSHandler`` - TCP log forwarding with TLS support\n* ``GELFHTTPHandler`` - HTTP log forwarding\n* ``GELFRabbitHandler`` - RabbitMQ log forwarding\n\nUDP Logging\n-----------\n\nUDP Log forwarding to a locally hosted Graylog server can be easily done with\nthe ``GELFUDPHandler``:\n\n.. code-block:: python\n\n    import logging\n    import graypy\n\n    my_logger = logging.getLogger('test_logger')\n    my_logger.setLevel(logging.DEBUG)\n\n    handler = graypy.GELFUDPHandler('localhost', 12201)\n    my_logger.addHandler(handler)\n\n    my_logger.debug('Hello Graylog.')\n\n\nUDP GELF Chunkers\n^^^^^^^^^^^^^^^^^\n\n`GELF UDP Chunking`_ is supported by the ``GELFUDPHandler`` and is defined by\nthe ``gelf_chunker`` argument within its constructor. By default the\n``GELFWarningChunker`` is used, thus, GELF messages that chunk overflow\n(i.e. consisting of more than 128 chunks) will issue a\n``GELFChunkOverflowWarning`` and **will be dropped**.\n\nOther ``gelf_chunker`` options are also available:\n\n* ``BaseGELFChunker`` silently drops GELF messages that chunk overflow\n* ``GELFTruncatingChunker`` issues a ``GELFChunkOverflowWarning`` and\n  simplifies and truncates GELF messages that chunk overflow in a attempt\n  to send some content to Graylog. If this process fails to prevent\n  another chunk overflow a ``GELFTruncationFailureWarning`` is issued.\n\nRabbitMQ Logging\n----------------\n\nAlternately, use ``GELFRabbitHandler`` to send messages to RabbitMQ and\nconfigure your Graylog server to consume messages via AMQP. This prevents log\nmessages from being lost due to dropped UDP packets (``GELFUDPHandler`` sends\nmessages to Graylog using UDP). You will need to configure RabbitMQ with a\n``gelf_log`` queue and bind it to the ``logging.gelf`` exchange so messages\nare properly routed to a queue that can be consumed by Graylog (the queue and\nexchange names may be customized to your liking).\n\n.. code-block:: python\n\n    import logging\n    import graypy\n\n    my_logger = logging.getLogger('test_logger')\n    my_logger.setLevel(logging.DEBUG)\n\n    handler = graypy.GELFRabbitHandler('amqp://guest:guest@localhost/', exchange='logging.gelf')\n    my_logger.addHandler(handler)\n\n    my_logger.debug('Hello Graylog.')\n\nDjango Logging\n--------------\n\nIt's easy to integrate ``graypy`` with Django's logging settings. Just add a\nnew handler in your ``settings.py``:\n\n.. code-block:: python\n\n    LOGGING = {\n        'version': 1,\n        # other dictConfig keys here...\n        'handlers': {\n            'graypy': {\n                'level': 'WARNING',\n                'class': 'graypy.GELFUDPHandler',\n                'host': 'localhost',\n                'port': 12201,\n            },\n        },\n        'loggers': {\n            'django.request': {\n                'handlers': ['graypy'],\n                'level': 'ERROR',\n                'propagate': True,\n            },\n        },\n    }\n\nTraceback Logging\n-----------------\n\nBy default log captured exception tracebacks are added to the GELF log as\n``full_message`` fields:\n\n.. code-block:: python\n\n    import logging\n    import graypy\n\n    my_logger = logging.getLogger('test_logger')\n    my_logger.setLevel(logging.DEBUG)\n\n    handler = graypy.GELFUDPHandler('localhost', 12201)\n    my_logger.addHandler(handler)\n\n    try:\n        puff_the_magic_dragon()\n    except NameError:\n        my_logger.debug('No dragons here.', exc_info=1)\n\nDefault Logging Fields\n----------------------\n\nBy default a number of debugging logging fields are automatically added to the\nGELF log if available:\n\n    * function\n    * pid\n    * process_name\n    * thread_name\n\nYou can disable automatically adding these debugging logging fields by\nspecifying ``debugging_fields=False`` in the handler's constructor:\n\n.. code-block:: python\n\n    handler = graypy.GELFUDPHandler('localhost', 12201, debugging_fields=False)\n\nAdding Custom Logging Fields\n----------------------------\n\ngraypy also supports including custom fields in the GELF logs sent to Graylog.\nThis can be done by using Python's LoggerAdapter_ and Filter_ classes.\n\nUsing LoggerAdapter\n^^^^^^^^^^^^^^^^^^^\n\nLoggerAdapter_ makes it easy to add static information to your GELF log\nmessages:\n\n.. code-block:: python\n\n    import logging\n    import graypy\n\n    my_logger = logging.getLogger('test_logger')\n    my_logger.setLevel(logging.DEBUG)\n\n    handler = graypy.GELFUDPHandler('localhost', 12201)\n    my_logger.addHandler(handler)\n\n    my_adapter = logging.LoggerAdapter(logging.getLogger('test_logger'),\n                                       {'username': 'John'})\n\n    my_adapter.debug('Hello Graylog from John.')\n\nUsing Filter\n^^^^^^^^^^^^\n\nFilter_ gives more flexibility and allows for dynamic information to be\nadded to your GELF logs:\n\n.. code-block:: python\n\n    import logging\n    import graypy\n\n    class UsernameFilter(logging.Filter):\n        def __init__(self):\n            # In an actual use case would dynamically get this\n            # (e.g. from memcache)\n            self.username = 'John'\n\n        def filter(self, record):\n            record.username = self.username\n            return True\n\n    my_logger = logging.getLogger('test_logger')\n    my_logger.setLevel(logging.DEBUG)\n\n    handler = graypy.GELFUDPHandler('localhost', 12201)\n    my_logger.addHandler(handler)\n\n    my_logger.addFilter(UsernameFilter())\n\n    my_logger.debug('Hello Graylog from John.')\n\nContributors\n============\n\n  * Sever Banesiu\n  * Daniel Miller\n  * Tushar Makkar\n  * Nathan Klapstein\n\n.. _GELF: https://docs.graylog.org/en/latest/pages/gelf.html\n.. _logging.Handler: https://docs.python.org/3/library/logging.html#logging.Handler\n.. _GELF UDP Chunking: https://docs.graylog.org/en/latest/pages/gelf.html#chunking\n.. _LoggerAdapter: https://docs.python.org/howto/logging-cookbook.html#using-loggeradapters-to-impart-contextual-information\n.. _Filter: https://docs.python.org/howto/logging-cookbook.html#using-filters-to-impart-contextual-information\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseverb%2Fgraypy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseverb%2Fgraypy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseverb%2Fgraypy/lists"}