diff --git a/project.clj b/project.clj index 84ba72f..1d95b54 100644 --- a/project.clj +++ b/project.clj @@ -5,4 +5,5 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.5.1"] [cheshire "5.0.1"] - [clj-http "3.0.1"]]) + [clj-http "3.0.1"] + [prone "1.0.1"]]) diff --git a/src/raven_clj/interfaces.clj b/src/raven_clj/interfaces.clj index b22abd0..64a7401 100644 --- a/src/raven_clj/interfaces.clj +++ b/src/raven_clj/interfaces.clj @@ -1,4 +1,5 @@ -(ns raven-clj.interfaces) +(ns raven-clj.interfaces + (:require [prone.stacks :as stacks])) (defn- make-http-info [req] {:url (str (name (:scheme req)) @@ -17,17 +18,31 @@ (assoc event-map "sentry.interfaces.Http" (alter-fn (make-http-info req)))) -(defn- make-frame [^StackTraceElement element app-namespaces] - {:filename (.getFileName element) - :lineno (.getLineNumber element) - :function (str (.getClassName element) "." (.getMethodName element)) - :in_app (boolean (some #(.startsWith (.getClassName element) %) app-namespaces))}) +(defn file->source [file-path line-number] + (some-> (io/resource file-path) + slurp + (str/split #"\n") + (#(drop (- line-number 6) %)) + (#(take 11 %)))) -(defn- make-stacktrace-info [elements app-namespaces] - {:frames (reverse (map #(make-frame % app-namespaces) elements))}) +(defn in-app [package app-namespaces] + (boolean (some #(.startsWith package %) app-namespaces))) + +(defn frame->sentry [app-namespaces frame] + (let [source (file->source (:class-path-url frame) (:line-number frame))] + {:filename (:file-name frame) + :lineno (:line-number frame) + :function (str (:package frame) "/" (:method-name frame)) + :in_app (in-app (:package frame) app-namespaces) + :context_line (nth source 5) + :pre_context (take 5 source) + :post_context (drop 6 source)})) (defn stacktrace [event-map ^Exception e & [app-namespaces]] - (assoc event-map - :exception [{:stacktrace (make-stacktrace-info (.getStackTrace e) app-namespaces) - :type (str (class e)) - :value (.getMessage e)}])) + (let [stacks (stacks/normalize-exception (stack/root-cause e)) + frames (map (partial frame->sentry app-namespaces) + (reverse (:frames stacks)))] + (assoc event-map + :exception [{:value (:message stacks) + :type (:type stacks) + :stacktrace {:frames frames}}])))