Introduce raven_dart, a Dart client for Sentry

Since I’ve been experimenting with Sentry and hacking around in Dart again lately, so what better way is there to combine these two activities than to write a Dart client for Sentry?

That said, there is already a Javascript client library for Sentry, which via the dart:js library you can probably save yourself some code by writing a wrapper around the Javascript library instead. But I chose to write the client from scratch because:

  1. it’s more fun
  2. you can take advantage of Dart’s support for static type checking
  3. you can make use of Dart’s isolates (think F# mailbox or Erlang processes, isolates is Dart’s implementation of Carl Hewitt’s actor model) to abstract over making concurrent requests and handling retries, etc.
  4. wrapping the Javascript library means hard dependency on the Javascript library being present, which means you won’t be able to use it on the server side
  5. it’s more fun!

 

Update 05/07/2014 : I had previously stated that raven-js had dependencies on jQuery, ember, etc. that was incorrect. As they were in fact raven-js plugins for those frameworks (as stated in its Plugins documentation page here) and the raven-js itself doesn’t have any dependencies.

 

And the result is a small (~600 LOC) Dart library called raven_dart, that allows you to capture generic messages or exceptions as events in Sentry. The most basic usage would look like this:

Operational params can be used to customize the behaviour of captureMessage and captureException, such as adding tags, or other metadata to go along with the events.

Following the official guidelines on writing a Sentry client, the library supports:

  • DSN configuration via constructor argument
    • null means disabled
  • Graceful failure handling
    • fallback to logging to console when Sentry is disabled
    • retry on error (except for HTTP status codes 400, 401, 403, and 503)
    • configurable max no. of retries
    • exponential delay when retrying
    • temporarily disable if Sentry is unavailable (503)
  • Support for tagging
    • common tags can be provided in the client constructor
    • additional tags are supplied for each event
    • when common and event-specific tags overlap, both are sent as part of the event
  • Non-blocking event submission
    • events are sent to available isolates in round-robin fashion, whom then process them asynchronously and concurrently
    • configurable level of concurrency per core which determines number of isolates running at the same time
  • Basic data sanitization/scrubbing
    • credit card number-like fields are scrubbed
    • Sentry key and secrets are scrubbed
    • Values that look like passwords or secrets are scrubbed

 

Please give it a try and let me know what you think, if you find any bugs or have feedbacks in general, feel free to add them to the issues page.

 

Related Links

raven_dart homepage

raven_dart on pub.dartlang.org

Libraries for C# and F# for easier integration with Sentry

Emulating F#’s discriminated unions (aka algebraic data types) in Dart

Emulating enums in Dart

Takeaways from Hewitt, Meijer and Szyperski’s talk on the Actor model

Announcing libraries for C# and F# to make it easier to integrate with Sentry

Here at Gamesys social team, we’re rethinking our current approach to logging in general, from both server and client’s perspective. Having looked at many different alternatives (it was a little hard to imagine how crowded a space log aggregation and visualization is..) one of the services which we have decided to experiment with is Sentry.

Sentry is a fairly simple service, with an easy to use API and straight forward to integrate with, especially if you already have a client library (the Sentry doc refers to them them as Ravens) for your language of choice. On the .Net side of things, you have a little library called SharpRaven.

As for integration, using custom log4net appender such as this one is obviously a good way to go, but you still need to implement the try-catch-log pattern everywhere though, unless you’re happy for these exceptions to bubble all the way up to the app domain and catch them there. And when I see implementation patterns I see opportunities to automate them with PostSharp!

C# custom attributes

If you grab the SharpRaven-Contrib package from Nuget you’ll have access to a pair of custom attributes – RavenLogException and RavenLogExecutionTimeAttribute – when you open the SharpRaven namespace. For example,

The attributes does what they say on the tin, RavenLogException captures and logs exception information as errors to Sentry whilst RavenLogExecutionTime monitors execution time of your methods and logs any method execution that took longer than your given threshold as warnings to Sentry.

For F# however, whilst the attributes would still work for methods, chances are you will be spending most of your time working and composing functions instead and these attributes won’t help you there. So for F# I decided to do something slightly different.

F# workflows

Thankfully, in F#, we have computation expressions* (aka workflows) which already power language features such as async workflows and sequence comprehensions.

Using the workflows defined in the SharpRaven-ContribFs package you can create blocks of code where:

  • any unhandled exceptions are logged as Error in Sentry
  • if the block of code takes longer than the specified threshold to execute, it’ll be logged as a warning in Sentry

and your code remains unchanged, you simply wrap them in { }:

Of course, you can also just create wrapper functions to achieve the same results, but I find that using workflows in this case makes for more readable code. Another good alternative is to use a Maybe monad, which I won’t go into too much detail here as Scott Wlaschin has a great explanation for this already.

 

As always, the source code for both libraries are available on github, and if you find any issues feel free to report them via the issues page.

 

* if you’re interested in learning more about computation expressions, I highly recommend Scott Wlaschin’s series on his F# for Fun and Profit blog, it’s by far the most comprehensive and easy to understand set of articles I have seen.

 

Links