{"id":17185010,"url":"https://github.com/magnars/prone","last_synced_at":"2025-10-24T04:23:24.030Z","repository":{"id":19841229,"uuid":"23102870","full_name":"magnars/prone","owner":"magnars","description":"Better exception reporting middleware for Ring.","archived":false,"fork":false,"pushed_at":"2024-09-13T12:13:30.000Z","size":523,"stargazers_count":514,"open_issues_count":4,"forks_count":25,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-05-03T02:40:17.849Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magnars.png","metadata":{"files":{"readme":"README.md","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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-19T08:35:24.000Z","updated_at":"2025-03-23T15:16:53.000Z","dependencies_parsed_at":"2024-11-28T13:47:02.574Z","dependency_job_id":null,"html_url":"https://github.com/magnars/prone","commit_stats":{"total_commits":276,"total_committers":15,"mean_commits":18.4,"dds":0.3804347826086957,"last_synced_commit":"b2314aabb7f5fdbe01de5fb2ea5615a2c1aab339"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magnars%2Fprone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magnars%2Fprone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magnars%2Fprone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magnars%2Fprone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magnars","download_url":"https://codeload.github.com/magnars/prone/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254046224,"owners_count":22005557,"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":[],"created_at":"2024-10-15T00:44:57.966Z","updated_at":"2025-10-24T04:23:23.953Z","avatar_url":"https://github.com/magnars.png","language":"Clojure","funding_links":[],"categories":["Debugging"],"sub_categories":[],"readme":"# prone\n\nBetter exception reporting middleware for Ring. Heavily inspired by\n[better_errors for Rails](https://github.com/charliesome/better_errors).\n\nSee it to believe it:\n[a quick video demoing Prone](https://youtu.be/Fgv6bxmxxpM).\n\nProne presents your stack traces in a consumable form. It optionally filters out\nstack frames that did not originate in your application, allowing you to focus\non your code. It allows you to browse environment data, such as the request map\nand exception data (when using `ex-info`). Prone also provides a debug function\nthat enables you to visually browse local bindings and any piece of data you\npass to `debug`.\n\n\u003cimg src=\"screenshot.png\"\u003e\n\n## Install\n\nAdd `[prone \"2021-04-23\"]` to `:dependencies` in your `project.clj`.\n\nThis project no longer uses Semantic Versioning. Instead we're aiming to never\nbreak the API. Feel free to check out the [change log](#change-log).\n\n## Usage\n\n- **with lein-ring**\n\n  Using `lein-ring` version `0.9.1` or above, add this to your `project.clj`:\n\n  ```clj\n  {:profiles {:dev {:ring {:stacktrace-middleware prone.middleware/wrap-exceptions}}}\n  ```\n\n- **without lein-ring**\n\n  Add it as a middleware to your Ring stack:\n\n  ```clj\n  (ns example\n    (:require [prone.middleware :as prone]))\n\n  (def app\n    (-\u003e my-app\n        prone/wrap-exceptions))\n  ```\n  \n  Please note, with this configuration you should make sure to\n  [only enable Prone in development](#should-i-use-prone-in-production).\n\n- **with pedestal**\n\n  See [prone-pedestal](https://github.com/eunmin/prone-pedestal)\n\n- **with catacumba**\n\n  See [catacumba-prone](https://github.com/funcool/catacumba-prone)\n\n## Debugging\n\nWhether you've tripped on an exception or not, you can use Prone to debug your\napplication:\n\n```clj\n(ns example\n  (:require [prone.debug :refer [debug]]))\n\n(defn myhandler [req]\n  ;; ...\n  (let [person (lookup-person (:id (:params req)))]\n    (debug)))\n```\n\nCalling `debug` without any arguments like this will cause Prone to render the\nexception page with information about your environment: the request map, and any\nlocal bindings (`req` and `person` in the above example).\n\nYou can call `debug` multiple times. To differentiate calls, you can pass a\nmessage as the first argument, but Prone will also indicate the source location\nthat triggered debugging.\n\n`debug` accepts any number of forms to present in a value browser on the\nerror/debug page:\n\n```clj\n(debug) ;; Inspect locals\n        ;; Halts the page if there are no exceptions\n\n(debug \"Here be trouble\") ;; Same as above, with a message\n\n(debug {:id 42}) ;; Inspect locals and the specific map\n                 ;; Halts the page if there are no exceptions\n\n(debug person project) ;; Same as above, with multiple values\n\n(debug \"What's this?\" person project) ;; Same as above, with message\n```\n\n## Q \u0026 A\n\n### Should I use Prone in production?\n\nNo. You would be exposing your innards to customers, and maybe even to someone with\nnefarious purposes.\n\nHere's one way to avoid it:\n\n```clj\n(def prone-enabled? (= \"true\" (System.getProperty \"prone.enable\")))\n\n(def app\n  (cond-\u003e my-app\n          prone-enabled? prone/wrap-exceptions))\n```\n\nYou can chain more optional middlewares in this `cond-\u003e` too. Pretty nifty.\n\n### How does Prone determine what parts of a stack trace belongs to the application?\n\nBy default it reads your `project.clj` and looks for namespaces starting with\nthe project name.\n\nYou can change this behavior by passing in some options to `wrap-exceptions`,\nlike so:\n\n```clj\n(-\u003e app\n    (prone/wrap-exceptions \n      {:app-namespaces ['our 'app 'namespace 'prefixes]}))\n```\n\nAll frames from namespaces prefixed with the names in the list will be marked as\napplication frames.\n\n### How do I skip prone for certain requests?\n\nPass a predicate function `skip-prone?` to `wrap-exceptions`. For example, to\nexclude Postman requests check for `postman-token` in the headers:\n\n```clj\n(-\u003e app\n    (prone/wrap-exceptions \n      {:skip-prone? (fn [req] (contains? (:headers req) \"postman-token\"))}))\n```\n\n### What about AJAX requests?\n\nYeah, that's a bit trickier. There's no point in serving a beautiful exception\npage when you have to inspect it in devtools.\n\nThe prone response includes a `Link` header with a `rel=help` attribute. Like this:\n\n```\nLink:\u003c/prone/d97fa078-7638-4fd1-8e4a-9a22576a321f\u003e; rel=help\n```\n\nUse this in your frontend code to display the page. Here's an example from one\nof our sites:\n\n```clj\n(def rel-help-regex #\"\u003c(.+)\u003e; rel=help\")\n\n(defn check-err [result]\n  (if-let [url (-\u003e\u003e (get-in result [:headers \"link\"] \"\")\n                    (re-find rel-help-regex)\n                    second)]\n    (set! js/location url)\n    (do (js/alert \"fail\")\n        (prn result))))\n\n(defn GET [url params]\n  (go\n    (let [result (\u003c! (http/get url {:query-params params}))]\n      (if (:success result)\n        (do-some-successful-stuff)\n        (check-err result)))))\n```\n\n#### A little trick\n\nThe latest prone error page can also be found under `/prone/latest`, so if you\nhaven't fixed your frontend code to use the `rel=help` header quite yet, you can\nalways go there to check it out.\n\n### I'm getting double printing of error messages\n\nYeah, I guess you already have a logging framework to print errors for you? And\nthen prone goes and prints them as well. Turn it off like so:\n\n```clj\n(-\u003e app\n    (prone/wrap-exceptions \n      {:print-stacktraces? false}))\n```\n\n## Known problems\n\n- We have not yet found a way to differentiate `some-name` and `some_name`\n  function names by inspecting the stack trace. Currently, we assume kebab case.\n- Using a middleware to always load the Austin `browser-connected-repl` for\n  ClojureScript causes JavaScript errors that partly trips up Prone\n\n## Change log\n\n#### From 1.6.3 to 2019-07-08\n\n- Add ability to copy values into clipboard\n- Navigation now starts directly at the root cause exception\n- Serialized values are now displayed better and more consistently\n- Improved display of functions\n\n#### From 1.6.1 to 1.6.3\n\n- Can now navigate into sets + weeded out some weird set bugs\n- Update realize, it now guards against infinite lazy seqs\n\n#### From 1.6 to 1.6.1\n\n- Don't crash without a project.clj-file.\n\n#### From 1.5 to 1.6\n\n- Support SQLException getNextException (timothypratley)\n- Add column in addition to line number (timothypratley)\n- Display `java.util.Date` like `#inst`\n\n#### From 1.4 to 1.5\n\n- Avoid expanding Datomic databases\n- Don't show too many extra exceptions\n- Always select the first source location when switching between exceptions\n\n#### From 1.3 to 1.4\n\n- Exceptions thrown when realizing lazy sequences are now handled properly.\n\n#### From 1.2 to 1.3\n\n- Add function to render self-contained page.\n\n  This can be used to store prone-pages for later perusal even when the prone\n  process is no longer running.\n\n  ```\n  (spit \"my-error.html\" (render-self-contained-page (create-exception-page e {})))\n  ```\n\n#### From 1.1 to 1.2\n\n- Serve contents as UTF-8 - fixes occasional regexp error warning\n- Upgrade Prism.JS - fixes graphical glitch with highlighted line\n- Upgrade ClojureScript version - now supports namespaced keys.\n- Show error page for assertion errors as well (alephyud)\n- Fix error when showing maps with complex keys\n- Fix compatibility Clojure 1.9 (lvh)\n- Don't crash on invalid or missing line-numbers\n\n#### From 1.0 to 1.1\n\n- Added option `:print-stacktraces?` (Max Ovsiankin)\n- Added latest prone error to `/prone/latest` (Daniel Lebrero)\n\n## Contributors\n\n- [Andrew Mcveigh](https://github.com/andrewmcveigh) added the `:app-namespaces` option.\n- [Chris McDevitt](https://github.com/minimal) added the `:skip-prone?` option.\n- [Malcolm Sparks](https://github.com/malcolmsparks) sorted map entries by keyword.\n- [Ryo Fukumuro](https://github.com/rkworks) fixed several bugs.\n- [Daniel Lebrero](https://github.com/dlebrero) added support for cljc files and `/prone/latest`.\n- [Max Ovsiankin](https://github.com/gratimax) added the `:print-stacktraces?` option.\n- [Timothy Pratley](https://github.com/timothypratley) added support for `SQLException getNextException`\n\nThanks!\n\n## Contribute\n\nYes, please do. And add tests for your feature or fix, or we'll certainly break\nit later.\n\n#### Up and running\n\nPrerequisites:\n\n- NPM: https://www.npmjs.org/\n\nTo start the server:\n\n- run `lein cljsbuild auto` in one terminal\n- run `lein ring server-headless` in another.\n\n`./bin/kaocha` will run all tests. (run `lein cljsbuild once` to generate\nrequired js files)\n\nTo run tests continuously: `./bin/kaocha --watch`\n\nAfter making changes to static files in `dev-resources`, run\n`./build-js-sources.sh` again to update the concatenated files.\n\n## License: BSD\n\nCopyright © 2014-2018 Christian Johansen \u0026 Magnar Sveen. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors\nmay be used to endorse or promote products derived from this software without\nspecific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagnars%2Fprone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagnars%2Fprone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagnars%2Fprone/lists"}