getsentry / sentry-elixir Goto Github PK
View Code? Open in Web Editor NEWThe official Elixir SDK for Sentry (sentry.io)
Home Page: https://sentry.io
License: MIT License
The official Elixir SDK for Sentry (sentry.io)
Home Page: https://sentry.io
License: MIT License
For some reason I can't get this to capture elixir based errors. For example, a GenServer termination error.
config :sentry,
dsn: "mydsn",
environment_name: 'dev',
use_error_logger: true
Discussed this with @mitchellhenke last night. I'll detail the issue here and let you decide what, if anything, needs to be done.
Currently, the Sentry's :error_logger
handler, which captures exceptions reported by :error_logger
, is only set to capture errors reported with the :error_report
tag, which reports a process crash. It will not capture exceptions reported with the :error
tag which is sent as an exception report.
Consider the following two problems (note, the error here is that we are trying to enumerate over a binary):
Task.async(fn -> Enum.each("hello", &IO.puts/1) end)
This causes the process running the task to crash and sends an :error_report
via :error_logger
. Therefore, this error will be seen by Sentry and reported.
Process.spawn(fn -> Enum.each("hello", &IO.puts/1) end, [])
This causes the process running the task to report an exception and then exit. It reports an error as :error
via :error_logger
, therefore this error will not be seen by Sentry.
An important thing to note is that :error
reports do not contain process information (i.e., the process dictionary is not included in the report, therefore the report will not contain any Sentry contextual data).
Should fallback to MIX_ENV=dev by default.
** (Mix) Could not start application sentry: exited in: Sentry.start(:normal, [])
** (EXIT) an exception was raised:
** (RuntimeError) environment_name not configured
(sentry) lib/sentry.ex:84: Sentry.check_required_env!/0
(sentry) lib/sentry.ex:37: Sentry.start/2
(kernel) application_master.erl:273: :application_master.start_it_old/4
Plug provides Plug.RequestId
, which assigns a unique request id to every request. If you're using Phoenix, it automatically wires this up for you.
Given request_id
goes in Logger.metadata
and we have configured logger to include it in every message, it would be suuuuper useful in Sentry.Plug
sent the request id to sentry when reporting errors. Then when investigating the cause of an error, I can grep through our logs looking for that request id to find every single log message related to the request.
Would you consider sending request_id
to sentry from Sentry.Plug
?
[error] Postgrex.Protocol (#PID<0.514.0>) failed to connect: ** (Postgrex.Error) tcp connect: connection refused - :econnrefused
[warn] unable to parse exception
Maybe time to remove that old code.
In my application's Router
, if I use Sentry.Plug
, then any test that uses assert_error_sent/2
fails to pass.
Does the Sentry plug's error handling conflict with this in some known way?
Possibly with a circuit breaker https://docs.getsentry.com/on-premise/clientdev/#handling-failures
Hello again,
Now that I've been running Sentry on my elixir instance for a while, I'm seeing random errors logged in the elixir app itself with a result "event dropped due to filter". In my project settings I have "Filter out known web crawlers", so I am guessing that's the filter in question.
The issue here is why would it be logged as an error? It is causing the papertrail logger to report false positives. Wouldn't it make sense to silently accept that the log was rejected, or at most log it as either a debug or info message?
Here are the logs in question. I tried my best to format it better.
[error] Failed to send sentry event.
{"user":{},"timestamp":"2016-11-15T22:02:46.763155Z","tags":{},"stacktrace":{"frames":
[
{"module":"cowboy_protocol","lineno":442,"function":":cowboy_protocol.execute/4","filename":"src/cowboy_protocol.erl"},
{"module":"Elixir.Plug.Adapters.Cowboy.Handler","lineno":15,"function":"Plug.Adapters.Cowboy.Handler.upgrade/4","filename":"lib/plug/adapters/cowboy/handler.ex"},
{"module":"Elixir.Socks.Endpoint","lineno":1,"function":"Socks.Endpoint.call/2","filename":"lib/socks/endpoint.ex"},
{"module":"Elixir.Socks.Endpoint","lineno":1,"function":"Socks.Endpoint.phoenix_pipeline/1","filename":"lib/socks/endpoint.ex"},
{"module":"Elixir.Socks.Router","lineno":64,"function":"Socks.Router.call/2","filename":"lib/plug/error_handler.ex"},
{"module":"Elixir.Socks.Router","lineno":1,"function":"Socks.Router.do_call/2","filename":"web/router.ex"},
{"module":"Elixir.Socks.Router","lineno":1,"function":"Socks.Router.match_route/4","filename":"web/router.ex"}
]},
"server_name":"dama-server","request":{"url":"http://topgadgeturi.com:80/","query_string":"","method":"GET",
"headers":{"user-agent":"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)","pragma":"no-cache",
"host":"topgadgeturi.com","from":"bingbot(at)microsoft.com","connection":"Keep-Alive","cache-control":"no-cache",
"accept-encoding":"gzip, deflate","accept":"*/*"},
"env":{"SERVER_PORT":80,"SERVER_NAME":"topgadgeturi.com","REQUEST_ID":"8d3pv3i852pmec0503meco5q34cvsu7c","REMOTE_PORT":2524,
"REMOTE_ADDR":"207.46.13.181"},"data":{},"cookies":{}},"release":"dfda8213a158c980581935e1307b4e50ba8df1ba",
"platform":"elixir","message":"(Phoenix.Router.NoRouteError) no route found for GET / (Socks.Router)",
"level":"error","extra":{},"exception":
[
{"value":"no route found for GET / (Socks.Router)","type":"Elixir.Phoenix.Router.NoRouteError"}
],
"event_id":"74dfe32b38ee48078ee4a5149b592bdf","environment":"prod","culprit":"Socks.Router.match_route/4","breadcrumbs":[]}
Received 403 from Sentry server: Event dropped due to filter
Currently, sentry is capturing Elixir.Phoenix.Router.NoRouteError, which is not what we'd prefer. Is it reasonable for there to be a config key like excluded_exceptions
?
The version on Hex is at 0.0.5 but there have been many changes since that version. Any reason you haven't published updated versions?
https://github.com/getsentry/raven-elixir/blob/master/lib/sentry/event.ex#L63
It causes
** (exit) an exception was raised:
** (ArgumentError) argument error
:erlang.binary_to_existing_atom(nil, :utf8)
(sentry) lib/sentry/event.ex:63: Sentry.Event.transform_exception/2
(sentry) lib/sentry.ex:59: Sentry.capture_exception/2
because MIX_ENV
is not set.
I think it could fallback to Mix.env
.
Should I expect calls to Logger.error to get sent? It appears not.
I would say that it provides an "erlang report handler" in the documentation instead of an "Elixir back end".
Is adding an actual Elixir back end logger a feature you would want to add?
The :proc_lib
module (and by extension Task
module) record ancestors by shoving them into the process dictionary under $ancestors
. Although a nasty hack, looking up context in from an ancestor would drastically help when trying to reproduce a bug.
Thoughts?
I was trying sentry out in my project and got this in my logs:
13:24:48.123 module=Sentry.Client [error] Failed to send sentry event.
# ...
Problem is, it does not tell me why it failed or give me any clue about it. I initially assumed it was a problem with my dsn, but that was correct. Eventually, I edited the code in Sentry.Client.request/4
to have it capture the unmatched values (instead of ignoring them with _
) and print them with IO.inspect
. The result was included this line:
{"X-Sentry-Error", "Creation of this event was denied due to rate limiting"},
...which clearly showed me the problem. Another one of our projects was reporting a lot of errors in a short period, triggering rate limiting.
It would be really nice if users did not have to edit the code of this library to figure this out. Can log_api_error
be updated to include some detail about what the failure was?
When using the setup described in #2 I get an issue where the body send to sentry looks like
{
id: "5f32bb58fc1744b9899e0319ec1dce99",
culprit: "",
message: "<no message value>",
checksum: "167f9e7fc79fabc58612e8dc6d84ff9a",
project: "api",
datetime: "2015-02-07T18:30:59.000000Z",
time_spent: null,
extra: { },
tags: [
[
"level",
"error"
],
[
"logger",
"root"
]
],
version: 5
}
Hi guys,
I have a Phoenix app and followed the instruction to add Sentry logging to it.
When I run
MIX_ENV=prod mix sentry.send_test_event
it also says that it is sending the test event. Great!
However nothing shows up in the web console on sentry.io
. Is that normal?
If so, I wanted to catch an error that I get in my Phoenix sockets with check_origin
. I have seen that this triggers a Logger.error
call.
So I put use_error_logger: true
in my config. Now this error should be caught, right?
related to #42
I don't understand by the docs if the
config :sentry,
use_error_logger: true
is enough to catch all the errors, or I need to also also with
use Plug.ErrorHandler
use Sentry.Plug
just in case the plug doesn't intercept all the errors?
I mean, it use_error_logger
something that works only for what Sentry.Plug
doesn't catch? Or using it alone is enough to work both outside of Plug and inside?
Figure out a better default configuration. #71
Hey when I use this with phoenix I have a couple things I need to do extra,
backends: [:console, Raven]
It seems that the :request
key is supported for Sentry.capture_exception/2
, but it can't be set ahead of time. The SDK documentation seems to indicate that this should be supported: https://docs.sentry.io/clientdev/context/#common-context-methods
Essentially, I'm trying to do the same thing as Sentry.Plug
but setting it at the time the plug is called so that Sentry.capture_exception/2
reports will have it.
We've been using this library just fine in a phoenix app. Today I took a stab at updating some non-phoenix apps (they do not provide an HTTP interface at all, actually -- they just do backend processing) to use this library with the use_error_logger
option, and now I'm getting a compile error:
== Compilation error on file lib/sentry/plug.ex ==
** (CompileError) lib/sentry/plug.ex:66: Plug.Conn.__struct__/0 is undefined, cannot expand struct Plug.Conn
Since my app does not use plug, it is not available, and the %Plug.Conn{}
in the pattern matching fails since the struct can't be expanded.
I think this can be fixed by changing it to not pattern match using the struct syntax. You could probably do %{__struct__: Plug.Conn}
to enforce that it is a Plug.Conn
struct w/o requiring Plug.Conn
to be available at compile time.
So, I was testing my first exception using HTTPie. Even though the request clearly has a body which is raising an exception, and that exception is properly reported in Sentry, the report doesn't include the body of the request. Instead, it just shows the body as {}
.
For extra details, I using v1.1.1, Elixir v1.3.3, OTP 19, Phoenix 1.2.1.
POST [path] HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 23
Content-Type: application/json
Host: [host]
User-Agent: HTTPie/0.9.6
{
"account_uid": "blah"
}
HTTP/1.1 400 Bad Request
cache-control: max-age=0, private, must-revalidate
content-length: 45
content-type: application/json; charset=utf-8
date: Tue, 15 Nov 2016 14:49:01 GMT
server: Cowboy
{
"errors": {
"detail": "Internal server error"
}
}
In raven-ruby
you can quickly test your Sentry configuration by running a rake task.
See https://github.com/getsentry/raven-ruby/wiki/Advanced-Configuration#testing-your-configuration
$ rake raven:test[https://public:[email protected]/3825]
Client configuration:
-> server: https://app.getsentry.com
-> project_id: 3825
-> public_key: public
-> secret_key: secret
Sending a test event:
-> event ID: 033c343c852b45c2a3add98e425ea4b4
Done!
I'd like to propose we have something similar. Maybe a mix task, if appropriate. But I would love to quickly test that my configuration is working from the CLI or some equivalent interface.
The setup instructions don't include setting environment_name
(presumably because it used to default to MIX_ENV), so my app wouldn't start after following those instructions. To get it to work, I had to put my config in config/config.exs
.
Poison lib is now 3.x (https://github.com/devinus/poison).
Is it possible to unlock the dep ?
currently {:poison, "~> 1.5 or ~> 2.0"}
To help with #42
I'm not sure if it's related to the following issue but I only get 127.0.0.1 as the ip address.
getsentry/sentry#1254
Can get config at compile time and macro the API call in or do nothing
When an exception is raised in my Phoenix app, nothing is reported to sentry. here is the log output:
** (exit) an exception was raised:
2016-12-01T23:14:00.741733+00:00 app[web.1]: ** (UndefinedFunctionError) undefined function String.trim/2
2016-12-01T23:14:00.741736+00:00 app[web.1]: (elixir) String.trim("** (Phoenix.ActionClauseError) bad request to MyApp.UserController.create, no matching action clause to process request", "*")
2016-12-01T23:14:00.741737+00:00 app[web.1]: (sentry) lib/sentry/event.ex:65: Sentry.Event.transform_exception/2
2016-12-01T23:14:00.741738+00:00 app[web.1]: (sentry) lib/sentry.ex:86: Sentry.capture_exception/2
2016-12-01T23:14:00.741739+00:00 app[web.1]: (plug) lib/plug/error_handler.ex:96: Plug.ErrorHandler.__catch__/5
2016-12-01T23:14:00.741740+00:00 app[web.1]: (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.phoenix_pipeline/1
2016-12-01T23:14:00.741741+00:00 app[web.1]: (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.call/2
2016-12-01T23:14:00.741742+00:00 app[web.1]: (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
2016-12-01T23:14:00.741742+00:00 app[web.1]: (cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
Any suggestions?
UPDATE
for some reason the String
module is not defined in production when deployed to Heroku
With, for example, a payload of {"some_property": false}, the default_body_scrubber
will fail with the following stacktrace:
Request: POST /some/endpoint
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in Regex.match?/2
(elixir) lib/regex.ex:159: Regex.match?(~r/^(?:\d[ -]*?){13,16}$/, false)
(sentry) lib/sentry/plug.ex:149: anonymous fn/1 in Sentry.Plug.default_body_scrubber/1
(elixir) lib/enum.ex:1188: anonymous fn/3 in Enum.map/2
(stdlib) lists.erl:1263: :lists.foldl/3
(elixir) lib/enum.ex:1188: Enum.map/2
(sentry) lib/sentry/plug.ex:146: Sentry.Plug.default_body_scrubber/1
(sentry) lib/sentry/plug.ex:107: Sentry.Plug.build_request_interface_data/2
Reason being, Regex.match?
expects a string as the second argument, which a boolean clearly is not. Same goes for any other non-string, ex. integer
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.