{"id":38053723,"url":"https://github.com/40ants/logging","last_synced_at":"2026-01-16T20:20:31.129Z","repository":{"id":143092981,"uuid":"609813796","full_name":"40ants/logging","owner":"40ants","description":"Functions to configure log4cl for different contexts: REPL, Backend, Command Line Application.","archived":false,"fork":false,"pushed_at":"2025-10-31T21:44:18.000Z","size":143,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-31T23:16:06.629Z","etag":null,"topics":["common-lisp","logging"],"latest_commit_sha":null,"homepage":"https://40ants.com/logging/","language":"Common Lisp","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/40ants.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","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":"2023-03-05T10:19:38.000Z","updated_at":"2025-10-31T21:44:22.000Z","dependencies_parsed_at":"2025-07-30T09:16:07.982Z","dependency_job_id":"2a1a557e-e4c6-4c3f-b4f0-8476b2b3c7ff","html_url":"https://github.com/40ants/logging","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/40ants/logging","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Flogging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Flogging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Flogging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Flogging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/40ants","download_url":"https://codeload.github.com/40ants/logging/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Flogging/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28482267,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","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":["common-lisp","logging"],"created_at":"2026-01-16T20:20:24.871Z","updated_at":"2026-01-16T20:20:31.122Z","avatar_url":"https://github.com/40ants.png","language":"Common Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca id=\"x-2840ANTS-LOGGING-DOCS-2FINDEX-3A-40README-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n# 40ants-logging - Functions to configure log4cl for different contexts: REPL, Backend, Command Line Application.\n\n\u003ca id=\"40-ants-logging-asdf-system-details\"\u003e\u003c/a\u003e\n\n## 40ANTS-LOGGING ASDF System Details\n\n* Description: Functions to configure log4cl for different contexts: `REPL`, Backend, Command Line Application.\n* Licence: Unlicense\n* Author: Alexander Artemenko \u003csvetlyak.40wt@gmail.com\u003e\n* Homepage: [https://40ants.com/logging/][3eb9]\n* Bug tracker: [https://github.com/40ants/logging/issues][cd63]\n* Source control: [GIT][0aac]\n* Depends on: [global-vars][07be], [log4cl-extras][691c]\n\n[![](https://github-actions.40ants.com/40ants/logging/matrix.svg?only=ci.run-tests)][2779]\n\n![](http://quickdocs.org/badge/40ants-logging.svg)\n\n\u003ca id=\"x-2840ANTS-LOGGING-DOCS-2FINDEX-3A-3A-40INSTALLATION-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## Installation\n\nYou can install this library from Quicklisp, but you want to receive updates quickly, then install it from Ultralisp.org:\n\n```\n(ql-dist:install-dist \"http://dist.ultralisp.org/\"\n                      :prompt nil)\n(ql:quickload :40ants-logging)\n```\n\u003ca id=\"x-2840ANTS-LOGGING-DOCS-2FINDEX-3A-3A-40USAGE-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## Usage\n\nThis small library encapsulates a logging approach for all `40Ants` projects. It provides\na few functions to setup structured logging for two kinds of applications: backend and command-line utility.\n\n\u003ca id=\"the-main-idea\"\u003e\u003c/a\u003e\n\n### The main idea\n\nThe idea of our approach to logging is that an application work in two modes:\n\n* regular;\n* `IDE` connected.\n\nIn regular mode application should log to the standard output or to the file usually using `JSON` format. These logs should be collected and stored in some kind of log store like ElasticSearch. Usually you want to limit log to store only `WARN` and `ERROR` levels.\n\nIn the second mode, a developer has connected to the app and wants to be able to see some log outputs in the `REPL`.\n\nWe define two log appenders for these two modes:\n\n* main log appender writes logs in regular mode.\n* repl log appender can be added when `REPL` is enabled. This is done automatically if you start Slynk using [`40ants-slynk`][04ac] system.\n\nNote, a developer don't need to see all `INFO` and `DEBUG` logs but only these logs from some package. So, we keep root logger's level the same as was specified for the main log appender. For example, imagine the main appender was configured to log `WARN` and `INFO`, but `REPL` appender configured to show `DEBUG`. When you'll connect to the `REPL`, it will not be cluttered with `DEBUG` messages from the all packages, instead only `WARN` and `ERROR` will be logged to the `REPL` the same as they will be logged to the main appender. But if you want to debug some package, you can set `DEBUG` level for this package only using `LOG4SLY`.\n\n\u003ca id=\"details\"\u003e\u003c/a\u003e\n\n### Details\n\nFor a backend you need to call [`40ants-logging:setup-for-backend`][d0af] function. It configures `LOG4CL` to output all logs to `STDOUT` in `JSON` format. We are doing this because these days most backends are running in the Docker or Kubernetes where easiest way to collect logs is to capture daemon's `STDOUT`.\n\nFor a command line utilities we are configuring `LOG4CL` to use plaintext format. Call [`40ants-logging:setup-for-cli`][78f4] to make the job. Why `LOG:CONFIG` is not enought? `LOG:CONFIG` uses `LOG4CL` appenders which are not aware of fields added by structured logging macro [`log4cl-extras/context:with-fields`][b464].\n\nYou can also build an example app to test how this logging works:\n\n```\n./build-example.sh\n./logging-example --help\n```\nHere is how it's output looks like for `CLI` mode:\n\n```\n% ./logging-example\n\u003cINFO\u003e [2023-03-05T10:44:25.861365Z] 40ants-logging-example/cli cli.lisp (run-as-cli) Running as a command line application.\n  Fields:\n    request-id: 120002\n\u003cINFO\u003e [2023-03-05T10:44:25.864960Z] 40ants-logging-example/cli cli.lisp (run-cli-loop) Sleeping 1 seconds\n  Fields:\n    request-id: 120002\n    iteration: 0\n\u003cINFO\u003e [2023-03-05T10:44:26.865200Z] 40ants-logging-example/cli cli.lisp (run-cli-loop) Sleeping 1 seconds\n  Fields:\n    request-id: 120002\n    iteration: 1\n...\n```\nand for backend mode:\n\n```json\n% ./logging-example --backend\n{\"fields\":{\"logger\":\"40ants-logging-example/cli\",\"func\":\"run-as-backend\",\"file\":\"cli.lisp\",\"request-id\":\"120002\"},\"level\":\"INFO\",\"message\":\"Running as a backend.\",\"timestamp\":\"2023-03-05T10:46:12.812570Z\"}\n{\"fields\":{\"logger\":\"40ants-logging-example/cli\",\"func\":\"run-backend-loop\",\"file\":\"cli.lisp\",\"request-id\":\"120002\",\"iteration\":0},\"level\":\"INFO\",\"message\":\"Sleeping 15 seconds\",\"timestamp\":\"2023-03-05T10:46:12.822253Z\"}\n{\"fields\":{\"logger\":\"40ants-logging-example/cli\",\"func\":\"run-backend-loop\",\"file\":\"cli.lisp\",\"request-id\":\"120002\",\"iteration\":1},\"level\":\"INFO\",\"message\":\"Sleeping 15 seconds\",\"timestamp\":\"2023-03-05T10:46:27.822530Z\"}\n...\n```\nIf you are using [`40ants-slynk`][04ac] system to setup a Slynk server, then [`40ants-logging:setup-for-repl`][d1f2] function will be called automatically on connect to the repl. You can observe logging configuration by like this:\n\n```\nCL-USER\u003e (log:config)\nROOT, DEBUG\n|\n+-(1)-#\u003cSTABLE-THIS-CONSOLE-APPENDER {10055B18F3}\u003e\n|     with #\u003cJSON-LAYOUT {10055B6AD3}\u003e\n|     :immediate-flush NIL\n|     :flush-interval  1\n|     :stream-owner    NIL\n|     :stream          #\u003cSB-SYS:FD-STREAM for \"standard output\" {1001D016C3}\u003e\n|     :message-count   0\n|     :filter          :INFO\n|\n+-(2)-#\u003cSTABLE-THIS-CONSOLE-APPENDER {10023FB1D3}\u003e\n      with #\u003cPLAIN-LAYOUT {10055B46D3}\u003e\n      :immediate-flush NIL\n      :flush-interval  1\n      :stream-owner    NIL\n      :stream          #\u003cSLYNK-GRAY::SLY-OUTPUT-STREAM {1001D00153}\u003e\n      :message-count   0\n      :filter          :WARN\n```\nTo change log level only for the `REPL`, call `(40ants-logging:setup-for-repl :level :warn)` function. If you will change log level via standard function of `LOG4CL`: `(log:config :warn)`, it will change the global logging level which will affect the backend's log in `JSON` format.\n\n\u003ca id=\"x-2840ANTS-LOGGING-DOCS-2FINDEX-3A-3A-40API-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## API\n\n\u003ca id=\"x-2840ANTS-LOGGING-3ASETUP-FOR-BACKEND-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n### [function](675e) `40ants-logging:setup-for-backend` \u0026key (level \\*default-level\\*) (filename nil) (layout :json)\n\nConfigures `LOG4CL` for logging in `JSON` format.\n\nHere we set for the root logger\nthe same level as for the main appender.\nUsually this level will be higher than level\nfor the `REPL` appender. We are doing this\nto not show `INFO` and `DEBUG` messages in the `REPL`\nby default if they are not logged by the main appender.\n\nBut you can use `LOG4SLY` to setup more verbose log\nlevels for subcategories. For example, main appender\ncan be configured to log `WARN`s and `REPL` appender\nconfigured to show `DEBUG`. But when you'll connect\nto the `REPL`, it will not be cluttered with `DEBUG`\nmessages from the all packages, instead only `WARN`s and `ERROR`s\nwill be logged to the `REPL` the same as they will be logged\nto the main appender. But if you want to debug some package,\nyou can set `DEBUG` level for it using `LOG4SLY`.\n\n\u003ca id=\"x-2840ANTS-LOGGING-3ASETUP-FOR-CLI-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n### [function](5c8f) `40ants-logging:setup-for-cli` \u0026key (level \\*default-level\\*)\n\nConfigures `LOG4CL` for logging in plain-text format with context fields support.\n\n\u003ca id=\"x-2840ANTS-LOGGING-3ASETUP-FOR-REPL-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n### [function](8d1b) `40ants-logging:setup-for-repl` \u0026key (level :debug) (stream \\*debug-io\\*)\n\nConfigures `LOG4CL` for logging in `REPL` when you connect to the running lisp image already configured as a backend or `CLI` application.\n\nIf you are using [`40ants-slynk`][04ac] system, this function will be called automatically\nwhen your `SLY` connects to the image.\n\n\u003ca id=\"x-2840ANTS-LOGGING-3AREMOVE-REPL-APPENDER-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n### [function](02df) `40ants-logging:remove-repl-appender`\n\nReturns configuration the state as it was after [`setup-for-backend`][d0af] or [`setup-for-cli`][78f4] call.\n\nIf you are using [`40ants-slynk`][04ac] system, this function will be called automatically\nwhen your `SLY` disconnects from the image.\n\n\n[b464]: https://40ants.com/log4cl-extras/#x-28LOG4CL-EXTRAS-2FCONTEXT-3AWITH-FIELDS-20-2840ANTS-DOC-2FLOCATIVES-3AMACRO-29-29\n[3eb9]: https://40ants.com/logging/\n[d0af]: https://40ants.com/logging/#x-2840ANTS-LOGGING-3ASETUP-FOR-BACKEND-20FUNCTION-29\n[78f4]: https://40ants.com/logging/#x-2840ANTS-LOGGING-3ASETUP-FOR-CLI-20FUNCTION-29\n[d1f2]: https://40ants.com/logging/#x-2840ANTS-LOGGING-3ASETUP-FOR-REPL-20FUNCTION-29\n[04ac]: https://40ants.com/slynk/#x-28-23A-28-2812-29-20BASE-CHAR-20-2E-20-2240ants-slynk-22-29-20ASDF-2FSYSTEM-3ASYSTEM-29\n[0aac]: https://github.com/40ants/logging\n[2779]: https://github.com/40ants/logging/actions\n[8d1b]: https://github.com/40ants/logging/blob/8c3957f7ef94be2caea0636605fe450ec5f17ac8/src/core.lisp#L122\n[02df]: https://github.com/40ants/logging/blob/8c3957f7ef94be2caea0636605fe450ec5f17ac8/src/core.lisp#L149\n[675e]: https://github.com/40ants/logging/blob/8c3957f7ef94be2caea0636605fe450ec5f17ac8/src/core.lisp#L38\n[5c8f]: https://github.com/40ants/logging/blob/8c3957f7ef94be2caea0636605fe450ec5f17ac8/src/core.lisp#L95\n[cd63]: https://github.com/40ants/logging/issues\n[07be]: https://quickdocs.org/global-vars\n[691c]: https://quickdocs.org/log4cl-extras\n\n* * *\n###### [generated by [40ANTS-DOC](https://40ants.com/doc/)]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F40ants%2Flogging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F40ants%2Flogging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F40ants%2Flogging/lists"}