Coder Social home page Coder Social logo

prone's Introduction

prone Build Status

Better exception reporting middleware for Ring. Heavily inspired by better_errors for Rails.

See it to believe it: a quick video demoing Prone.

Prone presents your stack traces in a consumable form. It optionally filters out stack frames that did not originate in your application, allowing you to focus on your code. It allows you to browse environment data, such as the request map and exception data (when using ex-info). Prone also provides a debug function that enables you to visually browse local bindings and any piece of data you pass to debug.

Install

Add [prone "2021-04-23"] to :dependencies in your project.clj.

This project no longer uses Semantic Versioning. Instead we're aiming to never break the API. Feel free to check out the change log.

Usage

  • with lein-ring

    Using lein-ring version 0.9.1 or above, add this to your project.clj:

    {:profiles {:dev {:ring {:stacktrace-middleware prone.middleware/wrap-exceptions}}}
  • without lein-ring

    Add it as a middleware to your Ring stack:

    (ns example
      (:require [prone.middleware :as prone]))
    
    (def app
      (-> my-app
          prone/wrap-exceptions))

    Please note, with this configuration you should make sure to only enable Prone in development.

  • with pedestal

    See prone-pedestal

  • with catacumba

    See catacumba-prone

Debugging

Whether you've tripped on an exception or not, you can use Prone to debug your application:

(ns example
  (:require [prone.debug :refer [debug]]))

(defn myhandler [req]
  ;; ...
  (let [person (lookup-person (:id (:params req)))]
    (debug)))

Calling debug without any arguments like this will cause Prone to render the exception page with information about your environment: the request map, and any local bindings (req and person in the above example).

You can call debug multiple times. To differentiate calls, you can pass a message as the first argument, but Prone will also indicate the source location that triggered debugging.

debug accepts any number of forms to present in a value browser on the error/debug page:

(debug) ;; Inspect locals
        ;; Halts the page if there are no exceptions

(debug "Here be trouble") ;; Same as above, with a message

(debug {:id 42}) ;; Inspect locals and the specific map
                 ;; Halts the page if there are no exceptions

(debug person project) ;; Same as above, with multiple values

(debug "What's this?" person project) ;; Same as above, with message

Q & A

Should I use Prone in production?

No. You would be exposing your innards to customers, and maybe even to someone with nefarious purposes.

Here's one way to avoid it:

(def prone-enabled? (= "true" (System.getProperty "prone.enable")))

(def app
  (cond-> my-app
          prone-enabled? prone/wrap-exceptions))

You can chain more optional middlewares in this cond-> too. Pretty nifty.

How does Prone determine what parts of a stack trace belongs to the application?

By default it reads your project.clj and looks for namespaces starting with the project name.

You can change this behavior by passing in some options to wrap-exceptions, like so:

(-> app
    (prone/wrap-exceptions 
      {:app-namespaces ["our" "app" "namespace" "prefixes"]}))

All frames from namespaces prefixed with the names in the list will be marked as application frames.

How do I skip prone for certain requests?

Pass a predicate function skip-prone? to wrap-exceptions. For example, to exclude Postman requests check for postman-token in the headers:

(-> app
    (prone/wrap-exceptions 
      {:skip-prone? (fn [req] (contains? (:headers req) "postman-token"))}))

What about AJAX requests?

Yeah, that's a bit trickier. There's no point in serving a beautiful exception page when you have to inspect it in devtools.

The prone response includes a Link header with a rel=help attribute. Like this:

Link:</prone/d97fa078-7638-4fd1-8e4a-9a22576a321f>; rel=help

Use this in your frontend code to display the page. Here's an example from one of our sites:

(def rel-help-regex #"<(.+)>; rel=help")

(defn check-err [result]
  (if-let [url (->> (get-in result [:headers "link"] "")
                    (re-find rel-help-regex)
                    second)]
    (set! js/location url)
    (do (js/alert "fail")
        (prn result))))

(defn GET [url params]
  (go
    (let [result (<! (http/get url {:query-params params}))]
      (if (:success result)
        (do-some-successful-stuff)
        (check-err result)))))

A little trick

The latest prone error page can also be found under /prone/latest, so if you haven't fixed your frontend code to use the rel=help header quite yet, you can always go there to check it out.

I'm getting double printing of error messages

Yeah, I guess you already have a logging framework to print errors for you? And then prone goes and prints them as well. Turn it off like so:

(-> app
    (prone/wrap-exceptions 
      {:print-stacktraces? false}))

Known problems

  • We have not yet found a way to differentiate some-name and some_name function names by inspecting the stack trace. Currently, we assume kebab case.
  • Using a middleware to always load the Austin browser-connected-repl for ClojureScript causes JavaScript errors that partly trips up Prone

Change log

From 1.6.3 to 2019-07-08

  • Add ability to copy values into clipboard
  • Navigation now starts directly at the root cause exception
  • Serialized values are now displayed better and more consistently
  • Improved display of functions

From 1.6.1 to 1.6.3

  • Can now navigate into sets + weeded out some weird set bugs
  • Update realize, it now guards against infinite lazy seqs

From 1.6 to 1.6.1

  • Don't crash without a project.clj-file.

From 1.5 to 1.6

  • Support SQLException getNextException (timothypratley)
  • Add column in addition to line number (timothypratley)
  • Display java.util.Date like #inst

From 1.4 to 1.5

  • Avoid expanding Datomic databases
  • Don't show too many extra exceptions
  • Always select the first source location when switching between exceptions

From 1.3 to 1.4

  • Exceptions thrown when realizing lazy sequences are now handled properly.

From 1.2 to 1.3

  • Add function to render self-contained page.

    This can be used to store prone-pages for later perusal even when the prone process is no longer running.

    (spit "my-error.html" (render-self-contained-page (create-exception-page e {})))
    

From 1.1 to 1.2

  • Serve contents as UTF-8 - fixes occasional regexp error warning
  • Upgrade Prism.JS - fixes graphical glitch with highlighted line
  • Upgrade ClojureScript version - now supports namespaced keys.
  • Show error page for assertion errors as well (alephyud)
  • Fix error when showing maps with complex keys
  • Fix compatibility Clojure 1.9 (lvh)
  • Don't crash on invalid or missing line-numbers

From 1.0 to 1.1

  • Added option :print-stacktraces? (Max Ovsiankin)
  • Added latest prone error to /prone/latest (Daniel Lebrero)

Contributors

Thanks!

Contribute

Yes, please do. And add tests for your feature or fix, or we'll certainly break it later.

Up and running

Prerequisites:

To start the server:

  • run lein cljsbuild auto in one terminal
  • run lein ring server-headless in another.

./bin/kaocha will run all tests. (run lein cljsbuild once to generate required js files)

To run tests continuously: ./bin/kaocha --watch

After making changes to static files in dev-resources, run ./build-js-sources.sh again to update the concatenated files.

License: BSD

Copyright © 2014-2018 Christian Johansen & Magnar Sveen. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

prone's People

Contributors

andrewmcveigh avatar cjohansen avatar damn avatar dlebrero avatar dspearson avatar eunmin avatar lvh avatar magnars avatar malcolmsparks avatar maxov avatar minimal avatar rfkm avatar stig avatar timothypratley avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prone's Issues

GPL License makes it incompatible with pretty much every Clojure library

Clojure is licensed under the Eclipse Public License, and most libraries seem to use the same license. Unfortunately, this license is incompatible with the GPL (see FSF's own explanation), so that makes prone legally incompatible with almost every Clojure library. In fact, I would imagine that the Clojure standard library has the same license, so I don't think it's even possible to have a legal Clojure program that uses prone :-(

The lazier/easier alternative would be to use EPL, although I would imagine that any "liberal" license (BSD and such) would work, too.

error from prone.js

Hi,

Getting this error from prone javascript code.

Uncaught Error: Could not find tag parser for :prone.prep in ("inst" "uuid" "queue" "js")

It seems cljs.reader not able to read tagged value sent by prone server. How to resolve this?

Thanks!

Prone isn't working with lein-ring

Hi,

Thanks for creating this awesome library.

I'm trying to use it with lein-ring. Snippet from project.clj:

  :profiles {:dev {:aliases {"run-dev" ["trampoline" "run" "-m" "my-api/-main"]}
                   :ring {:stacktrace-middleware prone.middleware/wrap-exceptions}
                   :dependencies [[lein-ring "0.9.6"]]}
             :uberjar {:aot :all}})

But that isn't taking place, nothing is happening.

What I'm doing wrong?

Lein 2.5.1, Clojure 1.7

Thanks again.

Test failures in 1.10.0+

Hey friends,

I tried running the test suite with clojure 1.10.3 and ran into some failures because of hardcoded assumptions about Reflector.java that have changed since 1.8. I'm not sure what a viable solution here is, as the tests are predicated on correctly listing entirely implementation-dependent information:

(deftest check-assumptions-about-exception
(is (= "Message for you, Sir!" (.getMessage ex)))
(is (= "prone.stacks_test$create_ex" (.getClassName clj-frame)))
(is (= "invokeStatic" (.getMethodName clj-frame)))
(is (= "stacks_test.clj" (.getFileName clj-frame)))
(is (= 8 (.getLineNumber clj-frame)))
(is (= "clojure.lang.Reflector" (.getClassName java-frame)))
(is (= "invokeConstructor" (.getMethodName java-frame)))
(is (= "Reflector.java" (.getFileName java-frame)))
(is (= 180 (.getLineNumber java-frame))))

(deftest normalize-frame-test
(is (= {:class-path-url "prone/stacks_test.clj"
:loaded-from nil
:file-name "stacks_test.clj"
:method-name "create-ex"
:line-number 8
:package "prone.stacks-test"
:lang :clj}
(normalize-frame clj-frame)))
(is (= {:class-path-url "clojure/lang/Reflector.java"
:loaded-from (clj-version)
:file-name "Reflector.java"
:method-name "invokeConstructor"
:line-number 180
:class-name "Reflector"
:package "clojure.lang"
:lang :java}
(normalize-frame java-frame)))

prone 1.1.2's prone.js causes a SyntaxError

After upgrading to prone 1.1.2 this error occurs in prone.js line 22055:

Uncaught SyntaxError: Invalid regular expression: /[A-Za-zÀ-ÖØ-öø-??-??-???-??-??-?]/: Range out of order in character class

prone 1.1.1 works fine but 1.1.2 fails on Firefox/Chrome/IE/...
Is it a problem with server response encoding maybe?

prone/debug macro

  • Queue up data structures to log out
  • After calling the upstream handler, check for debug - if any present, return the error page
  • Use the dump-locals macro to add information

prone ships with generated cljs+other sources

The [prone 0.8.0] .jar contains a whole lot of .cljs and .js files that are not required for its operation and confuse the cljs compiler when prone is used as a dependency.

Small excerpt:

    0 Fri Oct 17 20:49:20 CEST 2014 prone/generated/
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/
  3502 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/buffers.cljs
  9775 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/buffers.js
  7151 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/channels.cljs
 17470 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/channels.js
  1214 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/dispatch.cljs
  2537 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/dispatch.js
  4958 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/ioc_helpers.cljs
 26286 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/ioc_helpers.js
  1434 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/protocols.cljs
  8879 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/protocols.js
  5471 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/timers.cljs
 11596 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async/impl/timers.js
 29134 Fri Oct 17 20:49:30 CEST 2014 prone/generated/out/cljs/core/async.cljs
246316 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/core/async.js
220793 Fri Oct 17 20:49:26 CEST 2014 prone/generated/out/cljs/core.cljs
699075 Fri Oct 17 20:49:30 CEST 2014 prone/generated/out/cljs/core.js
 18071 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/reader.cljs
 37022 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/cljs/reader.js
   179 Fri Oct 17 20:49:26 CEST 2014 prone/generated/out/cljs/user.js
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/
     0 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/
  2950 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/event.cljs
  5915 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/event.js
  5382 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/net.cljs
 19084 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/net.js
  4204 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/repl.cljs
  6817 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/browser/repl.js
  5140 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/string.cljs
  7850 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/string.js
  3311 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/walk.cljs
  3906 Fri Oct 17 20:49:32 CEST 2014 prone/generated/out/clojure/walk.js

The resources folder is included in the jar and all tools (lein cljsbuild, build-js-sources.sh) are configured to put their output there. Those file should not be in a release jar though.

Should be enough to have

2176452 Fri Oct 17 21:00:08 CEST 2014 prone/generated/prone.js
2046841 Thu Aug 28 16:21:34 CEST 2014 prone/generated/prone.js.map

Missing content-type header (assets)

I understand that content-type header is technically not required, however it seems like a best practice to include it whenever possible. For example, Rails includes content-type when serving assets. Do you think it can be included here as well? The resources missing content-type are prone.js and prone.css.

HTTP/1.1 200 OK
Cache-Control: max-age=315360000
X-Runtime: 6.317E-6
Content-Length: 3402889
Server: http-kit
Date: Tue, 16 Jun 2020 17:27:21 GMT

The reason why I noticed this is that we have Clojure server sitting behind a reverse proxy, and when the proxy handles a response, it automatically sets missing content-type to default - text/plain. This makes browsers ignore assets, breaking the debug page.

Function to pre-process exceptions

When an error happens with pgsql, you see some description with helpful text saying "call .getNextException to see the cause". Having some ability to pre-process exception before showing it to user would be nice, I could write application-specific one for instance. :)

Prone does not catch AssertionErrors

At the moment prone catches only java.lang.Exceptions - which does not include AssertionErrors, among other error classes.

Is it intentional? Since prone is used in development, it would be good to be use it for debugging the code with assertions and pre- and post-conditions.

Would you consider making prone's middleware catch all Errors (or even any Throwable)? Or, alternatively, is there any other way to have the debug output for assertion failures?

Plugins? Example: prismatic schema

There should be extension points to further improve error reporting.

One such plugin could improve the schema data structure error (that's presented as text in the exception message):

Value does not match schema: {:articles {"/bah.md" (not (every? (check % a-clojure.lang.PersistentArrayMap) schemas))}}

Skip certain exception

Hi,

I have a web app, in which I use buddy-auth and prone (in dev mode).

I've implemented session authentication same as in this example.

In this example if user is not authenticated then the exception is raised:

(defn home
  [request]
  (if-not (authenticated? request)
    (throw-unauthorized)
    (let [content (slurp (io/resource "index.html"))]
      (render content request))))

This exception should be handled then by the buddy code:

(def auth-backend
  (session-backend {:unauthorized-handler unauthorized-handler}))

but in the development mode this doesn't work, because prone is catching and handling this exception. Is there any way to pass it down, to the unauthorized-handler?

Thanks in advance!

Is there a way to make prone work with ring on top of aleph?

Hi there,

I'm using ring with aleph and I'm trying to make prone work on top of aleph. Main problem is that aleph kind of breaks ring spec by allowing to return futures as a response. Normal way to port middleware is to use let-flow that aleph provides and reuse partial functionality from the middleware. But with prone most of logic is encapsulated in a wrap-exception function so my question is what would be idiomatic way to solve this problem? Should I just try to port entire wrapper? I'm mostly puzzled by things like debug/debug-data and why it's always empty for my errors.

Thanks!

Not compatible with spec?

I know it's still in alpha, just wanted to raise heads up. It does look to be incompatible. Tried on latest available at the time [org.clojure/clojure "1.9.0-alpha11"]. Thanks

Prone crashes for projects with unquoted forms in project.clj

I finally tracked down why I have stopped getting nice Prone stack traces. I suspect this began when I changed my project.clj to include some evaluated forms to build my Manifest entry when creating Jar files:

;...
  :uberjar-name "afterglow.jar"
  :manifest {"Name" ~#(str (clojure.string/replace (:group %) "." "/")
                            "/" (:name %) "/")
             "Package" ~#(str (:group %) "." (:name %))
             "Specification-Title" ~#(:name %)
             "Specification-Version" ~#(:version %)}
;...

The reason I suspect this is the problem is that now whenever I get a runtime error, instead of the nice Prone stack trace, I simply see “Error: 500 Something very bad has happened! We've dispatched a team of highly trained gnomes to take care of the problem.” And in my log file, I get a stack trace which ends:

prone.middleware/wrap-exceptions/fn             middleware.clj:   94
prone.middleware/get-application-name           middleware.clj:   20
prone.middleware/get-application-name/invokeStatic           middleware.clj:   25
clojure.edn/read-string                         edn.clj:   37
clojure.edn/read-string/invokeStatic            edn.clj:   37
clojure.edn/read-string/invokeStatic            edn.clj:   46

java.lang.RuntimeException: Invalid leading character: ~

And, indeed, I just tried removing my :manifest declaration, and I get back the lovely Prone stack trace. All right, now that I know this, when I encounter a problem I can shut down my REPL, hack the project.clj, restart the REPL, and try to recreate the problem so I can see the actual error. But I would much prefer to have Prone be able to coexist with this kind of code in the project—as things stand, the Prone crash completely obscures the original problem that I would like to debug.

I need to keep the evaluated expressions in my project definition, in order to build name and version information which is displayed to the user at runtime when executing from a jar file, either standalone, or embedded in the Max/MSP visual programming environment. And the sample project.clj in Leiningen itself includes such examples, so I very much hope this is something that Prone can be made to accommodate?

NodeJS

Have you thought of porting prone to nodejs?

I would like to see this and I don't mind contributing. Do you have any pointers?

Prone throws an IndexOutOfBoundsException handling a org.postgresql.util.PSQLException

My application throws an exception like this:

#error {
 :cause "Can't infer the SQL type to use for an instance of clojure.lang.Keyword. Use setObject() with an explicit Types value to specify the type to use."
 :via
 [{:type org.postgresql.util.PSQLException
   :message "Can't infer the SQL type to use for an instance of clojure.lang.Keyword. Use setObject() with an explicit Types value to specify the type to use."
   :at [org.postgresql.jdbc.PgPreparedStatement setObject "PgPreparedStatement.java" 1039]}]
 :trace
 [[org.postgresql.jdbc.PgPreparedStatement setObject "PgPreparedStatement.java" 1039]
  [com.zaxxer.hikari.pool.HikariProxyPreparedStatement setObject "HikariProxyPreparedStatement.java" -1]
  [clojure.java.jdbc$eval4067$fn__4068 invokePrim "jdbc.clj" 341]
;;; etc

But instead of Prone’s lovely debug UI, I get this:

java.lang.IndexOutOfBoundsException
    at clojure.lang.PersistentVector.arrayFor(PersistentVector.java:158)
    at clojure.lang.PersistentVector.nth(PersistentVector.java:162)
    at clojure.lang.RT.nth(RT.java:853)
    at prone.code_trunc$find_top_level_form.invokeStatic(code_trunc.clj:18)
    at prone.code_trunc$find_top_level_form.invoke(code_trunc.clj:8)
    at prone.code_trunc$truncate.invokeStatic(code_trunc.clj:54)
    at prone.code_trunc$truncate.invoke(code_trunc.clj:38)
    at prone.prep$load_source.invokeStatic(prep.clj:26)
    at prone.prep$load_source.invoke(prep.clj:20)
    at prone.prep$add_source.invokeStatic(prep.clj:30)
    at prone.prep$add_source.invoke(prep.clj:29)
    at clojure.core$mapv$fn__6953.invoke(core.clj:6627)
    at clojure.core.protocols$fn__6755.invokeStatic(protocols.clj:167)
    at clojure.core.protocols$fn__6755.invoke(protocols.clj:124)
    at clojure.core.protocols$fn__6710$G__6705__6719.invoke(protocols.clj:19)
    at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
    at clojure.core.protocols$fn__6738.invokeStatic(protocols.clj:75)
    at clojure.core.protocols$fn__6738.invoke(protocols.clj:75)
    at clojure.core.protocols$fn__6684$G__6679__6697.invoke(protocols.clj:13)
    at clojure.core$reduce.invokeStatic(core.clj:6545)
    at clojure.core$mapv.invokeStatic(core.clj:6618)
    at clojure.core$mapv.invoke(core.clj:6618)
    at prone.prep$prep_error$fn__12840.invoke(prep.clj:114)
    at clojure.lang.AFn.applyToHelper(AFn.java:154)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.core$apply.invokeStatic(core.clj:648)
    at clojure.core$update_in.invokeStatic(core.clj:5950)
    at clojure.core$update_in.doInvoke(core.clj:5939)
    at clojure.lang.RestFn.invoke(RestFn.java:445)
    at prone.prep$prep_error.invokeStatic(prep.clj:110)
    at prone.prep$prep_error.invoke(prep.clj:106)
    at prone.prep$prep_error_page.invokeStatic(prep.clj:149)
    at prone.prep$prep_error_page.invoke(prep.clj:148)
    at prone.middleware$exceptions_response.invokeStatic(middleware.clj:92)
    at prone.middleware$exceptions_response.invoke(middleware.clj:87)
    at prone.middleware$wrap_exceptions$fn__12928.invoke(middleware.clj:129)
(etc)

This is using HugSQL, FWIW, so some of the functions the exception passes through are created by macros.

Sort entries for request and ex-data maps by keyword

It would be nice if the request map was sorted, to make it easier to find what you looking for without scanning each entry.

For example

:content-type   "application/x-www-form-urlencoded"
:form-params    {"username" "[email protected]" "password" "foobar"}
:async-channel  "/0:0:0:0:0:0:0:1:8080<->/0:0:0:0:0:0:0:1:42667"<org.httpkit.server.AsyncChannel>
:server-name    "localhost"
:query-string   nil
:character-encoding "utf8"

would be nice if it were

:async-channel  "/0:0:0:0:0:0:0:1:8080<->/0:0:0:0:0:0:0:1:42667"<org.httpkit.server.AsyncChannel>
:character-encoding "utf8"
:content-type   "application/x-www-form-urlencoded"
:form-params    {"username" "[email protected]" "password" "foobar"}
:query-string   nil
:server-name    "localhost"

Friendly hints for common errors

Maybe we should add some friendly hints when you get one of Clojure's notorious error messages? ("Don't know how to create ISeq from: clojure.lang.Symbol", I'm looking at you). Something along the lines of "This usually occurs when ..."?

putting prone under single url prefix

I really like prone, but it generates urls which start with various numbers (like /1320042293/prone.css). And it's a bit hard to use those because of how my environment is configured (I can proxy only specific prefixes to a clojure app).

I wonder if it's possible to put it under some url like /prone, so the url will be /prone/123/prone.css or /prone/prone.css.

Better handling of compilation errors

The stack trace for compilation errors does not contain any application frames.

However, there is one clue in the message:

java.lang.RuntimeException: Unable to resolve symbol: prep in this context, compiling:(zombieclj/sweeper/game_loop.clj:7:5)

Maybe we could include this as a special frame?

Not able to see code snippets from within .cljc files

I cannot see code snippets from .cljc files.

Did:

  • threw an exception from a .cljc file

Happened:

  • The prone exception UI was shown in my browser, but there were issues with the frame to the right which shows code snippets.
    • Instead of showing code, it was grey and had a label: (could not locate source file on class path)
    • The top left label showing the path to the file was: "com/company/file.java", expected file extension to be .cljc not .java.
    • The top right label showing the function name, seems to always say invoke or doInvoke for .cljc files.

I don't have any problems with .clj files.
I have not tried to reproduce this with a minimal setup yet. Will update this issue when I have.

Unreadable form

The entire request map must be traversed, replacing all unreadables into their toString-form (and adding their original type).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.