Current section
22 Versions
Jump to
Current section
22 Versions
Compare versions
6
files changed
+102
additions
-27
deletions
| @@ -1,6 +1,4 @@ | |
| 1 | - ### This project is looking for a maintainer. As much as I love the language, ecosystem, community around Elixir, I'm not currently lucky enough to be doing any serious work in the language. If someone would like to take some responsibility for the project I would hugely appreciate it. |
| 2 | - |
| 3 | - # Bugsnag Elixir |
| 1 | + # Bugsnag Elixir [](https://travis-ci.org/jarednorman/bugsnag-elixir) |
| 4 2 | |
| 5 3 | Capture exceptions and send them to the [Bugsnag](http://bugsnag.com) API! |
| 6 4 | |
| @@ -19,6 +17,9 @@ end | |
| 19 17 | |
| 20 18 | # Open up your config/config.exs (or appropriate project config) |
| 21 19 | config :bugsnag, api_key: "bbf085fc54ff99498ebd18ab49a832dd" |
| 20 | + |
| 21 | + # Set the release stage in your environment configs (e.g. config/prod.exs) |
| 22 | + config :bugsnag, release_stage: "prod" |
| 22 23 | ``` |
| 23 24 | |
| 24 25 | ## Usage |
| @@ -3,19 +3,19 @@ | |
| 3 3 | {<<"description">>,<<"An Elixir interface to the Bugsnag API">>}. |
| 4 4 | {<<"elixir">>,<<"~> 1.0">>}. |
| 5 5 | {<<"files">>, |
| 6 | - [<<"lib/bugsnag.ex">>,<<"lib/bugsnag/payload.ex">>,<<"mix.exs">>, |
| 7 | - <<"README.md">>,<<"LICENSE">>]}. |
| 6 | + [<<"lib/bugsnag.ex">>,<<"lib/bugsnag/logger.ex">>, |
| 7 | + <<"lib/bugsnag/payload.ex">>,<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}. |
| 8 8 | {<<"licenses">>,[<<"MIT">>]}. |
| 9 9 | {<<"links">>, |
| 10 10 | [{<<"github">>,<<"https://github.com/jarednorman/bugsnag-elixir">>}]}. |
| 11 11 | {<<"name">>,<<"bugsnag">>}. |
| 12 12 | {<<"requirements">>, |
| 13 | - [{<<"httpoison">>, |
| 14 | - [{<<"app">>,<<"httpoison">>}, |
| 15 | - {<<"optional">>,false}, |
| 16 | - {<<"requirement">>,<<"~> 0.6">>}]}, |
| 17 | - {<<"poison">>, |
| 18 | - [{<<"app">>,<<"poison">>}, |
| 19 | - {<<"optional">>,false}, |
| 20 | - {<<"requirement">>,<<"~> 1.3">>}]}]}. |
| 21 | - {<<"version">>,<<"1.2.0">>}. |
| 13 | + [[{<<"app">>,<<"httpoison">>}, |
| 14 | + {<<"name">>,<<"httpoison">>}, |
| 15 | + {<<"optional">>,false}, |
| 16 | + {<<"requirement">>,<<"~> 0.6">>}], |
| 17 | + [{<<"app">>,<<"poison">>}, |
| 18 | + {<<"name">>,<<"poison">>}, |
| 19 | + {<<"optional">>,false}, |
| 20 | + {<<"requirement">>,<<"~> 1.5 or ~> 2.0">>}]]}. |
| 21 | + {<<"version">>,<<"1.3.0">>}. |
| @@ -1,21 +1,44 @@ | |
| 1 1 | defmodule Bugsnag do |
| 2 | + use Application |
| 3 | + |
| 4 | + alias Bugsnag.Payload |
| 5 | + |
| 2 6 | @notify_url "https://notify.bugsnag.com" |
| 3 7 | @request_headers [{"Content-Type", "application/json"}] |
| 4 8 | |
| 5 | - alias Bugsnag.Payload |
| 6 | - use HTTPoison.Base |
| 9 | + def start do |
| 10 | + config = Keyword.merge default_config, Application.get_all_env(:bugsnag) |
| 11 | + |
| 12 | + if config[:use_logger] do |
| 13 | + :error_logger.add_report_handler(Bugsnag.Logger) |
| 14 | + end |
| 15 | + |
| 16 | + # put normalized api key to application config |
| 17 | + Application.put_env(:bugsnag, :api_key, config[:api_key]) |
| 18 | + end |
| 7 19 | |
| 8 20 | def report(exception, options \\ []) do |
| 9 | - stacktrace = System.stacktrace |
| 21 | + stacktrace = options[:stacktrace] || System.stacktrace |
| 22 | + |
| 10 23 | spawn fn -> |
| 11 | - post(@notify_url, |
| 12 | - Payload.new(exception, stacktrace, options) |> to_json, |
| 13 | - @request_headers) |
| 24 | + Payload.new(exception, stacktrace, options) |
| 25 | + |> to_json |
| 26 | + |> send_notification |
| 14 27 | end |
| 15 28 | end |
| 16 29 | |
| 17 30 | def to_json(payload) do |
| 18 | - payload |
| 19 | - |> Poison.encode! |
| 31 | + payload |> Poison.encode! |
| 32 | + end |
| 33 | + |
| 34 | + defp send_notification(body) do |
| 35 | + HTTPoison.post @notify_url, body, @request_headers |
| 36 | + end |
| 37 | + |
| 38 | + defp default_config do |
| 39 | + [ |
| 40 | + api_key: System.get_env("BUGSNAG_API_KEY") || "FAKEKEY", |
| 41 | + use_logger: true |
| 42 | + ] |
| 20 43 | end |
| 21 44 | end |
| @@ -0,0 +1,46 @@ | |
| 1 | + defmodule Bugsnag.Logger do |
| 2 | + require Bugsnag |
| 3 | + require Logger |
| 4 | + |
| 5 | + use GenEvent |
| 6 | + |
| 7 | + def init(_mod, []), do: {:ok, []} |
| 8 | + |
| 9 | + def handle_call({:configure, new_keys}, _state) do |
| 10 | + {:ok, :ok, new_keys} |
| 11 | + end |
| 12 | + |
| 13 | + def handle_event({_level, gl, _event}, state) |
| 14 | + when node(gl) != node() do |
| 15 | + {:ok, state} |
| 16 | + end |
| 17 | + |
| 18 | + def handle_event({:error_report, _gl, {_pid, _type, [message | _]}}, state) |
| 19 | + when is_list(message) do |
| 20 | + try do |
| 21 | + error_info = message[:error_info] |
| 22 | + |
| 23 | + case error_info do |
| 24 | + {_kind, {exception, stacktrace}, _stack} when is_list(stacktrace) -> |
| 25 | + Bugsnag.report(exception, stacktrace: stacktrace) |
| 26 | + {_kind, exception, stacktrace} -> |
| 27 | + Bugsnag.report(exception, stacktrace: stacktrace) |
| 28 | + end |
| 29 | + rescue |
| 30 | + ex -> |
| 31 | + error_type = Exception.normalize(:error, ex).__struct__ |
| 32 | + |> Atom.to_string |
| 33 | + |> String.replace(~r{\AElixir\.}, "") |
| 34 | + |
| 35 | + reason = Exception.message(ex) |
| 36 | + |
| 37 | + Logger.warn "Unable to notify Bugsnag #{error_type}: #{reason}" |
| 38 | + end |
| 39 | + |
| 40 | + {:ok, state} |
| 41 | + end |
| 42 | + |
| 43 | + def handle_event({_level, _gl, _event}, state) do |
| 44 | + {:ok, state} |
| 45 | + end |
| 46 | + end |
| @@ -4,6 +4,7 @@ defmodule Bugsnag.Payload do | |
| 4 4 | version: Bugsnag.Mixfile.project[:version], |
| 5 5 | url: Bugsnag.Mixfile.project[:package][:links][:github], |
| 6 6 | } |
| 7 | + @release_stage Application.get_env(:bugsnag, :release_stage) || "test" |
| 7 8 | |
| 8 9 | defstruct api_key: nil, notifier: @notifier_info, events: nil |
| 9 10 | |
| @@ -18,15 +19,17 @@ defmodule Bugsnag.Payload do | |
| 18 19 | end |
| 19 20 | |
| 20 21 | defp add_event(payload, exception, stacktrace, options) do |
| 22 | + error = Exception.normalize(:error, exception) |
| 23 | + |
| 21 24 | event = |
| 22 25 | Map.new |
| 23 26 | |> add_payload_version |
| 24 | - |> add_exception(exception, stacktrace) |
| 27 | + |> add_exception(error, stacktrace) |
| 25 28 | |> add_severity(Keyword.get(options, :severity)) |
| 26 29 | |> add_context(Keyword.get(options, :context)) |
| 27 30 | |> add_user(Keyword.get(options, :user)) |
| 28 31 | |> add_metadata(Keyword.get(options, :metadata)) |
| 29 | - |> add_release_stage(Keyword.get(options, :release_stage, to_string Mix.env)) |
| 32 | + |> add_release_stage(Keyword.get(options, :release_stage, @release_stage)) |
| 30 33 | |
| 31 34 | Map.put payload, :events, [event] |
| 32 35 | end |
Loading more files…