Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printing a stack trace should show details for the "cause" Exceptions too #317

Closed
peterlindstrom123 opened this issue Sep 11, 2020 · 8 comments
Assignees
Milestone

Comments

@peterlindstrom123
Copy link

peterlindstrom123 commented Sep 11, 2020

The following neatly formatted stack trace printed by Timbre shows no trace of my own code, which makes it useless for figuring out where an error is happening.

                                          java.lang.Thread.run              Thread.java:  834
            java.util.concurrent.ThreadPoolExecutor$Worker.run  ThreadPoolExecutor.java:  628
             java.util.concurrent.ThreadPoolExecutor.runWorker  ThreadPoolExecutor.java: 1128
       jdk.internal.net.http.Http1Exchange.lambda$cancelImpl$9       Http1Exchange.java:  473
  java.util.concurrent.CompletableFuture.completeExceptionally   CompletableFuture.java: 2088
           java.util.concurrent.CompletableFuture.postComplete   CompletableFuture.java:  506
      java.util.concurrent.CompletableFuture$UniHandle.tryFire   CompletableFuture.java:  907
              java.util.concurrent.CompletableFuture.uniHandle   CompletableFuture.java:  930
jdk.internal.net.http.MultiExchange.lambda$responseAsyncImpl$7       MultiExchange.java:  339
          jdk.internal.net.http.MultiExchange.getExceptionalCF       MultiExchange.java:  412
        jdk.internal.net.http.MultiExchange.toTimeoutException       MultiExchange.java:  463
                java.net.ConnectException: HTTP connect timed out
java.net.http.HttpConnectTimeoutException: HTTP connect timed out
java.net.http.HttpConnectTimeoutException: HTTP connect timed out

But when I call a normal Java .printStackTrace, I see my own code in the details for one of the java.net.http.HttpConnectTimeoutExceptions

@ptaoussanis
Copy link
Member

ptaoussanis commented Sep 12, 2020

@peterlindstrom123 Hi there!

Could you please try provide a minimum reproducible example?

With the default config in v4.10.0 I'm seeing causes displayed as expected:

(timbre/error (ex-info "Ex.1" {} (ex-info "Ex.2" {} (ex-info "Ex.3" {}))) "Foo") ; =>
Sep 12 15:49 Schrebermann.local ERROR [taoensso.timbre:804] - Foo
nrepl.middleware.interruptible-eval/evaluate/fn  interruptible_eval.clj:   91
                              clojure.core/eval                core.clj: 3214
                                            ...                              
                      taoensso.timbre/eval14635               REPL Input     
                          taoensso.timbre/-log!              timbre.clj:  358
                             clojure.core/deref                core.clj: 2320
                                            ...                              
                   taoensso.timbre/eval14635/fn               REPL Input     
clojure.lang.ExceptionInfo: Ex.3
clojure.lang.ExceptionInfo: Ex.2
clojure.lang.ExceptionInfo: Ex.1

Thanks!

@peterlindstrom123
Copy link
Author

peterlindstrom123 commented Sep 13, 2020

Hi,

I'm not sure what you mean.

Is all of this output related to Ex.3?

nrepl.middleware.interruptible-eval/evaluate/fn  interruptible_eval.clj:   91
                              clojure.core/eval                core.clj: 3214
                                            ...                              
                      taoensso.timbre/eval14635               REPL Input     
                          taoensso.timbre/-log!              timbre.clj:  358
                             clojure.core/deref                core.clj: 2320
                                            ...                              
                   taoensso.timbre/eval14635/fn               REPL Input     

?

If that's correct, then as far as I can tell, my problem was that no source files or line numbers are mentioned for Ex.2 or Ex.1. A normal Java stack trace would show them all.

Obviously the details for all of the source exceptions are relevant?

@lnostdal
Copy link
Contributor

Yeah, hiding the chain of traces is a big mistake. I believe https://github.com/AvisoNovate/pretty is the culprit really. To deal with this I had to create my own :output-fn which basically uses clojure.stacktrace/print-cause-trace.

@ptaoussanis
Copy link
Member

Just to follow-up on this- I'm still not completely clear on what's being requested here.

It'd be helpful to have the following:

  • An example that I can run at the REPL
  • What output you're seeing
  • What output you'd rather see

Thanks!

@lnostdal
Copy link
Contributor

lnostdal commented Mar 23, 2022

Of course this is pointless here in this example, but in other cases the exception and the cause traces are both actually needed. Compare:

user> (clojure.stacktrace/print-cause-trace (Exception. "hi" (Exception. "cause")))                                                                                                                                                                                                         
java.lang.Exception: hi                                                                                                                                                                                                                                                                     
 at user$eval11357.invokeStatic (NO_SOURCE_FILE:1)                                                                                                                                                                                                                                          
    user$eval11357.invoke (NO_SOURCE_FILE:1)                                                                                                                                                                                                                                                
    clojure.lang.Compiler.eval (Compiler.java:7194)                                                                                                                                                                                                                                         
    clojure.lang.Compiler.eval (Compiler.java:7149)                                                                                                                                                                                                                                         
    clojure.core$eval.invokeStatic (core.clj:3215)                                                                                                                                                                                                                                          
    clojure.core$eval.invoke (core.clj:3211)                                                                                                                                                                                                                                                
    nrepl.middleware.interruptible_eval$evaluate$fn__1245$fn__1246.invoke (interruptible_eval.clj:87)                                                                                                                                                                                       
    clojure.lang.AFn.applyToHelper (AFn.java:152)                                                                                                                                                                                                                                           
    clojure.lang.AFn.applyTo (AFn.java:144)                                                                                                                                                                                                                                                 
    clojure.core$apply.invokeStatic (core.clj:667)                                                                                                                                                                                                                                          
    clojure.core$with_bindings_STAR_.invokeStatic (core.clj:1990)                                                                                                                                                                                                                           
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1990)                                                                                                                                                                                                                               
    clojure.lang.RestFn.invoke (RestFn.java:425)                                                                                                                                                                                                                                            
    nrepl.middleware.interruptible_eval$evaluate$fn__1245.invoke (interruptible_eval.clj:87)                                                                                                                                                                                                
    clojure.main$repl$read_eval_print__9206$fn__9209.invoke (main.clj:437)                                                                                                                                                                                                                  
    clojure.main$repl$read_eval_print__9206.invoke (main.clj:437)                                                                                                                                                                                                                           
    clojure.main$repl$fn__9215.invoke (main.clj:458)                                                                                                                                                                                                                                        
    clojure.main$repl.invokeStatic (main.clj:458)                                                                                                                                                                                                                                           
    clojure.main$repl.doInvoke (main.clj:368)                                                                                                                                                                                                                                               
    clojure.lang.RestFn.invoke (RestFn.java:1523)                                                                                                                                                                                                                                           
    nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)                                                                                                                                                                                                   
    nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)                                                                                                                                                                                                         
    nrepl.middleware.interruptible_eval$interruptible_eval$fn__1278$fn__1282.invoke (interruptible_eval.clj:152)                                                                                                                                                                            
    clojure.lang.AFn.run (AFn.java:22)                                                                                                                                                                                                                                                      
    nrepl.middleware.session$session_exec$main_loop__1348$fn__1352.invoke (session.clj:218)                                                                                                                                                                                                 
    nrepl.middleware.session$session_exec$main_loop__1348.invoke (session.clj:217)                                                                                                                                                                                                          
    clojure.lang.AFn.run (AFn.java:22)                                                                                                                                                                                                                                                      
    java.lang.Thread.run (Thread.java:833)                                                                                                                                                                                                                                                  
Caused by: java.lang.Exception: cause                                                                                                                                                                                                                                                       
 at user$eval11357.invokeStatic (NO_SOURCE_FILE:1)                                                                                                                                                                                                                                          
    user$eval11357.invoke (NO_SOURCE_FILE:1)                                                                                                                                                                                                                                                
    clojure.lang.Compiler.eval (Compiler.java:7194)                                                                                                                                                                                                                                         
    clojure.lang.Compiler.eval (Compiler.java:7149)                                                                                                                                                                                                                                         
    clojure.core$eval.invokeStatic (core.clj:3215)                                                                                                                                                                                                                                          
    clojure.core$eval.invoke (core.clj:3211)                                                                                                                                                                                                                                                
    nrepl.middleware.interruptible_eval$evaluate$fn__1245$fn__1246.invoke (interruptible_eval.clj:87)                                                                                                                                                                                       
    clojure.lang.AFn.applyToHelper (AFn.java:152)                                                                                                                                                                                                                                           
    clojure.lang.AFn.applyTo (AFn.java:144)                                                                                                                                                                                                                                                 
    clojure.core$apply.invokeStatic (core.clj:667)                                                                                                                                                                                                                                          
    clojure.core$with_bindings_STAR_.invokeStatic (core.clj:1990)                                                                                                                                                                                                                           
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1990)                                                                                                                                                                                                                               
    clojure.lang.RestFn.invoke (RestFn.java:425)                                                                                                                                                                                                                                            
    nrepl.middleware.interruptible_eval$evaluate$fn__1245.invoke (interruptible_eval.clj:87)                                                                                                                                                                                                
    clojure.main$repl$read_eval_print__9206$fn__9209.invoke (main.clj:437)                                                                                                                                                                                                                  
    clojure.main$repl$read_eval_print__9206.invoke (main.clj:437)                                                                                                                                                                                                                           
    clojure.main$repl$fn__9215.invoke (main.clj:458)                                                                                                                                                                                                                                        
    clojure.main$repl.invokeStatic (main.clj:458)                                                                                                                                                                                                                                           
    clojure.main$repl.doInvoke (main.clj:368)                                                                                                                                                                                                                                               
    clojure.lang.RestFn.invoke (RestFn.java:1523)                                                                                                                                                                                                                                           
    nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)                                                                                                                                                                                                   
    nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)                                                                                                                                                                                                         
    nrepl.middleware.interruptible_eval$interruptible_eval$fn__1278$fn__1282.invoke (interruptible_eval.clj:152)                                                                                                                                                                            
    clojure.lang.AFn.run (AFn.java:22)                                                                                                                                                                                                                                                      
    nrepl.middleware.session$session_exec$main_loop__1348$fn__1352.invoke (session.clj:218)                                                                                                                                                                                                 
    nrepl.middleware.session$session_exec$main_loop__1348.invoke (session.clj:217)                                                                                                                                                                                                          
    clojure.lang.AFn.run (AFn.java:22)                                                                                                                                                                                                                                                      
    java.lang.Thread.run (Thread.java:833)  

i.e. both traces vs.

2022-03-23T05:54:54.850Z bullseyeclub-5006 DEBUG [user:61] -                                                                                                                                                                                                                                
   nrepl.middleware.interruptible-eval/evaluate/fn  interruptible_eval.clj:   87                                                                                                                                                                                                            
                                               ...                                                                                                                                                                                                                                          
                       clojure.core/with-bindings*                core.clj: 1990 (repeats 2 times)                                                                                                                                                                                          
                                clojure.core/apply                core.clj:  667                                                                                                                                                                                                            
                                               ...                                                                                                                                                                                                                                          
nrepl.middleware.interruptible-eval/evaluate/fn/fn  interruptible_eval.clj:   87                                                                                                                                                                                                            
                                 clojure.core/eval                core.clj: 3215                                                                                                                                                                                                            
                                               ...                                                                                                                                                                                                                                          
                             user$eval11359.invoke          NO_SOURCE_FILE:   61                                                                                                                                                                                                            
                       user$eval11359.invokeStatic          NO_SOURCE_FILE:   61                                                                                                                                                                                                            
                             taoensso.timbre/-log!             timbre.cljc:  534                                                                                                                                                                                                            
                                clojure.core/deref                core.clj: 2337                                                                                                                                                                                                            
                                               ...                                                                                                                                                                                                                                          
                   user$eval11359$fn__11360.invoke          NO_SOURCE_FILE:   61                                                                                                                                                                                                            
java.lang.Exception: cause                                                                                                                                                                                                                                                                  
java.lang.Exception: hi    

..which has only one of the traces.

@ptaoussanis
Copy link
Member

@lnostdal Hi Lars, thanks for the clear example! Apologies for the delay replying.
This does indeed appear to be the current behaviour of https://github.com/AvisoNovate/pretty.

A couple possibilities:

  1. [Immediate workaround] alter-var-root could be used to change the default stacktrace fn.
  2. [Future Timbre version] default-output-fn could be given an option to specify a different/custom stacktrace fn.

How does (2) sound? Would also be open to ideas re: alternative stracktrace implementations!

Cheers :-)

@ptaoussanis ptaoussanis added this to the v6 milestone Oct 18, 2022
@ptaoussanis ptaoussanis self-assigned this Oct 18, 2022
@lnostdal
Copy link
Contributor

Hi there! I'm doing something similar to nr. 1 now - but nr. 2 seems like a better idea.

I don't know about alternatives to the pretty printing done by aviso, but this stacktrace stuff was so important to me I wanted all the details and even noise no matter what - so I just ended up doing: (with-out-str (clojure.stacktrace/print-cause-trace err))

@ptaoussanis
Copy link
Member

Great, thanks for the feedback @lnostdal.

@lnostdal @peterlindstrom123 An :error-output-fn option will be added to default-output-fn in a forthcoming release. This'll allow one to easily swap in an alternative stacktrace implementation 👍

ptaoussanis added a commit that referenced this issue Oct 19, 2022
This makes it easier to provide an alternative stacktrace implementation, etc.
ptaoussanis added a commit that referenced this issue Oct 19, 2022
This makes it easier to provide an alternative stacktrace implementation, etc.
ptaoussanis added a commit that referenced this issue Oct 20, 2022
This makes it easier to provide an alternative stacktrace implementation, etc.
ptaoussanis added a commit that referenced this issue Oct 22, 2022
This makes it easier to provide an alternative stacktrace implementation, etc.
ptaoussanis added a commit that referenced this issue Oct 23, 2022
This makes it easier to provide an alternative stacktrace implementation, etc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants