Skip to content

Commit

Permalink
Merge pull request #48 from Sija/develop
Browse files Browse the repository at this point in the history
v1.3
  • Loading branch information
Sija authored Feb 19, 2019
2 parents ff32385 + 915e811 commit b34bc81
Show file tree
Hide file tree
Showing 25 changed files with 402 additions and 184 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ install:

script:
- crystal spec
- crystal tool format --check src spec
- crystal spec --no-debug
- crystal spec --release
- crystal spec --release --no-debug
- crystal tool format --check
- bin/ameba src
73 changes: 38 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
# raven.cr [![Build Status](https://travis-ci.org/Sija/raven.cr.svg?branch=master)](https://travis-ci.org/Sija/raven.cr) [![Releases](https://img.shields.io/github/release/Sija/raven.cr.svg)](https://github.com/Sija/raven.cr/releases) [![License](https://img.shields.io/github/license/Sija/raven.cr.svg)](https://github.com/Sija/raven.cr/blob/master/LICENSE) [![Join the chat at https://gitter.im/raven-cr/Lobby](https://badges.gitter.im/raven-cr/Lobby.svg)](https://gitter.im/raven-cr/Lobby)
<p align="center">
<img src="https://sija.github.io/raven.cr/img/bug-fixing.svg" height="300" alt="Bug fixing illustration" />
</p>

A client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
<h1 align="center">
raven.cr • the Crystal client for Sentry
</h1>

<p align="center">
<a href="https://travis-ci.org/Sija/raven.cr"><img src="https://travis-ci.org/Sija/raven.cr.svg?branch=master" alt="Build Status" /></a>
<a href="https://www.codacy.com/app/Sija/raven.cr"><img src="https://api.codacy.com/project/badge/Grade/32cb8814a14d4a6cbe39d6768142c59b" alt="Codacy Badge" /></a>
<a href="https://github.com/Sija/raven.cr/releases"><img src="https://img.shields.io/github/release/Sija/raven.cr.svg" alt="Releases" /></a>
<a href="https://github.com/Sija/raven.cr/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Sija/raven.cr.svg" alt="License" /></a>
<a href="https://gitter.im/raven-cr/Lobby"><img src="https://img.shields.io/gitter/room/raven-cr/Lobby.svg" alt="Gitter Chat" /></a>
</p>

An unofficial Crystal-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.

Based on fine [raven-ruby](https://github.com/getsentry/raven-ruby) gem
from folks at [@getsentry](https://github.com/getsentry).

## Status
### Blog posts

- [Crystal error tracking with Sentry](https://sija.pl/en/notes/crystal-error-tracking-with-sentry)
- [Sentry error tracking for Kemal](https://sija.pl/en/notes/sentry-error-tracking-for-kemal)

### Feature support
## Features

- [x] Processors (data scrubbers)
- [x] Interfaces (Message, Exception, Stacktrace, User, HTTP, ...)
- [x] Contexts (tags, extra, `os`, `runtime`)
- [x] Breadcrumbs
- [x] Integrations ([Kemal](https://github.com/kemalcr/kemal), [Amber](https://github.com/amberframework/amber), [Lucky](https://github.com/luckyframework/lucky), [Sidekiq.cr](https://github.com/mperham/sidekiq.cr))
- [x] Async support
- [x] User Feedback (`Raven.send_feedback` + Kemal handler)
- [x] User Feedback
- [x] Crash Handler

### TODO

- [ ] Exponential backoff in case of connection error
- [ ] Caching unsent events for later send

## Installation

Add this to your application's `shard.yml`:
Expand All @@ -45,7 +57,7 @@ Raven will capture and send exceptions to the Sentry server whenever its DSN is
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!

```bash
```sh
# Set your SENTRY_DSN environment variable.
export SENTRY_DSN=https://public@example.com/project-id
```
Expand All @@ -57,7 +69,7 @@ Raven.configure do |config|
end
```

### Raven doesn't report some kinds of data by default.
### 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.
Expand Down Expand Up @@ -86,7 +98,7 @@ end

### More configuration

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

#### DSN

Expand All @@ -103,7 +115,7 @@ end

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

```crystal
Raven.configure do |config|
Expand Down Expand Up @@ -171,8 +183,8 @@ config.transport_failure_callback = ->(event : Raven::Event::HashType) {
#### 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 thread local
context data that is then submitted automatically with all 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:

Expand All @@ -192,12 +204,12 @@ For more information, see [Context](https://docs.sentry.io/clients/ruby/context/
## Crash Handler

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

### Setup

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

```yaml
targets:
Expand All @@ -207,15 +219,14 @@ targets:
main: lib/raven/src/crash_handler.cr
```
With above entry defined in `targets`, running `shards build` should result in
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 as
*Sentry* endpoint.
compiled into the binary (as plain-text) and used by the handler.

```bash
SENTRY_DSN=<private_dsn> shards build sentry.crash_handler
```sh
SENTRY_DSN=<your_dsn> shards build sentry.crash_handler
```

Pass `--release` flag to disable debug messages.
Expand All @@ -225,7 +236,7 @@ Pass `--release` flag to disable debug messages.
You need to run your app with previously built `bin/sentry.crash_handler` in
front.

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

Expand All @@ -237,17 +248,9 @@ in case you didn't do it while building the wrapper.

## More Information

* [Documentation](https://docs.sentry.io/clients/ruby)
* [Bug Tracker](https://github.com/Sija/raven.cr/issues)
* [Code](https://github.com/Sija/raven.cr)
* [Mailing List](https://groups.google.com/group/getsentry)
* [IRC](irc://irc.freenode.net/sentry) (irc.freenode.net, #sentry)

## Development

```
crystal spec
```
- [Documentation](https://docs.sentry.io/clients/ruby)
- [Bug Tracker](https://github.com/Sija/raven.cr/issues)
- [Code Repository](https://github.com/Sija/raven.cr)

## Contributing

Expand Down
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: raven
version: 1.2.0
version: 1.3.0

authors:
- Sijawusz Pur Rahnama <sija@sija.pl>
Expand Down
188 changes: 188 additions & 0 deletions spec/raven/backtrace_line_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
require "../spec_helper"

def with_line(path = "#{__DIR__}/foo.cr", method = "foo_bar?")
line = "#{path}:1:7 in '#{method}'"
yield Raven::Backtrace::Line.parse(line)
end

describe Raven::Backtrace::Line do
describe ".parse" do
it "fails to parse an empty string" do
expect_raises(ArgumentError) { Raven::Backtrace::Line.parse("") }
end

context "when --no-debug flag is set" do
it "parses line with any value as method" do
backtrace_line = "__crystal_main"
line = Raven::Backtrace::Line.parse(backtrace_line)

line.number.should be_nil
line.column.should be_nil
line.method.should eq(backtrace_line)
line.file.should be_nil
line.relative_path.should be_nil
line.under_src_path?.should be_false
line.shard_name.should be_nil
line.in_app?.should be_false
end
end

context "with ~proc signature" do
it "parses absolute path outside of src/ dir" do
backtrace_line = "~proc2Proc(Fiber, (IO::FileDescriptor | Nil))@/usr/local/Cellar/crystal/0.27.2/src/fiber.cr:72"
line = Raven::Backtrace::Line.parse(backtrace_line)

line.number.should eq(72)
line.column.should be_nil
line.method.should eq("~proc2Proc(Fiber, (IO::FileDescriptor | Nil))")
line.file.should eq("/usr/local/Cellar/crystal/0.27.2/src/fiber.cr")
line.relative_path.should be_nil
line.under_src_path?.should be_false
line.shard_name.should be_nil
line.in_app?.should be_false
end

it "parses relative path inside of lib/ dir" do
backtrace_line = "~procProc(HTTP::Server::Context, String)@lib/kemal/src/kemal/route.cr:11"
line = Raven::Backtrace::Line.parse(backtrace_line)

line.number.should eq(11)
line.column.should be_nil
line.method.should eq("~procProc(HTTP::Server::Context, String)")
line.file.should eq("lib/kemal/src/kemal/route.cr")
line.relative_path.should eq("lib/kemal/src/kemal/route.cr")
line.under_src_path?.should be_false
line.shard_name.should eq("kemal")
line.in_app?.should be_false
end
end

it "parses absolute path outside of configuration.src_path" do
path = "/some/absolute/path/to/foo.cr"
with_line(path: path) do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq(path)
line.relative_path.should be_nil
line.under_src_path?.should be_false
line.shard_name.should be_nil
line.in_app?.should be_false
end
end

context "with in_app? = false" do
it "parses absolute path outside of src/ dir" do
with_line do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq("#{__DIR__}/foo.cr")
line.relative_path.should eq("spec/raven/foo.cr")
line.under_src_path?.should be_true
line.shard_name.should be_nil
line.in_app?.should be_false
end
end

it "parses relative path outside of src/ dir" do
path = "some/relative/path/to/foo.cr"
with_line(path: path) do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq(path)
line.relative_path.should eq(path)
line.under_src_path?.should be_false
line.shard_name.should be_nil
line.in_app?.should be_false
end
end
end

context "with in_app? = true" do
it "parses absolute path inside of src/ dir" do
src_path = File.expand_path("../../src", __DIR__)
path = "#{src_path}/foo.cr"
with_line(path: path) do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq(path)
line.relative_path.should eq("src/foo.cr")
line.under_src_path?.should be_true
line.shard_name.should be_nil
line.in_app?.should be_true
end
end

it "parses relative path inside of src/ dir" do
path = "src/foo.cr"
with_line(path: path) do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq(path)
line.relative_path.should eq(path)
line.under_src_path?.should be_false
line.shard_name.should be_nil
line.in_app?.should be_true
end
end
end

context "with shard path" do
it "parses absolute path inside of lib/ dir" do
lib_path = File.expand_path("../../lib/bar", __DIR__)
path = "#{lib_path}/src/bar.cr"
with_line(path: path) do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq(path)
line.relative_path.should eq("lib/bar/src/bar.cr")
line.under_src_path?.should be_true
line.shard_name.should eq "bar"
line.in_app?.should be_false
end
end

it "parses relative path inside of lib/ dir" do
path = "lib/bar/src/bar.cr"
with_line(path: path) do |line|
line.number.should eq(1)
line.column.should eq(7)
line.method.should eq("foo_bar?")
line.file.should eq(path)
line.relative_path.should eq(path)
line.under_src_path?.should be_false
line.shard_name.should eq "bar"
line.in_app?.should be_false
end
end
end
end

it "#inspect" do
with_line do |line|
line.inspect.should match(/Backtrace::Line(.*)$/)
end
end

it "#to_s" do
with_line do |line|
line.to_s.should eq "`foo_bar?` at #{__DIR__}/foo.cr:1:7"
end
end

it "#==" do
with_line do |line|
with_line do |line2|
line.should eq(line2)
end
with_line(method: "other_method") do |line2|
line.should_not eq(line2)
end
end
end
end
8 changes: 5 additions & 3 deletions spec/raven/backtrace_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ describe Raven::Backtrace do
backtrace.inspect.should match(/#<Backtrace: .*>$/)
end

it "#to_s" do
backtrace.to_s.should match(/backtrace_spec.cr:4/)
end
{% unless flag?(:release) || !flag?(:debug) %}
it "#to_s" do
backtrace.to_s.should match(/backtrace_spec.cr:4/)
end
{% end %}

it "#==" do
backtrace2 = Raven::Backtrace.new(backtrace.lines)
Expand Down
6 changes: 6 additions & 0 deletions spec/raven/configuration_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ def with_configuration_with_dsn
end

describe Raven::Configuration do
it "should set #src_path to current dir from default" do
with_configuration do |configuration|
configuration.src_path.should eq(Dir.current)
end
end

it "should set some attributes when dsn is set" do
with_configuration do |configuration|
configuration.dsn = "http://12345:67890@sentry.localdomain:3000/sentry/42"
Expand Down
Loading

0 comments on commit b34bc81

Please sign in to comment.