Giter Club home page Giter Club logo

honeybadger-elixir's Introduction

Honeybadger for Elixir

Elixir CI

Elixir Plug, Logger and client for the โšก Honeybadger error notifier.

Upgrading to v0.11? See the release notes

Getting Started

ElixirSips

Watch our screencast by Josh Adams of ElixirSips!

Version Requirements

  • Erlang >= 21.0
  • Elixir >= 1.11
  • Plug >= 1.0
  • Phoenix >= 1.0 (This is an optional dependency and the version requirement applies only if you are using Phoenix)

1. Install the package

Add the Honeybadger package to deps/0 in your application's mix.exs file and run mix do deps.get, deps.compile

defp deps do
  [{:honeybadger, "~> 0.16"}]
end

2. Set your API key and environment name

By default the environment variable HONEYBADGER_API_KEY will be used to find your API key to the Honeybadger API. If you would like to specify your key or any other configuration options a different way, you can do so in config.exs:

config :honeybadger,
  api_key: "{{PROJECT_API_KEY}}"

We also need to set the name of the environment for each environment. This ensures that we can accurately report the environment that an error occurs in. You can add something like the following to each of your #{env}.exs files:

config :honeybadger,
  environment_name: :dev

If environment_name is not set we will fall back to the value of Mix.env(). Mix.env() uses the atomized value of the MIX_ENV environment variable and defaults to :prod when the environment variable is not set. This should be good for most setups. If you want to have an environment_name which is different than the Mix.env(), you should set environment_name in your config.exs files for each environment. This ensures that we can give you accurate environment information even during compile time. Explicitly setting the environment_name config takes higher precedence over the Mix.env() value.

3. Enable error reporting

The Honeybadger package can be used as a Plug alongside your Phoenix applications, as a logger backend, or as a standalone client for sprinkling in exception notifications where they are needed.

Phoenix and Plug

The Honeybadger Plug adds a Plug.ErrorHandler to your pipeline. Simply use the Honeybadger.Plug module inside of a Plug or Phoenix.Router and any crashes will be automatically reported to Honeybadger. It's best to use Honeybadger.Plug after the Router plugs so that exceptions due to non-matching routes are not reported to Honeybadger.

Phoenix app
defmodule MyPhoenixApp.Router do
  use Crywolf.Web, :router
  use Honeybadger.Plug

  pipeline :browser do
    [...]
  end
end
Plug app
defmodule MyPlugApp do
  use Plug.Router
  use Honeybadger.Plug

  [... the rest of your plug ...]
end

Logger

Just set the use_logger option to true in your application's config.exs and you're good to go! Any SASL compliant processes that crash will send an error report to the Honeybadger.Logger. After the error reaches the logger we take care of notifying Honeybadger for you!

Manual reporting

You can manually report rescued exceptions with the Honeybadger.notify function.

try do
  File.read! "this_file_really_should_exist_dang_it.txt"
rescue
  exception ->
    Honeybadger.notify(exception, metadata: %{}, stacktrace: __STACKTRACE__, fingerprint: "")
end

Breadcrumbs

Breadcrumbs allow you to record events along a processes execution path. If an error is thrown, the set of breadcrumb events will be sent along with the notice. These breadcrumbs can contain useful hints while debugging.

Breadcrumbs are stored in the logger context, referenced by the calling process. If you are sending messages between processes, breadcrumbs will not transfer automatically. Since a typical system might have many processes, it is advised that you be conservative when storing breadcrumbs as each breadcrumb consumes memory.

Automatic Breadcrumbs

We leverage the telemetry library to automatically create breadcrumbs from specific events.

Phoenix

If you are using phoenix (>= v1.4.7) we add a breadcrumb from the router start event.

Ecto

We can create breadcrumbs from Ecto SQL calls if you are using ecto_sql (>= v3.1.0). You also must specify in the config which ecto adapters you want to be instrumented:

config :honeybadger,
  ecto_repos: [MyApp.Repo]

Sample Application

If you'd like to see the module in action before you integrate it with your apps, check out our sample Phoenix application.

You can deploy the sample app to your Heroku account by clicking this button:

Deploy

Don't forget to destroy the Heroku app after you're done so that you aren't charged for usage.

The code for the sample app is available on Github, in case you'd like to read through it, or run it locally.

Filtering Sensitive Data

Before data is sent to Honeybadger, it is passed through a filter to remove sensitive fields and do other processing on the data. The default configuration is equivalent to:

config :honeybadger,
  filter: Honeybadger.Filter.Default,
  filter_keys: [:password, :credit_card]

This will remove any entries in the context, session, cgi_data and params that match one of the filter keys. The filter is case insensitive and matches atoms or strings.

If Honeybadger.Filter.Default does not suit your needs, you can implement your own filter. See the Honeybadger.Filter.Mixin module doc for details on implementing your own filter.

Filtering Arguments

Honeybadger can show arguments in the stacktrace for FunctionClauseError exceptions. To enable argument reporting, set filter_args to false:

config :honeybadger, filter_args: false

Excluding Errors

By default Honeybadger will be notified when an error occurs. To override this configuration in order not to send out errors to Honeybadger, set exclude_errors option in config/config.exs.

This can be done by passing a list of errors to be excluded:

config :honeybadger,
  exclude_errors: ["RuntimeError"]

or

config :honeybadger,
  exclude_errors: [RuntimeError]

Also you can implement the Honeybadger.ExcludeErrors behaviour function exclude_error?/1, which receives the full Honeybadger.Notice and returns a boolean signalling the error exclusion or not.

  defmodule ExcludeFunClauseErrors do
    alias Honeybadger.ExcludeErrors

    @behaviour ExcludeErrors

    @impl ExcludeErrors

    def exclude_error?(notice) do
      notice.error.class == "FunctionClauseError"
    end
  end
config :honeybadger,
  exclude_errors: ExcludeFunClauseErrors

Customizing Error Grouping

See the Error Monitoring Guide for more information about how honeybadger groups similar exception together. You can customize the grouping for each exception in Elixir by sending a custom fingerprint when the exception is reported.

To customize the fingerprint for all exceptions that are reported from your app, use the fingerprint_adapter configuration option in config.ex:

config :honeybadger, fingerprint_adapter: MyApp.CustomFingerprint
 defmodule MyApp.CustomFingerprint do
  @behaviour Honeybadger.FingerprintAdapter

  def parse(notice) do
    notice.notifier.language <> "-" <> notice.notifier.name
  end
end

You can also customize the fingerprint for individual exceptions when calling Honeybadger.notify:

Honeybadger.notify(%RuntimeError{}, fingerprint: "culprit_id-123")

Advanced Configuration

You can set configuration options in config.exs. It looks like this:

config :honeybadger,
  api_key: "{{PROJECT_API_KEY}}",
  environment_name: :prod

If you'd rather read, eg., environment_name from the OS environment, you can do like this:

config :honeybadger,
  environment_name: {:system, "HONEYBADGER_ENV"},
  revision: {:system, "HEROKU_SLUG_COMMIT"}

NOTE: This works only for the string options, and environment_name.

Here are all of the options you can pass in the keyword list:

Name Description Default
app Name of your app's OTP Application as an atom Mix.Project.config[:app]
api_key Your application's Honeybadger API key System.get_env("HONEYBADGER_API_KEY"))
environment_name (required) The name of the environment your app is running in. :prod
exclude_errors Filters out errors from being sent to Honeybadger []
exclude_envs Environments that you want to disable Honeybadger notifications [:dev, :test]
hostname Hostname of the system your application is running on :inet.gethostname
origin URL for the Honeybadger API "https://api.honeybadger.io"
project_root Directory root for where your application is running System.cwd/0
revision The project's git revision nil
filter Module implementing Honeybadger.Filter to filter data before sending to Honeybadger.io Honeybadger.Filter.Default
filter_keys A list of keywords (atoms) to filter. Only valid if filter is Honeybadger.Filter.Default [:password, :credit_card]
filter_args If true, will remove function arguments in backtraces true
filter_disable_url If true, will remove the request url false
filter_disable_session If true, will remove the request session false
filter_disable_params If true, will remove the request params false
fingerprint_adapter Implementation of FingerprintAdapter behaviour
notice_filter Module implementing Honeybadger.NoticeFilter. If nil, no filtering is done. Honeybadger.NoticeFilter.Default
sasl_logging_only If true, will notifiy for SASL errors but not Logger calls true
use_logger Enable the Honeybadger Logger for handling errors outside of web requests true
ignored_domains Add domains to ignore Error events in Honeybadger.Logger. [:cowboy]
breadcrumbs_enabled Enable breadcrumb event tracking false
ecto_repos Modules with implemented Ecto.Repo behaviour for tracking SQL breadcrumb events []

Public Interface

Honeybadger.notify: Send an exception to Honeybadger.

Use the Honeybadger.notify/2 function to send exception information to the collector API. The first parameter is the exception and the second parameter is the context/metadata/fingerprint. There is also a Honeybadger.notify/1 which doesn't require the second parameter.

Examples:

try do
  File.read! "this_file_really_should_exist_dang_it.txt"
rescue
  exception ->
    context = %{user_id: 5, account_name: "Foo"}
    Honeybadger.notify(exception, metadata: context, stacktrace: __STACKTRACE__)
end

Honeybadger.context/1: Set metadata to be sent if an error occurs

Honeybadger.context/1 is provided for adding extra data to the notification that gets sent to Honeybadger. You can make use of this in places such as a Plug in your Phoenix Router or Controller to ensure useful debugging data is sent along.

Examples:

def MyPhoenixApp.Controller
  use MyPhoenixApp.Web, :controller

  plug :set_honeybadger_context

  def set_honeybadger_context(conn, _opts) do
    user = get_user(conn)
    Honeybadger.context(user_id: user.id, account: user.account.name)
    conn
  end
end

Honeybadger.context/1 stores the context data in the process dictionary, so it will be sent with errors/notifications on the same process. The following Honeybadger.notify/1 call will not see the context data set in the previous line.

Honeybadger.context(user_id: 5)
Task.start(fn ->
  # this notify does not see the context set earlier
  # as this runs in a different elixir/erlang process.
  Honeybadger.notify(%RuntimeError{message: "critical error"})
end)

Honeybadger.add_breadcrumb/2: Store breadcrumb within process

Appends a breadcrumb to the notice. Use this when you want to add some custom data to your breadcrumb trace in effort to help debugging. If a notice is reported to Honeybadger, all breadcrumbs within the execution path will be appended to the notice. You will be able to view the breadcrumb trace in the Honeybadger interface to see what events led up to the notice.

Examples:

Honeybadger.add_breadcrumb("Email sent", metadata: %{
  user: user.id,
  message: message
})

Proxy configuration

If your server needs a proxy to access Honeybadger, add the following to your config

config :honeybadger,
  proxy: "url",
  proxy_auth: {"username", "password"}

Excluded environments

Honeybadger won't report errors from :dev and :test environments by default. To enable error reporting in dev:

  1. Set the HONEYBADGER_API_KEY as documented above
  2. Remove :dev from the exclude_envs by adding this to your config/dev.exs
config :honeybadger,
  exclude_envs: [:test]
  1. Run the mix honeybadger.test mix task task to simulate an error

Changelog

See https://github.com/honeybadger-io/honeybadger-elixir/blob/master/CHANGELOG.md

Contributing

If you're adding a new feature, please submit an issue as a preliminary step; that way you can be (moderately) sure that your pull request will be accepted.

To contribute your code:

  1. Fork it.
  2. Create a topic branch git checkout -b my_branch
  3. Commit your changes git commit -am "Boom"
  4. Push to your branch git push origin my_branch
  5. Send a pull request

Publishing a release on hex.pm

Github Workflow

A new version can be published on Hex.pm using the Publish New Release workflow. The workflow can be triggered manually from the Github Actions page and takes the following input:

  • version: One of patch, minor or major. The version number will be bumped accordingly.
  • changes: An entry to be added to the changelog.

Manual Release

Versioning, changelog generation and publishing to hex.pm is handled by the mix expublish task. You can read more about it here.

  1. mix deps.get
  2. echo "CHANGELOG ENTRY" > RELEASE.MD
  3. mix expublish.[patch|minor|major]

License

This library is MIT licensed. See the LICENSE file in this repository for details.

honeybadger-elixir's People

Contributors

aaronrenner avatar abshierjoel avatar abstractcoder avatar cbarratt avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar github-actions[bot] avatar ig3io avatar jasonroelofs avatar joshuap avatar minhajuddin avatar mitchellhenke avatar mwoods79 avatar nurugger07 avatar olleolleolle avatar pbm avatar pthompson avatar rabidpraxis avatar rbishop avatar smeevil avatar sorentwo avatar starrhorne avatar subzero10 avatar tehprofessor avatar thomasbrus avatar tielur avatar traceyonim avatar ugisozols avatar zachdaniel 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

honeybadger-elixir's Issues

Refine controller/action reporting in Plug/Phoenix

In Honeybadger we use the controller in our grouping algorithm. Currently we're using __MODULE__ to determine the current controller in our Plug:

https://github.com/honeybadger-io/honeybadger-elixir/blob/master/lib/honeybadger/plug.ex#L61

This works if you use the Plug inside each Phoenix controller. If you use the Plug inside the router, however (as many do), the router is reported instead of the controller.

The action is not currently reported at all, but should be.

Test fails randomly

This test fails randomly.

 1) test log levels lower than :error_report are ignored (Honeybadger.LoggerTest)
     test/logger_test.exs:44
     Expected false or nil, got true
     code: :meck.called(HTTP, :post, [:_, :_, :_])
     stacktrace:
       test/logger_test.exs:51: anonymous fn/1 in Honeybadger.LoggerTest.test log levels lower than :error_report are ignored/1
       (elixir) lib/enum.ex:604: Enum."-each/2-lists^foreach/1-0-"/2
       (elixir) lib/enum.ex:604: Enum.each/2
       test/logger_test.exs:47

It seems to fail locally and on CI with all supported versions of Elixir.

Track parameters from function invocations

In some cases it appears that a backtrace can include the parameters used to invoke a function that caused an error. Example:

2017-03-01T16:53:52.772605+00:00 app[web.1]: (my_web) web/controllers/gateway_controller.ex:126: MyWeb.GatewayController.my_function("", nil, 608, 2) 

It would be cool if we could capture these and display them in Honeybadger.

Getting the controller name and action name

Phoenix has controller_module and action_name functions for doing this. Unfortunately those attribtues are added later in the request after the ErrorHandler wrapper. I've opened an issue on Plug to see if it would be possible to get the later conn in the ErrorHandler. If we can't do that, we'll have to find another way to extract that information from the conn.

Errors during test run w/ use_logger

I'm getting these errors when running tests with the (extremely awesome!) use_logger option enabled:

10:24:50.457 [warn]  Unable to notify Honeybadger! UndefinedFunctionError: undefined function: :badmatch.__struct__/1 (module :badmatch is not available)
10:24:50.475 [warn]  Unable to notify Honeybadger! ArgumentError: unsupported dict: {:supervisor, {#PID<0.204.0>, :ranch_listener_sup}}
10:24:50.475 [warn]  Unable to notify Honeybadger! ArgumentError: unsupported dict: {:supervisor, {:local, Logplex.Supervisor}}

Honeybadger.notify differences between test and prod

Hi there,

We've been using the module in one of our projects, and one thing that caught my attention is that Honeybadger.notify returns something different depending if it's an active environment or not.

This will match only when the environment is active (by default, :prod):

{:ok, _pid} = Honeybadger.notify("an error")

This will match only when the environment is inactive (:dev and :test by default):

:ok = Honeybadger.notify("an error")

I'm relatively new to Elixir so this might be the right thing to do, but it's seems a bit weird to me that the return value changes between testing/development and production. In our final code we don't pattern match against Honeybadger.notify return, but while developing it was an odd surprise.

Another problem, is that, for example, Poison serialization problems can go unnoticed while testing since there's no interaction with the Client module at all.

Was this intentional? Do you think it'd make sense to move the logic deeper, so we get better dev/prod parity? I'd be happy to work on a PR for that.

Erlang v18 required

I had crywolf-elixir using Erlang 17 on Heroku and got this error when I upgraded to 0.5.0. Are many people still using v17? I'd say we should either support 17 and 18 or mention in the README that v18 is required. What do you think, @rbishop?

Phoenix session error in Honeybadger.Plug

I'm probably missing something obvious (first time using Phoenix), but I am getting the error "key :session not found in: %Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}" when I try to add the plug to a vanilla controller:

https://github.com/honeybadger-io/crywolf-elixir/blob/master/web/controllers/page_controller.ex#L12

Is the issue that I need to manually configure the session in Phoenix first? I'd expect it to skip the session data if it can't access it gracefully.

exq integration

This integration would automatically report exceptions from failed exq jobs, similar to how we do for Ruby/Sidekiq. See akira/exq#191 for a potential solution. We should also investigate if the current use_logger option already works for this case.

Relax Poison Version

If honeybadger could run on versions 2 of poison, that'd be awesome. I'm using Phoenix 1.2.1 and it requires poison v2.

When running mix deps.update --all:

Failed to use "poison" (version 2.2.0) because
ecto (version 2.1.0-rc.3) requires ~> 2.2 or ~> 3.0
ex_aws (version 1.0.0-rc.4) requires ~> 1.2 or ~> 2.0
honeybadger (version 0.6.2) requires ~> 3.0
phoenix (versions 1.2.0 and 1.2.1) requires ~> 1.5 or ~> 2.0

Honeybadger is the conflicting package that does not support poison v2.

Infinite errors logged

After a period of time (days-weeks), we'll notice things stop working in our production application. There are 500s happening, but no errors are reported to Honeybadger. I attach to the running error logs, and all I see is constant scrolling of errors originating in the HB lib. Here's a sample:

15:43:32.141 [error] Task #PID<0.14798.3740> started from :error_logger terminating
** (ArgumentError) argument error
    (honeybadger) lib/honeybadger/client.ex:36: Honeybadger.Client.send_notice/3
    (elixir) lib/task/supervised.ex:94: Task.Supervised.do_apply/2
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Function: #Function<0.116999615/0 in Honeybadger.Logger.handle_event/2>
    Args: []

=CRASH REPORT==== 27-Oct-2016::15:43:32 ===
  crasher:
    initial call: Elixir.Honeybadger.Logger:-handle_event/2-fun-0-/0
    pid: <0.14798.3740>
    registered_name: []
    exception exit: {badarg,
                        [{'Elixir.Honeybadger.Client',send_notice,3,
                             [{file,"lib/honeybadger/client.ex"},{line,36}]},
                         {'Elixir.Task.Supervised',do_apply,2,
                             [{file,"lib/task/supervised.ex"},{line,94}]},
                         {proc_lib,init_p_do_apply,3,
                             [{file,"proc_lib.erl"},{line,247}]}]}
      in function  'Elixir.Task.Supervised':exit/4 (lib/task/supervised.ex, line 125)
    ancestors: [error_logger,<0.3.0>]
    messages: []
    links: []
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 6772
    stack_size: 27
    reductions: 13795
  neighbours:

I have no idea if this is actually caused by this library, or if it is caused by something else. If it's caused by something else, I have no way of knowing because the logs are immediately clogged with the above message.

Any help would be much appreciated.

Consider failing fast when application is not started

Hi, I ran into a strange issue where my errors weren't being reported because the default configuration wasn't used (e.g. HONEYBADGER_API_KEY). When I manually entered the configuration based on the defaults it was OK. Turns out that I somehow forgot to add :honeybadger to applications: [...] in mix.exs. It would save me some time if Honeybadger.notify would have failed because of misconfigured app. I'm not sure how likely it is for other folks to run into this issue or if it's an Elixir good practice to ensure that apps are started, so please take this with a grain of salt.

Don't rely on Mix

When running in production i see you are relying on Mix.env but it's ill advised to include Mix as a dependency in production (according to Jose Valim and Chris McCord.

Also when using Exrm to deploy, Mix is not included in the build (unless explicitly added, which you should not:D ). Even if you do include it, Mix.env will return :dev in production.

It would be nice if you could update the dependency and in stead rely on the Application.get_env to get the values your are looking for, which as far as I could find is only getting the running environment (test/dev/prod).

I'm quite new to elixir / phoenix and am not yet sure if Application.get_env is the best way to do this, but as you are using it already extensively throughout the code base, it might be the right place. The only downside would be that you need to add the config to config/test.exs config/dev.exs config/prod.exs ?

An other option could be to set a shell environment value, but that might cause issues again for people using Heroku ?

/Gerard

Multiple Honeybadger.Metrics.Servers

Joshua asked me to open this issue based on a support ticket for Honeybadger.io.

Our application has an API, that is monitored for response time just fine by the Honeybadger.Plug, but the app also gets RPC requests over RabbitMQ. I'd like to add performance metric for the RPC calls to the servers in the app too, but I want to be able to separate the metrics for the API controllers from the RPC servers. I want those metrics separate because they are being served by different code and the RPC servers have more rendering, but the API controllers have the time to do authorizations, so I don't want their performance being conflated.

I had considered using a separate environment key for the API and RPC, but Honeybadger.Metrics.Server calls Honeybadger.Client.new without any arguments, so I can't start a separate Honeybadger.Metric.Server with a separate HoneyBadger.Client configuration.

The Honeybadger.Metric.Server could have a simple_one_for_one Supervisor installed above it that can be used to create additional Honeybadger.Metric.Server from multiple Application configuration entries or at runtime as described here. Then each Honeybadger.Metric.Server would have state that was passed to Honeybadger.Client.new, which would have to change to accept arguments.

This is one proposal, it's your library, so you can figure out if some other setup works better for the website's backend.

masking sensitive values in reports

Is there any support or planned support for being able to mask sensitive values in honeybadger reports? Or is there another way to pay into sasl reports so I can mask values there before they get sent to honeybadger?

In my use case there are GenServers that hold sensitive credentials in-memory to keep them hidden from the rest of the application, but if they fail the default error reports will include information about the state of the GenServer when it failed and that will include these sensitive credentials.

Maybe there's a standard way to handle this in OTP so it gets resolved before honeybadger gets involved? Any guidance would be very helpful

Honeybadger for use in umbrella project

We've been using HB in our project for a few months with good success. Our project has expanded into an elixir umbrella, that basically has two Phoenix Endpoints running under the same beam/erlang process.

Is it possible to configure honeybadger to work with both apps at the same time?

Thoughts?

Thanks!

Do not add report handler when in excluded env

Hi!

It seems you are adding the report handler always, even when running in a environment where I do not want to use the library.

In situations like running load tests I would appreciate that I could totally disable integrations like honeybadger. Just to avoid sending 10k reports. I can do that by making sure the library is not in my :applications list but its more convenient if the :exclude_envs would disable also the logger.

This is an issue because of Honeybadger.Logger exploding when handling some error reports.
See: #24

Enumerable not implemented error in do_notify method

** (Protocol.UndefinedError) protocol Enumerable not implemented for "feedback.push.apple.com:2196"
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:140: Enumerable.count/1
    (elixir) lib/enum.ex:437: Enum.count/1
    (honeybadger) lib/honeybadger.ex:133: Honeybadger.do_notify/3
    (elixir) lib/task/supervised.ex:74: Task.Supervised.do_apply/2
    (stdlib) proc_lib.erl:239: :proc_lib.init_p_do_apply/3
Function: #Function<0.101430325/0 in Honeybadger.Logger.handle_event/2>
    Args: []

Random test failure

  1) test log levels lower than :error_report are ignored (Honeybadger.LoggerTest)
     test/logger_test.exs:44
     Expected false or nil, got true
     code: :meck.called(HTTP, :post, [:_, :_, :_])
     stacktrace:
       test/logger_test.exs:51: anonymous fn/1 in Honeybadger.LoggerTest.test log levels lower than :error_report are ignored/1
       (elixir) lib/enum.ex:604: Enum."-each/2-lists^foreach/1-0-"/2
       (elixir) lib/enum.ex:604: Enum.each/2
       test/logger_test.exs:47

Not catching errors in channels

Trying to set this up today and it is working fine in the PagesController but I am completely unable to get it working with Channels. Is there something additional I need to configure? Am I missing anything?

Remove meck in favor of an API stub

Using meck for mocking is kind of weird and unnatural. It's easier and cleaner to just stand up a simple Plug app with a notify route and change the origin config for the test environment. We will probably also need to add Cowboy as a test dependency.

excluded envs not being excluded

I'm required to put in config for honeybadger in config/config.exs and I use my staging api key and set the env to dev and include dev in excluded envs. I'm still getting dev errors on my staging honeybadger dashboard.

  config :honeybadger,
  api_key: "xxxxxxxx",
  exclude_envs: [:test, :dev, :staging],
  environment_name: :dev

I'm on .6. You can see a screenshot of what I mean below. What I want is just no dev or staging bugs.

screen shot 2017-02-07 at 8 23 32 pm

Correctly mark poison as dependency

To correctly expose that this lib requires :poison library please add it to your :applications list.

Even when the application you depend on does not start a process (is a library application) it should be listed in the :applications, so that exrm release tool can find it.

Currently users must add :poison to their own mix.exs to get the release working.

Why not add it to :included_applications? see: bitwalker/exrm#147

And yes, application in Erlang refers to both applications and library applications:
http://www.erlang.org/doc/design_principles/des_princ.html (see 1.3)

Thanks!

Warnings when compiling under Elixir 1.3

==> honeybadger
Compiling 11 files (.ex)
warning: variable session is unused
  lib/honeybadger/plug.ex:50

warning: variable e is unused
  lib/honeybadger/plug.ex:52

warning: unused import Supervisor.Spec
  lib/honeybadger.ex:106

warning: variable context is unused
  lib/honeybadger/logger.ex:24

warning: variable exception is unused
  lib/honeybadger/logger.ex:27

warning: variable exception is unused
  lib/honeybadger/logger.ex:29

warning: variable stacktrace is unused
  lib/honeybadger/logger.ex:29

Generated honeybadger app

Use Mix.Project.config/0 to get otp_app name

Mix.Project.config/0 brings back all sorts of good data about the app. Here's what it looks like for crywolf:

[app: :crywolf, version: "0.0.1", elixir: "~> 1.0",
 elixirc_paths: ["lib", "web"],
 compilers: [:phoenix, :yecc, :leex, :erlang, :elixir, :app],
 build_embedded: false, start_permanent: false,
 deps: [{:phoenix, "~> 0.13.1"}, {:phoenix_ecto, "~> 0.4"},
  {:postgrex, ">= 0.0.0"}, {:phoenix_html, "~> 1.0"},
  {:phoenix_live_reload, "~> 0.4", [only: :dev]}, {:cowboy, "~> 1.0"},
  {:honeybadger, "~> 0.0.1", [path: "/Users/rb/code/honeybadger"]}],
 aliases: [], build_per_environment: true, default_task: "run",
 deps_path: "deps", erlc_paths: ["src"], erlc_include_path: "include",
 erlc_options: [:debug_info], lockfile: "mix.lock", preferred_cli_env: []]

We can derive the otp_app name from there instead of making users pass it in at configuration time. Maybe we can keep the app configuration in case they want to override it with something else, though I don't see a reason for doing that.

There's likely some other functions in Mix.Project we can use for generating better dependency file paths as well.

Add the ability to pass in a proxy config for HTTPoison

Currently this library isn't usable in a corporate / heavy firewall'd environments where you'd typically need a proxy to get outside of the network.

I'll take a look to see if I can butcher together a PR for this! But it's definitely a requirement at the company I work for :) Looking forward to using this library as Honeybadger is great!

GenServer error reporting fails in weird way

Hi I got this error in my logs:

** (Protocol.UndefinedError) protocol Enumerable not implemented for {GenServer, :call, [#PID<0.1911.0>, {:poll_notifications}, 5000]}
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:140: Enumerable.count/1
    (elixir) lib/enum.ex:437: Enum.count/1
    (honeybadger) lib/honeybadger.ex:135: Honeybadger.do_notify/3
    (elixir) lib/task/supervised.ex:74: Task.Supervised.do_apply/2
    (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.12943092/0 in Honeybadger.Logger.handle_event/2>
    Args: []

=CRASH REPORT==== 27-Oct-2015::08:01:07 ===
  crasher:
    initial call: Elixir.Honeybadger.Logger:-handle_event/2-fun-0-/0
    pid: <0.1237.0>
    registered_name: []
    exception exit: {#{'__exception__' => true,
                       '__struct__' => 'Elixir.Protocol.UndefinedError',
                       description => nil,
                       protocol => 'Elixir.Enumerable',
                       value => {'Elixir.GenServer',call,
                           [<0.1911.0>,{poll_notifications},5000]}},
                     [{'Elixir.Enumerable','impl_for!',1,
                          [{file,"lib/enum.ex"},{line,1}]},
                      {'Elixir.Enumerable',count,1,
                          [{file,"lib/enum.ex"},{line,140}]},
                      {'Elixir.Enum',count,1,
                          [{file,"lib/enum.ex"},{line,437}]},
                      {'Elixir.Honeybadger',do_notify,3,
                          [{file,"lib/honeybadger.ex"},{line,135}]},
                      {'Elixir.Task.Supervised',do_apply,2,
                          [{file,"lib/task/supervised.ex"},{line,74}]},
                      {proc_lib,init_p_do_apply,3,
                          [{file,"proc_lib.erl"},{line,240}]}]}
      in function  'Elixir.Task.Supervised':exit/4 (lib/task/supervised.ex, line 105)
    ancestors: [error_logger,<0.2.0>]
    messages: []
    links: []
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 610
    stack_size: 27
    reductions: 151
  neighbours:

Not sure whats the root cause it appeared after I had restarted my application server and received an error like this:

2015-10-27 08:01:07.859 [error] Discarding message {'$gen_call',{<0.1236.0>,#Ref<0.0.1.757>},{poll_notifications}} from <0.1236.0> to <0.1911.0> in an old incarnation (1) of this node (2)



=CRASH REPORT==== 27-Oct-2015::08:01:07 ===
  crasher:
    initial call: Elixir.Giger.Player:init/1
    pid: <0.1236.0>
    registered_name: []
    exception exit: {noproc,
                        {'Elixir.GenServer',call,
                            [<0.1911.0>,{poll_notifications},5000]}}
      in function  gen_fsm:init_it/6 (gen_fsm.erl, line 396)
    ancestors: [<0.1229.0>]
    messages: []
    links: [<0.1229.0>]
    dictionary: [{'$relock_lock',
                      #{'__struct__' => 'Elixir.Relocker.Lock',
                        lease_time => 10,
                        metadata => #{node => '[email protected]',
                          pid => <0.1236.0>},
                        name => <<"user:XC4MNHOl">>,
                        secret => <<"yMzDZ0RFqdVPjJ5RUyNQ4xHffErPXsi2LIne5m+L24g=">>,
                        valid_until => 1445932877}},
                  {random_seed,{24548,13903,23315}},
                  {logger_metadata,
                      {true,
                          [{userid,<<"user:XC4MNHOl">>},{id,"<0.1236.0>"}]}}]
    trap_exit: false
    status: running
    heap_size: 6772
    stack_size: 27
    reductions: 363946
...

Any idea what this could be?

Cheers,

Roope

Override Exception Name

When we do Honeybadger.notify("Something went wrong") how could we dynamically set the name of the exception that it reports to honey badger?

logger.ex:24: warning: variable context is unused

Saw these warnings when compiling:

lib/honeybadger/logger.ex:24: warning: variable context is unused
lib/honeybadger/logger.ex:27: warning: variable exception is unused
lib/honeybadger/logger.ex:29: warning: variable exception is unused
lib/honeybadger/logger.ex:29: warning: variable stacktrace is unused

Forked repo and intended to submit a pull but now I'm scratching my head. Why does Elixir think that these variables are unused? ๐Ÿ‘€

case error_info do
  {_kind, {exception, stacktrace}, _stack} when is_list(stacktrace) ->
    Honeybadger.notify(exception, context, stacktrace)
  {_kind, exception, stacktrace} ->
    Honeybadger.notify(exception, context, stacktrace)
end

https://github.com/honeybadger-io/honeybadger-elixir/blob/master/lib/honeybadger/logger.ex#L24

Why does the logger not report :error messages?

Hello!

I've been trying to move over to this client from my own honeybadger client that pre-dates this one.

It seems to work good except this client does not handle :error-level log messages. Is this by design somehow or does it make sense to add it?

https://github.com/honeybadger-io/honeybadger-elixir/blob/master/lib/honeybadger/logger.ex seems to only handle :error_report.

I've so far relied on this in my job queue library for error reporting but that means those errors don't turn up in honeybadger when using this client. The errors are reported here:
https://github.com/joakimk/toniq/blob/296b99346b86bad8a1380ccbab1b79f61bd412ec/lib/toniq/job_runner.ex#L47

Honeybadger.Metrics.Server crashes after upgrade deploy via Edeliver.

My Phoenix application uses Honeybadger 0.5.0 from Hex.

Application honeybadger is present in the list of applications.

def application do
    [mod: {API, []},
     applications: [
       :phoenix,
       :phoenix_html,
       :cowboy,
       :logger,
       :gettext,
       :guardian,
       :connection,
       :phoenix_ecto,
       :postgrex,
       :tzdata,
       :timex,
       :timex_ecto,
       :httpoison,
       :cors_plug,
       :exometer_core,
       :exometer,
       :elixometer,
       :ex_rated,
       :exjsx,
       :edown,
       :parse_trans,
       :runtime_tools,
       :honeybadger,
       :edeliver]]
  end

The dependency list is

defp deps do
  [{:phoenix, "~> 1.1.4"},
   {:phoenix_ecto, "~> 2.0"},
   {:postgrex, ">= 0.0.0"},
   {:phoenix_html, "~> 2.5"},
   {:phoenix_live_reload, "~> 1.0", only: :dev},
   {:gettext, "~> 0.9"},
   {:cowboy, "~> 1.0"},
   {:exrm, "1.0.4"},
   {:edeliver, ">= 1.2.8"},
   {:exjsx, "~> 3.2"},
   {:timex, "~> 1.0"},
   {:timex_ecto, "~> 0.7.0"},
   {:guardian, "~> 0.9.0"},
   {:httpoison, "~> 0.8.0"},
   {:decimal, "~> 1.1.0"},
   {:cors_plug, "~> 0.1.4"},
   {:edown, "~>0.7.0", override: true},
   {:lager, "~>3.0.2", override: true},
   {:setup, "1.7.0", override: true},
   {:parse_trans, "2.9.0", override: true},
   {:exometer_core, github: "PSPDFKit-labs/exometer_core", override: true},
   {:exometer, github: "PSPDFKit-labs/exometer", override: true},
   {:elixometer, github: "pinterest/elixometer"},
   {:honeybadger, "~> 0.5"},
   {:ex_rated, "~> 1.2"}]
end

eDeliver is being used to deploy and live-upgrade production environment via OTP releases. It uses exrm under the hood to do its job.

Honeybadger works well in case of 'cold' deploy and/or restarting the app. However, doing live upgrade via mix edeliver upgrade production makes Honeybadger.Metrics.Server to start crashing regularly with the following trace:

08:13:52.918 [error] GenServer Honeybadger.Metrics.Server terminating
** (ArgumentError) argument error
    (honeybadger) lib/honeybadger/client.ex:28: Honeybadger.Client.send_metric/3
    (honeybadger) lib/honeybadger/metrics/server.ex:49: Honeybadger.Metrics.Server.handle_info/2
    (stdlib) gen_server.erl:615: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:681: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

=CRASH REPORT==== 24-Jun-2016::08:13:52 ===
  crasher:
    initial call: Elixir.Honeybadger.Metrics.Server:init/1
    pid: <0.14934.32>
    registered_name: 'Elixir.Honeybadger.Metrics.Server'
    exception exit: {badarg,
                        [{'Elixir.Honeybadger.Client',send_metric,3,
                             [{file,"lib/honeybadger/client.ex"},{line,28}]},
                         {'Elixir.Honeybadger.Metrics.Server',handle_info,2,
                             [{file,"lib/honeybadger/metrics/server.ex"},
                              {line,49}]},
                         {gen_server,try_dispatch,4,
                             [{file,"gen_server.erl"},{line,615}]},
                         {gen_server,handle_msg,5,
                             [{file,"gen_server.erl"},{line,681}]},
                         {proc_lib,init_p_do_apply,3,
                             [{file,"proc_lib.erl"},{line,240}]}]}
      in function  gen_server:terminate/7 (gen_server.erl, line 826)
    ancestors: [<0.1537.0>,<0.1536.0>]
    messages: []
    links: [<0.1537.0>]
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 610
    stack_size: 27
    reductions: 922
  neighbours:

=SUPERVISOR REPORT==== 24-Jun-2016::08:13:52 ===
     Supervisor: {<0.1537.0>,'Elixir.Honeybadger.Metrics.Supervisor'}
     Context:    child_terminated
     Reason:     {badarg,
                     [{'Elixir.Honeybadger.Client',send_metric,3,
                          [{file,"lib/honeybadger/client.ex"},{line,28}]},
                      {'Elixir.Honeybadger.Metrics.Server',handle_info,2,
                          [{file,"lib/honeybadger/metrics/server.ex"},
                           {line,49}]},
                      {gen_server,try_dispatch,4,
                          [{file,"gen_server.erl"},{line,615}]},
                      {gen_server,handle_msg,5,
                          [{file,"gen_server.erl"},{line,681}]},
                      {proc_lib,init_p_do_apply,3,
                          [{file,"proc_lib.erl"},{line,240}]}]}
     Offender:   [{pid,<0.14934.32>},
                  {id,'Elixir.Honeybadger.Metrics.Server'},
                  {mfargs,{'Elixir.Honeybadger.Metrics.Server',start_link,[]}},
                  {restart_type,permanent},
                  {shutdown,5000},
                  {child_type,worker}]

The only way to fix this is to restart the app completely either by hand on each node or by mix deliver stop production / mix edeliver start production.

Please note that my Honeybadger account does not have performance metrics enabled at all due to its subscription plan limitations.

convert_time_unit maybe should use :native for FromUnits

There is an inconsistency with Plug.Logger: It uses :erlang.monotonic_time to get the start and end times and when converting from the :erlang.monotonic_time default units to microseconds it does:

(stop - start) |> :erlang.convert_time_unit(:native, :micro_seconds)

HoneyBadger.Plug uses :erlang.monotonic_time to get the start and end times (the same as Plug.Logger), but when converting from the :erlang.monotonic_time default units it does:

response_time = :erlang.convert_time_unit(after_response - before_response, :nano_seconds, :milli_seconds)

So, Plug.Logger uses :native for FromUnits while HoneyBadger.Plug uses :nano_seconds. They are probably equivalent on OSX and Linux, but I think it is probably safer for HoneyBadger.Plug to use :native like Plug.Logger in case it is used on a BEAM VM where :nano_seconds isn't the same as :native

Filter out sensitive request parameters

It doesn't appear that this library has the ability to filter sensitive request parameters. I'm seeing passwords in our HB error reports.

Is there something I'm missing, or an available workaround to filter out various headers and parameters from being logged to Honeybadger?

Honeybadger.Plug calls server multiple times when reporting an error

RE: PR #51

Copied and pasted from the failing test case in the PR:

When using the Honeybadger plug, it seems that multiple attempts to call Honeybadger are being performed.

This PR serves to demonstrate the problem with a failing test case, by setting up a Bypass server standing in for Honeybadger API. This server appears to receive messages twice from the plug machinery.

(Most of the test code exists to inject new configuration after the compilation of the existing PlugApp so that exclude_envs is meaningly overridden.)

I was unable to reproduce this problem by calling Honeybadger.notify directly.

Argument error in Honeybadger.Metrics.Server

May 19 11:38:46 app.production app/web.1:  10:38:46.185 [error] #PID<0.814.0> running Status.Endpoint terminated 
May 19 11:38:46 app.production app/web.1:  Request: POST /graphql 
May 19 11:38:46 app.production app/web.1:  ** (exit) an exception was raised: 
May 19 11:38:46 app.production app/web.1:      ** (ArgumentError) argument error 
May 19 11:38:46 app.production app/web.1:          :erlang.send(Honeybadger.Metrics.Server, {:"$gen_cast", {:add_timing, 3}}) 
May 19 11:38:46 app.production app/web.1:          (elixir) lib/gen_server.ex:639: GenServer.do_send/2 
May 19 11:38:46 app.production app/web.1:          (status) web/router.ex:3: Status.Router."call (overridable 2)"/2 
May 19 11:38:46 app.production app/web.1:          (status) lib/plug/error_handler.ex:63: Status.Router.call/2 
May 19 11:38:46 app.production app/web.1:          (status) lib/status/endpoint.ex:1: Status.Endpoint.phoenix_pipeline/1 
May 19 11:38:46 app.production app/web.1:          (status) lib/phoenix/endpoint/render_errors.ex:34: Status.Endpoint.call/2

@rbishop any ideas?

Making private functions (handle_errors/2 in this case) overridable is deprecated

with Elixir: 1.4-dev and Phoenix 1.2 --

warning: making private functions (handle_errors/2 in this case) overridable is deprecated
  (elixir) lib/module.ex:842: anonymous fn/2 in Module.make_overridable/2
  (stdlib) lists.erl:1338: :lists.foreach/2
  web/router.ex:3: (module)
  (elixir) src/elixir_compiler.erl:125: :elixir_compiler.dispatch_loaded/6
  (elixir) src/elixir_module.erl:192: :elixir_module.eval_form/6

From this commit in Elixir -- elixir-lang/elixir@3db1427

Elixir 1.4 compilation warnings

Looks like honeybadger is using a now deprecated module/api:

==> honeybadger
Compiling 11 files (.ex)
warning: Dict.get/3 is deprecated, use the Map module for working with maps or the Keyword module for working with keyword lists
  lib/honeybadger/notice.ex:12

warning: Dict.get/3 is deprecated, use the Map module for working with maps or the Keyword module for working with keyword lists
  lib/honeybadger/notice.ex:15

warning: Dict.put/3 is deprecated, use the Map module for working with maps or the Keyword module for working with keyword lists
  lib/honeybadger/notice.ex:17

warning: Dict.get/3 is deprecated, use the Map module for working with maps or the Keyword module for working with keyword lists
  lib/honeybadger/notice.ex:16

warning: Dict.merge/2 is deprecated, use the Map module for working with maps or the Keyword module for working with keyword lists
  lib/honeybadger.ex:170

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.