White Noise

Build Status Gem Version

TV Statics

This gem defines middleware which renders exceptions in JSON format and notifies Bugsnag.

Installation

Add this line to your application's Gemfile:

gem 'white_noise', require: 'noise/railtie'

Usage

Exception subclasses from PublicError may be registered and rendered as specific HTTP errors:

GoneError = Class.new(PublicError)
GoneError.register_as :gone, severity: :info

Later somewhere in controller you may throw this exception:

class V0::MoviesController < ApiController
  # @deprecated
  def index
    fail GoneError.new(:outdated_api, 'API v0 is no longer active. Please migrate to API v1')
  end
end

By default this error would be rendered in JSON-API like format internally used in SPB TV, but you can always define your own renderer:

Status: 410 Gone

{
  "errors": [{
    "id": "b55eacaf-c3db-4c5c-80c6-214149eb14c2",
    "code": "outdated_api",
    "title": "API v0 is no longer active. Please migrate to API v1",
    "status": 410,
     links: {
       about: {
         href: 'https://bugsnag.com/spb-tv%2Frosing-api/errors?filters[event.since][]=30d&filters[error.status][]=open&filters[event.message][]=unknown%20error&filters[event.class][]=OutdatedApiError'
       }
     },
    "
  }],
  "meta": {
    "status": 410
  }
}

Thus, the first parameter of the PublicError constructor is rendered as code and the second as title.

You may omit second argument to pick message from localization:

fail GoneError, :outdated_api

It is the equivalent of:

fail GoneError.new(:outdated_api, I18n.t('noise.outdated_api_error.outdated_api'))

If you have to pass attributes some substitution into localized string, provide the second attribute as a hash:

fail BadRequestError.new(:unknown_fields, fields: 'nickname, phone')
noise:
  bad_request_error:
    unknown_fields: "Server does not know how to recognize these fields: %{fields}"

There are number of predefined public errors you can use in your application:

Class HTTP status code
BadRequestError 400 Bad Request
UnauthorizedError 401 Unauthorized
ForbiddenError 403 Forbidden
NotFoundError 404 Not Found
GoneError 410 Gone
UnsupportedMediaTypeError 415 Unsupported Media Type
UnprocessableEntityError 422 Unprocessable Entity

Bugsnag Notification

This gem notifies Bugsnag about all errors. You are free to adjust severity of errors on per class basis:

GoneError.register_as :gone, severity: :info

You can customize tabs to be shown on Bugsnag:

Tab example

Noise::Notification.extract(:api_client, ApiClientExtractor)

class ApiClientExtractor
  # @param env [Hash]
  # @return [Hash] of values to be shown on the tab
  #
  def call(env)
    api_client = env['warden'].user(:api_client)
    if api_client
      {
        id: api_client.id,
        name: api_client.name,
        version: api_client.version.to_s
      }
    else
      {}
    end
  end
end

If you want to show link to Bugsnag error page on the error response, you have to configure Bugsnag project:

Noise.config.bugsnag_organization = 'spb-tv'
Noise.config.bugsnag_project = 'rosing-api'

To disable Bugsnag integration:

Noise.config.bugsnag_enabled = false

Override error response format:

class ApplicationRenderer < ExceptionRenderer
  def render(responder)
    {
      meta: {
        code: responder.status_code,
        error_id: error_id,
        error_description: error.message
      }
    }
  end
end
Rails.application.config.exceptions_app = Noise::ExceptionsApp.new(->(env) { ApplicationRenderer.new(env) })

Best Practices

It is strongly encouraged to throw public errors only in controllers. Your domain logic should throw domain-specific exceptions or better be exceptions-free.

Development

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in lib/noise/version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/SPBTV/white_noise.

License

Copyright 2018 SPB TV AG

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.