The println function writes to STDOUT. How can we write messages to STDERR instead?
(println "Hello, STDOUT!")
There is no specific function for this, however you can dynamically rebind the var holding the stream that println writes to like this:
(println "Hello, STDOUT!")
(binding [*out* *err*]
(println "Hello, STDERR!"))
In my REPL, the colour indicates the stream (red is STDERR):
Plain Java methods work fine and will be understood easily by Clojure novices:
(.println *err* "Hello, STDERR!")
Another alternative, just for fun, is clojure.java.io/copy:
(require '[clojure.java.io :as cjio])
(cjio/copy "Hello, STDERR!\n" *err*)
(.flush *err*)
If you're logging, another option is the use of a logging library, such as clojure/tools.logging. This offers a nice syntax:
(require [clojure.tools.logging :as log])
(log/error "There was an error here")
It also provides some formatting features, and spy functions that are like trace, but can be given various log levels.
Related
I'm currently writing a restful API and need to receive whole files as string.
I didn't write the actual functions which parse those files and must somehow feed these strings into functions which except a path.
So, what I want to find/build is a function which would solve this Problem:
(slurp (INSERT-MAGIC-HERE "The content of my file."))
EDIT:
While both answers seemed to work, the most reliable thing I found was to use "char-array". This prevents any error about the stream being closed which I got quite often.
slurp uses a very flexible mechanism to figure out how to understand its input arguments: it certainly doesn't insist that they be a file. For example, it will accept a java.io.Reader. And it is easy to build a Reader from a String, simply by constructing a StringReader. So,
(slurp (java.io.StringReader. "The content of my file."))
If you really need to write to the file system, a handy way is to use java.io.File/createTempFile. See
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/File.html
Another, easier option is to use tupelo.string/string->stream from the Tupelo Library. It was built for just this purpose:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[tupelo.core :as t]
[tupelo.string :as ts] ))
(dotest
(is= "Hello World!"
(slurp
(ts/string->stream "Hello World!"))) )
Add the following to your project.clj file:
[tupelo "0.9.152"]
I'd like to mock out a macro in a namespace.
For instance, clojure.tools.logging/error.
I tried with-redefs with no luck
(def logged false)
(defmacro testerror
{:arglists '([message & more] [throwable message & more])}
[& args]
`(def logged true))
(deftest foo
...
(with-redefs
[log/error testerror]
...
That gave this error:
CompilerException java.lang.RuntimeException: Can't take value of a macro
Amalloy provided you the answer for your direct question on how to mock a macro - you cannot.
However, you can solve your problem with other solutions (simpler than moving your whole application to component dependency injection). Let me suggest two alternative implementations (unfortunately, not very straightforward but still simpler than using component).
Mock the function called by logging macro
You cannot mock a macro but you can mock a function that will be used when the logging macro get expanded.
(require '[clojure.tools.logging :as log])
(require '[clojure.pprint :refer [pprint]])
(pprint (macroexpand `(log/error (Exception. "Boom") "There was a failure")))
Gives:
(let*
[logger__739__auto__
(clojure.tools.logging.impl/get-logger
clojure.tools.logging/*logger-factory*
#object[clojure.lang.Namespace 0x2c50fafc "boot.user"])]
(if
(clojure.tools.logging.impl/enabled? logger__739__auto__ :error)
(clojure.core/let
[x__740__auto__ (java.lang.Exception. "Boom")]
(if
(clojure.core/instance? java.lang.Throwable x__740__auto__)
(clojure.tools.logging/log*
logger__739__auto__
:error
x__740__auto__
(clojure.core/print-str "There was a failure"))
(clojure.tools.logging/log*
logger__739__auto__
:error
nil
(clojure.core/print-str x__740__auto__ "There was a failure"))))))
As you can see, the function that does actual logging (if a given level is enabled) is done with clojure.tools.logging/log* function.
We can mock it and write our test:
(require '[clojure.test :refer :all])
(def log-messages (atom []))
(defn log*-mock [logger level throwable message]
(swap! log-messages conj {:logger logger :level level :throwable throwable :message message}))
(with-redefs [clojure.tools.logging/log* log*-mock]
(let [ex (Exception. "Boom")]
(log/error ex "There was a failure")
(let [logged (first #log-messages)]
(is (= :error (:level logged)))
(is (= "There was a failure!" (:message logged)))
(is (= ex (:throwable logged))))))
Use your logging library API to collect and inspect log messages
Your logging library API might provide features that would allow you to plug into in your test to collect and assert logging events. For example with java.util.logging you can write your own implementation of Handler that would collect all logged log records and add it to a specific (or root) logger.
You cannot do this. The point of macros is that they are expanded when the code is compiled, and after that they are gone. The original code that included a call to the macro is unrecoverable. You cannot retroactively redefine a macro at runtime: you're too late already.
An alternative approach, if you want to have swappable logging implementations, would be to use something like Component for dependency injection, and use a different logging component depending on whether you are running tests or running your real program. Arguably that's a bit heavy-handed, and maybe there is a simpler approach, but I don't know it.
I'm writing a small debugging library and I would like to let users choose how to display data structures. I was imagining that users could require it in this kind of way:
(ns some-user-namespace
(:require
[clojure.pprint]
[my.library :with-args {print-fn clojure.pprint/pprint}]))
Is something like this possible, and if not, how can I solve this problem?
It's not possible to do it this way. If you really to offer this kind of setup, you could provide a configuration function to be called by the user after the import:
(ns some-namespace
(:require [my.library]))
(my.library/print-with! clojure.pprint/pprint)
Ending function name with ! is an idiomatic way of indicating that it's causing some side effects.
In your library it could look like:
(ns my.library)
(def config (atom {:printer println}))
(defn print-with! [new-printer]
(swap! config assoc :printer new-printer))
(defn my-lib-print [foo]
((:printer #config) foo))
EDIT: For a solution that does not require global, mutable state you can use dynamic bindings.
Lib:
(ns my.library)
(def ^:dynamic *printer* println)
(defn my-lib-print [foo]
(*printer* foo))
Usage:
(binding [my.library/*printer* clojure.pprint/pprint]
(my.library/my-lib-print {:hello "World"}))
These are the only two ways for some kind of external, contextual configuration I can think of. The only alternative is pure higher order function:
(defn my-lib-print [printer foo]
(printer foo))
I think this is a bug in clojure/tools.logging. I have the following db.clj file. What it does is unimportant. The important part is that for safety I have disabled the *read-eval*. I invoke db/start with no problems. However, if I uncomment the #_(log/info "Failed to bootstrap") form, it throws an EvalReader not allowed error. I've tried all sorts of combinations for the log/info call. If it's outside of the try block, it's fine. Inside the try block anywhere, whether it's in the body, catch, or finally, it raises this exception. However, when I wrap a try around log/info elsewhere, it's fine.
What gives?
(ns extenium.db
(:require [clojure.tools.logging :as log]
[clojure.java.io :as io])
(:import com.thinkaurelius.titan.core.TitanGraph
com.thinkaurelius.titan.core.TitanFactory))
(def ^:private
sentinel- (Object.))
(def ^:private
db- (atom nil))
...
(defn start [^String path]
(locking sentinel-
(log/info "Starting database at path" path)
(let [exists (.exists (io/file path))
^TitanGraph db_ (TitanFactory/open path)]
(if exists
(log/info "Path" path "exists")
(log/info "Path" path "does not exist"))
(log/info "Starting database engine")
(swap! db- (constantly db_))
(log/info "Started database engine")
(if (not exists)
(try
(bootstrap-)
(catch Throwable t
#_(log/info "Failed to bootstrap")
(stop)
(.delete (io/file path))
(throw t)))))
(log/info "Started database")
true))
EDIT: Trimmed down code per #alex-taggart. bootstrap- implementation not shown. I had originally included everything because this seemed like a context-specific bug and I felt it was safer to provide as much context as possible.
EDIT: Per #chouser, added how I'm disabling *read-eval*. This is the template that is generated by lein new app.
(defn -main
"The main entry point into Extenium."
[& args]
;; Prevent arbitrary eval injection
(alter-var-root #'*read-eval* (constantly false))
;; Initialize system settings from the command line and configuration file
(init!- args)
;; Start the service
(start!-))
It's not a bug, really. The clojure.tools.logging library is just an abstraction upon other Java logging facilities. To discover which one is available, it uses eval expression. You're welcome to check for your own: here is a quick search result and a certain file where it gets used.
In your case, I believe it's not necessary to care about the global read-eval. This is an internal feature and who knows what other libraries depend on it. If you validate the user input and prevent it from being evaluated, it's fine to leave the flag as is. I would say, SQL injections and XSS are the things you should be worried about first.
Context
I'm playing with ClojureScript, so Ajax works as follows for me:
(make-ajax-call url data handler);
where handler looks something like:
(fn [response] .... )
Now, this means when I want to say something like "fetch the new data, and update the left sidebar", my end ends up looking like:
(make-ajax-call "/fetch-new-data" {} update-sidebar!) [1]
Now, I'd prefer to write this as:
(update-sidebar! (make-ajax-call "/fetch-new-data" {})) [2]
but it won't work because make-ajax call returns immediately.
Question
Is there some way via monads, or macros, to make this work? So that [2] gets auto rewritten into [1] ? I believe:
there will be no performance penality, since it's rewritten into [1[
it's clearer for me to reason about since I can think in synchronous steps rather than async events
I suspect I'm not the first to run into this problem, so if this is a well known problem, answers of the form "Google for Problem Foo" is perfectly valid.
Thanks!
Since Jun 28, 2013, the time that is released clojure core.async lib, you can do it, more or less, in this way: https://gist.github.com/juanantonioruz/7039755
Here the code pasted:
(ns fourclojure.stack
(require [clojure.core.async :as async :refer :all]))
(defn update-sidebar! [new-data]
(println "you have updated the sidebar with this data:" new-data))
(defn async-handler [the-channel data-recieved]
(put! the-channel data-recieved)
)
(defn make-ajax-call [url data-to-send]
(let [the-channel (chan)]
(go
(<! (timeout 2000)); wait 2 seconds to response
(async-handler the-channel (str "return value with this url: " url)))
the-channel
)
)
(update-sidebar! (<!! (make-ajax-call "/fetch-new-data" {})))
More info in:
* http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
* https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj
a macro would change the appearance of the code while leaving the Ajax call asynchronous.
it's a simple template macro. another approach would be to wrap the call to make-ajax-call in a function that waits for the result. while either of these could be made to work they may seem a bit awkward and "un ajax like". will the benefits be worth the extra layer of abstraction?
What about using the threading macro? Isn't good enough?
(->> update-sidebar! (make-ajax-call "/fetch-new-data" {}))
We had rough ideas about this in the async branch of seesaw. See in particular the seesaw.async namespace.