Open vladprevi opened 2 years ago
Hi, thanks for the accurate report!
Could you please consolidate your (nice) repro steps into a repository that one could simply clone and run?
Thanks - V
I encountered the same problem just now as well. I wanted to add some quick observations, in case they are helpful:
In my particular case the user.clj
causes to actually require
s large parts of my application, including jetty. This happens before any nrepl code actually runs. The static initializers in jetty cause the log4j2 backend to be initialized and sets up logging to stdout. If one breaks this dependency in user.clj
and delays the require
of the dependencies, the problem goes away and log messages to the repl start to flow.
It seems that log4j2 captures System.out before nrepl can bring it under its control. I also tried to ensure that nrepl's static initializers (if existing?) are executed before jetty's but that didn't help much.
Much useful input, thanks!
As you may be well aware of already, user.clj
has a special semantic for the Clojure compiler - it's loaded before anything else.
Perhaps moving its contents to something like dev/dev.clj
would allow nrepl code to take precedence?
Yep, I actually wanted to exploit the user.clj
semantics of it being loaded early and available every time (controlled by deps.edn
).
My solution is:
I just had one dependency from my application's namespaces within a function in user.clj
. Not requiring it directly in the ns
block but using requiring-resolve
from within the function solved the problem with just one additional line of code. It causes the dependencies to only get loaded whenever I call that function, which is my main entry point to the application anyway.
This bug probably belongs to cider-nrepl anyway, where the out
middleware would probably have try to capture the *out*
and *err*
streams as soon as possible via static initializers and map it to some session. This might be nice but would have dubious semantics.
Expected behavior
When logging with
clojure.tools.logging
withlog4j2
backend set via relevantclojure.tools.logging.imlp
factory I expect log messages both in NREPL and in REPL buffer. Note that we havecider-redirect-server-output-to-repl
set to true and cider-nrepl loadded.Actual behavior
Log messages turn up in the NREPL only buffer, but not in REPL
Potentially related tickets: https://github.com/clojure-emacs/cider/issues/524 https://github.com/clojure-emacs/cider/issues/2138
but note that server output redirection to repl is set and works perfectly fine with e.g. logback backend.
Steps to reproduce the problem
With the following settings in your
project.clj
or similar indeps.edn
:Dependencies
JVM options that set the backend
Some simple config
log4j2.xml
in your classpathUse below or e.g. this .properties example provided by clojure.tools.logging.
Jack in as usual and try this code:
Fun observation and experiments that may help
Our log4j2 setup above rescans itself for changes every 5 seconds. If you do in fact change that xml config you'll notice that those log messages will now appear in REPL as you'd expect. Because in prod when deployed logs will end up in STDOUT and we're only having trouble with our dev setup, I thought I'd be clever and trigger reloading our logger from e.g.
user.clj
with this:It does in fact fixes the problem and message start logging in the REPL buffer. It has fun consequences however: killing the REPL will kill Emacs. What fun :)
Environment & Version information
CIDER version information
Lein / Clojure CLI version
Leiningen 2.9.8 on Java 18.0.1 OpenJDK 64-Bit Server VM
Emacs version
GNU Emacs 28.1 (build 2, x86_64-apple-darwin21.4.0, NS appkit-2113.40 Version 12.3.1 (Build 21E258)) of 2022-05-09
Operating system
Mac OS Monterey 12.3.1