Fork me on GitHub
#clojure
<
2020-05-10
>
noah01:05:08

I'm writing an app that uses the ring-jetty-adapter. I need it to not output any form of logging. It seems to automatically do so to STDERR at startup. I've read that in javaland (of which I have zero knowledge) there's a way by setting

Properties p = new Properties();
p.setProperty("org.eclipse.jetty.LEVEL", "WARN");
org.eclipse.jetty.util.log.StdErrLog.setProperties(p);
But I have no idea how to do something like this in Clojure before the app starts up and auto-writes that first debug line. Any help would be much appreciated!

potetm01:05:42

option 1: use java -Dorg.eclipse.jetty.LEVEL=WARN … option 2: create a resources/jetty-logging.properties file option 3: configure a logging framework (e.g. slf4j+logback) and configure logging in the logging properties file

seancorfield01:05:34

That JVM property doesn't seem to suppress logging:

$ clj -Sdeps '{:deps {ring {:mvn/version "RELEASE"}}}' -J-Dorg.eclipse.jetty.LEVEL=WARN
Clojure 1.10.1
user=> (require '[ring.adapter.jetty :as j])
2020-05-09 18:32:08.414:INFO::main: Logging initialized @6777ms to org.eclipse.jetty.util.log.StdErrLog
nil
user=>

seancorfield01:05:58

@noah I assume that's the sort of logging you're trying to suppress?

noah01:05:54

@potetm Thanks. I'll take a look at the link.

noah02:05:00

I ended up solving it with a little hacking in the logback.xml file created for a similar project with luminus. It's not a perfect solution, as I really only wanted to stop that first line from being output to the screen and then let any additional ones print as normal if the user passed arguments that would start the server. But it's workable. I'm just logging everything to a file now and nothing to the screen. Thanks again for the help.

eudis14:05:46

Is there a way to print the source of user defined functions in the repl? I've googled and found source but that doesn't print anything but nil for my functions

hiredman18:05:33

No, the source code is not stored in memory (the compiler generates bytecode and the source is thrown away)

hiredman18:05:24

The source macro works because sometimes there is enough information to retrieve the source for a given definition from disk again

kah0ona19:05:28

Question about protocols/records. I managed to not use them, even though I’m full time professionally programming in clojure for 4 years now (always use multimethods) 🙂 Today I want this to change. ;-) So: given this: (defrecord MyRecord [this] MyProtocol (my-fn [this] …)) If I have a function that takes a MyProtocol thing, how can I call my-fn?, ie. this doesn’t compile it seems, even if defined in the same namespace:

(defn some-other-fn
 [^MyProtocol x] 
  (my-fn x))

ghadi19:05:47

@kah0ona protocol functions like my-fn already have some type smarts within them, so it is not necessary to type-hint that argument to MyProtocol. (If you extend your protocol to cover Strings, those will not implement that MyProtocol type, so that hint won't be correct)

ghadi19:05:04

"this doesn't compile" --> what error message did you get?

ghadi19:05:26

(defn some-other-fn
 [x] 
 (my-fn x))
is sufficient (and performant)

kah0ona19:05:48

aaaaah ok then my thinking was kind of correct, but i was a bit confused by my error message

kah0ona19:05:57

yeah so it does work. thanks

kah0ona19:05:46

so what I am pondering is this… Say I have a protocol called Executable with a start and a stop method. Then I have a MyRecord implementing this protocol, and its start message fires up a thread to do some long running work. I would like to be able to ‘interrupt’ that through the stop method (called from ‘outside’). But they don’t share scope right? How to do such a thing? It probably would mean having some sort of global atom (or something else) I presume? Would this be an idiomatic way of doing things? I can also imagine instead of a stop method, just supply a kill-chan arg to the start method, which the implementor has to act upon… But not sure if that’s better. Because I would like to have many implementations (records) of Executable that can do various long running things, and can be interrupted from the outside based on some business logic.

pfeodrippe20:05:41

Do you mean something like below?

(defprotocol IExecutable
  (start [this])
  (stop [this]))

(defrecord Executable [f future-atom]
  IExecutable
  (start [_this]
    (reset! future-atom (future (f))))
  (stop [_this]
    (future-cancel @future-atom)))

(defn executable
  [f]
  (->Executable f (atom nil)))

(def proc (executable #(do (Thread/sleep 10000) (+ 1 2))))

(start proc)
(deref (:future-atom proc))
(stop proc)

pfeodrippe20:05:20

The executable function creates a Executable instance. Executable receives as args a function which will be called and a atom which will be used to store the future created.

kah0ona19:05:58

Any advice would be great 🙂

hiredman19:05:42

The basic structure I use for that kind of thing is start starts a thread that does something, and stop signals that thread to exit, then waits for it to exit

hiredman19:05:40

The are different ways to do that, often I use core async channels, and have some channel that is used to signal the thread to stop, and another channel that signals the thread has stopped

hiredman19:05:02

But you can use and atom and a promise too

kah0ona19:05:07

ah yeah, and do you use that in combination with protocols/records?

kah0ona19:05:51

Because I can and have used various ways with just channels, signalling back and forth. But I ’m just wondering if i’m missing out because I don’t use protocols/records…

kah0ona19:05:58

also, fooling around with them also makes it feel a bit OOP and I wonder if that isn’t going backwards in time 😉