GithubHelp home page GithubHelp logo

wyeworks / boom Goto Github PK

View Code? Open in Web Editor NEW
104.0 22.0 13.0 297 KB

Exception notification for plug based applications https://hex.pm/packages/boom_notifier

License: MIT License

Elixir 86.75% HTML 4.54% CSS 7.66% JavaScript 1.05%
notifier elixir hacktoberfest

boom's Introduction

BoomNotifier

hex Elixir CI


This package allows your Phoenix application to send notifications whenever an exception is raised. By default it includes an email and a webhook notifier, you can also implement custom ones, or use some of the independently realeased notifiers listed below.

It was inspired by the ExceptionNotification gem that provides a similar functionality for Rack/Rails applications.

You can read the full documentation at https://hexdocs.pm/boom_notifier.

Installation

The package can be installed by adding boom_notifier to your list of dependencies in mix.exs:

def deps do
  [
    {:boom_notifier, "~> 0.8.0"}
  ]
end

Getting started

This is an example for setting up an email notifier, you can see the full list of available notifiers here.

Email notifier

BoomNotifier has built in support for both Bamboo and Swoosh.

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
      notifier: BoomNotifier.MailNotifier.Bamboo,
      # or to use Swoosh
      # notifier: BoomNotifier.MailNotifier.Swoosh,
      options: [
        mailer: YourApp.Mailer,
        from: "[email protected]",
        to: "[email protected]",
        subject: "BOOM error caught"
      ]

  # ...

For the email to be sent, you need to define a valid mailer in the options keyword list. You can customize the from, to and subject attributes.

subject will be truncated at 80 chars, if you want more add the option max_subject_length.

Notifiers

BoomNotifier uses notifiers to deliver notifications when errors occur in your applications. By default, 2 notifiers are available:

You can also choose from these independetly-released notifiers:

On top of this, you can easily implement your own custom notifier.

Multiple notifiers

BoomNotifier allows you to setup multiple notifiers, like in the example below:

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    notifiers: [
      [
        notifier: BoomNotifier.WebhookNotifier,
        options: [
          url: "http://example.com",
        ]
      ],
      [
        notifier: CustomNotifier,
        options: # ...
      ]
    ]

Notification Trigger

By default, BoomNotifier will send a notification every time an exception is raised.

However, there are different strategies to decide when to send the notifications using the :notification_trigger option with one of the following values: :always and :exponential.

Always

This option is the default one. It will trigger a notification for every exception.

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    notification_trigger: :always,
    notifiers: [
      # ...
    ]

Exponential

It uses a formula of log2(errors_count) to determine whether to send a notification, based on the accumulated error count for each specific exception. This makes the notifier only send a notification when the count is: 1, 2, 4, 8, 16, 32, 64, 128, ..., (2**n).

You can also set an optional max value.

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    notification_trigger: :exponential,
    notifiers: [
      # ...
    ]
defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    notification_trigger: [exponential: [limit: 100]]
    notifiers: [
      # ...
    ]

Custom data or Metadata

By default, BoomNotifier will not include any custom data from your requests.

However, there are different strategies to decide which information do you want to include in the notifications using the :custom_data option with one of the following values: :assigns, :logger or both.

The included information will show up in your notification, in a new section titled "Metadata".

Assigns

This option will include the data that is in the connection assigns field.

You can also specify the fields you want to retrieve from conn.assigns.

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    custom_data: :assigns,
    notifiers: [
      # ...
    ]
defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    custom_data: [assigns: [fields: [:current_user, :session_data]]],
    notifiers: [
      # ...
    ]

Example of adding custom data to the connection:

assign(conn, :name, "John")

Logger

This option will include the data that is in the Logger metadata field.

You can also specify the fields you want to retrieve from Logger.metadata().

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    custom_data: :logger,
    notifiers: [
      # ...
    ]
defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    custom_data: [logger: [fields: [:request_id, :current_user]]],
    notifiers: [
      # ...
    ]

Example of adding custom data to the logger:

Logger.metadata(name: "John")

Using both

You can do any combination of the above settings to include data from both sources. The names of the fields are independent for each source, they will appear under the source namespace.

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    custom_data: [
      [assigns: [fields: [:current_user]]],
      [logger: [fields: [:request_id, :current_user]]]
    ],
    notifiers: [
      # ...
    ]
   # ...
end

Ignore exceptions

By default, all exceptions are captured by Boom. The :ignore_exceptions setting is provided to ignore exceptions of a certain kind. Said exceptions will not generate any kind of notification from Boom.

defmodule YourApp.Router do
  use Phoenix.Router

  use BoomNotifier,
    ignore_exceptions: [
      HTTPoison.Error, MyApp.CustomException
    ],
    notifiers: [
      # ...
    ]
   # ...
end

Implementation details

Boom uses Plug.ErrorHandler to trigger notifications. If you are already using that module you must use BoomNotifier after it.

License

BoomNotifier is released under the terms of the MIT License.

Credits

The authors of this project are Ignacio and Jorge. It is sponsored and maintained by Wyeworks.

boom's People

Contributors

2guti2 avatar andres-vidal avatar brunvez avatar eldano avatar gastonabella avatar grzuy avatar iaguirre88 avatar jmbejar avatar joaquinco avatar joulei avatar krainboltgreene avatar leticiaerrandonea avatar matsu911 avatar mcass19 avatar noelia-lencina avatar rafaeliga avatar rktjmp avatar romiparada avatar smartinez87 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

boom's Issues

Proposal: Improve styling of HTML emails

Reasoning

As of now HTML emails are rather crude, they are almost indistinguishable from the text version which kind of defeats the point of having two separate versions. While I'm not expecting something fancy, I think a bit of css can go a long way in improving them.

I propose something like the attached image presents, that while still being rudimentary, is more functional since the content sections can be identified clearly. Thoughts?

image

Include custom data in the notification

Provide a way to attach custom data in the notification such as the current user.

Dev notes
Maybe we can get that info from the assigns in the connection like thiscurrent_user = conn.assigns[:current_user]

Improve Phoenix error reason in subject

How to reproduce it:

Try to render a template that does not exist in a controller: render(conn, "index-does-not-exists.html")

Actual result:

Email subject is being set as:

BOOM error caught: %Phoenix.Template.UndefinedError{assigns: %{conn: %Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{layout: {MyAppWeb.LayoutView, "app.html"}}, body_params: %{}, cookies: %{"__gads" => "ID

Expected result

BOOM error caught: Could not render "index-does-not-exists.html" for MyAppWeb.PageView

Idea - Implement UDP notifier

I think having a UDP based notifier could be a great addition for some projects that interface with IoT devices. What do y'all think?

Idea background

While working on a simple IoT project I found out some of my house lights communicated via UDP, which gave me the silly idea of having those devices react (i.e turn red) when an exception was encountered.

Phoenix based apps that interface with IoT devices could make a lot of use of a notifier like this, provided their connected devices already handle UDP messages.

How could this be implemented?

We could spin up a GenServer that creates a socket using Erlang's :gen_udp (doc) and use that socket to send events to other connected devices (which can be listed by IP and port).

Alternatively, we could open and close a socket every time an exception occurs, in which case we wouldn't need a GenServer alive - This is just a thought as I don't really know what the best approach for UDP sockets is.

Final notes

This could very well be a separate package, as most Phoenix apps are not IoT related (I would assume). Also, we could add other protocols to the mix to interface with even more IoT devices (TCP, local WIfi, etc)

An error occurred when sending a notification

Hi ,

I have installed the boom notifier and it works fine in my local. But in cloud with production mode I am getting file not found error.
An error occurred when sending a notification: ** (File.Error) could not read file "/app/deps/boom_notifier/lib/boom_notifier/mail_notifier/templates/email_body.html.eex": no such file or directory in File.read!/1
Not sure if its the permission issue. Can you please confirm where I am missing.

@spastorino @joseicosta @jmbejar
TIA.

Ignore certain type of exception

It would be great to have an option to ignore some kind of exceptions. It could be done by setting an array of string with the exceptions you want not to get notifications from.

use Boom,
    ignore_exceptions: ["Ecto.QueryError", "HTTPoison.Error"]
    notifiers: [
      . . .
    ]

Error in production with release. "(File.Error) could not read file "

Hi, I'm trying to use BoomNotifier but i got this error when the mail should be deliver.
Here is the error message :

** (File.Error) could not read file "/home/build/tmp/deps/boom_notifier/lib/boom_notifier/mail_notifier/templates/email_body.html.eex": no such file or directory
(elixir 1.11.4) lib/file.ex:355: File.read!/1
(eex 1.11.4) lib/eex.ex:192: EEx.compile_file/2
(eex 1.11.4) lib/eex.ex:228: EEx.eval_file/3
(boom_notifier 0.4.0) lib/boom_notifier/mail_notifier.ex:53: BoomNotifier.MailNotifier.notify/2

This error happen in production.
Thanks :)

Image link broken

Image link to the wyeworks site is broken on hexdocs:

Screen Shot 2021-05-27 at 12 25 02 AM

This is not an issue on the markdown file as the logo is displayed correctly on github.

It seems to be an error on how ex_doc escapes html sometimes, as this can also be seen on other package pages like: https://hexdocs.pm/dust/readme.html

Emails should be delivered in background

Based on this line, emails seem to be delivered during the cycle of a request.

This means that if an exception occurs, a significant delay will take place while the notification is being sent. Furthermore, if someone hits an exception multiple times there's the possibility of suffering a DDoS while all the emails are being sent.

A suggestion could be sending emails in background, using Bamboo's deliver_later method rather than deliver_now

Fails if stacktrace entry doesn’t contain file and line info

For example, if the exception is caused by trying to access a field on a variable that’s expected to be a struct but is actually nil, then the first stacktrace entry will be {nil, :some_field, [], []}. This causes BoomNotifier.MailNotifier.HTMLContent.entry_to_map/1 to fail with a MatchError.

Callback for handle_errors

Hello,

I have an app that we handle json errors, using handle_errors:

def handle_errors(conn, assigns) do
  handle_errors(get_format(conn), conn, assigns)
end

defp handle_errors("json", %{status: status_code} = conn, %{reason: reason}) do
  conn
  |> json(%{error: %{status: status_code, message: Exception.message(reason)}})
  |> halt()
end

defp handle_errors(_format, conn, _assigns), do: conn

Is there a option to continue using this with Boom?

What do you think of a setting/config that sets a callback at the end of Boom handle_errors?

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.