Fork me on GitHub
#beginners
<
2024-07-15
>
Kishor Pandey18:07:47

Is there any way, to have multiple log file in taoensso.timbre ? I wrote simple code, But not working as my expectation ,

(defn initialize-log! [file-name]
  (timbre/merge-config!
   {:timestamp-opts {:pattern  "HH:mm:ss" #_"yy-MM-dd HH:mm:ss"
                     :locale   (java.util.Locale. "en")
                     :timezone (java.util.TimeZone/getTimeZone "Asia/Kolkata")}
    :appenders {:println {:enabled? false}
                :spit   (appenders/spit-appender {:fname (format "~/%S.log"file-name)
                                                   :fn (fn [data] (str (-> data :msg)))})
                }}))

(defn log-message [condition message]
  (case condition
    :file1 (timbre/with-merged-config
             {:appenders {:file1 (appenders/spit-appender {:fname "~/file1.log"})}}
             (timbre/info message))
    :file2 (timbre/with-merged-config
             {:appenders {:file2 (appenders/spit-appender {:fname "~/file2.log"})}}
             (timbre/info message))
    (timbre/info message))) ;; Default logger

(defn -main []
  (map #(initialize-log! %) ["file1" "file2"])
  (log-message :file1 "This is a log message for file1.")
  (log-message :file2 "This is a log message for file2.")
  (log-message :default "This is a default log message."))

(comment
  
  (-main)
  )

jwind19:07:02

(defn handler-twitter-code [req]
  (let [server-chan (:chan @auth-atom)
        {:strs [code]} (:params req)]
    (>!! server-chan code)
    {:status 200
     :headers {"Content-Type" "text/html"}
     :body "Hello world"}))

(defn get-access-token []
  (let [state "state"
        pkce (PKCE.)
        url (do
              (.setCodeChallenge pkce "challenge")
              (.setCodeChallengeMethod pkce PKCECodeChallengeMethod/PLAIN)
              (.setCodeVerifier pkce "challenge")
              (.getAuthorizationUrl service pkce state))]
    (swap! auth-atom assoc :chan (chan)) ;; Add our channel to the auth-atom
    (sh/sh "open" url)
    (let [server (handler/start-embedded-auth-server handler-twitter-code)
          code (<!! (:chan @auth-atom))]
      (.stop server)
      code)))
What a joy this language is. But, can anyone tell me if I'm not being idiomatic here? I start the jetty server to receive an oauth2 callback, then close it after. I communicate with channels. Is this ok?

Vincent20:07:04

Looks nice to me šŸ™‚

Vincent20:07:35

I wonder if you can use a map on that url thing instead of that (do ...) but it's probably fine given the constraints of the clientside

Vincent20:07:54

and yeah hell yeah use a channel why not, that's exactly what they're for: something asynchronous that progressively fills

Vincent20:07:37

not 100% sure about "stop server, start server" for handling twitter code. Maaybe you can elaborate more on your sparticular/pecific use case.

jwind00:07:32

Thank you! Yes indeed the (do ...) is because that PKCE object requires those methods to be called but each method has a void return. Regarding stop/start server, I spin up a local http server to grab the oauth2 request from the auth server, and extract the code. Stop the server when complete, so it only ever exists on auth

adi06:07:09

doto can help you clean up method calls on the pkce object. Examples here: https://clojuredocs.org/clojure.core/doto

adi07:07:34

Channels are totally fine, however if this is the only reason for using core.async, and you want to play around, alternatives can be something like... ā€¢ A globally defined java.util.concurrent.SynchronousQueue given that nothing should proceed until you receive the code (.put in the handler, .take in get-access-token). ā€¢ OR, If you want to play with the agent system, then that could work with a globally-defined agent too (send-off in the handler and await in get-access-token). In both cases, you won't need the atom either.

āž• 1
jwind12:07:33

ooooh the agent system sounds shiny

adi12:07:55

@U04BEMHMQRY then you may like this post I wrote recently (contains references to various useful resources, including official docs): https://www.evalapply.org/posts/poor-mans-job-runner-clojure-agents/

Nim Sadeh21:07:11

Is there an example of someone configuring next.jdbc to log out every SQL query? I think I can do that by extending https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.3.939/api/next.jdbc.protocols#Executable but wanted to see if there's an out of the box way

Nim Sadeh21:07:15

Wow can't believe I read all the protocol codes and missed this in getting started... thanks!

seancorfield21:07:57

I know that folks are encouraged to read the source code of libraries -- but it is usually worthwhile to only do that once you've exhausted the documentation šŸ™‚

Nim Sadeh00:07:26

Ended up bring a 10 minute easy setup, thanks

1
Nim Sadeh00:07:49

I do have a followup though: I have a middleware that injects a request ID into the logging context (I am using mulog) so that every log line invoked by this request logs out with that ID. However, it does not seem to be the case that database calls have that context. Is there a way to bring it in? I am using component

Nim Sadeh00:07:35

In general it seems hard to associate a SQL call to its results, I tried returning a random ID in the state but it seems like there's exactly one such random ID getting generated for the whole app (maybe a consequence of component)

mavbozo00:07:42

where and how do you generate the request ID? For your use case, I create a (ring) middleware to generate and assoc request ID to request map , then the next middlewares or handlers pull the request ID as needed.

Nim Sadeh00:07:18

I managed to get it working!

(defrecord SqlDatabase
           [conn-spec ;; db configuration
            datasource] ;; db state
  component/Lifecycle
  (start [this]
    (if datasource ;; make it idempotent
      this
      (let [datasource (jdbc/get-datasource conn-spec)
            migration-config {:datastore (r-jdbc/sql-database {:connection (jdbc/get-connection datasource)})
                              :migrations (r-jdbc/load-resources "migrations")}]
        (repl/migrate migration-config)
        (assoc this :datasource datasource))))

  (stop [this]
    (assoc this :datasource nil))

  ;; this allows the object to be instantiated as a function with no arguments to obtain the datasource
  clojure.lang.IFn
  (invoke [_]
    (jdbc/with-logging datasource log-sql-query log-sql-results)))

1