Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Bug: JRuby stacktraces with Java content can fail the reporting #47

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ language: ruby
cache: bundler
env:
- CI=true
before_install:
- gem install bundler
rvm:
- 2.0.0
- 2.1.6
- 2.2.3
- 2.3.3
- 2.4.0
- jruby-9.1.11.0
gemfile:
- gemfiles/Gemfile.rails-3.2.x
- gemfiles/Gemfile.rails-4.0.x
Expand All @@ -19,6 +22,8 @@ matrix:
include:
- rvm: 2.3.3
gemfile: gemfiles/Gemfile.rails-HEAD
- rvm: jruby-9.1.11.0
gemfile: gemfiles/Gemfile.rails-5.0.x

exclude:
- rvm: 2.0.0
Expand All @@ -33,6 +38,14 @@ matrix:
gemfile: gemfiles/Gemfile.rails-4.1.x
- rvm: 2.4.0
gemfile: gemfiles/Gemfile.rails-4.2.x
- rvm: jruby-9.1.11.0
gemfile: gemfiles/Gemfile.rails-3.2.x
- rvm: jruby-9.1.11.0
gemfile: gemfiles/Gemfile.rails-4.0.x
- rvm: jruby-9.1.11.0
gemfile: gemfiles/Gemfile.rails-4.1.x
- rvm: jruby-9.1.11.0
gemfile: gemfiles/Gemfile.rails-4.2.x

notifications:
email: false
Expand Down
9 changes: 6 additions & 3 deletions gemfiles/Gemfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ source "http://rubygems.org"

gemspec path: File.expand_path('../..', __FILE__)

ruby RUBY_VERSION

gem 'rake'
gem 'rspec'
gem 'timecop'
Expand All @@ -15,12 +17,13 @@ gem 'simplecov'

gem 'redis'
gem 'fakeredis'
gem 'sqlite3'
gem 'sqlite3', platform: :mri
gem 'sequel'

gem 'delayed_job', require: false
gem 'resque', require: false

unless RUBY_VERSION.to_i <= 1
gem 'sidekiq', require: false
# Freeze Sidekiq to < 5 in Ruby 2.2 Gemfiles
if RUBY_VERSION >= '2'
gem 'sidekiq', (RUBY_VERSION >= '2.2.2' ? '~> 5' : '~> 4'), require: false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A beautiful line of code 😆 👍🏼

Copy link
Contributor Author

@olleolleolle olleolleolle Jun 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminds us of the game "inte nudda golvet", "gulv brænder" etc.

Avoiiiiid the warnings.

end
2 changes: 1 addition & 1 deletion gemfiles/Gemfile.rails-5.0.x
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
eval_gemfile File.expand_path('../Gemfile.base', __FILE__)

gem 'rails', '~> 5.0.0'
gem 'sinatra', git: 'https://github.com/sinatra/sinatra.git'
gem 'sinatra'
26 changes: 25 additions & 1 deletion lib/opbeat/error_message/stacktrace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,19 @@ class Frame < Struct.new(:filename, :lineno, :abs_path, :function, :vars,

BACKTRACE_REGEX = /^(.+?):(\d+)(?::in `(.+?)')?$/.freeze

# regexp (optional leading X: on windows, or JRuby9000 class-prefix)
RUBY_INPUT_FORMAT = /
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
(\d+)
(?: :in \s `([^']+)')?$
/x

# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/

class << self
def from_line config, line
_, abs_path, lineno, function = line.match(BACKTRACE_REGEX).to_a
abs_path, lineno, function, _module_name = parse_line(line)
lineno = lineno.to_i
filename = strip_load_path(abs_path)

Expand All @@ -44,7 +54,21 @@ def from_line config, line

private

def parse_line(unparsed_line)
ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
if ruby_match
_, file, number, method = ruby_match.to_a
file.sub!(/\.class$/, '.rb')
module_name = nil
else
java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
_, module_name, method, file, number = java_match.to_a
end
[file, number, method, module_name]
end

def strip_load_path path
return '' unless path
prefix = $:
.map(&:to_s)
.select { |s| path.start_with?(s) }
Expand Down
1 change: 1 addition & 0 deletions opbeat.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Gem::Specification.new do |gem|
gem.summary = "The official Opbeat Ruby client library"
gem.homepage = "https://github.com/opbeat/opbeat-ruby"
gem.license = "BSD-3-Clause"
gem.required_ruby_version = ">= 2.0.0"

gem.files = `git ls-files -z`.split("\x0")
gem.require_paths = ["lib"]
Expand Down
64 changes: 42 additions & 22 deletions spec/opbeat/error_message/stacktrace_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,58 @@

module Opbeat
RSpec.describe ErrorMessage::Stacktrace do

def real_exception
1 / 0
rescue => e
e
end

def java_exception
require 'java'
java_import 'java.lang.ClassNotFoundException'
java.lang::Class.forName('foo.Bar')
rescue ClassNotFoundException => e
e
end

let(:config) { Configuration.new }
let(:exception) { real_exception }

describe ".from" do
it "initializes from an exception" do
stacktrace = ErrorMessage::Stacktrace.from config, exception
expect(stacktrace.frames).to_not be_empty

# so meta
last_frame = stacktrace.frames.last
expect(last_frame.filename).to eq "opbeat/error_message/stacktrace_spec.rb"
expect(last_frame.lineno).to be 7
expect(last_frame.abs_path).to_not be_nil
expect(last_frame.function).to eq "/"
expect(last_frame.vars).to be_nil

expect(last_frame.pre_context.last).to match(/def real_exception/)
expect(last_frame.context_line).to match(/1 \/ 0/)
expect(last_frame.post_context.first).to match(/rescue/)
describe '.from' do
context 'when on JRuby', if: RSpec::Support::Ruby.jruby? do
it 'initializes from a Java exception' do
stacktrace = ErrorMessage::Stacktrace.from config, java_exception
expect(stacktrace.frames).to_not be_empty
end

it 'initializes from an exception' do
stacktrace = ErrorMessage::Stacktrace.from config, exception
expect(stacktrace.frames).to_not be_empty
end
end

context "when context lines are off" do
context 'when on MRI', unless: RSpec::Support::Ruby.jruby? do
it 'initializes from an exception' do
stacktrace = ErrorMessage::Stacktrace.from config, exception
expect(stacktrace.frames).to_not be_empty

# so meta
last_frame = stacktrace.frames.last
expect(last_frame.filename).to eq 'opbeat/error_message/stacktrace_spec.rb'
expect(last_frame.lineno).to be 6
expect(last_frame.abs_path).to_not be_nil
expect(last_frame.function).to eq '/'
expect(last_frame.vars).to be_nil

expect(last_frame.pre_context.last).to match(/def real_exception/)
expect(last_frame.context_line).to match(/1 \/ 0/)
expect(last_frame.post_context.first).to match(/rescue/)
end
end

context 'when context lines are off' do
let(:config) { Configuration.new context_lines: nil }
it "initializes too" do
it 'initializes too' do
stacktrace = ErrorMessage::Stacktrace.from config, exception
expect(stacktrace.frames).to_not be_empty

Expand All @@ -44,13 +65,12 @@ def real_exception
end
end

describe "#to_h" do
it "is a hash" do
describe '#to_h' do
it 'is a hash' do
hsh = ErrorMessage::Stacktrace.from(config, exception).to_h
expect(hsh).to be_a Hash
expect(hsh.keys).to eq [:frames]
end
end

end
end
2 changes: 1 addition & 1 deletion spec/opbeat/injections/sequel_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require 'sequel'

module Opbeat
RSpec.describe Injections::Sequel do
RSpec.describe Injections::Sequel, unless: RSpec::Support::Ruby.jruby? do

it "is installed" do
reg = Opbeat::Injections.installed['Sequel']
Expand Down