This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-03-20
Channels
- # arachne (4)
- # bangalore-clj (1)
- # beginners (38)
- # boot (182)
- # cider (21)
- # cljs-dev (9)
- # clojars (5)
- # clojure (229)
- # clojure-austin (1)
- # clojure-berlin (1)
- # clojure-czech (3)
- # clojure-dusseldorf (3)
- # clojure-ireland (5)
- # clojure-italy (4)
- # clojure-russia (33)
- # clojure-spec (73)
- # clojure-taiwan (6)
- # clojure-uk (22)
- # clojure-ukraine (1)
- # clojurescript (80)
- # core-async (26)
- # cursive (3)
- # datascript (20)
- # datomic (9)
- # defnpodcast (8)
- # editors (4)
- # emacs (7)
- # garden (41)
- # hoplon (2)
- # java (1)
- # lambdaisland (2)
- # lein-figwheel (1)
- # leiningen (5)
- # luminus (4)
- # lumo (36)
- # off-topic (4)
- # om (21)
- # onyx (1)
- # pedestal (33)
- # re-frame (33)
- # ring-swagger (70)
- # spacemacs (26)
- # specter (7)
- # sql (6)
- # timbre (2)
- # untangled (12)
- # vim (3)
- # yada (1)
@ikitommi I stumbled upon https://github.com/metosin/compojure-api/blob/master/src/compojure/api/impl/logging.clj and I find it really scary 🙂
Is it really necessary to do it this way? It caused issues with our logging, if the logging lib wasn't required in the handler.clj namespace with the api
clojure.tools.logging also does some nasty stuff at the top-level w.r.t. figuring out which implementation to use (https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj#L288)
and by nasty stuff, I mean it just picks a logger implementation based on whatever random by trying to load a bunch of java classes in a loop with try/catch. if it finds one, then it evals a whole boatload of implementation stuff.
@mrchance @bja yes, idea was not to require c.t.l as a dependency. If that is causing problems, let's fix them. Ideas welcome.
@ikitommi it doesn't bother me; I already had a namespace dependency order issue due to using timbre to control all of the java logging libraries (my timbre config namespace has to be loaded before any of my other code)
at the very least, it might be worth mentioning in documentation. something like "If you intend on debug messages and errors from this library using clojure.tools.logging, clojure.tools.logging needs to be loaded before requiring compojure-api namespaces."
We have a lot of relatively new Clojure developers, it's hard to explain something like that, and also making sure no one gets it wrong
Idea in the code was to see if there is a c.t.l as a dependency, guess it doesn't do that now? Requires an manual import too?
also ring-swagger checks if there is Java1.8+ and adds swagger-bindings to java.time
classes if there are.
user=> (compojure.api.impl.logging/log! :error "foo-bar")
Mar 20, 2017 10:29:31 AM clojure.tools.logging$eval420$fn__424 invoke
SEVERE: foo-bar
vs w/o clojure.tools.logging on the classpath:
user=> (compojure.api.impl.logging/log! :debug "foo-bar")
DEBUG foo-bar
that seems to work as-intended to me (use c.t.l. when available, default to prn otherwise)
I think I've seen people use a multimethod with a default (for the console logging) and then a standalone namespace for implementations (shipped with c.t.l). The downside is that multimethod dispatch adds to the overhead and it would be a breaking change for people who use c.t.l. right now. Those people would suddenly need an extra require to continue working as-is.
@mrchance if you're unhappy with runtime eval at the top-level, how are you okay with c.t.l. to begin with?
I am not really in favor of c.t.l., I just want my own logging to behave deterministically, regardless of the order in which I require namespaces
@mrchance from my testing, the order of loading namespaces doesn't appear to matter to compojure-api
@mrchance if you create a new project and then add the latest compojure-api, you can require compojure.api.impl.logging
and then use log!
to see that the console prn implementation is selected. if you then add c.t.l. and restart your repl, you'll see that c.t.l. is used
I didn't check myself, but from what my coworker told me, it appears that errors are swallowed if the main compojure api using ns doesn't require c.t.l.
the only thing that would affect that would be if you muck around with your classloader at runtime (i.e. require some part of compojure-api and then add c.t.l. to your classloader and use it somewhere else. IMO that would be your own fault for mucking with the classloader)
https://github.com/metosin/compojure-api/blob/master/src/compojure/api/impl/logging.clj#L9
Instead of find-ns
, Compojure-api could check if (io/resource "clojure/tools/logging.clj")
exists
find-ns
only finds the namespace if it is already loaded, resource is in classpath if the c.t.l dependency is included
@juhoteperi that doesn't seem consistent with basic testing
i.e.
(defproject comp-api-ctl-test "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url ""
:license {:name "Eclipse Public License"
:url ""}
:dependencies [[org.clojure/clojure "1.8.0"]
[metosin/compojure-api "1.2.0-alpha3"]
[org.clojure/tools.logging "0.3.1"]])
[bja@tatooine comp-api-ctl-test]$ lein repl
nREPL server started on port 40443 on host 127.0.0.1 -
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_121-b14
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> (require 'compojure.api.impl.logging)
nil
user=> (compojure.api.impl.logging/log! :error "foo-bar")
Mar 20, 2017 10:43:54 AM clojure.tools.logging$eval420$fn__424 invoke
SEVERE: foo-bar
nil
aha hmm
how about https://github.com/metosin/muuntaja/blob/master/src/clj/muuntaja/util.clj#L31
although I like that more than find-ns or using io/resource, since clojure.core/require
will actually verify that c.t.l. is available
Find-ns shouldn't see the namespace if it isn't already loaded
user=> (find-ns 'clojure.tools.logging) nil
oh well in this case I don't even have the dependency, 1 sec
user=> (find-ns 'clojure.tools.logging) #namespace[clojure.tools.logging]
hmm, sure looks like lein repl
is doing something that lies to me:
user=> (find-ns 'clojure.tools.logging)
#object[clojure.lang.Namespace 0x2ae8aefa "clojure.tools.logging"]
user=> (find-ns 'compojure.api.core)
nil
hmm somehow it loaded automatically
shouldn't matter as this is empty repl
since the require will actually verify that clojure.tools.logging gets loaded if it's available
what does this log! macro even do when the c.t.l is loaded
why does it log that "function name + invoke"
why is log! fn in else branch and macro in then branch
because c.t.l calls are macros