{"id":17093802,"url":"https://github.com/nberger/ring-logger","last_synced_at":"2025-04-05T08:06:34.598Z","repository":{"id":1211487,"uuid":"41628848","full_name":"nberger/ring-logger","owner":"nberger","description":"Log ring requests \u0026 responses using your favorite logging backend","archived":false,"fork":false,"pushed_at":"2022-01-21T08:10:07.000Z","size":960,"stargazers_count":101,"open_issues_count":0,"forks_count":21,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T07:06:06.107Z","etag":null,"topics":["clojure","http","logging","ring","ring-middleware"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nberger.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-30T13:01:53.000Z","updated_at":"2024-11-04T14:25:15.000Z","dependencies_parsed_at":"2022-08-06T10:15:46.628Z","dependency_job_id":null,"html_url":"https://github.com/nberger/ring-logger","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberger%2Fring-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberger%2Fring-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberger%2Fring-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberger%2Fring-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nberger","download_url":"https://codeload.github.com/nberger/ring-logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247305933,"owners_count":20917208,"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":["clojure","http","logging","ring","ring-middleware"],"created_at":"2024-10-14T14:08:23.401Z","updated_at":"2025-04-05T08:06:34.580Z","avatar_url":"https://github.com/nberger.png","language":"Clojure","funding_links":[],"categories":["Clojure"],"sub_categories":[],"readme":"# Ring-logger [![Circle CI](https://circleci.com/gh/nberger/ring-logger.svg?style=svg)](https://circleci.com/gh/nberger/ring-logger)\n\n[Ring](https://github.com/ring-clojure/ring) [middleware](https://github.com/ring-clojure/ring/wiki/Concepts#middleware) to log\nresponse time and other details of each request that arrives to your server.\n\n- Logs request start, finish, parameters and exceptions by default.\n- The user can choose which of those messages to log by using the more specific middleware.\n- \"Logs as data\": Log messages are simple clojure maps. You can provide a `transform-fn` to\n  transform to other representations (string, JSON).\n- Uses [clojure.tools.logging](https://github.com/clojure/tools.logging) by default,\n  accepts a `log-fn` for switching to other log backends ([timbre](https://github.com/ptaoussanis/timbre), etc.)\n\n[DOCUMENTATION](https://nberger.github.io/ring-logger/doc) | [0.7.x](https://github.com/nberger/ring-logger/tree/0.7.x)\n\n[![Clojars Project](http://clojars.org/ring-logger/latest-version.svg)](http://clojars.org/ring-logger)\n\n## Getting started\n\nAdd the dependency to your project.\n\nLeiningen:\n\n```clojure\n[ring-logger \"1.1.1\"]\n```\n\ndeps.edn:\n\n```clojure\nring-logger/ring-logger {:mvn/version \"1.1.1\"}\n```\n\n## Usage\n\nAdd the middleware to your ring stack:\n\n```clojure\n    (ns foo\n      (:require [ring.adapter.jetty :as jetty]\n                [ring.logger :as logger]))\n\n    (defn my-ring-app [request]\n         {:status 200\n          :headers {\"Content-Type\" \"text/html\"}\n          :body \"Hello world!\"})\n\n    (jetty/run-jetty (logger/wrap-with-logger my-ring-app) {:port 8080})\n```\n\nExample output:\n\n    INFO  ring.logger: {:request-method :get, :uri \"/\", :server-name \"localhost\", :ring.logger/type :starting}\n    DEBUG ring.logger: {:request-method :get, :uri \"/\", :server-name \"localhost\", :ring.logger/type :params, :params {:name \"ring-logger\", :password \"[REDACTED]\"}}\n    INFO  ring.logger: {:request-method :get, :uri \"/\", :server-name \"localhost\", :ring.logger/type :finish, :status 200, :ring.logger/ms 11}\n\n## Advanced usage\n\nring.logger comes with more fine-grained middleware apart from `wrap-with-logger`:\n\n- `wrap-log-request-start`: Logs the start of the request\n- `wrap-log-response`\n- `wrap-log-request-params`: Logs the request parameters, using redaction to hide sensitive values (passwords, tokens, etc)\n\nTo log just the start and finish of requests (no parameters):\n\n```clojure\n    (-\u003e handler\n        logger/wrap-log-response\n        ;; more middleware to parse params, cookies, etc.\n        logger/wrap-log-request-start)\n```\n\nTo measure request latency, `wrap-log-response` will use the `ring.logger/start-ms` key added by `wrap-log-request-start`\nif both middlewares are being used, or will call `System/currentTimeMillis` to obtain the value by itself.\n\n---\n\nTo explicitly log start, finish, and parameters of requests:\n\n```clojure\n    (-\u003e (handler)\n        wrap-log-response\n        ;; the following line must come before `wrap-params`\n        (wrap-log-request-params {:transform-fn #(assoc % :level :info)})\n        wrap-keyword-params        ;; optional\n        wrap-params                ;; required\n        wrap-log-request-start)\n```\n\nNote that in the above example, the `:transform-fn` is optional. You can either bump your log level to DEBUG or use :transform-fn to adjust the log level of params logging before it hits the log-fn. The latter is often preferable, since DEBUG tends to be very noisy.\n\nAlso see [the example](https://github.com/nberger/ring-logger/blob/d30e011f0f97afcd944e7a382195db7796ad1015/example/src/example/core.clj#L65-L67).\n\n## Using other logging backends\n\nOther logging backends can be plugged by passing the `log-fn` option. This is how you could use\n[timbre](https://github.com/ptaoussanis/timbre) instead of c.t.logging:\n\n\n```clojure\n    (require '[timbre.core :as timbre])\n\n    (-\u003e handler\n        (logger/wrap-log-response {:log-fn (fn [{:keys [level throwable message]}]\n                                             (timbre/log level throwable message))}))\n```\n\n## What gets logged\n\n\n\n* an :info level message when a request begins.\n* a :debug level message with the request parameters (redacted).\n* an :info level message when a response is returned without server\n  errors (i.e. its HTTP status is \u003c 500), otherwise an :error level message is logged.\n* an :error level message with a stack trace when an exception is thrown during response generation.\n\nAll messages will be usually timestamped by your logging infrastructure.\n\n## How to disable exceptions logging\n\nThis is especially useful when also using ring.middleware.stacktrace.\n\n```clojure\n(wrap-with-logger app {:log-exceptions? false})\n```\n\n## Password: \"[REDACTED]\"\n\nSensitive information in params and headers can be redacted before it's sent to\nthe logs.\n\n**This is very important**: Nobody wants user passwords or authentication\ntokens to get to the logs and live there forever, in plain text, *right*?\n\nBy default, ring-logger will redact any parameter whose name is in the\n`ring.logger/default-redact-key?` set (:password, :token, :secret, etc).\nYou can pass your own set or function to determine which keys to redact\nas the `redact-key?` option\n\n```clojure\n(wrap-with-logger app {:redact-key? #{:senha :token})\n```\n\n## Logging only certain requests\n\nIf you wish to restrict logging to certain paths (or other\nconditions), combine ring-logger with\n[ring.middleware.conditional](https://github.com/pjlegato/ring.middleware.conditional), like so:\n\n```clojure\n(:require [ring.middleware.conditional :as c :refer  [if-url-starts-with\n                                                      if-url-doesnt-start-with\n                                                      if-url-matches\n                                                      if-url-doesnt-match]])\n\n(def my-ring-app\n   (-\u003e handler\n       (if-url-starts-with \"/foo\" wrap-with-logger)\n\n        ;; Or:\n        ;; (c/if some-test-fn wrap-with-logger)\n        ;; etc.\n\n       wrap-with-other-handler))\n```\n\nConsult the [ring.middleware.conditional docs](https://github.com/pjlegato/ring.middleware.conditional) for full details.\n\n## Similar projects\n\n[pjlegato/ring.middleware.logger](http://github.com/pjlegato/ring.middleware.logger): ring-logger started as a fork\nof ring.middleware.logger. It's a great option if you don't mind pulling a transitive dependency on onelog \u0026 log4j.\n\n[lambdaisland/ring.middleware.logger](https://github.com/RadicalZephyr/ring.middleware.logger): a fork of r.m.logger\nthat replaces onelog with clojure.tools.logging\n\n## Contributing\n\nPull requests are welcome!\n\n## License\n\nCopyright (C) 2015-2018 Nicolás Berger\nCopyright (C) 2012-2014 Paul Legato.\n\nDistributed under the Eclipse Public License, the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnberger%2Fring-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnberger%2Fring-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnberger%2Fring-logger/lists"}