diff --git a/src/asciinema/main.clj b/src/asciinema/main.clj index 0a84342..41d70d4 100644 --- a/src/asciinema/main.clj +++ b/src/asciinema/main.clj @@ -1,24 +1,41 @@ (ns asciinema.main (:gen-class) - (:require [com.stuartsierra.component :as component] + (:require [asciinema.yada :as y] + [clj-bugsnag.core :as bugsnag] + [com.stuartsierra.component :as component] [duct.util.runtime :refer [add-shutdown-hook]] [duct.util.system :refer [load-system]] [environ.core :refer [env]] [clojure.java.io :as io])) +(defn- request-context [req] + (str (-> req (get :request-method :unknown) name .toUpperCase) + " " + (:uri req))) + +(defn- create-exception-notifier [] + (when-let [key (:bugsnag-key env)] + (let [environment (:env-name env "production") + version (:git-sha env)] + (fn [ex req] + (bugsnag/notify ex {:api-key key + :environment environment + :project-ns "asciinema" + :version version + :context (request-context req) + :meta {:request (dissoc req :body)}}))))) + (defn -main [& args] - (let [bindings {'http-port (Integer/parseInt (:port env "3000")) - 'db-uri (:database-url env) - 'env-name (:env-name env "production") - 'git-sha (:git-sha env) - 'bugsnag-key (:bugsnag-key env) - 's3-bucket (:s3-bucket env) - 's3-access-key (:s3-access-key env) - 's3-secret-key (:s3-secret-key env) - 'redis-host (:redis-host env "localhost") - 'redis-port (Integer/parseInt (:redis-port env "6379"))} - system (->> (load-system [(io/resource "asciinema/system.edn")] bindings) + (binding [y/*exception-notifier* (create-exception-notifier)] + (let [bindings {'http-port (Integer/parseInt (:port env "3000")) + 'db-uri (:database-url env) + 's3-bucket (:s3-bucket env) + 's3-access-key (:s3-access-key env) + 's3-secret-key (:s3-secret-key env) + 'redis-host (:redis-host env "localhost") + 'redis-port (Integer/parseInt (:redis-port env "6379"))} + system (->> (load-system [(io/resource "asciinema/system.edn")] bindings) (component/start))] - (add-shutdown-hook ::stop-system #(component/stop system)) - (println "Started HTTP server on port" (-> system :http :port))) + (add-shutdown-hook ::stop-system #(component/stop system)) + (println "Started HTTP server on port" (-> system :http :port)))) @(promise)) diff --git a/src/asciinema/yada.clj b/src/asciinema/yada.clj index 573a0ee..06d7057 100644 --- a/src/asciinema/yada.clj +++ b/src/asciinema/yada.clj @@ -4,6 +4,8 @@ [yada.status :as status] [yada.yada :as yada])) +(def ^:dynamic *exception-notifier* nil) + (def not-found-model {:produces #{"text/html" "text/plain"} @@ -22,15 +24,22 @@ "text/html" (str "

" status-name "

") status-name))) -(defn logger [ctx] - (when-let [error (:error ctx)] - (when (not= (-> ctx :response :status) 404) - (log/error error)))) +(defn create-logger [] + (let [notifier *exception-notifier*] + (fn [ctx] + (when-let [error (:error ctx)] + (let [status (-> ctx :response :status)] + (when (not= status 404) + (log/error error)) + (when (and (= status 500) notifier) + (let [ex (or (-> error ex-data :error) error)] + (notifier ex (:request ctx)))))) + ctx))) (defn resource [model] (let [error-statuses (set (concat (range 400 404) (range 405 600) ))] (-> model - (assoc :logger logger) + (assoc :logger (create-logger)) (update-in [:responses 404] #(or % not-found-model)) (update-in [:responses error-statuses] #(or % {:produces #{"text/html" "text/plain"} :response error-response}))