A Clojure library to send events to a sentry host.
The main exported function is capture!
and has three arities:
(capture! dsn event)
: Send a capture over the network, see the description of DSN and ev below.(capture! dsn event tags)
: Send a capture passing an extra map of tags.(capture! context dsn event tags)
: Send a capture passing additional context, such as a specific HTTP client.The capture!
function returns the Sentry Event ID.
(println "Sentry event created" (capture! <dsn> (Exception.)))
In many cases, it makes sense to reuse an already existing aleph conneciton pool (created
with http/connection-pool). Raven will reuse a connection pool if it is passed to
the (capture!) function through the context
parameter, as :pool
.
(capture! {:pool (http/connection-pool {:connection-options {:raw-stream? true}})} "<dsn>" "My message")
You can also pass the following aleph configuration through the context:
(capture! {:pool nil
:middleware nil
:pool-timeout nil
:response-executor nil
:request-timeout nil
:read-timeout nil
:connection-timeout nil})
On top of being able to set tags at capture time, it is possible to add extra
tags using the add-tag!
function, declaring the following arity:
(add-tag! tag value)
Adds a tag entry with the specified tag name and
value to a thread-local storage.(add-tag! context tag value)
Adds a specified tag in a user-specified
context. Context is expected to be map-like.Tags specified this way will be overwritten by tag specified as part of the
(capture!)
call.
Adding sentry "breadcrumbs" can be done using the add-breadcrumb!
function,
that has the following arities:
(add-breadcrumb! breadcrumb)
Store a breadcrumb in thread-local storage.(add-breadcrumb! context breadcrumb)
Store a breadcrumb in a user-specified
context. Context is expected to be map-like.Well-formatted breadcrumb maps can be created with the make-breadcrumb!
helper, with the following arities:
(make-breadcrumb! message category)
A breadcrumb will be created with the
"info" level.(make-breadcrumb! message category level)
This allows specifying a level.
Levels can be one of: 'debug' 'info' 'warning' 'warn' 'error' 'exception' 'critical' 'fatal'(make-breadcrumb! message category level timestamp)
This allows setting a
custom timestamp instead of letting the helper get one for you. Timestamp
must be a floating point representation of seconds elapsed since the
epoch (not milliseconds).More information can be found on Sentry's documentation website
Sentry supports adding information about the user when capturing events. This
library makes it possible using the add-user!
function, with the following
arities:
(add-user! user)
Store a user in thread-local storage.(add-user! context user)
Store a user in a user-specified context. Context
is expected to be map-like.Well-formatted user maps can be created with the make-user
helper function,
with the following arities:
(make-user id)
A simple user map with the only required field (the user's
id) is created.(make-user id email ip-address username)
A map with all "special"
fields recognised by sentry is created. Additional fields can be added to the
created user map if desired, and will simply show up in the interface as
extra fields.More information can be found on Sentry's documentation website
As for Users, Sentry supports adding information about the HTTP request that
resulted in the captured exception. To fill in that information this library
provides add-ring-request!
and add-full-ring-request!
functions,
with the following arities:
(add-ring-request! ring-request)
Extract the required information from the
supplied ring-compatible request map, and store the result in thread-local
storage for future delivery with a call to (capture!)
(add-ring-request! context ring-request)
Store the HTTP information
extracted from the passed ring-compatible request in the user-specified
map-like context (expected to be ultimately passed to (capture!)
).The add-full-ring-request!
function provides the same arities, and includes
the request body in the capture, while add-ring-request!
does not.
Well formatted HTTP information maps can otherwise be created with the
make-http-info
helper function, with the following arities:
(make-http-info url method)
A simple HTTP info map with only required
fields (the request's URL and method) is created.(make-http-info url method headers query_string cookies data env)
Creates a
map with all the "special" fields recognised by Sentry. Additional fields can
be added to the created HTTP map if desired, and will simply show up in the
interface as extra fields.Those maps can be passed to the Sentry context using the add-http-info!
function, with the following arities:
(add-http-info! info)
Store the HTTP information in thread-local storage.(add-http-info! context info)
Store the HTTP information in the
user-specified map-like context (expected to be ultimately passed to (capture!)
).Example:
(add-ring-request! ring-request)
(capture! <dsn> "First capture")
(add-http-info! (make-http-info "http://example.com" :get))
(capture! <dsn> "Second capture")
More information about the HTTP interface can be found on Sentry's documentation website.
In cases where you do not send an exception, Sentry will try to group your message by looking at differences in interfaces. In some cases, this is not enough, and you will want to specify a particular grouping fingerprint, as explained in this part of the Sentry documentation.
To set a custom fingerprint for a particular event, this library provides the
add-fingerprint!
function with the following arities:
(add-fingerprint! fingerprint)
Store the fingerprint in thread-local
storage.(add-fingerprint! context fingerprint)
Store the fingerprint in the
user-specified map-like context (expected to be passed to capture!
).The contents of the :fingerprint entry is expected to be a list of strings.
The following examples send Sentry a payload with all extra interfaces provided by this library, using the thread-local storage.
(def dsn "https://098f6bcd4621d373cade4e832627b4f6:ad0234829205b9033196ba818f7a872b@sentry.example.com/42")
(add-breadcrumb! (make-breadcrumb! "The user did something" "com.example.Foo"))
(add-breadcrumb! (make-breadcrumb! "The user did something wrong" "com.example.Foo" "error"))
(add-user! (make-user "user-id" "test@example.com" "127.0.0.1" "username"))
(add-ring-request! ring-request)
(add-tag! :my_custom_tag "some value")
(capture! dsn (Exception.) {:another_tag "another value"})
Alternatively you can compose and send a valid payload using something like the following:
(capture! dsn (-> {} (add-exception! e)
(add-user! (make-user "user-id")
(add-ring-request! ring-request)
(add-tag! :my_custom_tag "some value"))
As usual in the clojure world, a simple lein test
should run unit tests.
To ensure the results are correctly handled by Sentry and that this library produces correct JSON payloads, a simple integration test can be run with
DSN=http://... lein test :integration
This will publish a test event in the project associated with the DSN with as much test data as possible.
In order to facilitate testing of programs using this library, a special
":memory:" DSN is supported. When passed to this library in place of a real
DSN, the payload map that would be sent to sentry in an HTTP request is instead
stored in the http-requests-payload-stub
atom.
In your tests, you can assert that a Sentry payload conforming to your expectations would have been sent to the sentry server with:
(do
(code-that-invokes-capture-once)
(is (= 1 (count @http-requests-payload-stub))))
Users are responsible for cleaning the atom up between test runs, for example
using the clear-http-stub
convenience function.
ex-data
Largely inspired by https://github.com/sethtrain/raven-clj
Copyright © 2016 Pierre-Yves Ritschard pyr@spootnik.org
Distributed under the MIT/ISC License
Can you improve this documentation? These fine people already did:
Chris Glass, Pierre-Yves Ritschard, Yoan Blanc & Mathieu CorbinEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close