Giter VIP home page Giter VIP logo

raven.cr's Introduction

Bug fixing illustration

raven.cr • the Crystal client for Sentry

Build Status Codacy Badge Releases License

An unofficial Crystal-language client and integration layer for the Sentry error reporting API.

Based on fine raven-ruby gem from folks at @getsentry.

Blog posts

Features

  • Processors (data scrubbers)
  • Interfaces (Message, Exception, Stacktrace, User, HTTP, ...)
  • Contexts (user, tags, extra, os, runtime)
  • Breadcrumbs
  • Integrations (Kemal, Amber, Lucky, Sidekiq.cr, action-controller)
  • Async support
  • User Feedback
  • Source code context for stack traces
  • Dedicated Log backend
  • Crash Handler

Installation

Add this to your application's shard.yml:

dependencies:
  raven:
    github: Sija/raven.cr

Usage

require "raven"

Raven only runs when SENTRY_DSN is set

Raven will capture and send exceptions to the Sentry server whenever its DSN is set. This makes environment-based configuration easy - if you don't want to send errors in a certain environment, just don't set the DSN in that environment!

# Set your SENTRY_DSN environment variable.
export SENTRY_DSN=https://[email protected]/project-id
# Or you can configure the client in the code (not recommended - keep your DSN secret!)
Raven.configure do |config|
  config.dsn = "https://[email protected]/project-id"
end

Raven doesn't report some kinds of data by default

If used with integrations, Raven ignores some exceptions by default - most of these are related to 404s or controller actions not being found.

Raven doesn't report POST, PUT, PATCH data or cookies by default. In addition, it will attempt to remove any obviously sensitive data, such as credit card or Social Security numbers. For more information about how Sentry processes your data, check out the documentation on the processors config setting.

Call

Raven supports two methods of capturing exceptions:

Raven.capture do
  # capture any exceptions which happen during execution of this block
  1 // 0
end

begin
  1 // 0
rescue ex : DivisionByZeroError
  Raven.capture(ex)
end

More configuration

You're all set - but there are a few more settings you may want to know about too!

DSN

While we advise that you set your Sentry DSN through the SENTRY_DSN environment variable, there are two other configuration settings for controlling Raven:

# DSN can be configured as a config setting instead.
# Place in config/initializers or similar.
Raven.configure do |config|
  config.dsn = "your_dsn"
end

And, while not necessary if using SENTRY_DSN, you can also provide an environments setting. Raven will only capture events when SENTRY_ENVIRONMENT matches an environment on the list.

Raven.configure do |config|
  config.environments = %w(staging production)
end

async

When an error or message occurs, the notification is immediately sent to Sentry. Raven can be configured to send asynchronously:

# define your own handler
config.async = ->(event : Raven::Event) {
  spawn { Raven.send_event(event) }
}
# or use default implementation based on fibers (i.e. the one above)
config.async = true

If the async callback raises an exception, Raven will attempt to send synchronously.

We recommend creating a background job, using your background job processor, that will send Sentry notifications in the background. Rather than enqueuing an entire Raven::Event object, we recommend providing the Hash representation of an event as a job argument.

Here’s an example for Sidekiq.cr:

config.async = ->(event : Raven::Event) {
  # enqueue the job with a hash...
  SentryJob.async.perform(event.to_hash)
  # or with JSON string
  # SentryJob.async.perform(event.to_json)
}

class SentryJob
  include Sidekiq::Worker

  sidekiq_options do |job|
    job.queue = "sentry"
    job.retry = true
  end

  def perform(event : Raven::Event::HashType)
    Raven.send_event(event)
  end
end

transport_failure_callback

If Raven fails to send an event to Sentry for any reason (either the Sentry server has returned a 4XX or 5XX response), this Proc will be called.

config.transport_failure_callback = ->(event : Raven::Event::HashType) {
  AdminMailer.async.perform("Oh god, it's on fire!", event)
}

Context

Much of the usefulness of Sentry comes from additional context data with the events. Raven makes this very convenient by providing methods to set context data that is then submitted automatically with all events.

There are three primary methods for providing request context:

# bind the logged in user
Raven.user_context email: "[email protected]"

# tag the request with something interesting
Raven.tags_context interesting: "yes"

# provide a bit of additional context
Raven.extra_context happiness: "very"

For more information, see Context.

Log backend

Raven::LogBackend allows for intercepting log entries, and takes following options:

  • record_breadcrumbs - records every log entry as Breadcrumbs
  • capture_exceptions - captures exceptions attached to the log entry
  • capture_all - captures every log entry

Every captured Exception or a Breadcrumb will have corresponding fields mapped directly from the original Log::Entry.

Metadata will be passed as Event#tags and Breadcrumb#data, respectively.

Usage

# append it to the existing bindings
Log.builder.bind "*", :info, Raven::LogBackend.new(
  record_breadcrumbs: true,
  capture_exceptions: false,
  capture_all: false,
)

# or bind it within the `Log.setup` block
Log.setup do |c|
  # bind the regular io-based backend
  c.bind "*", :info, Log::IOBackend.new

  # bind raven's backend
  c.bind "*", :info, Raven::LogBackend.new(record_breadcrumbs: true)
  c.bind "*", :warn, Raven::LogBackend.new(capture_exceptions: true)
  c.bind "*", :fatal, Raven::LogBackend.new(capture_all: true)
end

See more in Crystal's Log documentation.

Crash Handler

Since Crystal doesn't provide native handlers for unhandled exceptions and segfaults, raven.cr introduces its own crash handler compiled as external binary.

Setup

The easiest way of using it is by adding the appropriate entry to the project's shard.yml:

targets:
  # other target definitions if any...

  sentry.crash_handler:
    main: lib/raven/src/crash_handler.cr

With the above entry defined in targets, running shards build should result in binary built in bin/sentry.crash_handler.

NOTE: While building you might specify SENTRY_DSN env variable, which will be compiled into the binary (as plain-text) and used by the handler.

SENTRY_DSN=<your_dsn> shards build sentry.crash_handler

Pass --release flag to disable debug messages.

Usage

You need to run your app with previously built bin/sentry.crash_handler in front.

bin/sentry.crash_handler bin/your_app --some arguments --passed to your program

As one would expect, STDIN is passed to the original process, while STDOUT and STDERR are piped back from it.

NOTE: You can always pass SENTRY_DSN env variable during execution in case you didn't do it while building the wrapper.

More Information

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

  • @Sija Sijawusz Pur Rahnama - creator, maintainer

raven.cr's People

Contributors

benoist avatar caspiano avatar dependabot[bot] avatar greenbigfrog avatar mamantoha avatar sija avatar stephendolan avatar straight-shoota avatar wout 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

raven.cr's Issues

`send_event` tries to connect even if DSN not set

When no DSN is set (for example when running specs), raven should be disabled. This works for error reporting, but not for sending events:

sentry: Unable to record event with remote Sentry server (Exception - Unknown transport scheme ''): lib/raven/src/raven/client.cr:0:9 in 'transport'
lib/raven/src/raven/client.cr:61:9 in 'send_event'
lib/raven/src/raven/instance.cr:110:7 in 'send_event'
lib/raven/src/raven/instance.cr:109:5 in 'send_event'
lib/raven/src/raven.cr:10:5 in 'send_event'

I suppose Client#send_event should check for Connection#valid? (or a specific method for sending events?) and just silently exit if no DSN is configured.

Question using additional info

I'm not sure if I have this setup correctly or not. Is this the proper way to use this?

def catch_exception(error : Exception, context : HTTP::Server::Context )
  Raven.extra_context({
        headers: context.request.headers.to_h,
        params: context.request.query_params.to_h,
        path: context.request.path
  })
  Raven.capture(error)
end

No JSON data was found

I got this error when send event to sentry server.
ERROR -- sentry: Unable to record event with remote Sentry server (Raven::Transport::HTTP::Error - No JSON data was found)

I am very confused.
does anybody know why?

https

Has this been tested with https ?
My sentry server has ssl, and I'm getting the following error from the failure_callback -

ERROR -- sentry: Unable to record event with remote Sentry server (Raven::Error - Moved Permanently): 0x944245: ??? at /app/lib/raven/src/raven/transports/http.cr 64:11

I'm pretty sure this happens when traffic is redirected from http, to https? Just a guess though as I've not read the source.

Raven crashes host app

Process exited with code 139

Segmentation fault (core dumped)

Process exited with code 134

malloc(): unsorted double linked list corrupted
Aborted (core dumped)
corrupted size vs. prev_size
Aborted (core dumped)

User Feeback page broken

Exception: Closed stream (IO::Error)
  from /usr/lib/crystal/io.cr:128:5 in 'check_open'
  from /usr/lib/crystal/io/buffered.cr:130:15 in 'write'
  from /usr/lib/crystal/http/server/response.cr:80:7 in 'write'
  from /usr/lib/crystal/io.cr:481:7 in 'write_utf8'
  from /usr/lib/crystal/string.cr:4285:5 in 'to_s'
  from /usr/lib/crystal/io.cr:184:5 in '<<'
  from /usr/lib/crystal/io.cr:198:5 in 'print'
  from lib/raven/src/raven/integrations/shared/user_feedback_handler.cr:9:9 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/raven/src/raven/integrations/http/handler.cr:44:7 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/kemal/src/kemal/static_file_handler.cr:68:9 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/kemal/src/kemal/exception_handler.cr:8:7 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/kemal/src/kemal/log_handler.cr:8:37 in 'call'
  from lib/raven/src/raven/integrations/kemal/log_handler.cr:38:26 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/kemal/src/kemal/init_handler.cr:12:7 in 'call'
  from /usr/lib/crystal/http/server/request_processor.cr:48:11 in 'process'
  from /usr/lib/crystal/http/server/request_processor.cr:22:3 in 'process'
  from /usr/lib/crystal/http/server.cr:497:5 in 'handle_client'
  from /usr/lib/crystal/http/server.cr:463:13 in '->'
  from /usr/lib/crystal/fiber.cr:255:3 in 'run'
  from /usr/lib/crystal/fiber.cr:48:34 in '->'
  from ???

Unhandled exception on HTTP::Handler
Closed stream (IO::Error)
  from /usr/lib/crystal/io.cr:128:5 in 'check_open'
  from /usr/lib/crystal/io/buffered.cr:130:15 in 'write'
  from /usr/lib/crystal/http/server/response.cr:80:7 in 'write'
  from /usr/lib/crystal/io.cr:481:7 in 'write_utf8'
  from /usr/lib/crystal/string.cr:4285:5 in 'to_s'
  from /usr/lib/crystal/io.cr:184:5 in '<<'
  from /usr/lib/crystal/io.cr:198:5 in 'print'
  from lib/kemal/src/kemal/helpers/templates.cr:33:3 in 'render_500'
  from lib/kemal/src/kemal/exception_handler.cr:17:7 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/kemal/src/kemal/log_handler.cr:8:37 in 'call'
  from lib/raven/src/raven/integrations/kemal/log_handler.cr:38:26 in 'call'
  from /usr/lib/crystal/http/server/handler.cr:26:7 in 'call_next'
  from lib/kemal/src/kemal/init_handler.cr:12:7 in 'call'
  from /usr/lib/crystal/http/server/request_processor.cr:48:11 in 'process'
  from /usr/lib/crystal/http/server/request_processor.cr:22:3 in 'process'
  from /usr/lib/crystal/http/server.cr:497:5 in 'handle_client'
  from /usr/lib/crystal/http/server.cr:463:13 in '->'
  from /usr/lib/crystal/fiber.cr:255:3 in 'run'
  from /usr/lib/crystal/fiber.cr:48:34 in '->'
  from ???
require "kemal"

require "raven"
require "raven/integrations/kemal"

Kemal.config.logger = Raven::Kemal::LogHandler.new(Kemal::LogHandler.new)

Kemal.config.env = "production"

add_handler Raven::Kemal::ExceptionHandler.new
add_handler Raven::Kemal::UserFeedbackHandler.new

get "/404" do |env|
  halt env, status_code: 404
end

get "/" do
  "Hello World!"
end

Kemal.run

Kemal Example

Thanks for this module BTW, it looking good so far.

It would be good to see a kemal example. I've required this into my app, but the only exception reported are those I am explicitly sending with raven capture. I'm guessing I need to chuck Raven.capture(exception) into my 500 error handler?

Strange SSL error

I'm using Raven 1.2.0. For some reason, it is failing to record a lot of errors. I found this in the log (after this point, Raven does not even attempt to send any more errors). I am not sure how to troubleshoot further, any advice would be appreciated.

E, [2019-02-09 07:25:32 +00:00 #19883] ERROR -- sentry: Unable to record event with remote Sentry server (OpenSSL::SSL::Error - SSL_read: error:1408F119:SSL routines:ssl3_get_record:decryption failed or bad record mac): /usr/share/crystal/src/openssl/ssl/socket.cr:0:9 in 'unbuffered_read'
/usr/share/crystal/src/io/buffered.cr:228:5 in 'gets'
/usr/share/crystal/src/io/stapled.cr:0:5 in 'exec_internal_single'
/usr/share/crystal/src/http/client.cr:499:5 in 'exec'
/usr/share/crystal/src/http/client.cr:612:5 in 'send_event'
/home/app/myapp/lib/raven/src/raven/instance.cr:107:7 in 'capture'
/home/app/myapp/lib/raven/src/raven.cr:10:5 in '->'
/usr/share/crystal/src/fiber.cr:255:3 in '???'
???
E, [2019-02-09 07:25:32 +00:00 #19883] ERROR -- sentry: Failed to submit event: IO::EOFError: End of file reached

Gauging Interest in Performance Monitoring Capabilities

Hey there!

Thanks so much for this lovely library. It has saved me many production headaches thus far working with my Lucky apps, and the next horizon I'm trying to get to is some basic server-level application performance monitoring. Sentry has actually rolled out some really nifty performance stuff:

https://develop.sentry.dev/sdk/performance/

I've been digging through the code for a bit, and while it seems like they're using a relatively simple backing of the Event object, I can't seem to get any performance data sending over with some Raven.capture trickery. Is this performance tracing something that the maintainers would be willing to have included in this library?

If so, any guidance on where I should start with a pull request would be really helpful, in terms of architecting/setting it up in a way that's most in line with how the project is structured.

Issue with renaming #spawn

While trying to capture Exceptions within fibers, I've discovered that there's an issue with overriding #spawn.

Using the code at src/raven/integrations/kernel/spawn.cr in combination with the following code produces the error beneath:

require "raven"
# require "./lib/raven/src/raven/integrations/kernel/*"

def spawn(*, name : String? = nil, &block)
  # ameba:disable Style/RedundantBegin
  wrapped_block = ->{
    begin
      block.call
    rescue ex
      Raven.capture(ex, extra: {
        in_fiber:   true,
        fiber_name: name,
      })
      raise ex
    end
  }
  previous_def(name: name, &wrapped_block)
end


Raven.capture do
  spawn do
    raise "This is a test #{Time.now}"
  end
end

sleep
Module validation failed: !dbg attachment points at wrong subprogram for function
!10 = distinct !DISubprogram(name: "initialize", linkageName: "initialize", scope: !5, file: !5, line: 115, type: !6, isLocal: true, isDefinition: true, scopeLine: 115, isOptimized: false, unit: !0, variables: !2)
void (%"OpenSSL::BIO"*, %TCPSocket*)* @"*OpenSSL::BIO#initialize<TCPSocket>:Nil"
  %2 = call i8** @"~OpenSSL::BIO::CRYSTAL_BIO:read"(), !dbg !12
!12 = !DILocation(line: 14, column: 5, scope: !13)
!13 = distinct !DISubprogram(name: "set_data", linkageName: "set_data", scope: !5, file: !5, line: 13, type: !6, isLocal: true, isDefinition: true, scopeLine: 13, isOptimized: false, unit: !0, variables: !2)
!13 = distinct !DISubprogram(name: "set_data", linkageName: "set_data", scope: !5, file: !5, line: 13, type: !6, isLocal: true, isDefinition: true, scopeLine: 13, isOptimized: false, unit: !0, variables: !2)
 (Exception)
Unhandled exception: Error opening file 'crystal' with mode 'r': No such file or directory (Errno)
Failed to raise an exception: END_OF_STACK
[0x5607c1dd4e86] ???
[0x5607c1507f0b] __crystal_raise +43
[0x5607c150948c] ???
[0x5607c1519cdb] ???
[0x5607c15130fb] ???
[0x5607c15121fc] ???
[0x5607c150ed49] ???
[0x5607c1543b94] ???
[0x5607c150bb5d] main +45
[0x7f62d2dfc223] __libc_start_main +243
[0x5607c150448e] _start +46
[0x0] ???

Renaming the modified #spawn makes it work without any issues.

Not sure how this can be fixed so I thought I'd open an issue here

Improve documentation of LogBackend configuration

The readme and API docs show which options exist to configure LogBackend. But it's not clear what they mean or what the default behaviour is.

From reading the code I assume that by default LogBackend doesn't actually log anything. You need to set capture_exceptions: true to capture log entries with exceptions or capture_all: true to capture every log entry.

I presume both settings together don't really make sense? When capture_all: true the value of capture_exceptions doesn't matter. So maybe it would be better to unify those configuration values to a single option with different levels (as an enum)?
Also - if my assumption about not logging anything by default is correct, wouldn't it be more sensible to log at least exceptions if you don't configure anything? What else would be the point of hooking up a LogBackend?

Add support for User Feedback

Client-side

Using Raven.showReportDialog() from raven-js along with usual backtrace information (unless in production).

Server-side

With method possibly called Instance/Event#send_feedback taking id, name, email and comment as an arguments.

Async

Implement support for sending events in asynchronous fashion.

Issue with raven.cr and Hash/Array inheritance

Hi.

I face an issue when trying to use raven.cr with jennifer.cr.

Module validation failed: Function return type does not match operand type of return inst!
  ret %"(Array(AnyHash::JSONTypes::Value) | Bool | Float32 | Float64 | Hash(String | Symbol, AnyHash::JSONTypes::Value)+ | Int128 | Int16 | Int32 | Int64 | Int8 | JSON::Any | Set(AnyHash::JSONTypes::Value) | String | Symbol | Time | UInt128 | UInt16 | UInt32 | UInt64 | UInt8 | Nil)" %1, !dbg !21
 %"(Array(AnyHash::JSONTypes::Value) | Bool | Float32 | Float64 | Hash(String | Symbol, AnyHash::JSONTypes::Value) | Int128 | Int16 | Int32 | Int64 | Int8 | JSON::Any | Set(AnyHash::JSONTypes::Value) | String | Symbol | Time | UInt128 | UInt16 | UInt32 | UInt64 | UInt8 | Nil)" = type { i32, [3 x i64] } (Exception)
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues

I made some research, and this is the minimal code to reproduce this issue.

require "raven"

class MyHash(V) < Hash(String, V)
  # Code.
  # Actually, it doesn't matter.
end

begin
  1 / 0
rescue ex : DivisionByZeroError
  Raven.capture(ex)
end

The same with Array.

Support Log class

Log class (introduced in Crystal version 0.34.0) is a total rewrite of the old Logger class (now deprecated) - which raven has supported by means of automagically recording logged messages as breadcrumbs - see:

private def write(severity, datetime, progname, message)
record_breadcrumb(
severity,
datetime,
self.class.deansify(progname),
self.class.deansify(message),
)
previous_def
end

This integration needs to be reworked now in order to support the new Log class - preferably as a custom Log::Backend.

Some of the things to keep in mind:

  • Usage of Logger#progname needs to be changed to use Log#source instead
  • Having Raven::Logger class might prove redundant
  • Having wildcard support for excluded source names (db.*) would be nice
  • Raven::CrashHandler needs to be updated accordingly
  • Old Logger breadcrumb integration would need to stay until Logger class is finally removed from Crystal's stdlib

Refs #64

Fix remaining pending specs for Processor::SanitizeData

pending "sanitizes hashes nested in arrays" do
data = {
"empty_array" => [] of String,
"array" => [{"password" => "secret"}],
}
result = processor.process(data)
result["array"].should eq([{"password" => Raven::Processor::SanitizeData::STRING_MASK}])
end

pending "handles multiple values for a key" do
data = {
"sentry.interfaces.Http" => {
"data" => {
"query_string" => "foo=bar&foo=fubar&foo=barfoo",
},
},
}
result = processor.process(data)
result = result.to_any_json
query_string = result["sentry.interfaces.Http", "data", "query_string"].as(String).split('&')
query_string.should contain("foo=bar")
query_string.should contain("foo=fubar")
query_string.should contain("foo=barfoo")
end

Weird macro issue

require "raven"

class StringArray < Array(String)
end

Raven.capture(Exception.new("test"))

This program gives the following error message.
Using: Crystal 0.23.1 (2017-07-13) LLVM 4.0.1

lib/raven/src/raven/interface.cr:17, line 7:

   1.
   2.
   3.
   4.       ::Raven::Interface.registered[:stacktrace] = self
   5.
   6.       def initialize(**attributes)
>  7.         initialize_with(**attributes)
   8.       end
   9.
  10.       def initialize(**attributes, &block)
  11.         initialize_with(**attributes)
  12.         yield self
  13.       end
  14.

instantiating 'initialize_with(NamedTuple(message: String))'
in lib/raven/src/raven/mixins/initialize_with.cr:28: macro didn't expand to a valid program, it expanded to:

================================================================================
--------------------------------------------------------------------------------
   1.
   2.           __temp_975 = [] of Symbol
   3.
   4.
   5.
   6.
   7.
   8.             if arg = attributes[:frames]?
   9.               unless __temp_975.includes?(:frames)
  10.                 self.frames = arg
  11.                 __temp_975 << :frames
  12.               end
  13.             end
  14.
  15.             if arg = attributes[:backtrace]?
  16.               unless __temp_975.includes?(:backtrace)
  17.                 self.backtrace = arg
  18.                 __temp_975 << :backtrace
  19.               end
  20.             end
  21.
  22.
  23.
  24.
  25.
  26.
  27.
  28.             if arg = attributes[:frames]?
  29.               unless __temp_975.includes?(:frames)
  30.                 if arg.is_a?(Array(Raven::Interface::Stacktrace::Frame)+)
  31.                   @frames = arg
  32.                   __temp_975 << :frames
  33.                 end
  34.               end
  35.             end
  36.
  37.
--------------------------------------------------------------------------------
Syntax error in expanded macro: macro_4695818352:30: expecting token ')', not '+'

                if arg.is_a?(Array(Raven::Interface::Stacktrace::Frame)+)
                                                                       ^

================================================================================

        {% begin %}

Is it possible to capture values along with stack trace ?

Hello.
I have tested your plugin on one of our source code and it works perfectly by displaying stack trace. It's displayed properly in Sentry.
However, what I would like also to have values of certain objects before crash. Is it possible to have these values displayed somehow by modifing Raven maybe ? Something like inspect maybe ?

Error with the Lucky implementation

When I include raven, my Lucky app fails to compile with the following error:

Module validation failed: Function return type does not match operand type of return inst!
  ret %"(Array(AnyHash::JSONTypes::Value)+ | Bool | Float32 | Float64 | Hash(String | Symbol, AnyHash::JSONTypes::Value) | Int128 | Int16 | Int32 | Int64 | Int8 | JSON::Any | Set(AnyHash::JSONTypes::Value) | String | Symbol | Time | UInt128 | UInt16 | UInt32 | UInt64 | UInt8 | Nil)" %1, !dbg !21
 %"(Array(AnyHash::JSONTypes::Value) | Bool | Float32 | Float64 | Hash(String | Symbol, AnyHash::JSONTypes::Value) | Int128 | Int16 | Int32 | Int64 | Int8 | JSON::Any | Set(AnyHash::JSONTypes::Value) | String | Symbol | Time | UInt128 | UInt16 | UInt32 | UInt64 | UInt8 | Nil)" = type { i32, [3 x i64] } (Exception)
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues

I already reported this at the Crystal repo, but do you have an idea how to work around this? I believe it has something to do with AnyHash. You probably know better where to look.

Issue capturing Stripe errors using raven.cr

Hey @Sija,

First of all, I want to offer my thanks for all of your contributions to the ecosystem. The way you communicate in GitHub issues is always super friendly and thorough, which I know is a challenge when you've got as many repos as you do going!

I'm not 100% sure why this issue is occurring yet, and if there's not enough here for you to know either then you can say so and I'll go bang my head against the wall a bit more 😄 .

I'm using the raven.cr shard (thank you!) to track errors in my Lucky Framework app. In that app, I'm also using the stripe.cr shard for payments. stripe.cr has a custom error that's serializable, and as of Crystal 0.36.1 the compiler is complaining with the following message:

web          | In lib/any_hash/src/any_hash.cr:74:7
web          | 
web          |  74 | value.as(V)
web          |       ^
web          | Error: can't cast JSON::PullParser to AnyHash::JSONTypes::Value

Best I can tell from a build command with --error-trace, this is coming from an issue where the custom (JSON::Serializable) Stripe::Error in stripe.cr can't be parsed by raven.cr when an exception is raised.

stripe.cr extends Exception to support JSON::Serializable:

class Exception
  @[JSON::Field(ignore: true)]
  @cause : Exception?

  @[JSON::Field(ignore: true)]
  @callstack : Exception::CallStack?
end

Then defines a Stripe::Error that I think is causing the issue:

class Stripe::Error < Exception
  include JSON::Serializable

  enum Type
    ApiConnectionError
    ApiError
    AuthenticationError
    CardError
    IdempotencyError
    InvalidRequestError
    RateLimitError
  end

  @[JSON::Field(converter: Enum::StringConverter(Stripe::Error::Type))]
  property type : Stripe::Error::Type
  property charge : String?
  property code : String?
  property decline_code : String?
  property doc_url : String?
  property message : String?
  property param : String?
end

Do you have any ideas for a PR I could submit to stripe.cr that would allow its Stripe::Error to be handled by raven.cr, or do you think I'm barking up the wrong tree, and the issue doesn't lie with either stripe.cr or any_hash.cr?

Catching app crashes

Could be possible by overwriting __crystal_raise and __crystal_sigfault_handler, yet using a wrapper is far cleaner solution.

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.