Sunday 4 October 2015

simple http-kit app with logging

So far in building a super simple clojure app I’ve made the app and configured it to run nicely with hot code reloading. In it’s current state, the app is not logging anything out to the console, so I’ve got no basic information about the requests and responses that http-kit is returning. This sucks, so I’m going to fix that now.

New dependencies

Clojure has a rich ecosystem of libraries and we’re going to use one of - ring.middleware.logger to get our application logging in a sensible way.

Update project.clj with the new dependencies…

(defproject simple "0.0.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [ring/ring-devel "1.4.0"]
                 [ring.middleware.logger "0.5.0"]
                 [ring/ring-core "1.4.0"]
                 [http-kit "2.1.19"]])

And now wire in the logger to our application…

(ns simple.core
  (:use [org.httpkit.server :only [run-server]])
  (:require [ring.middleware.reload :as reload]
             [ring.middleware.logger :as logger]))

(defn app [req]
  {:status  200
   :headers {"Content-Type" "text/html"}
   :body    "hello world!"})

(defn serve [& args]
  ; configure our log4j
  (org.apache.log4j.BasicConfigurator/configure)
  
  (run-server
    ;; now wrap the app in reload and logger
    ;; TODO: make this neater
    (logger/wrap-with-logger
      (reload/wrap-reload #'app))
    {:port 8080}))

Running the app now with lein run -m simple.core/serve and viewing it in a browser you will note that the app is logging in a very verbose fashion. This is obviously too much for production, but for development I find it perfect.

My aim in this app is simple, not elegant, terse or perfect so I’m ok with a trading off conciseness to reach my goal. I mention this because a few things have crept into the code now that I would otherwise move around.

You can see that we’re now having to configure the logger inside of the serve function. This is not ideal, but if it is not done, then we’ll get no logging and a nice error message. This post on log4j and clojure was a big help in solving the error log4j:WARN No appenders could be found for logger (onelog.core). I echo the authors sentiments of why no sensible default is present, however given the my aims in this application I will tolerate a little extra code as it gives insight into the workings of all the parts.

Also, the serve function is now showing an emerging pattern in that the app itself is becoming increasingly wrapped. It could be that I only see this as problematic because I am new to functional programming, and that this pattern is beautiful, but I thought it was something to keep an eye on.

Next

Next up I’m going to add routes into the application because right now it serves the same response no matter what the request path is.

  1. Build the simplest possible http-kit app
  2. App running via lein run and live reloading of source
  3. Logging requests to stdout
  4. Routes with and without parameters
  5. Postgres integration
  6. Writing Tests
  7. Configuring the application to return JSON Responses (coming soon)
  8. A Clojurescript UI (coming soon)
  9. Websockets (coming soon)
  10. Putting your application into production (coming soon)

The full source code can be found on github and I’ve tagged the code for this post as 3.0.1.