Giter Site home page Giter Site logo

clj-airbrake's Introduction

clj-airbrake

Clojars Project

Clojure client for the Airbrake API

Usage

(require '[clj-airbrake.core :as airbrake])

(def airbrake-config ..)

(def request {:context {:url "http://example.com"
                        :component "foo"
                        :action "bar"
                        :headers {"SERVER_NAME" "nginx", "HTTP_USER_AGENT" "Mozilla"}}
              :params {"city" "LA", "state" "CA"}
              :session {"user-id" "23"}})

(def exception (try (throw (Exception. "Foo")) (catch Exception e e)) ; throw to get a stacktrace

;; blocking notify
(airbrake/notify airbrake-configuration exception request)
=> {:error-id 42 :id 100 :url "http://sub.airbrakeapp.com/errors/42/notices/100"}

;; async notify
(airbrake/notify-async airbrake-configuration (fn [resp] ...) exception request)

;; wrapper shorthand
(airbrake/with-airbrake airbrake-configuration
                        request
                        ;; your code goes here
                        )

Note: notify and notify-async use http-kit to send the notice. To avoid possible deadlocks with other requests when sending the notice (see issue #30), we create our own threadpool for http-kit to use rather than using the default threadpool.

Airbrake configuration

Below is an example of the airbrake-configuration:

{
 :api-key "API_KEY"        ;required
 :project "PROJECT_ID"     ;required
 :host                     ;optional
 :environment-name "env"   ;optional
 :root-dirctory "/app/dir" ;optional

 :ignored-environments #{"test" "development"} ;optional but defaults to 'development' and 'test'
 :sensitive-environment-variables [#"pass"] ;optional
 :sensitive-params [#"pass"] ;optional
 }

Both api-key and project can both be found in the settings for your project in the Airbrake website.

Senstive data

There are times that your environment and params may contain sensitive data (e.g. passwords) that you don't want sent to airbrake. We try to provide sensible defaults for this but can be configured throught the keys sensitive-environment-variables and sensitive-params. Both values are a vector of regexes that will be tested against the keys in your environment variable and params.

Currying

Unsurprisingly, passing the configuration to notify for every single call could be painful. So a convinience macro is provided.

(def airbrake-config {:api-key "api-key" :project "project"})

(def-notify my-notify airbrake-config)

(my-notify (Exception. "Something went wrong."))

Notify is also overloaded so if you just pass the airbrake configuration it will return a function that can be used to send a notification.

Request

Optionally you can pass a 3rd parameter to notify and 4th parameter to notify-async

This parameter must be a map and will look for three keys in this map: session, params, and context

session and params are expected to be maps with any keys.

Context

Context can contain the following keys:

{
 :environment ""   ; will default to `environment-name` from configuration
 :rootDirectory "" ; will default to `root-directory` from configuration
 :os ""            ; will look up operating system
 :language ""      ; will default to "Clojure-1.7.0" (or whichever version of Clojure you're running)
 :component ""
 :action ""
 :version ""
 :url ""
 :userAgent ""
 :userId ""
 :userUsername ""
 :userName ""
 :userEmail ""
}

More information about what can be passed to Airbrake can be found in the Airbrake documentation - https://airbrake.io/docs/#create-notice-v3

Ring Middleware

Basic support for Ring is provided in the clj-airbrake.ring namespace: request parameters and session information are passed to Airbrake. A simple ring example:

(use 'ring.adapter.jetty)
(use 'ring.middleware.params)
(use 'ring.middleware.stacktrace)
(use 'clj-airbrake.ring)

(defn app [req]
  {:status  200
   :headers {"Content-Type" "text/html"}
   :body    (throw (Exception. "Testing"))})

(run-jetty (-> app
               (wrap-params)
               (wrap-airbrake airbrake-configuration)
               (wrap-stacktrace))
           {:port 8080})

clj-airbrake is available as a Maven artifact Clojars.

Leiningen:

:dependencies
  [[clj-airbrake "3.0.3"] ...]

Maven:

<dependency>
  <groupId>clj-airbrake</groupId>
  <artifactId>clj-airbrake</artifactId>
  <version>3.0.3</version>
</dependency>

Development

Running the tests:

$ lein deps
$ lein test

TODO

  • Param filtering. (e.g. automatically filter out any 'password' params)

License

Copyright (C) 2010 LeadTune and Ben Mabey

Released under the MIT License: http://www.opensource.org/licenses/mit-license.php

clj-airbrake's People

Contributors

arohner avatar bmabey avatar cap10morgan avatar christianblunden avatar duey-sonian avatar emilssolmanis avatar firthh avatar gja avatar leonid-shevtsov avatar martintrojer avatar mattly avatar pingles avatar tgk avatar thiagotnunes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clj-airbrake's Issues

Unable to find symbol as-str.

Hey guys,

trying to run clj-airbrake and could not because I am getting the following exception:

Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: as-str in this context, compiling:(clj_airbrake/core.clj:40)

Are we missing any dependency, maybe on clojure.string?

Thanks!

Calling clj-airbrake within callback from HTTP-kit request can result in a deadlock

It looks like the HTTP-kit client has a threadpool to serve callbacks from requests.

This means if you try to call out to airbrake within a callback you can end up in a deadlock situation.

For example this can result in a deadlock if the endpoint that will result in errors:

(take
 1000
 (repeatedly
  #(http/get "http://host.com/path" options
             (fn [{:keys [status headers body error]}] ;; asynchronous response handling
               (if error
                 (airbrake/notify {:config :config} error)
                 (println "Async HTTP GET: " status))))))

The main solution I'm considering is to replace http-kit with clj-http-lite. The goal would be to give the caller more flexibility with the choice of asynchronous mechanisms and even http library. Part of this I would like to deprecating the function notify-async and the implementation for it will call notify within a future.

Please let me know if anyone has feedback.

project version is not read correcly when packaged in uberjar

The following error is thrown:

Caused by: java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil
        at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:495)
        at clojure.java.io$fn__7795$G__7790__7802.invoke(io.clj:63)
        at clojure.java.io$reader.doInvoke(io.clj:96)
        at clojure.lang.RestFn.invoke(RestFn.java:410)
        at clojure.lang.AFn.applyToHelper(AFn.java:161)
        at clojure.lang.RestFn.applyTo(RestFn.java:132)
        at clojure.core$apply.invoke(core.clj:602)
        at clojure.core$slurp.doInvoke(core.clj:6024)
        at clojure.lang.RestFn.invoke(RestFn.java:410)
        at clj_airbrake.core$airbrake_project.invoke(core.clj:26)
        at clj_airbrake.core$get_version.invoke(core.clj:33)
        at clj_airbrake.core__init.load(Unknown Source)
        at clj_airbrake.core__init.<clinit>(Unknown Source)
        ... 30 more

The bug was introduced in this commit 33fcc1a. The issue is that there is no project matching clj-airbrake in the uberjar's resources causing slurp to be called on nil.

Inspecting the ubjerjar it seems that all the clj-airbrake files included were compiled versions:

clj_airbrake/core$xml_ex_response$iter__206__210$fn__211.class
clj_airbrake/core$parse_xml.class
clj_airbrake/core$notify.class
clj_airbrake/core$classloader$fn__194.class
clj_airbrake/core$make_notice.class
clj_airbrake/core$projects.class
clj_airbrake/core__init.class
clj_airbrake/core$xml_ex_response$iter__206__210.class
clj_airbrake/core$airbrake_project$fn__199.class
clj_airbrake/core$airbrake_project.class
clj_airbrake/core$map__GT_xml_vars$iter__222__226$fn__227.class
clj_airbrake/core$map__GT_xml_vars.class
clj_airbrake/core$classloader.class
clj_airbrake/core$send_notice$text_at__245.class
clj_airbrake/core$map__GT_xml_vars$iter__222__226$fn__227$fn__228.class
clj_airbrake/core$sanitize.class
clj_airbrake/core$xml_ex_response.class
clj_airbrake/core$send_notice.class
clj_airbrake/core$xml_ex_response$iter__206__210$fn__211$fn__212.class
clj_airbrake/core$get_version.class

I seems like we could get the version at compile time (i.e. bind a var to the results of get-version) to avoid having the version form being looked up at runtime. Or perhaps there is a way to prevent the compiling from happening.

Do you have any thoughts/ideas @arohner?

Release new version & tag 2.4.3

It looks like master has some cool features like ignoring environments. It would be nice to have those released.

Also, 2.4.3 is out but not tagged in here, making it hard to see exactly what code we're getting in the 2.4.3 release.

automatically pull out data using ex-data when possible and send to airbrake

One thing to be wary of is how large the maps of data can be. For example, the entire system may be part of the exception info map. Sending the entire thing may be problematic so some safeguards on how much to send by default (maybe using pretty print) would be worth exploring. Airbrake doesn't want you posting the entire state of your system for each exception. :)

Is Throwable support desired?

We have some services running that could throw Throwables due to some pre-conditions and assertions. I've added Throwable-support in a local project, and it seems to work fine. Is it something that is needed and wanted in the general clj-airbrake lib? I'd be happy to add it and send a pull request.

Clojure 1.4.0 Can't dynamically bind non-dynamic var

When using version 2.0.1 with Clojure 1.4.0, warnings found on repl startup

Warning: html-compatible not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic html-compatible or change the name. (clojure/contrib/prxml.clj:32)
Warning: prxml-indent not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic prxml-indent or change the name. (clojure/contrib/prxml.clj:36)
Warning: prxml-tag-depth not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic prxml-tag-depth or change the name. (clojure/contrib/prxml.clj:41)

and error when using (actual values substituted)
(airbrake/notify "my-api-key" "production" "/app/dir" exception)

yields

IllegalStateException Can't dynamically bind non-dynamic var: clojure.contrib.prxml/prxml-indent clojure.lang.Var.pushThreadBindings (Var.java:353)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.