Fork me on GitHub
#clojure
<
2018-09-16
>
Nick Cabral00:09:27

Anyone have any best-practices, patterns, or clever macros for unobtrusive logging in clojure code? My current approach usually results in adding do blocks or unused bindings within let blocks.

seancorfield01:09:45

Do you mean logging or tracing? What is your goal with logging @nick652?

Nick Cabral01:09:19

Oh right. My goal at the moment would be more accurately described as tracing. I’m trying to output enough data that it’s possible to reproduce a user-reported issue by examining my backend trace output.

seancorfield01:09:57

Have you looked at tools.trace?

Nick Cabral01:09:06

Not until now. Looks great! Is it a commonly used approach in released code, or is it usually just used in development?

Nick Cabral01:09:10

Thanks for pointing me to that, in any case. It’s just what I was looking for (I think).

seancorfield01:09:34

I personally haven't used it but I know some people seem to love tools.trace...

😁 4
seancorfield01:09:39

Whenever I talk about running a REPL inside production processes to debug and/or fix issues, there are always a lot of folks who are shocked about that. Using tools.trace in released code seems to require using a REPL (to apply and then remove tracing) so...

bja04:09:35

I've used tools.trace and it's kinda nice for systems where you don't have a ton of schema/spec validation to enable to narrow down issues

bja04:09:47

I think sayid replaced tools.trace in the spacemacs Clojure layer and that's what I used most recently for tracing something. I tend to just use the step debugger with a condition if I'm not in prod (or if I can isolate traffic)

Nick Cabral01:09:55

sayid looks interesting, thanks for the suggestion

Dormo06:09:19

Is there any reason to use clj-http over clj-http-lite if the latter has all the features you need?

Karol Wójcik08:09:21

Need some help with regex matching 😞

(def banned-words
  ["token" "password"])

(def filter-regexp
  (let [left-part (reduce #(str %1 %2 "|") "(.*)(" banned-words)
        right-part " \\\"([a-zA-Z0-9.]+)\\\""
        normalize-left #(if (string/ends-with? % "|") (string/join (butlast %)) %)]
    (Pattern/compile (str (normalize-left left-part) ")" right-part))))
I wanted to create a regexp like #"(.*)(token|password) \\"([a-zA-Z0-9.]+)\\"" but for some reason java Pattern removes the slash #"(.*)(token|password) \"([a-zA-Z0-9.]+)\"" and I am unable to match the string string. EDIT: Here is the string I want to match "Ended [req :get] [path /development/installation-access-token] [s 200] [bd {:token \"v1.1231231231231\"}]" Please help 😛

roti08:09:39

I think the correct regex is (.*)(token|password) "([a-zA-Z0-9.]+)", not (.*)(token|password) \"([a-zA-Z0-9.]+)\"

roti08:09:40

that would be

(def filter-regexp
  (let [left-part (reduce #(str %1 %2 "|") "(.*)(" banned-words)
        right-part " \"([a-zA-Z0-9.]+)\""
        normalize-left #(if (str/ends-with? % "|") (str/join (butlast %)) %)]
    (str (normalize-left left-part) ")" right-part)))

Karol Wójcik08:09:32

@roti Check please the string which I want to match 😛 https://regexr.com/3vi8f As you can see your regexp does not match the string. The correct regexp is #"(.*)(token|password) \\"([a-zA-Z0-9.]+)\\"" but for some reason java.util.Pattern removes the slash ;(

roti09:09:18

yours doesn't match either

roti09:09:43

probably because token appear twice

roti09:09:36

anyway, you want to match the backslash as well, so it needs to be escaped in regex (and then again in the Java string 🙂 )

Karol Wójcik09:09:38

@roti My regexp matches 😛 Please check https://regexr.com/3vi8r It's escaped: right-part " \\\"([a-zA-Z0-9.]+)\\\""

roti09:09:40

this is the regex that matches: (.*)(token|password) \\"([a-zA-Z0-9.]+)\\"

roti09:09:28

that would be this:

(def filter-regexp
  (let [left-part (reduce #(str %1 %2 "|") "(.*)(" banned-words)
        right-part " \\\\\"([a-zA-Z0-9.]+)\\\\\""
        normalize-left #(if (str/ends-with? % "|") (str/join (butlast %)) %)]
    (str (normalize-left left-part) ")" right-part)))

roti09:09:55

you need to escape backslash twice, once because of Java Strings, and again because of reged syntax

Karol Wójcik09:09:37

(def string
  "Ended [req :get] [path /development/installation-access-token] [s 200] [bd {:token \"v1.12312312312312312312\"}]")
(re-matches filter-regexp string)
It does not match anything 😞

Karol Wójcik09:09:18

Ok I got this sorry Roti! My bad ;( thank you very much for your help. You was right since the beginning.

awb9911:09:39

Does someone have a sample how to do interactive web development with ring/compojure/hiccup/jetty? I tried several samples that use ring-jetty-adapter, but none of them worked.

roti11:09:02

aren't there some leiningen templates that provide a useful example?

awb9911:09:48

@roti I Did 'lein new compojure my-webapp' but this did not have any code for starting /stopping the http server in the repl.

awb9911:09:21

Most of the samples I found use "lein ring server" - but when I do that, then I loose all of the interactive development experience of the repl.

roti12:09:56

first, you should know that the code is automatically loaded when you run with "lein ring server"

awb9912:09:50

@roti This sample also does not contain a way to run it from the repl

awb9912:09:39

I dont think that the code is being re-loaded with "lein ring server"

awb9912:09:15

"lein ring server" seems to compile the project, then run the function that is defined in the project.clj

roti12:09:42

last time I tried it, it was 🙂

roti12:09:44

oh, I did not read your message carefully. hmm, I think ring-jetty-adapter should do the trick. in the past it was mentioned in the compojure wiki, now I see it's gone

awb9912:09:57

@roti actually you are right, if there are no errors in the code, then it recompiles.

awb9912:09:01

I guess this works somehow.

awb9912:09:05

Not the ideal solution though.

awb9912:09:18

The ring-jetty-adapter woudl do it.

awb9912:09:21

But the samples,

awb9912:09:25

some are ring.jetty.adapter

awb9912:09:29

some are ring.adapter.jetty

awb9912:09:32

and none works.

awb9912:09:48

somewhere I read that compojure verison needs to be identical to ring.jetty.adapter.

roti12:09:20

well, if you want the repl you just have to start jetty yourself. the jetty-adapter was a helper for that, but you can also start jetty yourself, it's more work though

awb9912:09:11

I will check into that then.

roti12:09:43

actually, this is the helper I was using, not the jetty adapter: https://github.com/weavejester/ring-serve

roti12:09:56

I think this does what you want

awb9912:09:57

BTW: the leinigen ring runner, it recompiles the solution, but it does not push the new version to the browser. I have seen some presentation by I thikn bob bauman, where everything was getting live reloaded.

roti12:09:56

you are talking about fighwheel. yes, but that's for clojurescript, not clojure.

roti12:09:20

compojure and ring run on the server

awb9912:09:46

but still,

awb9912:09:55

if the page changes, I dont want to refresh.

awb9912:09:59

if it would auto refresh,

awb9912:09:08

then I could see the effect of my programming immediately.

roti12:09:57

I don't think it's possible. you could have some piece of code in the browser which would make a request to the server when something changed and then compute a diff and apply it, but it would run into problems because the old state (kept in javascript variables) might not be compatible with the new page. if you don't have such state in your page, then yes it would work, but it would only spare you a keypress

roti12:09:15

the big value which figwheel offers is loading code changes while keeping the state. so if you work on some component which you need 4-5 user actions to reach, it will spare you those actions (like: login, then search for "xxx", click on the second result)

awb9912:09:40

I want to start using om/next or reagent in the future.

awb9912:09:52

But for now, I decided to to some quick stuff with hiccup and ring,

awb9912:09:06

because reagent is too complicated for me right now.

roti12:09:07

I believe I saw a library which did such diffing with ring, but I can't remember the name now

awb9912:09:39

It would be really cool, to have a library that sends you the data from the server to the reagent client sort of automatically,

awb9912:09:07

I think hoplon does this.

awb9912:09:19

Unfortuntately the ring-serve does not work anymore.

awb9912:09:26

I guess it uses way too old dependencies.

awb9912:09:47

Lein deps does not show error messages,

awb9912:09:55

but then when I try to exeucte I get the error messages.

awb9912:09:52

I tried just copying the one source code file over, but then I could not find the dependency org.mortbay.log.Logger

awb9912:09:07

But I guess it is feasable for me to re-write this code.

awb9912:09:09

Many thanks roti!

dpsutton15:09:39

playing around with writing scripts to run on the command line. How can I "return" strings so they can be piped and manipulated in the shell after running?

dpsutton15:09:06

I can print them but they don't seem to be able to be piped and manipulated after the program finishes

dpsutton15:09:32

clj -m levenshtein ant and | echo i would hope to echo 1 but nothing gets piped through

dpsutton15:09:30

just figured it out. have to direct std out >&1

blambin15:09:44

maybe your bash script is wrong? the echo "2" | cat output 2, but | echo not.

andycoffwa20:09:08

Any #honeysql gurus out there at the moment? I'm using honey in a JVM lambda function and have loved it so far. However, I just went to deploy code and I'm over my 70 MB jar limit. Honey appears to pull in 20+ MB of goog dependencies. Does anyone know if it's possible to build and use without these deps? Am I possibly doing something incorrectly that brings in Clojurescript deps?

noisesmith20:09:39

if you use leiningen to create your jar, you can add a global :exclusions clause, and if you don't hit code paths that need that artifact it should just work

andycoffwa20:09:43

Great. Thanks, I'll give that a go. I don't know exactly how #honeysql is implemented. I'll need to figure out where and why goog is used.

noisesmith20:09:00

my first guess is that it comes in via cljs - you can check lein deps :tree

andycoffwa20:09:18

Cheers, @noisesmith. I'll dig around

lilactown20:09:38

somebody save me from myself: at work we’re using a headless CMS (basically a RESTish DB-as-a-service), but we’re likely to move to a regular DB - either DynamoDB or some RDBS - in the future. so I’ve implemented a data-oriented DSL for creating tables in the headless CMS, and am now contemplating implementing something similar to datomic’s query language as well, with the idea that we could write a driver to use it with DDB or Postgres or what-have-you later. Is this… is this a bad idea? I feel like this must be a bad idea, but I’m not experienced enough with DBs to know why yet.

dadair21:09:16

There’s a project for pull syntax for sql DBs here https://github.com/walkable-server/walkable

val_waeselynck21:09:47

Rolling out your own query engine for something as expressive as Datalog on top of a remote data source certainly is a big endeavour, even without performance constraints. Probably a bad idea unless you lower your ambitions

lilactown21:09:53

how would you hedge yourself against the fact that your remote data source will change in the near future?

dadair22:09:22

I’d isolate where those data sources are used. E.g., use abstracted functions rather than the core data source. For example, use a (get-items [db] ..) function that internally uses some driver, rather than calling (jdbc/query conn ..) itself

dadair22:09:59

Ideally, group these functions under some protocol, so you can extend that protocol for different data sources

dadair22:09:19

Duct’s “boundaries” demonstrate this