{"id":38180958,"url":"https://github.com/dailymuse/muselog","last_synced_at":"2026-01-16T23:51:18.277Z","repository":{"id":47442041,"uuid":"107575776","full_name":"dailymuse/muselog","owner":"dailymuse","description":"JSON Datadog Attributed Python Logger w/ Flask and Tornado Request Hook Support","archived":false,"fork":false,"pushed_at":"2025-10-02T17:26:12.000Z","size":162,"stargazers_count":6,"open_issues_count":4,"forks_count":3,"subscribers_count":29,"default_branch":"main","last_synced_at":"2025-10-02T19:22:27.230Z","etag":null,"topics":["datadog","docker-compose","flask","library","logger","ops","python","tornado"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dailymuse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-10-19T17:07:54.000Z","updated_at":"2025-08-07T11:14:46.000Z","dependencies_parsed_at":"2024-04-15T20:33:10.353Z","dependency_job_id":"0365917c-8491-4e71-99e3-f15675433304","html_url":"https://github.com/dailymuse/muselog","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/dailymuse/muselog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dailymuse%2Fmuselog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dailymuse%2Fmuselog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dailymuse%2Fmuselog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dailymuse%2Fmuselog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dailymuse","download_url":"https://codeload.github.com/dailymuse/muselog/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dailymuse%2Fmuselog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28488804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T22:54:02.790Z","status":"ssl_error","status_checked_at":"2026-01-16T22:50:10.344Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["datadog","docker-compose","flask","library","logger","ops","python","tornado"],"created_at":"2026-01-16T23:51:17.519Z","updated_at":"2026-01-16T23:51:18.268Z","avatar_url":"https://github.com/dailymuse.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Muselog\nMuselog standardizes logging across all Python applications in use at The Muse.\nIt integrates with [DataDog](https://www.datadoghq.com/), and it provides request hooks for the following web frameworks or interfaces.\nWe're moving away from using DataDog's ddtrace library and integrating Muselog with OpenTelemetry, which provides instrumentation for many libraries and frameworks.\nConsider the custom hooks deprecated since 3.0.0. Muselog can now be considered as a DataDog support layer for OTel logging, providing JSON formatting and trace correlation.\n\n- [ASGI](https://asgi.readthedocs.io/en/latest/)\n- [Django](https://www.djangoproject.com/)\n- [Flask](https://palletsprojects.com/p/flask/)\n- [Tornado](https://www.tornadoweb.org/en/stable/)\n\n## Installation\n\n### pip\n`muselog` is available on themuse's public gemfury index `https://pypi.fury.io/themuse/` . You'll need to add our index to your `requirements.txt` in order to resolve the module.\n\n```sh\n# requirements.txt\n--extra-index-url https://pypi.fury.io/themuse/\n\nmuselog==2.5.0\n```\n\n### git\nYou can still install `muselog` through git via the tags we publish on github and an egg _(string directory that gets checked out as part of the install)_.\n\n```sh\n# requirements.txt\n\n# example\n-e git+git://github.com/dailymuse/muselog.git@1.8.4#egg=muselog[tornado]\n```\n\n## Usage\n\n### From the command line\nThe most effective manner to use muselog is to run your python program using `muselog-run`.\nThis will ensure that muselog is setup before anything else.\n\nSay you wanted to run the file \"main.py\" with arguments \"--file data.txt\". You only care about\nERROR logs for all modules, except 'muselog', for which you want to see INFO logs,\nand 'muselog.logger', for which you want to see DEBUG logs.\nYour command would look as follows.\n\n```\nmuselog-run --root-log-level ERROR --module-log-level muselog=INFO --module-log-level muselog.logger=DEBUG python main.py --file data.txt\n```\n\n### In code\nImport `muselog` as early as possible. At The Muse, this is usually in the application's top-level `__init__.py`.\nAfter import, call the `setup_logging` function to initialize the library. For example,\n\n```\nimport muselog\n\nmuselog.setup_logging(root_log_level=os.environ.get(\"LOG_LEVEL\", \"INFO\"),\n                      module_log_levels={\"themuse\": os.environ.get(\"THEMUSE_LOG_LEVEL\", \"INFO\")},\n                      add_console_handler=True,\n                      console_handler_format=os.environ.get(\"LOG_FORMAT\"))\n```\n\nSee the method's documentation if any of the configuration options in this example are not clear.\n\n\n## Integrations\n### Datadog\n\n- DATADOG_ERROR_STACK_LIMIT  :: truncate the stack trace sent in `error.stack` to X number of characters, default 10000\n\n#### Send logs to stdout\n- ENABLE_DATADOG_JSON_FORMATTER  :: set to `True` to enable datadog docker logging\n\nThis option will only work if muselog.setup_logging's `add_console_handler` parameter is `True` (the default).\n\n#### Send logs to a UDP listener\nSet the following environment variables to enable datadog UDP integration.\n\n- DATADOG_HOST            :: Datadog host to send JSON logs to\n- DATADOG_UDP_PORT        :: datadog server port that `udp` handler type sends messages to. (Default: 10518).\n\n### Web framework\nMuselog provides middleware / request hooks (depending on the framework) to logs request data at the conclusion of each request.\nBelow are instructions to setup muselog for each supported web framework.\n\n#### ASGI\nMuselog supports any ASGI-compatible web framework, such as FastAPI and Starlette.\nTo use, first install muselog with the `[asgi]` extra.\nThen add the `muselog.asgi.RequestLoggingMiddleware` middleware to your ASGI application.\nIn FastAPI, this could look as follows.\n\n```\nfrom fastapi import Depends, FastAPI\nfrom muselog.asgi import RequestLoggingMiddleware\n\napp = FastAPI()\n# RequestLoggingMiddleware is a muselog middleware that logs the end of a request.\n# It will add a `request_id` to the context for you, which you can access as follows.\n# from muselog import context\n# req_id = context.get(\"request_id\")\napp.add_middleware(RequestLoggingMiddleware)\n```\n\n#### Django\nInstall with the `[django]` extra.\nAdd `muselog.django.MuseDjangoRequestLoggingMiddleware` to your middleware list.\n\n#### Flask\nInstall with the `[flask]` extra.\nCall `muselog.flask.register_muselog_request_hooks` immediately after instantiating the Flask application object.\nFor example,\n\n```\nimport flask\nimport muselog.flask\n\napp = flask.Flask(\"example\")\nmuselog.flask.register_muselog_request_hooks(app)\n```\n\n#### Tornado\nInstall with the `[tornado]` extra.\nSet Tornado's `log_function` to `muselog.tornado.log_request`.\nTo log exceptions with more detail, add `muselog.tornado.ExceptionLogger`\nas a base class for your request handlers.\n\n## Development\n### Testing\nRun `docker-compose up test` to run unit tests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdailymuse%2Fmuselog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdailymuse%2Fmuselog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdailymuse%2Fmuselog/lists"}