Logo of AppSignal

Menu
Docs navigation

Frontend error catching beta

This is a Beta implementation, which means:

  • There is no official JavaScript library supported by AppSignal.
  • The API might change in the future to support more frameworks.
  • This feature is not enabled by default and requires a setup that uses an appsignal.yml config file.

Starting with AppSignal for Ruby gem version 0.11.8 and up we've added a frontend error catcher to our gem.

For use with AppSignal for Elixir, there's an unofficial plug available on GitHub at tombruijn/appsignal-elixir_js_plug.

Table of Contents

Installation

Ruby

If you are using Ruby on Rails, it's included automatically, but still requires some configuration (see below). For Sinatra/Rack apps you need to require the JSExceptionCatcher middleware.

1
::Sinatra::Application.use(Appsignal::Rack::JSExceptionCatcher)

Elixir

Add the appsignal_js_plug package as a dependency in your mix.exs file.

1
2
3
4
5
6
7
# mix.exs
def deps do
  [
    {:appsignal, "~> 1.3"},
    {:appsignal_js_plug, "~> 0.1.0"}
  ]
end

Add the following to your endpoint.ex file.

1
2
3
4
5
6
7
8
# lib/your_app/endpoint.ex
plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json],
  pass: ["*/*"],
  json_decoder: Poison

use Appsignal.Phoenix # Below the AppSignal (Phoenix) plug
plug Appsignal.JSPlug

Configuration

Ruby

Enable frontend error catching by enabling enable_frontend_error_catching in the appsignal.yml config file.

1
2
3
4
staging:
  <<: *defaults
  active: true
  enable_frontend_error_catching: true

Path

The Rack middleware will expose the following error catcher path /appsignal_error_catcher. You can change this path by adding frontend_error_catching_path to your appsignal.yml config file:

1
2
3
4
5
staging:
  <<: *defaults
  active: true
  enable_frontend_error_catching: true
  frontend_error_catching_path: '/foo/bar'

This path will accept POST requests that contain frontend errors in a JSON format. The gem will take care of processing it and sending it to AppSignal.

Elixir

See the README at tombruijn/appsignal-elixir_js_plug for instructions.

Request parameters

Param Type Description
action string model/view/component that triggered the exception
message string exception message
name string exception name
backtrace array array of backtrace lines (strings)
path string path where the exception happened
params hash/object hash/object of request params
tags hash/object hash/object of tags (e.g. logged in user id)
environment hash/object hash/object of environment variables

Example of an error JSON POST

The action, message, name and backtrace field are required. If they are not set the error will not be processed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
  "action": "IncidentIndexComponent",
  "message": "Foo is not defined",
  "name": "ReferenceError",
  "backtrace": [
    "a/backtrace/line.js:10"
  ],
  "path": "/foo/bar",
  "tags": {
    "user_id": 123
  },
  "environment": {
    "agent": "Mozilla Firefox",
    "platform": "OSX",
    "vendor": "",
    "screen_width": 100,
    "screen_height": 100
  }
}

A sample implementation in CoffeeScript

Currently we do not provide a JavaScript library that catches frontend errors. The (coffee)script below is something we use to test the functionality, use and modify at your own risk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
## Example ##
##
##  appsignal = new Appsignal
##  appsignal.tag_request({user_id: 123})
##  appsignal.set_action('ErrorTest')
##
##  try
##    adddlert("Welcome guest!");
##  catch err
##    appsignal.sendError(err)
##

class @Appsignal
  constructor: ->
    @action = ""
    @tags   = {}

  set_action: (action) ->
    @action = action

  tag_request: (tags) ->
    for key, value of tags
      @tags[key] = value

  sendError: (error) ->
    data = {
      action:    @action
      message:   error.message
      name:      error.name
      backtrace: error.stack?.split("\n")
      path:      window.location.pathname
      tags:      @tags
      environment: {
        agent:         navigator.userAgent
        platform:      navigator.platform
        vendor:        navigator.vendor
        screen_width:  screen.width
        screen_height: screen.height
      }
    }

    xhr = new XMLHttpRequest()
    xhr.open('POST', '/appsignal_error_catcher', true)
    xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8')
    xhr.send(JSON.stringify(data))

appsignal        = new Appsignal
window.appsignal = appsignal

window.onerror = (message, filename, lineno, colno, error) ->
  if error
    appsignal.sendError(error)
  else
    appsignal.sendError(new Error('Null error raised, no exception message available'))

Here at AppSignal we're very keen on "eating our own dogfood". This means we use AppSignal to monitor AppSignal and since we're rewriting most of our frontend code to ReactJS we decided that we need to monitor it.

Once we get a good feel of the requirements for JavaScript error catching we plan on supporting an official library that hopefully will support vanilla JS and all the popular frontend frameworks.

You are welcome to try frontend error catching as well and we really like to hear feedback on our implementation. If you have any questions or suggestions, don't hesitate to contact us on contact@appsignal.com.