pax_global_header00006660000000000000000000000064135761362220014521gustar00rootroot0000000000000052 comment=065cf973cb0ad3672d0d213e80b6e8a9a8e6f8cb raven-ruby-2.13.0/000077500000000000000000000000001357613622200136765ustar00rootroot00000000000000raven-ruby-2.13.0/.gitignore000066400000000000000000000001711357613622200156650ustar00rootroot00000000000000coverage pkg ruby/ log/ .bundle *.gem gemfiles/*.lock Gemfile.lock .coveralls.yml .ruby-version .ruby-gemset .idea *.rdb raven-ruby-2.13.0/.gitmodules000066400000000000000000000000001357613622200160410ustar00rootroot00000000000000raven-ruby-2.13.0/.rspec000066400000000000000000000000111357613622200150030ustar00rootroot00000000000000--colour raven-ruby-2.13.0/.rubocop.yml000066400000000000000000000023031357613622200161460ustar00rootroot00000000000000AllCops: Include: - 'lib/**/*.rb' - 'spec/**/*.rb' Exclude: - 'examples/**/*' - 'vendor/**/*' Metrics/ClassLength: Max: 300 CountComments: false Metrics/AbcSize: Max: 40 Metrics/CyclomaticComplexity: Max: 12 Metrics/PerceivedComplexity: Max: 11 Metrics/LineLength: Max: 155 Metrics/MethodLength: Max: 30 Style/SignalException: Enabled: false Performance/Casecmp: Enabled: false Style/ClassAndModuleChildren: Enabled: false Style/ParallelAssignment: Enabled: false Style/Documentation: Enabled: false Style/RescueModifier: Enabled: false Style/StringLiterals: Enabled: false Style/CaseEquality: Enabled: false Style/DoubleNegation: Enabled: false Style/FileName: Exclude: - 'lib/sentry-raven-without-integrations.rb' - 'lib/sentry-raven.rb' Style/NumericLiterals: Exclude: - 'spec/raven/processors/sanitizedata_processor_spec.rb' Style/HashSyntax: EnforcedStyle: hash_rockets Lint/RescueException: Exclude: - 'lib/raven/base.rb' - 'lib/raven/instance.rb' - 'lib/raven/integrations/delayed_job.rb' - 'lib/raven/integrations/rack.rb' - 'lib/raven/integrations/sidekiq.rb' - 'spec/raven/event_spec.rb' raven-ruby-2.13.0/.travis.yml000066400000000000000000000015601357613622200160110ustar00rootroot00000000000000language: ruby dist: trusty group: beta cache: bundler services: - redis-server branches: only: [master] rvm: - 2.2.10 - 2.3.8 - 2.4.9 - 2.5.7 - 2.6.5 env: - RAILS_VERSION=4 - RAILS_VERSION=5 - RAILS_VERSION=0 addons: apt: packages: - haveged before_install: - service haveged start # Pin bundler version due to https://github.com/rubygems/rubygems/issues/2055 - gem install bundler -v 1.16.0 matrix: include: - rvm: 1.9 env: RAILS_VERSION=4 - rvm: jruby-1.7.27 env: JRUBY_OPTS="--dev" RAILS_VERSION=4 - rvm: jruby-9.2.9.0 env: JRUBY_OPTS="--dev -J-Djruby.launch.inproc=true -J-Xmx1024M" RAILS_VERSION=4 - rvm: jruby-9.2.9.0 env: JRUBY_OPTS="--dev -J-Djruby.launch.inproc=true -J-Xmx1024M" RAILS_VERSION=5 - rvm: ruby-head env: RAILS_VERSION=0 allow_failures: - rvm: ruby-head raven-ruby-2.13.0/Gemfile000066400000000000000000000016201357613622200151700ustar00rootroot00000000000000source "https://rubygems.org/" gemspec if ENV["RAILS_VERSION"] && (ENV["RAILS_VERSION"].to_i == 4) gem "rails", "< 5" gem "rspec-rails", "> 3" elsif ENV["RAILS_VERSION"] && (ENV["RAILS_VERSION"].to_i == 0) # no-op. No Rails. else gem "rails", "< 6" gem "rspec-rails", "> 3" end if RUBY_VERSION < '2.0' gem "mime-types", "< 3.0.0" gem "nokogiri", "~> 1.6.8" gem "rack", "~> 1.6.8" gem "sidekiq", "< 3.2" gem "rack-timeout", "0.3.0" else gem "rack" gem "sidekiq" gem "rack-timeout" end gem "pry" gem "pry-coolline" gem "benchmark-ips" gem "benchmark-ipsa" if RUBY_VERSION > '2.0' gem "ruby-prof", platform: :mri gem "rake", "> 12" gem "rubocop", "~> 0.41.1" # Last version that supported 1.9, upgrade to 0.50 after we drop 1.9 gem "rspec", "> 3" gem "capybara" # rspec system tests gem "puma" # rspec system tests gem "timecop" gem "test-unit", platform: :mri if RUBY_VERSION > '2.2' raven-ruby-2.13.0/LICENSE000066400000000000000000000251371357613622200147130ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2015 Functional Software, Inc Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. raven-ruby-2.13.0/README.md000066400000000000000000000123571357613622200151650ustar00rootroot00000000000000


# Raven-Ruby, the Ruby Client for Sentry [![Gem Version](https://img.shields.io/gem/v/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven) [![Build Status](https://img.shields.io/travis/getsentry/raven-ruby/master.svg)](https://travis-ci.org/getsentry/raven-ruby) [![Gem](https://img.shields.io/gem/dt/sentry-raven.svg)](https://rubygems.org/gems/sentry-raven/) [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=sentry-raven&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=sentry-raven&package-manager=bundler&version-scheme=semver) [Documentation](https://docs.sentry.io/clients/ruby/) | [Bug Tracker](https://github.com/getsentry/raven-ruby/issues) | [Forum](https://forum.sentry.io/) | IRC: irc.freenode.net, #sentry The official Ruby-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API. ## Requirements We test on Ruby 1.9, 2.2, 2.3, and 2.4 at the latest patchlevel/teeny version. We also support JRuby 1.7 and 9.0. Our Rails integration works with Rails 4.2+ (including Rails 5). ## Getting Started ### Install ```ruby gem "sentry-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! ```bash # Set your SENTRY_DSN environment variable. export SENTRY_DSN=http://public@example.com/project-id ``` ```ruby # Or you can configure the client in the code (not recommended - keep your DSN secret!) Raven.configure do |config| config.dsn = 'http://public@example.com/project-id' end ``` ### Raven doesn't report some kinds of data by default **Raven ignores some exceptions by default** - most of these are related to 404s or controller actions not being found. [For a complete list, see the `IGNORE_DEFAULT` constant](https://github.com/getsentry/raven-ruby/blob/master/lib/raven/configuration.rb). Raven doesn't report POST 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.](https://docs.getsentry.com/hosted/clients/ruby/config/) ### Usage **If you use Rails, you're already done - no more configuration required!** Check [Integrations](https://docs.getsentry.com/hosted/clients/ruby/integrations/) for more details on other gems Sentry integrates with automatically. Otherwise, Raven supports two methods of capturing exceptions: ```ruby Raven.capture do # capture any exceptions which happen during execution of this block 1 / 0 end begin 1 / 0 rescue ZeroDivisionError => exception Raven.capture_exception(exception) end ``` ### More configuration You're all set - but there's a few more settings you may want to know about too! #### async When an error or message occurs, the notification is immediately sent to Sentry. Raven can be configured to send asynchronously: ```ruby config.async = lambda { |event| Thread.new { Raven.send_event(event) } } ``` Using a thread to send events will be adequate for truly parallel Ruby platforms such as JRuby, though the benefit on MRI/CRuby will be limited. If the async callback raises an exception, Raven will attempt to send synchronously. Note that the naive example implementation has a major drawback - it can create an infinite number of threads. We recommend creating a background job, using your background job processor, that will send Sentry notifications in the background. ```ruby config.async = lambda { |event| SentryJob.perform_later(event) } class SentryJob < ActiveJob::Base queue_as :default def perform(event) 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 or lambda will be called. ```ruby config.transport_failure_callback = lambda { |event| AdminMailer.email_admins("Oh god, it's on fire!", event).deliver_later } ``` #### 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. There are three primary methods for providing request context: ```ruby # bind the logged in user Raven.user_context email: 'foo@example.com' # 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](https://docs.sentry.io/clients/ruby/context/). ## More Information * [Documentation](https://docs.sentry.io/clients/ruby/) * [Bug Tracker](https://github.com/getsentry/raven-ruby/issues) * [Forum](https://forum.sentry.io/) - [Discord](https://discord.gg/ez5KZN7) raven-ruby-2.13.0/Rakefile000066400000000000000000000012301357613622200153370ustar00rootroot00000000000000require 'rake' require 'raven' require 'rubygems/package_task' require 'bundler/gem_tasks' gemspec = Gem::Specification.load(Dir['*.gemspec'].first) Gem::PackageTask.new(gemspec).define begin require 'rubygems' require 'rspec/core/rake_task' require 'rubocop/rake_task' RuboCop::RakeTask.new(:rubocop) do |task| task.patterns = ['lib/**/*.rb','spec/**/*.rb',] task.options << '--display-cop-names' end RSpec::Core::RakeTask.new(:spec) do |spec| spec.pattern = 'spec/**/*_spec.rb' end rescue LoadError task :spec do abort "Rspec is not available. bundle install to run unit tests" end end task :default => [:rubocop, :spec] raven-ruby-2.13.0/benchmarks/000077500000000000000000000000001357613622200160135ustar00rootroot00000000000000raven-ruby-2.13.0/benchmarks/allocation_report.rb000066400000000000000000000014201357613622200220550ustar00rootroot00000000000000require 'benchmark/ips' require 'benchmark/ipsa' require 'raven' require 'raven/breadcrumbs/logger' require 'raven/transports/dummy' require_relative "../spec/support/test_rails_app/app" TestApp.configure do |config| config.middleware.delete ActionDispatch::DebugExceptions config.middleware.delete ActionDispatch::ShowExceptions end Raven.configure do |config| config.logger = Logger.new(nil) config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42" end TestApp.initialize! @app = Rack::MockRequest.new(TestApp) RAILS_EXC = begin @app.get("/exception") rescue => exc exc end Raven.capture_exception(RAILS_EXC) # fire it once to get one-time stuff out of rpt report = MemoryProfiler.report do Raven.capture_exception(RAILS_EXC) end report.pretty_print raven-ruby-2.13.0/benchmarks/async_benchmark.rb000066400000000000000000000022511357613622200214670ustar00rootroot00000000000000require 'benchmark/ips' require 'benchmark/ipsa' require 'raven' require 'raven/breadcrumbs/logger' require 'raven/transports/dummy' require 'rack/test' require_relative "../spec/support/test_rails_app/app" def build_exception 1 / 0 rescue ZeroDivisionError => exception exception end TestApp.configure do |config| config.middleware.delete ActionDispatch::DebugExceptions config.middleware.delete ActionDispatch::ShowExceptions end Raven.configure do |config| config.logger = Logger.new(nil) config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42" config.async = ->(event) { event.to_hash } # Simulate throwing this into a Sidekiq job, etc end TestApp.initialize! @app = Rack::MockRequest.new(TestApp) RAILS_EXC = begin @app.get("/exception") rescue => exc exc end DIVIDE_BY_ZERO = build_exception LOGGER = Logger.new(nil) Benchmark.ipsa do |x| x.config(:time => 5, :warmup => 2) x.report("simple") { Raven.capture_exception(DIVIDE_BY_ZERO) } x.report("rails") { Raven.capture_exception(RAILS_EXC) } x.report("lots o logs") do 100.times { LOGGER.debug(rand(100_000).to_s) } Raven.capture_exception(DIVIDE_BY_ZERO) end x.compare! end raven-ruby-2.13.0/benchmarks/benchmark.rb000066400000000000000000000017121357613622200202730ustar00rootroot00000000000000require 'benchmark/ips' require 'benchmark/ipsa' require 'raven' require 'raven/breadcrumbs/logger' require 'raven/transports/dummy' require 'rack/test' require_relative "../spec/support/test_rails_app/app" def build_exception 1 / 0 rescue ZeroDivisionError => exception exception end TestApp.configure do |config| config.middleware.delete ActionDispatch::DebugExceptions config.middleware.delete ActionDispatch::ShowExceptions end Raven.configure do |config| config.logger = Logger.new(nil) config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42" end TestApp.initialize! @app = Rack::MockRequest.new(TestApp) RAILS_EXC = begin @app.get("/exception") rescue => exc exc end DIVIDE_BY_ZERO = build_exception LOGGER = Logger.new(nil) Benchmark.ipsa do |x| x.config(:time => 10, :warmup => 2) x.report("simple") { Raven.capture_exception(DIVIDE_BY_ZERO) } x.report("rails") { Raven.capture_exception(RAILS_EXC) } x.compare! end raven-ruby-2.13.0/benchmarks/profile.rb000066400000000000000000000015341357613622200200030ustar00rootroot00000000000000require 'raven' require 'raven/breadcrumbs/logger' require 'raven/transports/dummy' require_relative "../spec/support/test_rails_app/app" TestApp.configure do |config| config.middleware.delete ActionDispatch::DebugExceptions config.middleware.delete ActionDispatch::ShowExceptions end Raven.configure do |config| config.logger = Logger.new(nil) config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42" end TestApp.initialize! @app = Rack::MockRequest.new(TestApp) RAILS_EXC = begin @app.get("/exception") rescue => exc exc end require 'ruby-prof' RubyProf.measure_mode = RubyProf::PROCESS_TIME # profile the code result = RubyProf.profile do 100.times { Raven.capture_exception(RAILS_EXC) } end # print a graph profile to text printer = RubyProf::MultiPrinter.new(result) printer.print(:path => "./tmp", :profile => "profile") raven-ruby-2.13.0/changelog.md000066400000000000000000000517421357613622200161600ustar00rootroot000000000000002.13.0 ---- * FIX: Sanitize event data before they are sent to async job. [@edariedl, #895] * FIX: Serialization MongoDB ObjectId to JSON problem with gem delayed_job_mongoid conjunction. [@eagleas, #935] * FEAT: Skip ActiveJob integration if there is a better one [@fsateler, #909] * FIX: Bugs with send_event in asynchronous mode (#940) [@cstyles, #940] 2.12.3 ---- * FIX: crash when Process.wait is used [@asBrettisay, #895] 2.12.2 ---- * FIX: return tags/extra for [@rivayama, #931] 2.12.1 ---- * FIX: undefined method `[]' for nil:NilClass [@HazAT, #932] 2.12.0 ---- * FIX: Remove duplicate message when exception is emitted * FIX: Frozen string bug in utf8conversation * FEATURE: Allow block on tags_context and extra_context 2.11.3 ---- * FIX: infinite backoff under pressure [@Bonias, #886] 2.11.2 ---- * REF: Warn on 4xx error [@iloveitaly, #862] 2.11.1 ---- * FIX: Call `to_s` on breadcrumb message [@halkeye, #914] 2.11.0 ---- * FEATURE: Prepend the transaction around_action so libraries with controllers can alter the value. [@drcapulet, #887] 2.10.0 ----- * FEATURE: Added support for `SENTRY_ENVIRONMENT` [@mtsmfm, #910] * FEATURE: Added support for `SENTRY_RELEASE` [@coorasse, #911] 2.9.0 ----- * FEATURE: Added `config.inspect_exception_causes_for_exclusion`. Determines if the exception cause should be inspected for `config.excluded_exceptions` option. [@effron, #872] 2.8.0 ----- * FEATURE: Added `config.before_send`. Provide a lambda or proc to this config setting, which will be `call`ed before sending an event to Sentry. Receives `event` and `hint` as parameters. `hint` is a hash `{:exception => ex | nil, :message => message | nil}`. [@hazat, #882] 2.7.4 ----- * BUGFIX: Correctly handle public only DSNs [@mitsuhiko, #847] * BUGFIX: context attributes with nil raised error [@joker-777, 824] * BUGFIX: Suppress warning about enabling dyno metadata in Heroku CI [@meganemura, #833] 2.7.3 ----- * BUGFIX: Fix proxy settings for Faraday [@Strnadj, #820] * BUGFIX: Fix duplicated events in ActiveJob w/DelayedJob and Sidekiq [@BrentWheeldon, #815] 2.7.2 ----- * BUGFIX: GlobalIDs are now displayed correctly in Sidekiq contexts [@louim, #798] * BUGFIX: If git is not installed, fail silently during release detection [@nateberkopec] * BUGFIX: We do not support rack-timeout <= 0.2, fix errors when incompat version present [@nateberkopec] * BUGFIX: Put cookies in the correct spot of event [@nateberkopec, #812] * BUGFIX: Exception context is deep_merged [@janklimo, #782] 2.7.1 ----- * BUGFIX: Fixed LocalJumpError in Rails controllers [@nateberkopec w/@frodsan, #774] 2.7.0 ----- * FEATURE: Add random sampling. [@nateberkopec, #734] * FEATURE: Transactions. See Context docs for usage. [@nateberkopec, #743] * FEATURE: You can set the current environment for Sentry via `SENTRY_CURRENT_ENV` env variable. Useful if your staging environment's RACK_ENV is "production", for example. [@tijmenb, #736] * BUGFIX: Fix wrapped classnames in old versions of Sidekiq and ActiveJob [@nateberkopec, #702] * BUGFIX: Server names on Heroku were pretty useless before - now they follow the dyno name ("worker.1", "web.2") [@nateberkopec, #703] * BUGFIX: ActiveJob::DeserializationError is now ignored by default. Not doing so can cause infinite loops if you are using an ActiveJob async callback. [@nateberkopec, #701] * BUGFIX: Binary conversion to UTF-8 when binary is frozen is fixed [@nateberkopec, #757] * BUGFIX: Our credit-card regex now matches Sentry's server behavior, which means it does not censor milliseconds since the epoch [@nateberkopec, #771] * REFACTOR: We now use an updated port of Rails' deep_merge which should be 5-10% faster [@nateberkopec, #770] * REFACTOR: Tests have been cleaned up, and now run in random order. [@nateberkopec] * REFACTOR: Raven::Event has been refactored a bit [@nateberkopec] 2.6.3 ----- * BUGFIX: Fixed typo in the Heroku warning [@greysteil, #728] * BUGFIX: Swallow IOErrors when reading the Rack request body [@nateberkopec] * BUGFIX: Fix invalid UTF-8/circular references when using async [@nateberkopec, #730] 2.6.2 ----- * BUGFIX: If using the Sidekiq or DelayedJob adapters with ActiveJob, ActiveJob wouldn't re-raise upon capturing an exception. [@nateberkopec, 5b02ad4ff2] * KNOWN ISSUE: When using `async`, Rack integration is not thread-safe [#721] * KNOWN ISSUE: When using `async`, encoding errors may be raised [#725] 2.6.1 ----- * BUGFIX: Fix cases where ActionDispatch::RemoteIP would blow up during event creation [@cmoylan, #722] * BUGFIX: In ActiveJob, don't report exceptions which can be rescued by rescue_from handlers [@bensheldon, #719] 2.6.0 ----- * FEATURE: raven-ruby now marks itself as the "ruby" logger by default, to match raven-js behavior [@nateberkopec] * FEATURE: You may now override the default sanitization parameters [#712, @nateberkopec] * FEATURE: Breadcrumb buffers are now publicly accessible [#686, @nateberkopec] * FEATURE: We yell at you now if you're using Heroku but don't have runtime-dyno-metadata enabled [#715, @nateberkopec] * FEATURE: project_root will always be set, regardless of framework [#716, @nateberkopec] * BUGFIX: Request body and message limits now match Sentry server defaults [#714, @nateberkopec] * BUGFIX: Sidekiq context now works as expected [#713, @nateberkopec] * BUGFIX: Capture exceptions in ActiveJob when not using Sidekiq adapter [#709, #671, @nateberkopec] 2.5.3 ----- * BUGFIX: Deal properly with ASCII_8BIT/BINARY encodings [#689, #696, @nateberkopec] 2.5.2 ----- * BUGFIX: raven test executable should be available [#691, @nateberkopec] * BUGFIX: Fix stack overflow when calling Backtrace#inspect [#690, @nateberkopec] * KNOWN ISSUE: Character encoding errors [#689] 2.5.1 ----- * BUGFIX: Fix case where Pathname objects are on the load path [@nateberkopec] * BUGFIX: Fix bad UTF-8 characters in the URL querystring [@nateberkopec] * BUGFIX: Fix case where rack-timeout could be required twice [@nateberkopec] * REFACTOR: Slightly cleaner character encoding fixing [@nateberkopec, @bf4] 2.5.0 ----- * FEATURE: Greatly improved performance (2-3x faster capture) [@nateberkopec] * FEATURE: Frozen objects are now sanitized [@nateberkopec] * BUGFIX: Grabbing Sidekiq context from "wrapped" classes works [@nateberkopec] * BUGFIX: Relaxed Faraday dependency [@nateberkopec] 2.4.0 ----- * FEATURE: Allow customization of the Faraday adapter [#639, @StupidCodeFactory] * BUGFIX: Report the SDK name as "raven-ruby", not "sentry-raven" [#641, @bretthoerner] * BUGFIX: Sidekiq jobs now clear context/breadcrumbs properly between jobs [#637, @drewish] * BUGFIX: Overriding the logger in Rails wasn't working [#638, @eugeneius] 2.3.1 ----- * BUGFIX: Backtrace parser fixed for JRuby 9k [#619, @the-michael-toy] * BUGFIX: Rake tasks should show the correct task name [#621, @Bugagazavr] * BUGFIX: Formatted messages work if params are `nil` [#625, @miyachik] * BUGFIX: Backtrace logger on failed event send works with custom formatters [#627, @chulkilee] * BUGFIX: Fix typo that caused Version headers to not be corrected [#628, @nateberkopec] * BUGFIX: Faraday errors are more descriptive when no server response [#629, @drewish] * BUGFIX: DelayedJob handler no longer truncates unneccessarily short [#633, @darrennix] * BUGFIX: Fix several processors not working correctly w/async jobs stored in backends like Redis [#634, @nateberkopec] 2.3.0 ----- * CHANGE: Log levels of some messages have been changed. Raven logger is INFO level by default. [@nateberkopec] * BUGFIX: Exception messages are now limited to 10,000 bytes. [#617, @mattrobenolt] 2.2.0 ----- * ENHANCEMENT: Sentry server errors now return some information about the response headers. [#585, @rafadc] * BUGFIX/ENHANCEMENT: Frozen objects are no longer sanitized. This prevents some bugs, but you can now also freeze objects if you don't want them to be sanitized by the SanitizeData processor. [#594, @nateberkopec] * ENHANCEMENT: The ability to use Raven::Instance alone is greatly improved. You can now call #capture_exception directly on an Instance (#595), give it it's own Logger (#599), and set it's own config which will be used when creating Events (#601). Thanks to * ENHANCEMENT: You may now provide your own LineCache-like class to Raven. This is useful if you have source code which is not available on disk. [#606, @nateberkopec] * BUGFIX: Raven no longer emits anything to STDOUT if a system command fails [#596, @nateberkopec] * ENHANCEMENT: Raven now tells you exactly why it will not send an event in the logs [#602, @nateberkopec] 2.1.4 ----- * FIX: Remove `contexts` key, because it was disabling browser auto-tagging [#587, @nateberkopec] 2.1.3 ----- * Move `os` context key to `server_os` [@nateberkopec] 2.1.2 ----- * FIX: `sys_command` not falling back to Windows commands properly, logging output [@jmalves, @nateberkopec] 2.1.1 ----- * FIX: Message params should accept nil [@jmalves, #570] 2.1.0 ----- ENHANCEMENTS: * Your client version is now included in all Events. [@nateberkopec, #559] * OS and Ruby runtime information now included in all Events. [@nateberkopec, #560] * Transport errors (like Sentry 4XX errors) now raise Sentry::Error, not Faraday errors. [@nateberkopec, #565] * Sidekiq integration is streamlined and improved. Supports Sidekiq 3.x and up. [@nateberkopec, #555] FIXES: * Heroku release detection is improved and more accurate. You must `heroku labs:enable runtime-dyno-metadata` for it to work. [@nateberkopec, #566] 2.0.2 ----- * FIX: Don't set up Rack-Timeout middleware. [@janraasch, #558] 2.0.1 ----- * FIX: UUIDs were being rejected by Sentry as being too long [@nateberkopec] 2.0.0 ----- BREAKING CHANGES: * The object passed to the `async` callback is now a JSON-compatible hash, not a Raven::Event. This fixes many bugs with backend job processors like DelayedJob. [@nateberkopec, #547] * Several deprecated accessors have been removed [@nateberkopec, #543] * You can no longer pass an object which cannot be called to `should_capture` [@nateberkopec, #542] ENHANCEMENTS: * Rack::Timeout exceptions are now fingerprinted by URL, making them more useful [@nateberkopec, #538] * Added an HTTP header processor by default. We now scrub `Authorization` headers correctly. You can use `config.sanitize_http_headers` to add a list of HTTP headers you don't want sent to Sentry (e.g. ["Via", "Referer", "User-Agent", "Server", "From"]) [@nateberkopec] FIXES: * User/Event IP addresses are now set more accurately. This will fix many issues with local proxy setups (nginx, etc). [@nateberkopec, #546] * We now generate a real UUID in the correct format for Event IDs [@nateberkopec, #549] * If `async` sending fails, we retry with sync sending. [@nateberkopec, #548] * Changed truncation approach - event messages and HTTP bodies now limited to the same amount of characters they're limited to at the Sentry server [@nateberkopec, #536] OTHER: * Codebase cleaned up with Rubocop [@nateberkopec, #544] 1.2.3 ----- * ENHANCEMENT: Send the current environment to Sentry [@dcramer, #530] * BUGFIX: Fix all warnings emitted by Ruby verbose mode [@nateberkopec] * BUGFIX: Fix compat with `log4r` [@nateberkopec, #535] 1.2.2 ----- * BUGFIX: NameError in DelayedJob integration. [janraasch, #525] 1.2.1 ----- * BUGFIX: Context clearing should now work properly in DelayedJob and Sidekiq. Also, we properly clear context if Sentry causes an exception. [nateberkopec, #520] * BUGFIX: If Sentry will not send the event (due to environments or no DSN set), it will not attempt to "capture" (construct an event) [nateberkopec, #518] 1.2.0 ----- * FEATURE: Raven now supports Breadcrumbs, though they aren't on by default. Check the docs for how to enable. [dcramer, #497] * FEATURE: Raven is no longer a singleton, you may have many `Raven::Instance`s. [phillbaker, #504] * PERFORMANCE: Raven no longer uses a vendored JSON implementation. JSON processing and encoding should be up to 6x faster. [dcramer, #510] * BUGFIX: silence_ready now works for Rails apps. [ream88, #512] * BUGFIX: transport_failure_callback now works correctly [nateberkopec, #508] 1.1.0 ----- * The client exposes a ``last_event_id`` accessor at `Raven.last_event_id`. [dcramer, #493] * PERFORMANCE: Skip identical backtraces from "re-raised" exceptions [databus23, #499] * Support for ActionController::Live and Rails template streaming [nateberkopec, #486] 1.0.0 ----- We (i.e. @nateberkopec) decided that `raven-ruby` has been stable enough for some time that it's time for a 1.0.0 release! BREAKING CHANGES: - Dropped support for Ruby 1.8.7 [nateberkopec, #465] - `raven-ruby` no longer reports form POST data or web cookies by default. To re-enable this behavior, remove the appropriate Processors from your config (see docs or PR) [nateberkopec, #466] - UDP transport has been removed [dcramer, #472] OTHER CHANGES: - Improved performance [zanker] - Deprecated `config.catch_debugged_exceptions`, replaced with `config.rails_report_rescued_exceptions`. `catch_debugged_exceptions` will be removed in 1.1. [nateberkopec, #483] - Added `config.transport_failure_callback`. Provide a lambda or proc to this config setting, which will be `call`ed when Sentry returns a 4xx/5xx response. [nateberkopec, #484] - JRuby builds fixed [RobinDaugherty] - Fix problems with duplicate exceptions and `Exception.cause` [dcramer, #490] - Added Exception Context. Any Exception class can define a `raven_context` instance variable, which will be merged into any Event's context which contains this exception. [nateberkopec, #491] + Documentation from shaneog, squirly, dcramer, ehfeng, nateberkopec. 0.15.6 ------ - Fixed bug where return value of debug middleware was nil [eugeneius, #461] - Fixed a bug in checking `catch_debugged_exceptions` [greysteil, #458] - Fixed a deprecation warning for Rails 5 [Elektron1c97, #457] 0.15.5 ------ - DelayedJob integration fixed when last_error not present [dcramer, #454] - Release detection doesn't overwrite manual release setting in Rails [eugeneius, #450] - Deal properly with Cap 3.0/3.1 revision logs [timcheadle, #449] - Rails 5 support [nateberkopec, #423] 0.15.4 ------ - DelayedJob integration now also truncates last_error to 100 characters [nateberkopec] - Fix several issues with release detection - silence git log message, fix Capistrano detection [nateberkopec, kkumler] 0.15.3 ------ - Double exception reporting in Rails FIXED! [nateberkopec, #422] - Rails 3 users having issues with undefined runner fixed [nateberkopec, #428] - Sidekiq integration works properly when ActiveJob enabled [mattrobenolt] - Fix problems with invalid UTF-8 in exception messages [nateberkopec, #426] - Backtraces now consider "exe" directories part of the app [nateberkopec, #420] - Sinatra::NotFound now ignored by default [drcapulet, #383] - Release versions now properly set. Support for Heroku, Capistrano, and Git. [iloveitaly #377, Sija #380] - DelayedJob integration plays well with ActiveJob [kkumler, #378] - DelayedJob handlers now truncated [nateberkopec, #431] - Tons of code quality improvements [amatsuda, ddrmanxbxfr, pmbrent, cpizzaia, wdhorton, PepperTeasdale] 0.15.2 ------ - Reverted ActiveJob support due to conflicts [#368] 0.15.1 ------ - Fix ActiveJob support [greysteil, #367] 0.15.0 ------ - Remove Certifi and use default Ruby SSL config [zanker, #352] - Support for ``fingerprint`` [dcramer] - Improved documentation and tests around various attributes [dcramer] - Allow configurable integrations [cthornton] - Prevent recursion with ``Exception.cause`` [dcramer, #357] - Use empty hash if false-y value [GeekOnCoffee, #354] - Correct some behavior with at_exit error capturing [kratob, #355] - Sanitize matches whole words [alyssa, #361] - Expose more debugging info to active_job integration [tonywok, #365] - Capture exceptions swallowed by rails [robertclancy, #343] - Sanitize the query string when the key is a symbol [jason-o-matic, #349] - Moved documentation to docs.getsentry.com [mitsuhiko] 0.14.0 ------ - Correct handling of JRuby stacktraces [dcramer] - Better handling of unreachable file contexts [dcramer, #335] - SSL is now default ON [dcramer, #338] - Capture exceptions in runner tasks [eugeneius, #339] - ActiveJob integration [lucasmazza, #327] - Cleanup return values of async blocks [lucasmazza, #344] - Better handling when sending NaN/Infinity JSON values [Alric, #345] - Fix issues with digest/md5 namespace [lsb, #346] 0.13.3 ------ - Fix a deprecation warning being shown in regular operation [ripta, #332] 0.13.2 ------ - DelayedJob integration now includes the job id [javawizard, #321] - Rails integration now works properly when you're not using all parts of Rails (e.g. just ActiveRecord) [lucasmazza, #323] - Bugfix CLI tool when async config is on [if1live, #324] - Fix and standardize tag hierarchies. Event tags > context tags > configuration tags in all cases. [JonathanBatten, #322 and eugeneius, #330] - Using #send on Client, Base, and Transports is now deprecated. See [the commit](https://github.com/getsentry/raven-ruby/commit/9f482022a648ab662c22177ba24fd2e2b6794c34) (or the deprecation message) for their replacements. [nateberkopec, #326] - You can now disable credit-card-like value filtering. [codekitchen, #329] 0.13.1 ------ - Raven::Transports::HTTP#send returns the response now. [eagletmt, #317] - Filenames now work a lot better when you vendor your gems. [eugeneius, #316] - Fix raven:test issue when testing non-async configurations. [weynsee, #318] - Fix blockless Raven#capture. [dinosaurjr, #320] - Fix some log messages [eagletmt, #319] 0.13.0 ------ - Support exception chaining [javawizard, #312] - Add support for sending release version [eugeneius, #310] - Better status reports on configuration [faber, #309] - Client "send" method accepts an event in object or hash format - this will make it much easier to send Sentry events in a delayed job! [marclennox, #300] - Fix duplicate fields in SanitizeData [wyattisimo, #294] - Always preserve filename paths under project_root [eugeneius, #291] - Truncate project root prefixes from filenames [eagletmt, #278] - Renamed should_send callback to should_capture [nateberkopec, #270] - Silencing the ready message now happens in the config as normal [nateberkopec, #260] - Various internal refactorings [see here](https://github.com/getsentry/raven-ruby/compare/0-12-stable...master) 0.12.3 ------ - URL query parameters are now sanitized for sensitive data [pcorliss, #275] - Raven::Client can now use a proxy server when sending events to Sentry [dcramer, #277] - Raven::Client will now use a timed backoff strategy if the server fails [codekitchen, #267] - Automatic integration loading is now a lot less brittle [dcramer, handlers, #263, #264] - Fixed some issues with prefixes and DSN strings [nateberkopec, #259] - If Raven is initialized without a server config, it will no longer send events [nateberkopec, #258] - Slightly nicer credit-card-like number scrubbing [nateberkopec, #254] - Fix some exceptions not being caught by Sidekiq middleware [nateberkopec, #251] - Uncommon types are now encoded correctly [nateberkopec, #249] 0.12.2 ------ - Security fix where exponential numbers in specially crafted params could cause a CPU attack [dcramer, #262] 0.12.1 ------ - Integrations (Sidekiq, DelayedJob, etc) now load independently of your Gemfile order. [nateberkopec, #236] - Fixed bug where setting tags mutated your configuration [berg, #239] - Fixed several issues with SanitizeData and UTF8 sanitization processors [nateberkopec, #238, #241, #244] 0.12.0 ------ - You can now give additional fields to the SanitizeData processor. Values matched are replaced by the string mask (*********). Full documentation (and how to use with Rails config.filter_parameters) [here](https://docs.getsentry.com/hosted/clients/ruby/config/). [jamescway, #232] - An additional processor has been added, though it isn't turned on by default: RemoveStacktrace. Use it to remove stacktraces from exception reports. [nateberkopec, #233] - Dependency on `uuidtools` has been removed. [nateberkopec, #231] 0.11.2 ------ - Fix some issues with the SanitizeData processor when processing strings that look like JSON 0.11.1 ------ - Raven now captures exceptions in Rake tasks automatically. [nateberkopec, troelskn #222] - There is now a configuration option called ```should_send``` that can be configured to use a Proc to determine whether or not an event should be sent to Sentry. This can be used to implement rate limiters, etc. [nateberkopec, #221] - Raven now includes three event processors by default instead of one, which can be turned on and off independently. [nateberkopec, #223] - Fixed bug with YAJL compatibility. [nateberkopec, #223] 0.10.1 ------ - Updated to RSpec 3. - Apply filters to encoded JSON data. 0.10.0 ------ - Events are now sent to Sentry in all environments. To change this behavior, either unset ```SENTRY_DSN``` or explicitly configure it via ```Raven.configure```. - gzip is now the default encoding - Removed hashie dependency 0.9.0 ----- - Native support for Delayed::Job [pkuczynski, #176] - Updated to Sentry protocol version 5 0.5.0 ----- - Rails 2 support [sluukonen, #45] - Controller methods in Rails [jfirebaugh] - Runs by default in any environment other than test, cucumber, or development. [#81] raven-ruby-2.13.0/examples/000077500000000000000000000000001357613622200155145ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/000077500000000000000000000000001357613622200171275ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/.gitignore000066400000000000000000000007321357613622200211210ustar00rootroot00000000000000# See https://help.github.com/articles/ignoring-files for more about ignoring files. # # If you find yourself ignoring temporary files generated by your text editor # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile '~/.gitignore_global' # Ignore bundler config. /.bundle # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal # Ignore all logfiles and tempfiles. /log/* !/log/.keep /tmp raven-ruby-2.13.0/examples/rails-4.2/Gemfile000066400000000000000000000030061357613622200204210ustar00rootroot00000000000000source 'https://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '4.2.5.1' # Use sqlite3 as the database for Active Record gem 'sqlite3' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.1.0' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks gem 'turbolinks' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.0' # bundle exec rake doc:rails generates the API under doc/api. gem 'sdoc', '~> 0.4.0', group: :doc gem 'sentry-raven', :path => "../../" # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Unicorn as the app server # gem 'unicorn' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' end group :development do # Access an IRB console on exception pages or by using <%= console %> in views gem 'web-console', '~> 2.0' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' end raven-ruby-2.13.0/examples/rails-4.2/README.rdoc000066400000000000000000000007361357613622200207430ustar00rootroot00000000000000== README This README would normally document whatever steps are necessary to get the application up and running. Things you may want to cover: * Ruby version * System dependencies * Configuration * Database creation * Database initialization * How to run the test suite * Services (job queues, cache servers, search engines, etc.) * Deployment instructions * ... Please feel free to use a different markup language if you do not plan to run rake doc:app. raven-ruby-2.13.0/examples/rails-4.2/Rakefile000066400000000000000000000003711357613622200205750ustar00rootroot00000000000000# Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require File.expand_path('../config/application', __FILE__) Rails.application.load_tasks raven-ruby-2.13.0/examples/rails-4.2/app/000077500000000000000000000000001357613622200177075ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/assets/000077500000000000000000000000001357613622200212115ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/assets/images/000077500000000000000000000000001357613622200224565ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/assets/images/.keep000066400000000000000000000000001357613622200233710ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/assets/javascripts/000077500000000000000000000000001357613622200235425ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/assets/javascripts/application.js000066400000000000000000000012251357613622200264030ustar00rootroot00000000000000// This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require jquery //= require jquery_ujs //= require turbolinks //= require_tree . raven-ruby-2.13.0/examples/rails-4.2/app/assets/javascripts/welcome.coffee000066400000000000000000000003231357613622200263440ustar00rootroot00000000000000# Place all the behaviors and hooks related to the matching controller here. # All this logic will automatically be available in application.js. # You can use CoffeeScript in this file: http://coffeescript.org/ raven-ruby-2.13.0/examples/rails-4.2/app/assets/stylesheets/000077500000000000000000000000001357613622200235655ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/assets/stylesheets/application.css000066400000000000000000000012561357613622200266060ustar00rootroot00000000000000/* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any styles * defined in the other CSS/SCSS files in this directory. It is generally better to create a new * file per style scope. * *= require_tree . *= require_self */ raven-ruby-2.13.0/examples/rails-4.2/app/assets/stylesheets/welcome.scss000066400000000000000000000002621357613622200261150ustar00rootroot00000000000000// Place all the styles related to the welcome controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ raven-ruby-2.13.0/examples/rails-4.2/app/controllers/000077500000000000000000000000001357613622200222555ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/controllers/application_controller.rb000066400000000000000000000006251357613622200273530ustar00rootroot00000000000000class ApplicationController < ActionController::Base before_action :set_raven_context # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception private def set_raven_context # Raven.user_context(email: 'david@getsentry.com') # Raven.extra_context(params: params.to_hash, url: request.url) end end raven-ruby-2.13.0/examples/rails-4.2/app/controllers/concerns/000077500000000000000000000000001357613622200240675ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/controllers/concerns/.keep000066400000000000000000000000001357613622200250020ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/controllers/errors_controller.rb000066400000000000000000000002331357613622200263570ustar00rootroot00000000000000class ErrorsController < ApplicationController def internal_server_error @sentry_event_id = Raven.last_event_id render(:status => 500) end end raven-ruby-2.13.0/examples/rails-4.2/app/controllers/welcome_controller.rb000066400000000000000000000001671357613622200265040ustar00rootroot00000000000000class WelcomeController < ApplicationController def index Rails.logger.info("zomg division") 1 / 0 end end raven-ruby-2.13.0/examples/rails-4.2/app/helpers/000077500000000000000000000000001357613622200213515ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/helpers/application_helper.rb000066400000000000000000000000351357613622200255360ustar00rootroot00000000000000module ApplicationHelper end raven-ruby-2.13.0/examples/rails-4.2/app/helpers/welcome_helper.rb000066400000000000000000000000311357613622200246620ustar00rootroot00000000000000module WelcomeHelper end raven-ruby-2.13.0/examples/rails-4.2/app/mailers/000077500000000000000000000000001357613622200213435ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/mailers/.keep000066400000000000000000000000001357613622200222560ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/models/000077500000000000000000000000001357613622200211725ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/models/.keep000066400000000000000000000000001357613622200221050ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/models/concerns/000077500000000000000000000000001357613622200230045ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/models/concerns/.keep000066400000000000000000000000001357613622200237170ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/views/000077500000000000000000000000001357613622200210445ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/views/errors/000077500000000000000000000000001357613622200223605ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/views/errors/internal_server_error.html.erb000066400000000000000000000005741357613622200304360ustar00rootroot00000000000000 Internal Server Error

Internal Server Error

='(

<% if @sentry_event_id %> <% end %> raven-ruby-2.13.0/examples/rails-4.2/app/views/layouts/000077500000000000000000000000001357613622200225445ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/views/layouts/application.html.erb000066400000000000000000000010751357613622200265070ustar00rootroot00000000000000 Rails42 <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> <%= yield %> raven-ruby-2.13.0/examples/rails-4.2/app/views/welcome/000077500000000000000000000000001357613622200224775ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/app/views/welcome/index.html.erb000066400000000000000000000001121357613622200252350ustar00rootroot00000000000000

Welcome#index

Find me in app/views/welcome/index.html.erb

raven-ruby-2.13.0/examples/rails-4.2/bin/000077500000000000000000000000001357613622200176775ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/bin/bundle000077500000000000000000000002011357613622200210670ustar00rootroot00000000000000#!/usr/bin/env ruby ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) load Gem.bin_path('bundler', 'bundle') raven-ruby-2.13.0/examples/rails-4.2/bin/rails000077500000000000000000000004141357613622200207360ustar00rootroot00000000000000#!/usr/bin/env ruby begin load File.expand_path('../spring', __FILE__) rescue LoadError => e raise unless e.message.include?('spring') end APP_PATH = File.expand_path('../../config/application', __FILE__) require_relative '../config/boot' require 'rails/commands' raven-ruby-2.13.0/examples/rails-4.2/bin/rake000077500000000000000000000003251357613622200205470ustar00rootroot00000000000000#!/usr/bin/env ruby begin load File.expand_path('../spring', __FILE__) rescue LoadError => e raise unless e.message.include?('spring') end require_relative '../config/boot' require 'rake' Rake.application.run raven-ruby-2.13.0/examples/rails-4.2/bin/setup000077500000000000000000000014451357613622200207710ustar00rootroot00000000000000#!/usr/bin/env ruby require 'pathname' # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) Dir.chdir APP_ROOT do # This script is a starting point to setup your application. # Add necessary setup steps to this file: puts "== Installing dependencies ==" system "gem install bundler --conservative" system "bundle check || bundle install" # puts "\n== Copying sample files ==" # unless File.exist?("config/database.yml") # system "cp config/database.yml.sample config/database.yml" # end puts "\n== Preparing database ==" system "bin/rake db:setup" puts "\n== Removing old logs and tempfiles ==" system "rm -f log/*" system "rm -rf tmp/cache" puts "\n== Restarting application server ==" system "touch tmp/restart.txt" end raven-ruby-2.13.0/examples/rails-4.2/bin/spring000077500000000000000000000007501357613622200211310ustar00rootroot00000000000000#!/usr/bin/env ruby # This file loads spring without using Bundler, in order to be fast. # It gets overwritten when you run the `spring binstub` command. unless defined?(Spring) require 'rubygems' require 'bundler' if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) } gem 'spring', match[1] require 'spring/binstub' end end raven-ruby-2.13.0/examples/rails-4.2/config.ru000066400000000000000000000002311357613622200207400ustar00rootroot00000000000000# This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) run Rails.application raven-ruby-2.13.0/examples/rails-4.2/config/000077500000000000000000000000001357613622200203745ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/config/application.rb000066400000000000000000000032371357613622200232310ustar00rootroot00000000000000require File.expand_path('../boot', __FILE__) require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Rails42 class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. # config.time_zone = 'Central Time (US & Canada)' # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de # Do not swallow errors in after_commit/after_rollback callbacks. config.active_record.raise_in_transactional_callbacks = true config.consider_all_requests_local = false # https://github.com/getsentry/raven-ruby/issues/494 config.exceptions_app = self.routes # With this enabled 'exceptions_app' isnt executed, so instead we # set ``config.consider_all_requests_local = false`` in development. # config.action_dispatch.show_exceptions = false # Inject Sentry logger breadcrumbs require 'raven/breadcrumbs/logger' Raven.configure do |config| config.dsn = 'https://6bca098db7ef423ab983e26e27255fe8:650b2fcf94f942fe9093f656b809a94e@app.getsentry.com/3825' end end end raven-ruby-2.13.0/examples/rails-4.2/config/boot.rb000066400000000000000000000002041357613622200216600ustar00rootroot00000000000000ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) require 'bundler/setup' # Set up gems listed in the Gemfile. raven-ruby-2.13.0/examples/rails-4.2/config/database.yml000066400000000000000000000010501357613622200226570ustar00rootroot00000000000000# SQLite version 3.x # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: sqlite3 pool: 5 timeout: 5000 development: <<: *default database: db/development.sqlite3 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: db/test.sqlite3 production: <<: *default database: db/production.sqlite3 raven-ruby-2.13.0/examples/rails-4.2/config/environment.rb000066400000000000000000000002261357613622200232650ustar00rootroot00000000000000# Load the Rails application. require File.expand_path('../application', __FILE__) # Initialize the Rails application. Rails.application.initialize! raven-ruby-2.13.0/examples/rails-4.2/config/environments/000077500000000000000000000000001357613622200231235ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/config/environments/development.rb000066400000000000000000000027351357613622200260010ustar00rootroot00000000000000Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false # Do not eager load code on boot. config.eager_load = false config.action_controller.perform_caching = false # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. config.assets.debug = true # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. config.assets.digest = true # Adds additional error checking when serving assets at runtime. # Checks for improperly declared sprockets dependencies. # Raises helpful error messages. config.assets.raise_runtime_errors = true # Raises error for missing translations # config.action_view.raise_on_missing_translations = true end raven-ruby-2.13.0/examples/rails-4.2/config/environments/production.rb000066400000000000000000000063501357613622200256420ustar00rootroot00000000000000Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. config.cache_classes = true # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers # and those relying on copy on write to perform better. # Rake tasks automatically ignore this option for performance. config.eager_load = true # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true # Enable Rack::Cache to put a simple HTTP cache in front of your application # Add `rack-cache` to your Gemfile before enabling this. # For large-scale production use, consider using a caching reverse proxy like # NGINX, varnish or squid. # config.action_dispatch.rack_cache = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. config.assets.digest = true # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true # Use the lowest log level to ensure availability of diagnostic information # when problems arise. config.log_level = :debug # Prepend all log lines with the following tags. # config.log_tags = [ :subdomain, :uuid ] # Use a different logger for distributed setups. # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) # Use a different cache store in production. # config.cache_store = :mem_cache_store # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false end raven-ruby-2.13.0/examples/rails-4.2/config/environments/test.rb000066400000000000000000000033331357613622200244310ustar00rootroot00000000000000Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that # preloads Rails for running tests, you may have to set it to true. config.eager_load = false # Configure static file server for tests with Cache-Control for performance. config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test # Randomize the order test cases are executed. config.active_support.test_order = :random # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr # Raises error for missing translations # config.action_view.raise_on_missing_translations = true end raven-ruby-2.13.0/examples/rails-4.2/config/initializers/000077500000000000000000000000001357613622200231025ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/config/initializers/assets.rb000066400000000000000000000007461357613622200247400ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. Rails.application.config.assets.version = '1.0' # Add additional assets to the asset load path # Rails.application.config.assets.paths << Emoji.images_path # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. # Rails.application.config.assets.precompile += %w( search.js ) raven-ruby-2.13.0/examples/rails-4.2/config/initializers/backtrace_silencers.rb000066400000000000000000000006241357613622200274170ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. # Rails.backtrace_cleaner.remove_silencers! raven-ruby-2.13.0/examples/rails-4.2/config/initializers/cookies_serializer.rb000066400000000000000000000002011357613622200273050ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. Rails.application.config.action_dispatch.cookies_serializer = :json raven-ruby-2.13.0/examples/rails-4.2/config/initializers/filter_parameter_logging.rb000066400000000000000000000003021357613622200304550ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. Rails.application.config.filter_parameters += [:password] raven-ruby-2.13.0/examples/rails-4.2/config/initializers/inflections.rb000066400000000000000000000012071357613622200257440ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections # are locale specific, and you may define rules for as many different # locales as you wish. All of these examples are active by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end # These inflection rules are supported but not enabled by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.acronym 'RESTful' # end raven-ruby-2.13.0/examples/rails-4.2/config/initializers/mime_types.rb000066400000000000000000000002341357613622200256010ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf raven-ruby-2.13.0/examples/rails-4.2/config/initializers/session_store.rb000066400000000000000000000002151357613622200263240ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. Rails.application.config.session_store :cookie_store, key: '_rails-4_2_session' raven-ruby-2.13.0/examples/rails-4.2/config/initializers/wrap_parameters.rb000066400000000000000000000010051357613622200266170ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] if respond_to?(:wrap_parameters) end # To enable root element in JSON for ActiveRecord objects. # ActiveSupport.on_load(:active_record) do # self.include_root_in_json = true # end raven-ruby-2.13.0/examples/rails-4.2/config/locales/000077500000000000000000000000001357613622200220165ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/config/locales/en.yml000066400000000000000000000011721357613622200231440ustar00rootroot00000000000000# Files in the config/locales directory are used for internationalization # and are automatically loaded by Rails. If you want to use locales other # than English, add the necessary files in this directory. # # To use the locales, use `I18n.t`: # # I18n.t 'hello' # # In views, this is aliased to just `t`: # # <%= t('hello') %> # # To use a different locale, set it with `I18n.locale`: # # I18n.locale = :es # # This would use the information in config/locales/es.yml. # # To learn more, please read the Rails Internationalization guide # available at http://guides.rubyonrails.org/i18n.html. en: hello: "Hello world" raven-ruby-2.13.0/examples/rails-4.2/config/routes.rb000066400000000000000000000032121357613622200222400ustar00rootroot00000000000000Rails.application.routes.draw do get 'welcome/index' get '500', :to => 'errors#internal_server_error' # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". # You can have the root of your site routed with "root" root 'welcome#index' # Example of regular route: # get 'products/:id' => 'catalog#view' # Example of named route that can be invoked with purchase_url(id: product.id) # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase # Example resource route (maps HTTP verbs to controller actions automatically): # resources :products # Example resource route with options: # resources :products do # member do # get 'short' # post 'toggle' # end # # collection do # get 'sold' # end # end # Example resource route with sub-resources: # resources :products do # resources :comments, :sales # resource :seller # end # Example resource route with more complex sub-resources: # resources :products do # resources :comments # resources :sales do # get 'recent', on: :collection # end # end # Example resource route with concerns: # concern :toggleable do # post 'toggle' # end # resources :posts, concerns: :toggleable # resources :photos, concerns: :toggleable # Example resource route within a namespace: # namespace :admin do # # Directs /admin/products/* to Admin::ProductsController # # (app/controllers/admin/products_controller.rb) # resources :products # end end raven-ruby-2.13.0/examples/rails-4.2/config/secrets.yml000066400000000000000000000017041357613622200225710ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Your secret key is used for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. # You can use `rake secret` to generate a secure secret key. # Make sure the secrets in this file are kept private # if you're sharing your code publicly. development: secret_key_base: ccd93ed8f0d469aabac280ec20fc066c8a049c4c1e99228cc0cb0ed7eaeebec40096b5adcb58f05c4ee310d1cbb6917c37effdc3998b11731fcd7320ee78c9dc test: secret_key_base: e09744809a164613edb32e8eb22617d571c4516c43709e53f593ee54aa8861bc3f668b6d0def7ed077ecf2658eadbf66e84e6124cbd45801ea8b9cc3032885bc # Do not keep production secrets in the repository, # instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> raven-ruby-2.13.0/examples/rails-4.2/db/000077500000000000000000000000001357613622200175145ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/db/seeds.rb000066400000000000000000000005271357613622200211500ustar00rootroot00000000000000# This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). # # Examples: # # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) # Mayor.create(name: 'Emanuel', city: cities.first) raven-ruby-2.13.0/examples/rails-4.2/lib/000077500000000000000000000000001357613622200176755ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/lib/assets/000077500000000000000000000000001357613622200211775ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/lib/assets/.keep000066400000000000000000000000001357613622200221120ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/lib/tasks/000077500000000000000000000000001357613622200210225ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/lib/tasks/.keep000066400000000000000000000000001357613622200217350ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/log/000077500000000000000000000000001357613622200177105ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/log/.keep000066400000000000000000000000001357613622200206230ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/public/000077500000000000000000000000001357613622200204055ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/public/404.html000066400000000000000000000030341357613622200216020ustar00rootroot00000000000000 The page you were looking for doesn't exist (404)

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

If you are the application owner check the logs for more information.

raven-ruby-2.13.0/examples/rails-4.2/public/422.html000066400000000000000000000030131357613622200215770ustar00rootroot00000000000000 The change you wanted was rejected (422)

The change you wanted was rejected.

Maybe you tried to change something you didn't have access to.

If you are the application owner check the logs for more information.

raven-ruby-2.13.0/examples/rails-4.2/public/favicon.ico000066400000000000000000000000001357613622200225140ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/public/robots.txt000066400000000000000000000003121357613622200224520ustar00rootroot00000000000000# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file # # To ban all spiders from the entire site uncomment the next two lines: # User-agent: * # Disallow: / raven-ruby-2.13.0/examples/rails-4.2/test/000077500000000000000000000000001357613622200201065ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/controllers/000077500000000000000000000000001357613622200224545ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/controllers/.keep000066400000000000000000000000001357613622200233670ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/controllers/welcome_controller_test.rb000066400000000000000000000002441357613622200277360ustar00rootroot00000000000000require 'test_helper' class WelcomeControllerTest < ActionController::TestCase test "should get index" do get :index assert_response :success end end raven-ruby-2.13.0/examples/rails-4.2/test/fixtures/000077500000000000000000000000001357613622200217575ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/fixtures/.keep000066400000000000000000000000001357613622200226720ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/helpers/000077500000000000000000000000001357613622200215505ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/helpers/.keep000066400000000000000000000000001357613622200224630ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/integration/000077500000000000000000000000001357613622200224315ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/integration/.keep000066400000000000000000000000001357613622200233440ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/mailers/000077500000000000000000000000001357613622200215425ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/mailers/.keep000066400000000000000000000000001357613622200224550ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/models/000077500000000000000000000000001357613622200213715ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/models/.keep000066400000000000000000000000001357613622200223040ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/test/test_helper.rb000066400000000000000000000004701357613622200227520ustar00rootroot00000000000000ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. fixtures :all # Add more helper methods to be used by all tests here... end raven-ruby-2.13.0/examples/rails-4.2/vendor/000077500000000000000000000000001357613622200204245ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/vendor/assets/000077500000000000000000000000001357613622200217265ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/vendor/assets/javascripts/000077500000000000000000000000001357613622200242575ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/vendor/assets/javascripts/.keep000066400000000000000000000000001357613622200251720ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/vendor/assets/stylesheets/000077500000000000000000000000001357613622200243025ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-4.2/vendor/assets/stylesheets/.keep000066400000000000000000000000001357613622200252150ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/000077500000000000000000000000001357613622200171265ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/.gitignore000066400000000000000000000010371357613622200211170ustar00rootroot00000000000000# See https://help.github.com/articles/ignoring-files for more about ignoring files. # # If you find yourself ignoring temporary files generated by your text editor # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile '~/.gitignore_global' # Ignore bundler config. /.bundle # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal # Ignore all logfiles and tempfiles. /log/* /tmp/* !/log/.keep !/tmp/.keep # Ignore Byebug command history file. .byebug_history raven-ruby-2.13.0/examples/rails-5.0/Gemfile000066400000000000000000000033261357613622200204250ustar00rootroot00000000000000source 'https://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.0' # Use sqlite3 as the database for Active Record gem 'sqlite3' # Use Puma as the app server gem 'puma', '~> 3.0' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.2' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby gem 'sentry-raven', path: "../../" # Use jquery as the JavaScript library gem 'jquery-rails' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 3.0' # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platform: :mri end group :development do # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. gem 'web-console' gem 'listen', '~> 3.0.5' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] raven-ruby-2.13.0/examples/rails-5.0/README.md000066400000000000000000000005661357613622200204140ustar00rootroot00000000000000# README This README would normally document whatever steps are necessary to get the application up and running. Things you may want to cover: * Ruby version * System dependencies * Configuration * Database creation * Database initialization * How to run the test suite * Services (job queues, cache servers, search engines, etc.) * Deployment instructions * ... raven-ruby-2.13.0/examples/rails-5.0/Rakefile000066400000000000000000000003431357613622200205730ustar00rootroot00000000000000# Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require_relative 'config/application' Rails.application.load_tasks raven-ruby-2.13.0/examples/rails-5.0/app/000077500000000000000000000000001357613622200177065ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/channels/000077500000000000000000000000001357613622200215015ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/channels/application_cable/000077500000000000000000000000001357613622200251325ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/channels/application_cable/channel.rb000066400000000000000000000001171357613622200270660ustar00rootroot00000000000000module ApplicationCable class Channel < ActionCable::Channel::Base end end raven-ruby-2.13.0/examples/rails-5.0/app/channels/application_cable/connection.rb000066400000000000000000000001251357613622200276140ustar00rootroot00000000000000module ApplicationCable class Connection < ActionCable::Connection::Base end end raven-ruby-2.13.0/examples/rails-5.0/app/controllers/000077500000000000000000000000001357613622200222545ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/controllers/application_controller.rb000066400000000000000000000004511357613622200273470ustar00rootroot00000000000000class ApplicationController < ActionController::Base before_action :set_raven_context protect_from_forgery with: :exception private def set_raven_context # Raven.user_context(email: 'david@getsentry.com') # Raven.extra_context(params: params.to_hash, url: request.url) end end raven-ruby-2.13.0/examples/rails-5.0/app/controllers/concerns/000077500000000000000000000000001357613622200240665ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/controllers/concerns/.keep000066400000000000000000000000001357613622200250010ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/controllers/welcome_controller.rb000066400000000000000000000003301357613622200264730ustar00rootroot00000000000000class WelcomeController < ApplicationController def index Rails.logger.info("zomg division") 1 / 0 end def report_demo @sentry_event_id = Raven.last_event_id render(:status => 500) end end raven-ruby-2.13.0/examples/rails-5.0/app/jobs/000077500000000000000000000000001357613622200206435ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/jobs/application_job.rb000066400000000000000000000000531357613622200243230ustar00rootroot00000000000000class ApplicationJob < ActiveJob::Base end raven-ruby-2.13.0/examples/rails-5.0/app/models/000077500000000000000000000000001357613622200211715ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/models/application_record.rb000066400000000000000000000001161357613622200253550ustar00rootroot00000000000000class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end raven-ruby-2.13.0/examples/rails-5.0/app/models/concerns/000077500000000000000000000000001357613622200230035ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/models/concerns/.keep000066400000000000000000000000001357613622200237160ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/views/000077500000000000000000000000001357613622200210435ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/views/layouts/000077500000000000000000000000001357613622200225435ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/views/layouts/application.html.erb000066400000000000000000000006601357613622200265050ustar00rootroot00000000000000 Rails50 <%= csrf_meta_tags %> <%= yield %> raven-ruby-2.13.0/examples/rails-5.0/app/views/layouts/mailer.html.erb000066400000000000000000000003451357613622200254530ustar00rootroot00000000000000 <%= yield %> raven-ruby-2.13.0/examples/rails-5.0/app/views/layouts/mailer.text.erb000066400000000000000000000000151357613622200254650ustar00rootroot00000000000000<%= yield %> raven-ruby-2.13.0/examples/rails-5.0/app/views/welcome/000077500000000000000000000000001357613622200224765ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/app/views/welcome/report_demo.html.erb000066400000000000000000000005741357613622200264600ustar00rootroot00000000000000 Internal Server Error

Internal Server Error

='(

<% if @sentry_event_id %> <% end %> raven-ruby-2.13.0/examples/rails-5.0/bin/000077500000000000000000000000001357613622200176765ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/bin/bundle000077500000000000000000000002011357613622200210660ustar00rootroot00000000000000#!/usr/bin/env ruby ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) load Gem.bin_path('bundler', 'bundle') raven-ruby-2.13.0/examples/rails-5.0/bin/rails000077500000000000000000000004101357613622200207310ustar00rootroot00000000000000#!/usr/bin/env ruby begin load File.expand_path('../spring', __FILE__) rescue LoadError => e raise unless e.message.include?('spring') end APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' raven-ruby-2.13.0/examples/rails-5.0/bin/rake000077500000000000000000000003251357613622200205460ustar00rootroot00000000000000#!/usr/bin/env ruby begin load File.expand_path('../spring', __FILE__) rescue LoadError => e raise unless e.message.include?('spring') end require_relative '../config/boot' require 'rake' Rake.application.run raven-ruby-2.13.0/examples/rails-5.0/bin/setup000077500000000000000000000016301357613622200207640ustar00rootroot00000000000000#!/usr/bin/env ruby require 'pathname' require 'fileutils' include FileUtils # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end chdir APP_ROOT do # This script is a starting point to setup your application. # Add necessary setup steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') # cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" system! 'bin/rails db:setup' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" system! 'bin/rails restart' end raven-ruby-2.13.0/examples/rails-5.0/bin/spring000077500000000000000000000007501357613622200211300ustar00rootroot00000000000000#!/usr/bin/env ruby # This file loads spring without using Bundler, in order to be fast. # It gets overwritten when you run the `spring binstub` command. unless defined?(Spring) require 'rubygems' require 'bundler' if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) } gem 'spring', match[1] require 'spring/binstub' end end raven-ruby-2.13.0/examples/rails-5.0/bin/update000077500000000000000000000014161357613622200211100ustar00rootroot00000000000000#!/usr/bin/env ruby require 'pathname' require 'fileutils' include FileUtils # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end chdir APP_ROOT do # This script is a way to update your development environment automatically. # Add necessary update steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') puts "\n== Updating database ==" system! 'bin/rails db:migrate' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" system! 'bin/rails restart' end raven-ruby-2.13.0/examples/rails-5.0/config.ru000066400000000000000000000002021357613622200207350ustar00rootroot00000000000000# This file is used by Rack-based servers to start the application. require_relative 'config/environment' run Rails.application raven-ruby-2.13.0/examples/rails-5.0/config/000077500000000000000000000000001357613622200203735ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/config/application.rb000066400000000000000000000015701357613622200232260ustar00rootroot00000000000000require_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Rails50 class Application < Rails::Application config.consider_all_requests_local = false config.rails_activesupport_breadcrumbs = true # https://github.com/getsentry/raven-ruby/issues/494 config.exceptions_app = self.routes # With this enabled 'exceptions_app' isnt executed, so instead we # set ``config.consider_all_requests_local = false`` in development. # config.action_dispatch.show_exceptions = false # Inject Sentry logger breadcrumbs require 'raven/breadcrumbs/logger' Raven.configure do |config| config.dsn = 'https://6bca098db7ef423ab983e26e27255fe8:650b2fcf94f942fe9093f656b809a94e@app.getsentry.com/3825' end end end raven-ruby-2.13.0/examples/rails-5.0/config/boot.rb000066400000000000000000000002001357613622200216530ustar00rootroot00000000000000ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. raven-ruby-2.13.0/examples/rails-5.0/config/cable.yml000066400000000000000000000001641357613622200221650ustar00rootroot00000000000000development: adapter: async test: adapter: async production: adapter: redis url: redis://localhost:6379/1 raven-ruby-2.13.0/examples/rails-5.0/config/database.yml000066400000000000000000000010501357613622200226560ustar00rootroot00000000000000# SQLite version 3.x # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: sqlite3 pool: 5 timeout: 5000 development: <<: *default database: db/development.sqlite3 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: db/test.sqlite3 production: <<: *default database: db/production.sqlite3 raven-ruby-2.13.0/examples/rails-5.0/config/environment.rb000066400000000000000000000002001357613622200232540ustar00rootroot00000000000000# Load the Rails application. require_relative 'application' # Initialize the Rails application. Rails.application.initialize! raven-ruby-2.13.0/examples/rails-5.0/config/environments/000077500000000000000000000000001357613622200231225ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/config/environments/development.rb000066400000000000000000000034201357613622200257700ustar00rootroot00000000000000Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false # Do not eager load code on boot. config.eager_load = false # Enable/disable caching. By default caching is disabled. if Rails.root.join('tmp/caching-dev.txt').exist? config.action_controller.perform_caching = true config.cache_store = :memory_store config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=172800' } else config.action_controller.perform_caching = false config.cache_store = :null_store end # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false config.action_mailer.perform_caching = false # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. config.assets.debug = true # Suppress logger output for asset requests. config.assets.quiet = true # Raises error for missing translations # config.action_view.raise_on_missing_translations = true # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker end raven-ruby-2.13.0/examples/rails-5.0/config/environments/production.rb000066400000000000000000000067761357613622200256550ustar00rootroot00000000000000Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. config.cache_classes = true # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers # and those relying on copy on write to perform better. # Rake tasks automatically ignore this option for performance. config.eager_load = true # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass # Do not fallback to assets pipeline if a precompiled asset is missed. config.assets.compile = false # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil # config.action_cable.url = 'wss://example.com/cable' # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true # Use the lowest log level to ensure availability of diagnostic information # when problems arise. config.log_level = :debug # Prepend all log lines with the following tags. config.log_tags = [ :request_id ] # Use a different cache store in production. # config.cache_store = :mem_cache_store # Use a real queuing backend for Active Job (and separate queues per environment) # config.active_job.queue_adapter = :resque # config.active_job.queue_name_prefix = "rails-5_0_#{Rails.env}" config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new # Use a different logger for distributed setups. # require 'syslog/logger' # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') if ENV["RAILS_LOG_TO_STDOUT"].present? logger = ActiveSupport::Logger.new(STDOUT) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false end raven-ruby-2.13.0/examples/rails-5.0/config/environments/test.rb000066400000000000000000000033241357613622200244300ustar00rootroot00000000000000Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that # preloads Rails for running tests, you may have to set it to true. config.eager_load = false # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr # Raises error for missing translations # config.action_view.raise_on_missing_translations = true end raven-ruby-2.13.0/examples/rails-5.0/config/initializers/000077500000000000000000000000001357613622200231015ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/config/initializers/application_controller_renderer.rb000066400000000000000000000002421357613622200320600ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # ApplicationController.renderer.defaults.merge!( # http_host: 'example.org', # https: false # ) raven-ruby-2.13.0/examples/rails-5.0/config/initializers/assets.rb000066400000000000000000000007461357613622200247370ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. Rails.application.config.assets.version = '1.0' # Add additional assets to the asset load path # Rails.application.config.assets.paths << Emoji.images_path # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. # Rails.application.config.assets.precompile += %w( search.js ) raven-ruby-2.13.0/examples/rails-5.0/config/initializers/backtrace_silencers.rb000066400000000000000000000006241357613622200274160ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. # Rails.backtrace_cleaner.remove_silencers! raven-ruby-2.13.0/examples/rails-5.0/config/initializers/cookies_serializer.rb000066400000000000000000000003641357613622200273160ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. # Valid options are :json, :marshal, and :hybrid. Rails.application.config.action_dispatch.cookies_serializer = :json raven-ruby-2.13.0/examples/rails-5.0/config/initializers/filter_parameter_logging.rb000066400000000000000000000003021357613622200304540ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. Rails.application.config.filter_parameters += [:password] raven-ruby-2.13.0/examples/rails-5.0/config/initializers/inflections.rb000066400000000000000000000012071357613622200257430ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections # are locale specific, and you may define rules for as many different # locales as you wish. All of these examples are active by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end # These inflection rules are supported but not enabled by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.acronym 'RESTful' # end raven-ruby-2.13.0/examples/rails-5.0/config/initializers/mime_types.rb000066400000000000000000000002341357613622200256000ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf raven-ruby-2.13.0/examples/rails-5.0/config/initializers/new_framework_defaults.rb000066400000000000000000000021201357613622200301560ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # # This file contains migration options to ease your Rails 5.0 upgrade. # # Read the Rails 5.0 release notes for more info on each option. # Enable per-form CSRF tokens. Previous versions had false. Rails.application.config.action_controller.per_form_csrf_tokens = true # Enable origin-checking CSRF mitigation. Previous versions had false. Rails.application.config.action_controller.forgery_protection_origin_check = true # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. # Previous versions had false. ActiveSupport.to_time_preserves_timezone = true # Require `belongs_to` associations by default. Previous versions had false. Rails.application.config.active_record.belongs_to_required_by_default = true # Do not halt callback chains when a callback returns false. Previous versions had true. ActiveSupport.halt_callback_chains_on_return_false = false # Configure SSL options to enable HSTS with subdomains. Previous versions had false. Rails.application.config.ssl_options = { hsts: { subdomains: true } } raven-ruby-2.13.0/examples/rails-5.0/config/initializers/session_store.rb000066400000000000000000000002151357613622200263230ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. Rails.application.config.session_store :cookie_store, key: '_rails-5_0_session' raven-ruby-2.13.0/examples/rails-5.0/config/initializers/wrap_parameters.rb000066400000000000000000000007451357613622200266300ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] end # To enable root element in JSON for ActiveRecord objects. # ActiveSupport.on_load(:active_record) do # self.include_root_in_json = true # end raven-ruby-2.13.0/examples/rails-5.0/config/locales/000077500000000000000000000000001357613622200220155ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/config/locales/en.yml000066400000000000000000000011721357613622200231430ustar00rootroot00000000000000# Files in the config/locales directory are used for internationalization # and are automatically loaded by Rails. If you want to use locales other # than English, add the necessary files in this directory. # # To use the locales, use `I18n.t`: # # I18n.t 'hello' # # In views, this is aliased to just `t`: # # <%= t('hello') %> # # To use a different locale, set it with `I18n.locale`: # # I18n.locale = :es # # This would use the information in config/locales/es.yml. # # To learn more, please read the Rails Internationalization guide # available at http://guides.rubyonrails.org/i18n.html. en: hello: "Hello world" raven-ruby-2.13.0/examples/rails-5.0/config/puma.rb000066400000000000000000000037251357613622200216710ustar00rootroot00000000000000# Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers a minimum and maximum. # Any libraries that use thread pools should be configured to match # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum, this matches the default thread size of Active Record. # threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i threads threads_count, threads_count # Specifies the `port` that Puma will listen on to receive requests, default is 3000. # port ENV.fetch("PORT") { 3000 } # Specifies the `environment` that Puma will run in. # environment ENV.fetch("RAILS_ENV") { "development" } # Specifies the number of `workers` to boot in clustered mode. # Workers are forked webserver processes. If using threads and workers together # the concurrency of the application would be max `threads` * `workers`. # Workers do not work on JRuby or Windows (both of which do not support # processes). # # workers ENV.fetch("WEB_CONCURRENCY") { 2 } # Use the `preload_app!` method when specifying a `workers` number. # This directive tells Puma to first boot the application and load code # before forking the application. This takes advantage of Copy On Write # process behavior so workers use less memory. If you use this option # you need to make sure to reconnect any threads in the `on_worker_boot` # block. # # preload_app! # The code in the `on_worker_boot` will be called if you are using # clustered mode by specifying a number of `workers`. After each worker # process is booted this block will be run, if you are using `preload_app!` # option you will want to use this block to reconnect to any threads # or connections that may have been created at application boot, Ruby # cannot share connections between processes. # # on_worker_boot do # ActiveRecord::Base.establish_connection if defined?(ActiveRecord) # end # Allow puma to be restarted by `rails restart` command. plugin :tmp_restart raven-ruby-2.13.0/examples/rails-5.0/config/routes.rb000066400000000000000000000001521357613622200222370ustar00rootroot00000000000000Rails.application.routes.draw do get '500', :to => 'welcome#report_demo' root to: "welcome#index" end raven-ruby-2.13.0/examples/rails-5.0/config/secrets.yml000066400000000000000000000017051357613622200225710ustar00rootroot00000000000000# Be sure to restart your server when you modify this file. # Your secret key is used for verifying the integrity of signed cookies. # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. # You can use `rails secret` to generate a secure secret key. # Make sure the secrets in this file are kept private # if you're sharing your code publicly. development: secret_key_base: d91733e434c05e6905d6a0db58f91befa539464342558770b43c8acb11959cd3749bb196869a98ac8e82feeb9faafe9d6d92b2462a9e8c0642a1c881f0bbe608 test: secret_key_base: b35e5485b128e991295e7649d4ba0b466d56208414ca842de01e38908a55b53442c33753a02898949883743d68c82bb039ee5adede75a7c9d400b05b76746e47 # Do not keep production secrets in the repository, # instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> raven-ruby-2.13.0/examples/rails-5.0/config/spring.rb000066400000000000000000000001571357613622200222250ustar00rootroot00000000000000%w( .ruby-version .rbenv-vars tmp/restart.txt tmp/caching-dev.txt ).each { |path| Spring.watch(path) } raven-ruby-2.13.0/examples/rails-5.0/db/000077500000000000000000000000001357613622200175135ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/db/seeds.rb000066400000000000000000000005621357613622200211460ustar00rootroot00000000000000# This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). # # Examples: # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) raven-ruby-2.13.0/examples/rails-5.0/log/000077500000000000000000000000001357613622200177075ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/log/.keep000066400000000000000000000000001357613622200206220ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/public/000077500000000000000000000000001357613622200204045ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/public/404.html000066400000000000000000000030341357613622200216010ustar00rootroot00000000000000 The page you were looking for doesn't exist (404)

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

If you are the application owner check the logs for more information.

raven-ruby-2.13.0/examples/rails-5.0/public/422.html000066400000000000000000000030131357613622200215760ustar00rootroot00000000000000 The change you wanted was rejected (422)

The change you wanted was rejected.

Maybe you tried to change something you didn't have access to.

If you are the application owner check the logs for more information.

raven-ruby-2.13.0/examples/rails-5.0/public/apple-touch-icon-precomposed.png000066400000000000000000000000001357613622200265650ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/public/apple-touch-icon.png000066400000000000000000000000001357613622200242470ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/public/favicon.ico000066400000000000000000000000001357613622200225130ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/public/robots.txt000066400000000000000000000003121357613622200224510ustar00rootroot00000000000000# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file # # To ban all spiders from the entire site uncomment the next two lines: # User-agent: * # Disallow: / raven-ruby-2.13.0/examples/rails-5.0/tmp/000077500000000000000000000000001357613622200177265ustar00rootroot00000000000000raven-ruby-2.13.0/examples/rails-5.0/tmp/.keep000066400000000000000000000000001357613622200206410ustar00rootroot00000000000000raven-ruby-2.13.0/exe/000077500000000000000000000000001357613622200144575ustar00rootroot00000000000000raven-ruby-2.13.0/exe/raven000077500000000000000000000010441357613622200155170ustar00rootroot00000000000000#!/usr/bin/env ruby require "raven" require "raven/cli" require "optparse" parser = OptionParser.new do |opt| opt.banner = "Usage: raven COMMAND [OPTIONS]" opt.separator "" opt.separator "Commands" opt.separator " test: send a test event" opt.separator "" opt.separator "Options" opt.on("-h", "--help", "help") do puts parser end end parser.parse! case ARGV[0] when "test" dsn = ARGV[1] if ARGV.length > 1 if !dsn puts "Usage: raven test " else Raven::CLI.test(dsn) end else puts parser end raven-ruby-2.13.0/lib/000077500000000000000000000000001357613622200144445ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven.rb000066400000000000000000000000431357613622200161010ustar00rootroot00000000000000require 'raven/base' Raven.inject raven-ruby-2.13.0/lib/raven/000077500000000000000000000000001357613622200155575ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/backtrace.rb000066400000000000000000000066571357613622200200410ustar00rootroot00000000000000## Inspired by Rails' and Airbrake's backtrace parsers. module Raven # Front end to parsing the backtrace for each notice class Backtrace # Handles backtrace parsing line by line class Line RB_EXTENSION = ".rb".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+)\)$/ # The file portion of the line (such as app/models/user.rb) attr_reader :file # The line number portion of the line attr_reader :number # The method of the line (such as index) attr_reader :method # The module name (JRuby) attr_reader :module_name # Parses a single line of a given backtrace # @param [String] unparsed_line The raw line from +caller+ or some backtrace # @return [Line] The parsed backtrace line def self.parse(unparsed_line) ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT) if ruby_match _, file, number, method = ruby_match.to_a file.sub!(/\.class$/, RB_EXTENSION) module_name = nil else java_match = unparsed_line.match(JAVA_INPUT_FORMAT) _, module_name, method, file, number = java_match.to_a end new(file, number, method, module_name) end def initialize(file, number, method, module_name) self.file = file self.module_name = module_name self.number = number.to_i self.method = method end def in_app if file =~ self.class.in_app_pattern true else false end end # Reconstructs the line in a readable fashion def to_s "#{file}:#{number}:in `#{method}'" end def ==(other) to_s == other.to_s end def inspect "" end def self.in_app_pattern @in_app_pattern ||= begin project_root = Raven.configuration.project_root && Raven.configuration.project_root.to_s Regexp.new("^(#{project_root}/)?#{Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN}") end end private attr_writer :file, :number, :method, :module_name end APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/ # holder for an Array of Backtrace::Line instances attr_reader :lines def self.parse(backtrace, opts = {}) ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/) filters = opts[:filters] || [] filtered_lines = ruby_lines.to_a.map do |line| filters.reduce(line) do |nested_line, proc| proc.call(nested_line) end end.compact lines = filtered_lines.map do |unparsed_line| Line.parse(unparsed_line) end new(lines) end def initialize(lines) self.lines = lines end def inspect "" end def to_s content = [] lines.each do |line| content << line end content.join("\n") end def ==(other) if other.respond_to?(:lines) lines == other.lines else false end end private attr_writer :lines end end raven-ruby-2.13.0/lib/raven/base.rb000066400000000000000000000074621357613622200170270ustar00rootroot00000000000000require 'raven/version' require 'raven/backtrace' require 'raven/breadcrumbs' require 'raven/processor' require 'raven/processor/sanitizedata' require 'raven/processor/removecircularreferences' require 'raven/processor/utf8conversion' require 'raven/processor/cookies' require 'raven/processor/post_data' require 'raven/processor/http_headers' require 'raven/configuration' require 'raven/context' require 'raven/client' require 'raven/event' require 'raven/linecache' require 'raven/logger' require 'raven/interfaces/message' require 'raven/interfaces/exception' require 'raven/interfaces/single_exception' require 'raven/interfaces/stack_trace' require 'raven/interfaces/http' require 'raven/transports' require 'raven/transports/http' require 'raven/utils/deep_merge' require 'raven/utils/real_ip' require 'raven/utils/exception_cause_chain' require 'raven/instance' require 'forwardable' require 'English' module Raven AVAILABLE_INTEGRATIONS = %w(delayed_job railties sidekiq rack rack-timeout rake).freeze class Error < StandardError end class << self extend Forwardable def instance @instance ||= Raven::Instance.new end def_delegators :instance, :client=, :configuration=, :context, :logger, :configuration, :client, :report_status, :configure, :send_event, :capture, :capture_type, :last_event_id, :annotate_exception, :user_context, :tags_context, :extra_context, :rack_context, :breadcrumbs def_delegator :instance, :report_status, :report_ready def_delegator :instance, :capture_type, :capture_message def_delegator :instance, :capture_type, :capture_exception # For cross-language compatibility def_delegator :instance, :capture_type, :captureException def_delegator :instance, :capture_type, :captureMessage def_delegator :instance, :annotate_exception, :annotateException def_delegator :instance, :annotate_exception, :annotate # Injects various integrations. Default behavior: inject all available integrations def inject inject_only(*Raven::AVAILABLE_INTEGRATIONS) end def inject_without(*exclude_integrations) include_integrations = Raven::AVAILABLE_INTEGRATIONS - exclude_integrations.map(&:to_s) inject_only(*include_integrations) end def inject_only(*only_integrations) only_integrations = only_integrations.map(&:to_s) integrations_to_load = Raven::AVAILABLE_INTEGRATIONS & only_integrations not_found_integrations = only_integrations - integrations_to_load if not_found_integrations.any? logger.warn "Integrations do not exist: #{not_found_integrations.join ', '}" end integrations_to_load &= Gem.loaded_specs.keys # TODO(dcramer): integrations should have some additional checks baked-in # or we should break them out into their own repos. Specifically both the # rails and delayed_job checks are not always valid (i.e. Rails 2.3) and # https://github.com/getsentry/raven-ruby/issues/180 integrations_to_load.each do |integration| load_integration(integration) end end def load_integration(integration) require "raven/integrations/#{integration}" rescue Exception => error logger.warn "Unable to load raven/integrations/#{integration}: #{error}" end def safely_prepend(module_name, opts = {}) return if opts[:to].nil? || opts[:from].nil? if opts[:to].respond_to?(:prepend, true) opts[:to].send(:prepend, opts[:from].const_get(module_name)) else opts[:to].send(:include, opts[:from].const_get("Old" + module_name)) end end def sys_command(command) result = `#{command} 2>&1` rescue nil return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0) result.strip end end end raven-ruby-2.13.0/lib/raven/breadcrumbs.rb000066400000000000000000000023601357613622200203760ustar00rootroot00000000000000module Raven class Breadcrumb attr_accessor :category, :data, :message, :level, :timestamp, :type def initialize @category = nil @data = {} @level = nil @message = nil @timestamp = Time.now.to_i @type = nil end def to_hash { :category => @category, :data => @data, :level => @level, :message => @message, :timestamp => @timestamp, :type => @type } end end end module Raven class BreadcrumbBuffer include Enumerable attr_accessor :buffer def self.current Thread.current[:sentry_breadcrumbs] ||= new end def self.clear! Thread.current[:sentry_breadcrumbs] = nil end def initialize(size = 100) @buffer = Array.new(size) end def record(crumb = nil) if block_given? crumb = Breadcrumb.new if crumb.nil? yield(crumb) end @buffer.slice!(0) @buffer << crumb end def members @buffer.compact end def peek members.last end def each(&block) members.each(&block) end def empty? !members.any? end def to_hash { :values => members.map(&:to_hash) } end end end raven-ruby-2.13.0/lib/raven/breadcrumbs/000077500000000000000000000000001357613622200200505ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/breadcrumbs/activesupport.rb000066400000000000000000000010171357613622200233040ustar00rootroot00000000000000module Raven module ActiveSupportBreadcrumbs class << self def add(name, started, _finished, _unique_id, data) Raven.breadcrumbs.record do |crumb| crumb.data = data crumb.category = name crumb.timestamp = started.to_i end end def inject ActiveSupport::Notifications.subscribe(/.*/) do |name, started, finished, unique_id, data| add(name, started, finished, unique_id, data) end end end end end raven-ruby-2.13.0/lib/raven/breadcrumbs/logger.rb000066400000000000000000000047301357613622200216600ustar00rootroot00000000000000require 'logger' module Raven module BreadcrumbLogger LEVELS = { ::Logger::DEBUG => 'debug', ::Logger::INFO => 'info', ::Logger::WARN => 'warn', ::Logger::ERROR => 'error', ::Logger::FATAL => 'fatal' }.freeze EXC_FORMAT = /^([a-zA-Z0-9]+)\:\s(.*)$/ def self.parse_exception(message) lines = message.split(/\n\s*/) # TODO: wat return nil unless lines.length > 2 match = lines[0].match(EXC_FORMAT) return nil unless match _, type, value = match.to_a [type, value] end def add(*args) add_breadcrumb(*args) super end def add_breadcrumb(severity, message = nil, progname = nil) message = progname if message.nil? # see Ruby's Logger docs for why return if ignored_logger?(progname) return if message.nil? || message == "" # some loggers will add leading/trailing space as they (incorrectly, mind you) # think of logging as a shortcut to std{out,err} message = message.to_s.strip last_crumb = Raven.breadcrumbs.peek # try to avoid dupes from logger broadcasts if last_crumb.nil? || last_crumb.message != message error = Raven::BreadcrumbLogger.parse_exception(message) # TODO(dcramer): we need to filter out the "currently captured error" if error Raven.breadcrumbs.record do |crumb| crumb.level = Raven::BreadcrumbLogger::LEVELS.fetch(severity, nil) crumb.category = progname || 'error' crumb.type = 'error' crumb.data = { :type => error[0], :value => error[1] } end else Raven.breadcrumbs.record do |crumb| crumb.level = Raven::BreadcrumbLogger::LEVELS.fetch(severity, nil) crumb.category = progname || 'logger' crumb.message = message end end end end private def ignored_logger?(progname) progname == "sentry" || Raven.configuration.exclude_loggers.include?(progname) end end module OldBreadcrumbLogger def self.included(base) base.class_eval do include Raven::BreadcrumbLogger alias_method :add_without_raven, :add alias_method :add, :add_with_raven end end def add_with_raven(*args) add_breadcrumb(*args) add_without_raven(*args) end end end Raven.safely_prepend( "BreadcrumbLogger", :from => Raven, :to => ::Logger ) raven-ruby-2.13.0/lib/raven/cli.rb000066400000000000000000000033131357613622200166530ustar00rootroot00000000000000module Raven class CLI def self.test(dsn = nil, silent = false, config = nil) # rubocop:disable all config ||= Raven.configuration config.logger = if silent ::Logger.new(nil) else logger = ::Logger.new(STDOUT) logger.formatter = proc do |_severity, _datetime, _progname, msg| "-> #{msg}\n" end logger end config.timeout = 5 config.dsn = dsn if dsn # wipe out env settings to ensure we send the event unless config.capture_allowed? env_name = config.environments.pop || 'production' config.current_environment = env_name end instance = Raven::Instance.new(nil, config) instance.logger.debug "Sending a test event:" instance.logger.debug "" begin 1 / 0 rescue ZeroDivisionError => exception evt = instance.capture_exception(exception) end if evt && !(evt.is_a? Thread) if evt.is_a? Hash instance.logger.debug "-> event ID: #{evt[:event_id]}" else instance.logger.debug "-> event ID: #{evt.id}" end elsif evt # async configuration if evt.value.is_a? Hash instance.logger.debug "-> event ID: #{evt.value[:event_id]}" else instance.logger.debug "-> event ID: #{evt.value.id}" end else instance.logger.debug "" instance.logger.debug "An error occurred while attempting to send the event." exit 1 end instance.logger.debug "" instance.logger.debug "Done!" evt end end end raven-ruby-2.13.0/lib/raven/client.rb000066400000000000000000000104041357613622200173610ustar00rootroot00000000000000# frozen_string_literal: true require 'base64' require 'json' require 'zlib' module Raven # Encodes events and sends them to the Sentry server. class Client PROTOCOL_VERSION = '5'.freeze USER_AGENT = "raven-ruby/#{Raven::VERSION}".freeze CONTENT_TYPE = 'application/json'.freeze attr_accessor :configuration def initialize(configuration) @configuration = configuration @processors = configuration.processors.map { |v| v.new(self) } @state = ClientState.new end def send_event(event, hint = nil) return false unless configuration.sending_allowed?(event) event = configuration.before_send.call(event, hint) if configuration.before_send if event.nil? configuration.logger.info "Discarded event because before_send returned nil" return end # Convert to hash event = event.to_hash unless @state.should_try? failed_send(nil, event) return end event_id = event[:event_id] || event['event_id'] configuration.logger.info "Sending event #{event_id} to Sentry" content_type, encoded_data = encode(event) begin transport.send_event(generate_auth_header, encoded_data, :content_type => content_type) successful_send rescue => e failed_send(e, event) return end event end def transport @transport ||= case configuration.scheme when 'http', 'https' Transports::HTTP.new(configuration) when 'stdout' Transports::Stdout.new(configuration) when 'dummy' Transports::Dummy.new(configuration) else fail "Unknown transport scheme '#{configuration.scheme}'" end end private def encode(event) hash = @processors.reduce(event.to_hash) { |a, e| e.process(a) } encoded = JSON.fast_generate(hash) case configuration.encoding when 'gzip' ['application/octet-stream', Base64.strict_encode64(Zlib::Deflate.deflate(encoded))] else ['application/json', encoded] end end def get_message_from_exception(event) ( event && event[:exception] && event[:exception][:values] && event[:exception][:values][0] && event[:exception][:values][0][:type] && event[:exception][:values][0][:value] && "#{event[:exception][:values][0][:type]}: #{event[:exception][:values][0][:value]}" ) end def get_log_message(event) (event && event[:message]) || (event && event['message']) || get_message_from_exception(event) || '' end def generate_auth_header now = Time.now.to_i.to_s fields = { 'sentry_version' => PROTOCOL_VERSION, 'sentry_client' => USER_AGENT, 'sentry_timestamp' => now, 'sentry_key' => configuration.public_key } fields['sentry_secret'] = configuration.secret_key unless configuration.secret_key.nil? 'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ') end def successful_send @state.success end def failed_send(e, event) if e # exception was raised @state.failure configuration.logger.warn "Unable to record event with remote Sentry server (#{e.class} - #{e.message}):\n#{e.backtrace[0..10].join("\n")}" else configuration.logger.warn "Not sending event due to previous failure(s)." end configuration.logger.warn("Failed to submit event: #{get_log_message(event)}") configuration.transport_failure_callback.call(event) if configuration.transport_failure_callback end end class ClientState def initialize reset end def should_try? return true if @status == :online interval = @retry_after || [@retry_number, 6].min**2 return true if Time.now - @last_check >= interval false end def failure(retry_after = nil) @status = :error @retry_number += 1 @last_check = Time.now @retry_after = retry_after end def success reset end def reset @status = :online @retry_number = 0 @last_check = nil @retry_after = nil end def failed? @status == :error end end end raven-ruby-2.13.0/lib/raven/configuration.rb000066400000000000000000000364651357613622200207710ustar00rootroot00000000000000require 'uri' module Raven class Configuration # Directories to be recognized as part of your app. e.g. if you # have an `engines` dir at the root of your project, you may want # to set this to something like /(app|config|engines|lib)/ attr_accessor :app_dirs_pattern # Provide an object that responds to `call` to send events asynchronously. # E.g.: lambda { |event| Thread.new { Raven.send_event(event) } } attr_reader :async alias async? async # Number of lines of code context to capture, or nil for none attr_accessor :context_lines # RACK_ENV by default. attr_reader :current_environment # Encoding type for event bodies. Must be :json or :gzip. attr_reader :encoding # Whitelist of environments that will send notifications to Sentry. Array of Strings. attr_accessor :environments # Logger 'progname's to exclude from breadcrumbs attr_accessor :exclude_loggers # Array of exception classes that should never be sent. See IGNORE_DEFAULT. # You should probably append to this rather than overwrite it. attr_accessor :excluded_exceptions # Boolean to check nested exceptions when deciding if to exclude. Defaults to false attr_accessor :inspect_exception_causes_for_exclusion alias inspect_exception_causes_for_exclusion? inspect_exception_causes_for_exclusion # DSN component - set automatically if DSN provided attr_accessor :host # The Faraday adapter to be used. Will default to Net::HTTP when not set. attr_accessor :http_adapter # A Proc yeilding the faraday builder allowing for further configuration # of the faraday adapter attr_accessor :faraday_builder # You may provide your own LineCache for matching paths with source files. # This may be useful if you need to get source code from places other than # the disk. See Raven::LineCache for the required interface you must implement. attr_accessor :linecache # Logger used by Raven. In Rails, this is the Rails logger, otherwise # Raven provides its own Raven::Logger. attr_accessor :logger # Timeout waiting for the Sentry server connection to open in seconds attr_accessor :open_timeout # DSN component - set automatically if DSN provided attr_accessor :path # DSN component - set automatically if DSN provided attr_accessor :port # Processors to run on data before sending upstream. See DEFAULT_PROCESSORS. # You should probably append to this rather than overwrite it. attr_accessor :processors # Project ID number to send to the Sentry server # If you provide a DSN, this will be set automatically. attr_accessor :project_id # Project directory root for in_app detection. Could be Rails root, etc. # Set automatically for Rails. attr_reader :project_root # Proxy information to pass to the HTTP adapter (via Faraday) attr_accessor :proxy # Public key for authentication with the Sentry server # If you provide a DSN, this will be set automatically. attr_accessor :public_key # Turns on ActiveSupport breadcrumbs integration attr_accessor :rails_activesupport_breadcrumbs # Rails catches exceptions in the ActionDispatch::ShowExceptions or # ActionDispatch::DebugExceptions middlewares, depending on the environment. # When `rails_report_rescued_exceptions` is true (it is by default), Raven # will report exceptions even when they are rescued by these middlewares. attr_accessor :rails_report_rescued_exceptions # Release tag to be passed with every event sent to Sentry. # We automatically try to set this to a git SHA or Capistrano release. attr_accessor :release # The sampling factor to apply to events. A value of 0.0 will not send # any events, and a value of 1.0 will send 100% of events. attr_accessor :sample_rate # Boolean - sanitize values that look like credit card numbers attr_accessor :sanitize_credit_cards # By default, Sentry censors Hash values when their keys match things like # "secret", "password", etc. Provide an array of Strings that, when matched in # a hash key, will be censored and not sent to Sentry. attr_accessor :sanitize_fields # If you're sure you want to override the default sanitization values, you can # add to them to an array of Strings here, e.g. %w(authorization password) attr_accessor :sanitize_fields_excluded # Sanitize additional HTTP headers - only Authorization is removed by default. attr_accessor :sanitize_http_headers # DSN component - set automatically if DSN provided. # Otherwise, can be one of "http", "https", or "dummy" attr_accessor :scheme # Secret key for authentication with the Sentry server # If you provide a DSN, this will be set automatically. # # This is deprecated and not necessary for newer Sentry installations any more. attr_accessor :secret_key # Include module versions in reports - boolean. attr_accessor :send_modules # Simple server string - set this to the DSN found on your Sentry settings. attr_reader :server attr_accessor :server_name # Provide a configurable callback to determine event capture. # Note that the object passed into the block will be a String (messages) or # an exception. # e.g. lambda { |exc_or_msg| exc_or_msg.some_attr == false } attr_reader :should_capture # Silences ready message when true. attr_accessor :silence_ready # SSL settings passed directly to Faraday's ssl option attr_accessor :ssl # The path to the SSL certificate file attr_accessor :ssl_ca_file # Should the SSL certificate of the server be verified? attr_accessor :ssl_verification # Default tags for events. Hash. attr_accessor :tags # Timeout when waiting for the server to return data in seconds. attr_accessor :timeout # Optional Proc, called when the Sentry server cannot be contacted for any reason # E.g. lambda { |event| Thread.new { MyJobProcessor.send_email(event) } } attr_reader :transport_failure_callback # Optional Proc, called before sending an event to the server/ # E.g.: lambda { |event, hint| event } # E.g.: lambda { |event, hint| nil } # E.g.: lambda { |event, hint| # event[:message] = 'a' # event # } attr_reader :before_send # Errors object - an Array that contains error messages. See # attr_reader :errors IGNORE_DEFAULT = [ 'AbstractController::ActionNotFound', 'ActionController::InvalidAuthenticityToken', 'ActionController::RoutingError', 'ActionController::UnknownAction', 'ActiveRecord::RecordNotFound', 'CGI::Session::CookieStore::TamperedWithCookie', 'Mongoid::Errors::DocumentNotFound', 'Sinatra::NotFound', 'ActiveJob::DeserializationError' ].freeze # Note the order - we have to remove circular references and bad characters # before passing to other processors. DEFAULT_PROCESSORS = [ Raven::Processor::RemoveCircularReferences, Raven::Processor::UTF8Conversion, Raven::Processor::SanitizeData, Raven::Processor::Cookies, Raven::Processor::PostData, Raven::Processor::HTTPHeaders ].freeze HEROKU_DYNO_METADATA_MESSAGE = "You are running on Heroku but haven't enabled Dyno Metadata. For Sentry's "\ "release detection to work correctly, please run `heroku labs:enable runtime-dyno-metadata`".freeze LOG_PREFIX = "** [Raven] ".freeze MODULE_SEPARATOR = "::".freeze def initialize self.async = false self.context_lines = 3 self.current_environment = current_environment_from_env self.encoding = 'gzip' self.environments = [] self.exclude_loggers = [] self.excluded_exceptions = IGNORE_DEFAULT.dup self.inspect_exception_causes_for_exclusion = false self.linecache = ::Raven::LineCache.new self.logger = ::Raven::Logger.new(STDOUT) self.open_timeout = 1 self.processors = DEFAULT_PROCESSORS.dup self.project_root = detect_project_root self.rails_activesupport_breadcrumbs = false self.rails_report_rescued_exceptions = true self.release = detect_release self.sample_rate = 1.0 self.sanitize_credit_cards = true self.sanitize_fields = [] self.sanitize_fields_excluded = [] self.sanitize_http_headers = [] self.send_modules = true self.server = ENV['SENTRY_DSN'] self.server_name = server_name_from_env self.should_capture = false self.ssl_verification = true self.tags = {} self.timeout = 2 self.transport_failure_callback = false self.before_send = false end def server=(value) return if value.nil? uri = URI.parse(value) uri_path = uri.path.split('/') if uri.user # DSN-style string self.project_id = uri_path.pop self.public_key = uri.user self.secret_key = !(uri.password.nil? || uri.password.empty?) ? uri.password : nil end self.scheme = uri.scheme self.host = uri.host self.port = uri.port if uri.port self.path = uri_path.join('/') # For anyone who wants to read the base server string @server = "#{scheme}://#{host}" @server << ":#{port}" unless port == { 'http' => 80, 'https' => 443 }[scheme] @server << path end alias dsn= server= def encoding=(encoding) raise(Error, 'Unsupported encoding') unless %w(gzip json).include? encoding @encoding = encoding end def async=(value) unless value == false || value.respond_to?(:call) raise(ArgumentError, "async must be callable (or false to disable)") end @async = value end def transport_failure_callback=(value) unless value == false || value.respond_to?(:call) raise(ArgumentError, "transport_failure_callback must be callable (or false to disable)") end @transport_failure_callback = value end def should_capture=(value) unless value == false || value.respond_to?(:call) raise ArgumentError, "should_capture must be callable (or false to disable)" end @should_capture = value end def before_send=(value) unless value == false || value.respond_to?(:call) raise ArgumentError, "before_send must be callable (or false to disable)" end @before_send = value end # Allows config options to be read like a hash # # @param [Symbol] option Key for a given attribute def [](option) public_send(option) end def current_environment=(environment) @current_environment = environment.to_s end def capture_allowed?(message_or_exc = nil) @errors = [] valid? && capture_in_current_environment? && capture_allowed_by_callback?(message_or_exc) && sample_allowed? end # If we cannot capture, we cannot send. alias sending_allowed? capture_allowed? def error_messages @errors = [errors[0]] + errors[1..-1].map(&:downcase) # fix case of all but first errors.join(", ") end def project_root=(root_dir) @project_root = root_dir Backtrace::Line.instance_variable_set(:@in_app_pattern, nil) # blow away cache end def exception_class_allowed?(exc) if exc.is_a?(Raven::Error) # Try to prevent error reporting loops logger.debug "Refusing to capture Raven error: #{exc.inspect}" false elsif excluded_exception?(exc) logger.debug "User excluded error: #{exc.inspect}" false else true end end private def detect_project_root if defined? Rails.root # we are in a Rails application Rails.root.to_s else Dir.pwd end end def detect_release detect_release_from_env || detect_release_from_git || detect_release_from_capistrano || detect_release_from_heroku rescue => ex logger.error "Error detecting release: #{ex.message}" end def excluded_exception?(incoming_exception) excluded_exceptions.any? do |excluded_exception| matches_exception?(get_exception_class(excluded_exception), incoming_exception) end end def get_exception_class(x) x.is_a?(Module) ? x : qualified_const_get(x) end def matches_exception?(excluded_exception_class, incoming_exception) if inspect_exception_causes_for_exclusion? Raven::Utils::ExceptionCauseChain.exception_to_array(incoming_exception).any? { |cause| excluded_exception_class === cause } else excluded_exception_class === incoming_exception end end # In Ruby <2.0 const_get can't lookup "SomeModule::SomeClass" in one go def qualified_const_get(x) x = x.to_s if !x.match(/::/) Object.const_get(x) else x.split(MODULE_SEPARATOR).reject(&:empty?).inject(Object) { |a, e| a.const_get(e) } end rescue NameError # There's no way to safely ask if a constant exist for an unknown string nil end def detect_release_from_heroku return unless running_on_heroku? return if ENV['CI'] logger.warn(HEROKU_DYNO_METADATA_MESSAGE) && return unless ENV['HEROKU_SLUG_COMMIT'] ENV['HEROKU_SLUG_COMMIT'] end def running_on_heroku? File.directory?("/etc/heroku") end def detect_release_from_capistrano revision_file = File.join(project_root, 'REVISION') revision_log = File.join(project_root, '..', 'revisions.log') if File.exist?(revision_file) File.read(revision_file).strip elsif File.exist?(revision_log) File.open(revision_log).to_a.last.strip.sub(/.*as release ([0-9]+).*/, '\1') end end def detect_release_from_git Raven.sys_command("git rev-parse --short HEAD") if File.directory?(".git") end def detect_release_from_env ENV['SENTRY_RELEASE'] end def capture_in_current_environment? return true unless environments.any? && !environments.include?(current_environment) @errors << "Not configured to send/capture in environment '#{current_environment}'" false end def capture_allowed_by_callback?(message_or_exc) return true if !should_capture || message_or_exc.nil? || should_capture.call(*[message_or_exc]) @errors << "should_capture returned false" false end def valid? return true if %w(server host path public_key project_id).all? { |k| public_send(k) } if server %w(server host path public_key project_id).map do |key| @errors << "No #{key} specified" unless public_send(key) end else @errors << "DSN not set" end false end def sample_allowed? return true if sample_rate == 1.0 if Random::DEFAULT.rand >= sample_rate @errors << "Excluded by random sample" false else true end end # Try to resolve the hostname to an FQDN, but fall back to whatever # the load name is. def resolve_hostname Socket.gethostname || Socket.gethostbyname(hostname).first rescue server_name end def current_environment_from_env ENV['SENTRY_CURRENT_ENV'] || ENV['SENTRY_ENVIRONMENT'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default' end def server_name_from_env if running_on_heroku? ENV['DYNO'] else resolve_hostname end end end end raven-ruby-2.13.0/lib/raven/context.rb000066400000000000000000000021761357613622200175760ustar00rootroot00000000000000require 'rbconfig' module Raven class Context def self.current Thread.current[:sentry_context] ||= new end def self.clear! Thread.current[:sentry_context] = nil end attr_accessor :transaction, :extra, :server_os, :rack_env, :runtime, :tags, :user def initialize self.server_os = self.class.os_context self.runtime = self.class.runtime_context self.extra = { :server => { :os => server_os, :runtime => runtime } } self.rack_env = nil self.tags = {} self.user = {} self.transaction = [] end class << self def os_context @os_context ||= { :name => Raven.sys_command("uname -s") || RbConfig::CONFIG["host_os"], :version => Raven.sys_command("uname -v"), :build => Raven.sys_command("uname -r"), :kernel_version => Raven.sys_command("uname -a") || Raven.sys_command("ver") # windows } end def runtime_context @runtime_context ||= { :name => RbConfig::CONFIG["ruby_install_name"], :version => Raven.sys_command("ruby -v") } end end end end raven-ruby-2.13.0/lib/raven/event.rb000066400000000000000000000177201357613622200172340ustar00rootroot00000000000000# frozen_string_literal: true require 'socket' require 'securerandom' module Raven class Event # See Sentry server default limits at # https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8 SDK = { "name" => "raven-ruby", "version" => Raven::VERSION }.freeze attr_accessor :id, :logger, :transaction, :server_name, :release, :modules, :extra, :tags, :context, :configuration, :checksum, :fingerprint, :environment, :server_os, :runtime, :breadcrumbs, :user, :backtrace, :platform, :sdk alias event_id id attr_reader :level, :timestamp, :time_spent def initialize(init = {}) # Set some simple default values self.id = SecureRandom.uuid.delete("-") self.timestamp = Time.now.utc self.level = :error self.logger = :ruby self.platform = :ruby self.sdk = SDK # Set some attributes with empty hashes to allow merging @interfaces = {} self.user = {} # TODO: contexts self.extra = {} # TODO: contexts self.server_os = {} # TODO: contexts self.runtime = {} # TODO: contexts self.tags = {} # TODO: contexts copy_initial_state # Allow attributes to be set on the event at initialization yield self if block_given? init.each_pair { |key, val| public_send("#{key}=", val) unless val.nil? } set_core_attributes_from_configuration set_core_attributes_from_context end def self.from_exception(exc, options = {}, &block) exception_context = if exc.instance_variable_defined?(:@__raven_context) exc.instance_variable_get(:@__raven_context) elsif exc.respond_to?(:raven_context) exc.raven_context else {} end options = Raven::Utils::DeepMergeHash.deep_merge(exception_context, options) configuration = options[:configuration] || Raven.configuration return unless configuration.exception_class_allowed?(exc) new(options) do |evt| evt.add_exception_interface(exc) yield evt if block end end def self.from_message(message, options = {}) new(options) do |evt| evt.message = message, options[:message_params] || [] if options[:backtrace] evt.interface(:stacktrace) do |int| int.frames = evt.stacktrace_interface_from(options[:backtrace]) end end end end def message @interfaces[:logentry] && @interfaces[:logentry].unformatted_message end def message=(args) message, params = *args interface(:message) do |int| int.message = message.byteslice(0...MAX_MESSAGE_SIZE_IN_BYTES) # Messages limited to 10kb int.params = params end end def timestamp=(time) @timestamp = time.is_a?(Time) ? time.strftime('%Y-%m-%dT%H:%M:%S') : time end def time_spent=(time) @time_spent = time.is_a?(Float) ? (time * 1000).to_i : time end def level=(new_level) # needed to meet the Sentry spec @level = new_level == "warn" || new_level == :warn ? :warning : new_level end def interface(name, value = nil, &block) int = Interface.registered[name] raise(Error, "Unknown interface: #{name}") unless int @interfaces[int.sentry_alias] = int.new(value, &block) if value || block @interfaces[int.sentry_alias] end def [](key) interface(key) end def []=(key, value) interface(key, value) end def to_hash data = [:checksum, :environment, :event_id, :extra, :fingerprint, :level, :logger, :message, :modules, :platform, :release, :sdk, :server_name, :tags, :time_spent, :timestamp, :transaction, :user].each_with_object({}) do |att, memo| memo[att] = public_send(att) if public_send(att) end data[:breadcrumbs] = @breadcrumbs.to_hash unless @breadcrumbs.empty? @interfaces.each_pair do |name, int_data| data[name.to_sym] = int_data.to_hash end data end def to_json_compatible cleaned_hash = async_json_processors.reduce(to_hash) { |a, e| e.process(a) } JSON.parse(JSON.generate(cleaned_hash)) end def add_exception_interface(exc) interface(:exception) do |exc_int| exceptions = Raven::Utils::ExceptionCauseChain.exception_to_array(exc).reverse backtraces = Set.new exc_int.values = exceptions.map do |e| SingleExceptionInterface.new do |int| int.type = e.class.to_s int.value = e.to_s int.module = e.class.to_s.split('::')[0...-1].join('::') int.stacktrace = if e.backtrace && !backtraces.include?(e.backtrace.object_id) backtraces << e.backtrace.object_id StacktraceInterface.new do |stacktrace| stacktrace.frames = stacktrace_interface_from(e.backtrace) end end end end end end def stacktrace_interface_from(backtrace) Backtrace.parse(backtrace).lines.reverse.each_with_object([]) do |line, memo| frame = StacktraceInterface::Frame.new frame.abs_path = line.file if line.file frame.function = line.method if line.method frame.lineno = line.number frame.in_app = line.in_app frame.module = line.module_name if line.module_name if configuration[:context_lines] && frame.abs_path frame.pre_context, frame.context_line, frame.post_context = \ configuration.linecache.get_file_context(frame.abs_path, frame.lineno, configuration[:context_lines]) end memo << frame if frame.filename end end # For cross-language compat class << self alias captureException from_exception alias captureMessage from_message alias capture_exception from_exception alias capture_message from_message end private def copy_initial_state self.configuration = Raven.configuration self.breadcrumbs = Raven.breadcrumbs self.context = Raven.context end def set_core_attributes_from_configuration self.server_name ||= configuration.server_name self.release ||= configuration.release self.modules = list_gem_specs if configuration.send_modules self.environment ||= configuration.current_environment end def set_core_attributes_from_context self.transaction ||= context.transaction.last # If this is a Rack event, merge Rack context add_rack_context if !self[:http] && context.rack_env # Merge contexts self.user = context.user.merge(user) # TODO: contexts self.extra = context.extra.merge(extra) # TODO: contexts self.tags = configuration.tags.merge(context.tags).merge!(tags) # TODO: contexts end def add_rack_context interface :http do |int| int.from_rack(context.rack_env) end context.user[:ip_address] = calculate_real_ip_from_rack end # When behind a proxy (or if the user is using a proxy), we can't use # REMOTE_ADDR to determine the Event IP, and must use other headers instead. def calculate_real_ip_from_rack Utils::RealIp.new( :remote_addr => context.rack_env["REMOTE_ADDR"], :client_ip => context.rack_env["HTTP_CLIENT_IP"], :real_ip => context.rack_env["HTTP_X_REAL_IP"], :forwarded_for => context.rack_env["HTTP_X_FORWARDED_FOR"] ).calculate_ip end def async_json_processors configuration.processors.map { |v| v.new(self) } end def list_gem_specs # Older versions of Rubygems don't support iterating over all specs Hash[Gem::Specification.map { |spec| [spec.name, spec.version.to_s] }] if Gem::Specification.respond_to?(:map) end end end raven-ruby-2.13.0/lib/raven/instance.rb000066400000000000000000000151571357613622200177210ustar00rootroot00000000000000module Raven # A copy of Raven's base module class methods, minus some of the integration # and global hooks since it's meant to be used explicitly. Useful for # sending errors to multiple sentry projects in a large application. # # @example # class Foo # def initialize # @other_raven = Raven::Instance.new # @other_raven.configure do |config| # config.server = 'http://...' # end # end # # def foo # # ... # rescue => e # @other_raven.capture_exception(e) # end # end class Instance # See Raven::Client. attr_writer :client # See Raven::Configuration. attr_accessor :configuration def initialize(context = nil, config = nil) @context = @explicit_context = context self.configuration = config || Configuration.new end def context if @explicit_context @context ||= Context.new else Context.current end end def logger configuration.logger end # The client object is responsible for delivering formatted data to the # Sentry server. def client @client ||= Client.new(configuration) end # Tell the log that the client is good to go def report_status return if configuration.silence_ready if configuration.capture_allowed? logger.info "Raven #{VERSION} ready to catch errors" else logger.info "Raven #{VERSION} configured not to capture errors: #{configuration.error_messages}" end end # Call this method to modify defaults in your initializers. # # @example # Raven.configure do |config| # config.server = 'http://...' # end def configure yield(configuration) if block_given? self.client = Client.new(configuration) report_status client end # Send an event to the configured Sentry server # # @example # evt = Raven::Event.new(:message => "An error") # Raven.send_event(evt) def send_event(event, hint = nil) client.send_event(event, hint) end # Capture and process any exceptions from the given block. # # @example # Raven.capture do # MyApp.run # end def capture(options = {}) if block_given? begin yield rescue Error raise # Don't capture Raven errors rescue Exception => e capture_type(e, options) raise end else install_at_exit_hook(options) end end def capture_type(obj, options = {}) unless configuration.capture_allowed?(obj) logger.debug("#{obj} excluded from capture: #{configuration.error_messages}") return false end message_or_exc = obj.is_a?(String) ? "message" : "exception" options[:configuration] = configuration options[:context] = context if (evt = Event.send("from_" + message_or_exc, obj, options)) yield evt if block_given? if configuration.async? begin # We have to convert to a JSON-like hash, because background job # processors (esp ActiveJob) may not like weird types in the event hash configuration.async.call(evt.to_json_compatible) rescue => ex logger.error("async event sending failed: #{ex.message}") send_event(evt, make_hint(obj)) end else send_event(evt, make_hint(obj)) end Thread.current["sentry_#{object_id}_last_event_id".to_sym] = evt.id evt end end alias capture_message capture_type alias capture_exception capture_type def last_event_id Thread.current["sentry_#{object_id}_last_event_id".to_sym] end # Provides extra context to the exception prior to it being handled by # Raven. An exception can have multiple annotations, which are merged # together. # # The options (annotation) is treated the same as the ``options`` # parameter to ``capture_exception`` or ``Event.from_exception``, and # can contain the same ``:user``, ``:tags``, etc. options as these # methods. # # These will be merged with the ``options`` parameter to # ``Event.from_exception`` at the top of execution. # # @example # begin # raise "Hello" # rescue => exc # Raven.annotate_exception(exc, :user => { 'id' => 1, # 'email' => 'foo@example.com' }) # end def annotate_exception(exc, options = {}) notes = (exc.instance_variable_defined?(:@__raven_context) && exc.instance_variable_get(:@__raven_context)) || {} Raven::Utils::DeepMergeHash.deep_merge!(notes, options) exc.instance_variable_set(:@__raven_context, notes) exc end # Bind user context. Merges with existing context (if any). # # It is recommending that you send at least the ``id`` and ``email`` # values. All other values are arbitrary. # # @example # Raven.user_context('id' => 1, 'email' => 'foo@example.com') def user_context(options = nil) context.user = options || {} end # Bind tags context. Merges with existing context (if any). # # Tags are key / value pairs which generally represent things like # application version, environment, role, and server names. # # @example # Raven.tags_context('my_custom_tag' => 'tag_value') def tags_context(options = nil) context.tags.merge!(options || {}) yield if block_given? context.tags ensure context.tags.delete_if { |k, _| options.keys.include? k } if block_given? end # Bind extra context. Merges with existing context (if any). # # Extra context shows up as Additional Data within Sentry, and is # completely arbitrary. # # @example # Raven.extra_context('my_custom_data' => 'value') def extra_context(options = nil) context.extra.merge!(options || {}) yield if block_given? context.extra ensure context.extra.delete_if { |k, _| options.keys.include? k } if block_given? end def rack_context(env) env = nil if env.empty? context.rack_env = env end def breadcrumbs BreadcrumbBuffer.current end private def install_at_exit_hook(options) at_exit do exception = $ERROR_INFO if exception logger.debug "Caught a post-mortem exception: #{exception.inspect}" capture_type(exception, options) end end end def make_hint(obj) obj.is_a?(String) ? { :exception => nil, :message => obj } : { :exception => obj, :message => nil } end end end raven-ruby-2.13.0/lib/raven/integrations/000077500000000000000000000000001357613622200202655ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/integrations/delayed_job.rb000066400000000000000000000040161357613622200230540ustar00rootroot00000000000000require 'delayed_job' module Delayed module Plugins class Raven < ::Delayed::Plugin callbacks do |lifecycle| lifecycle.around(:invoke_job) do |job, *args, &block| begin # Forward the call to the next callback in the callback chain block.call(job, *args) rescue Exception => exception # Log error to Sentry extra = { :delayed_job => { :id => job.id.to_s, :priority => job.priority, :attempts => job.attempts, :run_at => job.run_at, :locked_at => job.locked_at, :locked_by => job.locked_by, :queue => job.queue, :created_at => job.created_at } } # last_error can be nil extra[:last_error] = job.last_error[0...1000] if job.last_error # handlers are YAML objects in strings, we definitely can't # report all of that or the event will get truncated randomly extra[:handler] = job.handler[0...1000] if job.handler if job.respond_to?('payload_object') && job.payload_object.respond_to?('job_data') extra[:active_job] = job.payload_object.job_data end ::Raven.capture_exception(exception, :logger => 'delayed_job', :tags => { :delayed_job_queue => job.queue, :delayed_job_id => job.id.to_s }, :extra => extra) # Make sure we propagate the failure! raise exception ensure ::Raven::Context.clear! ::Raven::BreadcrumbBuffer.clear! end end end end end end ## # Register DelayedJob Raven plugin # Delayed::Worker.plugins << Delayed::Plugins::Raven raven-ruby-2.13.0/lib/raven/integrations/rack-timeout.rb000066400000000000000000000015471357613622200232250ustar00rootroot00000000000000# We need to do this because of the way integration loading works require "rack/timeout/base" unless defined?(Rack::Timeout) # This integration is a good example of how to change how exceptions # get grouped by Sentry's UI. Simply override #raven_context in # the exception class, and append something to the fingerprint # that will distinguish exceptions in the way you desire. module RackTimeoutExtensions def raven_context # Only rack-timeout 0.3.0+ provides the request environment, but we can't # gate this based on a gem version constant because rack-timeout does # not provide one. { :fingerprint => ["{{ default }}", env["REQUEST_URI"]] } if defined?(env) end end # Include is private in Ruby 1.9 Rack::Timeout::Error.__send__(:include, RackTimeoutExtensions) Rack::Timeout::RequestTimeoutException.__send__(:include, RackTimeoutExtensions) raven-ruby-2.13.0/lib/raven/integrations/rack.rb000066400000000000000000000103171357613622200215340ustar00rootroot00000000000000require 'time' require 'rack' module Raven # Middleware for Rack applications. Any errors raised by the upstream # application will be delivered to Sentry and re-raised. # # Synopsis: # # require 'rack' # require 'raven' # # Raven.configure do |config| # config.server = 'http://my_dsn' # end # # app = Rack::Builder.app do # use Raven::Rack # run lambda { |env| raise "Rack down" } # end # # Use a standard Raven.configure call to configure your server credentials. class Rack def self.capture_type(exception, env, options = {}) if env['raven.requested_at'] options[:time_spent] = Time.now - env['raven.requested_at'] end Raven.capture_type(exception, options) do |evt| evt.interface :http do |int| int.from_rack(env) end end end class << self alias capture_message capture_type alias capture_exception capture_type end def initialize(app) @app = app end def call(env) # store the current environment in our local context for arbitrary # callers env['raven.requested_at'] = Time.now Raven.rack_context(env) Raven.context.transaction.push(env["PATH_INFO"]) if env["PATH_INFO"] begin response = @app.call(env) rescue Error raise # Don't capture Raven errors rescue Exception => e Raven::Rack.capture_exception(e, env) raise end error = env['rack.exception'] || env['sinatra.error'] Raven::Rack.capture_exception(error, env) if error response ensure Context.clear! BreadcrumbBuffer.clear! end end module RackInterface def from_rack(env_hash) req = ::Rack::Request.new(env_hash) self.url = req.scheme && req.url.split('?').first self.method = req.request_method self.query_string = req.query_string self.data = read_data_from(req) self.cookies = req.cookies self.headers = format_headers_for_sentry(env_hash) self.env = format_env_for_sentry(env_hash) end private # See Sentry server default limits at # https://github.com/getsentry/sentry/blob/master/src/sentry/conf/server.py def read_data_from(request) if request.form_data? request.POST elsif request.body # JSON requests, etc data = request.body.read(4096 * 4) # Sentry server limit request.body.rewind data end rescue IOError => ex ex.message end def format_headers_for_sentry(env_hash) env_hash.each_with_object({}) do |(key, value), memo| begin key = key.to_s # rack env can contain symbols value = value.to_s next unless key.upcase == key # Non-upper case stuff isn't either # Rack adds in an incorrect HTTP_VERSION key, which causes downstream # to think this is a Version header. Instead, this is mapped to # env['SERVER_PROTOCOL']. But we don't want to ignore a valid header # if the request has legitimately sent a Version header themselves. # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29 next if key == 'HTTP_VERSION' && value == env_hash['SERVER_PROTOCOL'] next if key == 'HTTP_COOKIE' # Cookies don't go here, they go somewhere else next unless key.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(key) # Rack stores headers as HTTP_WHAT_EVER, we need What-Ever key = key.gsub("HTTP_", "") key = key.split('_').map(&:capitalize).join('-') memo[key] = value rescue StandardError => e # Rails adds objects to the Rack env that can sometimes raise exceptions # when `to_s` is called. # See: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb#L134 Raven.logger.warn("Error raised while formatting headers: #{e.message}") next end end end def format_env_for_sentry(env_hash) env_hash.select do |k, _v| %w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s end end end class HttpInterface include RackInterface end end raven-ruby-2.13.0/lib/raven/integrations/rails.rb000066400000000000000000000043051357613622200217260ustar00rootroot00000000000000require 'rails' module Raven class Rails < ::Rails::Railtie require 'raven/integrations/rails/overrides/streaming_reporter' require 'raven/integrations/rails/controller_methods' require 'raven/integrations/rails/controller_transaction' initializer "raven.use_rack_middleware" do |app| app.config.middleware.insert 0, Raven::Rack end initializer 'raven.action_controller' do ActiveSupport.on_load :action_controller do include Raven::Rails::ControllerMethods include Raven::Rails::ControllerTransaction if ::Rails::VERSION::STRING >= "4.0.0" Raven.safely_prepend( "StreamingReporter", :from => Raven::Rails::Overrides, :to => ActionController::Live ) end end end initializer 'raven.action_view' do ActiveSupport.on_load :action_view do Raven.safely_prepend( "StreamingReporter", :from => Raven::Rails::Overrides, :to => ActionView::StreamingTemplateRenderer::Body ) end end config.before_initialize do Raven.configuration.logger = ::Rails.logger end config.after_initialize do if Raven.configuration.rails_activesupport_breadcrumbs require 'raven/breadcrumbs/activesupport' Raven::ActiveSupportBreadcrumbs.inject end if Raven.configuration.rails_report_rescued_exceptions require 'raven/integrations/rails/overrides/debug_exceptions_catcher' if defined?(::ActionDispatch::DebugExceptions) exceptions_class = ::ActionDispatch::DebugExceptions elsif defined?(::ActionDispatch::ShowExceptions) exceptions_class = ::ActionDispatch::ShowExceptions end Raven.safely_prepend( "DebugExceptionsCatcher", :from => Raven::Rails::Overrides, :to => exceptions_class ) end end initializer 'raven.active_job' do ActiveSupport.on_load :active_job do require 'raven/integrations/rails/active_job' end end rake_tasks do require 'raven/integrations/tasks' end if defined?(runner) runner do Raven.capture end end end end raven-ruby-2.13.0/lib/raven/integrations/rails/000077500000000000000000000000001357613622200213775ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/integrations/rails/active_job.rb000066400000000000000000000033011357613622200240260ustar00rootroot00000000000000module Raven class Rails module ActiveJobExtensions ALREADY_SUPPORTED_SENTRY_ADAPTERS = %w( ActiveJob::QueueAdapters::SidekiqAdapter ActiveJob::QueueAdapters::DelayedJobAdapter ).freeze def self.included(base) base.class_eval do around_perform do |job, block| if already_supported_by_specific_integration?(job) block.call else capture_and_reraise_with_sentry(job, block) end end end end def capture_and_reraise_with_sentry(job, block) block.call rescue Exception => exception # rubocop:disable Lint/RescueException return if rescue_with_handler(exception) Raven.capture_exception(exception, :extra => raven_context(job)) raise exception ensure Context.clear! BreadcrumbBuffer.clear! end def already_supported_by_specific_integration?(job) if ::Rails.version.to_f < 5.0 ALREADY_SUPPORTED_SENTRY_ADAPTERS.include?(job.class.queue_adapter.to_s) else ALREADY_SUPPORTED_SENTRY_ADAPTERS.include?(job.class.queue_adapter.class.to_s) end end def raven_context(job) ctx = { :active_job => job.class.name, :arguments => job.arguments, :scheduled_at => job.scheduled_at, :job_id => job.job_id, :locale => job.locale } # Add provider_job_id details if Rails 5 if job.respond_to?(:provider_job_id) ctx[:provider_job_id] = job.provider_job_id end ctx end end end end class ActiveJob::Base include Raven::Rails::ActiveJobExtensions end raven-ruby-2.13.0/lib/raven/integrations/rails/controller_methods.rb000066400000000000000000000005171357613622200256350ustar00rootroot00000000000000module Raven class Rails module ControllerMethods def capture_message(message, options = {}) Raven::Rack.capture_message(message, request.env, options) end def capture_exception(exception, options = {}) Raven::Rack.capture_exception(exception, request.env, options) end end end end raven-ruby-2.13.0/lib/raven/integrations/rails/controller_transaction.rb000066400000000000000000000005221357613622200265130ustar00rootroot00000000000000module Raven class Rails module ControllerTransaction def self.included(base) base.prepend_around_action do |controller, block| Raven.context.transaction.push "#{controller.class}##{controller.action_name}" block.call Raven.context.transaction.pop end end end end end raven-ruby-2.13.0/lib/raven/integrations/rails/overrides/000077500000000000000000000000001357613622200234015ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb000066400000000000000000000017161357613622200307530ustar00rootroot00000000000000module Raven class Rails module Overrides module DebugExceptionsCatcher def render_exception(env_or_request, exception) begin env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request Raven::Rack.capture_exception(exception, env) rescue # rubocop:disable Lint/HandleExceptions end super end end module OldDebugExceptionsCatcher def self.included(base) base.send(:alias_method_chain, :render_exception, :raven) end def render_exception_with_raven(env_or_request, exception) begin env = env_or_request.respond_to?(:env) ? env_or_request.env : env_or_request Raven::Rack.capture_exception(exception, env) rescue # rubocop:disable Lint/HandleExceptions end render_exception_without_raven(env_or_request, exception) end end end end end raven-ruby-2.13.0/lib/raven/integrations/rails/overrides/streaming_reporter.rb000066400000000000000000000007761357613622200276530ustar00rootroot00000000000000module Raven class Rails module Overrides module StreamingReporter def log_error(exception) Raven.capture_exception(exception) super end end module OldStreamingReporter def self.included(base) base.send(:alias_method_chain, :log_error, :raven) end def log_error_with_raven(exception) Raven.capture_exception(exception) log_error_without_raven(exception) end end end end end raven-ruby-2.13.0/lib/raven/integrations/railties.rb000066400000000000000000000000431357613622200224230ustar00rootroot00000000000000require 'raven/integrations/rails' raven-ruby-2.13.0/lib/raven/integrations/rake.rb000066400000000000000000000006741357613622200215430ustar00rootroot00000000000000require 'rake' require 'rake/task' require 'raven/integrations/tasks' module Rake class Application alias orig_display_error_messsage display_error_message def display_error_message(ex) Raven.capture_exception( ex, :transaction => top_level_tasks.join(' '), :logger => 'rake', :tags => { 'rake_task' => top_level_tasks.join(' ') } ) orig_display_error_messsage(ex) end end end raven-ruby-2.13.0/lib/raven/integrations/sidekiq.rb000066400000000000000000000045731357613622200222540ustar00rootroot00000000000000require 'time' require 'sidekiq' module Raven class SidekiqCleanupMiddleware def call(_worker, job, queue) Raven.context.transaction.push "Sidekiq/#{job['class']}" Raven.extra_context(:sidekiq => job.merge("queue" => queue)) yield Context.clear! BreadcrumbBuffer.clear! end end class SidekiqErrorHandler ACTIVEJOB_RESERVED_PREFIX = "_aj_".freeze HAS_GLOBALID = const_defined?('GlobalID') def call(ex, context) context = filter_context(context) Raven.context.transaction.push transaction_from_context(context) Raven.capture_exception( ex, :message => ex.message, :extra => { :sidekiq => context } ) Context.clear! BreadcrumbBuffer.clear! end private # Once an ActiveJob is queued, ActiveRecord references get serialized into # some internal reserved keys, such as _aj_globalid. # # The problem is, if this job in turn gets queued back into ActiveJob with # these magic reserved keys, ActiveJob will throw up and error. We want to # capture these and mutate the keys so we can sanely report it. def filter_context(context) case context when Array context.map { |arg| filter_context(arg) } when Hash Hash[context.map { |key, value| filter_context_hash(key, value) }] else format_globalid(context) end end def filter_context_hash(key, value) (key = key[3..-1]) if key [0..3] == ACTIVEJOB_RESERVED_PREFIX [key, filter_context(value)] end # this will change in the future: # https://github.com/mperham/sidekiq/pull/3161 def transaction_from_context(context) classname = (context["wrapped"] || context["class"] || (context[:job] && (context[:job]["wrapped"] || context[:job]["class"])) ) if classname "Sidekiq/#{classname}" elsif context[:event] "Sidekiq/#{context[:event]}" else "Sidekiq" end end def format_globalid(context) if HAS_GLOBALID && context.is_a?(GlobalID) context.to_s else context end end end end if Sidekiq::VERSION > '3' Sidekiq.configure_server do |config| config.error_handlers << Raven::SidekiqErrorHandler.new config.server_middleware do |chain| chain.add Raven::SidekiqCleanupMiddleware end end end raven-ruby-2.13.0/lib/raven/integrations/tasks.rb000066400000000000000000000004301357613622200217340ustar00rootroot00000000000000require 'rake' require 'raven/cli' namespace :raven do desc "Send a test event to the remote Sentry server" task :test, [:dsn] do |_t, args| Rake::Task["environment"].invoke if Rake::Task.tasks.map(&:to_s).include?("environment") Raven::CLI.test(args.dsn) end end raven-ruby-2.13.0/lib/raven/interface.rb000066400000000000000000000011241357613622200200420ustar00rootroot00000000000000module Raven class Interface def initialize(attributes = nil) attributes.each do |attr, value| public_send "#{attr}=", value end if attributes yield self if block_given? end def self.inherited(klass) name = klass.name.split("::").last.downcase.gsub("interface", "") registered[name.to_sym] = klass super end def self.registered @@registered ||= {} # rubocop:disable Style/ClassVars end def to_hash Hash[instance_variables.map { |name| [name[1..-1].to_sym, instance_variable_get(name)] }] end end end raven-ruby-2.13.0/lib/raven/interfaces/000077500000000000000000000000001357613622200177025ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/interfaces/exception.rb000066400000000000000000000004251357613622200222260ustar00rootroot00000000000000module Raven class ExceptionInterface < Interface attr_accessor :values def self.sentry_alias :exception end def to_hash(*args) data = super(*args) data[:values] = data[:values].map(&:to_hash) if data[:values] data end end end raven-ruby-2.13.0/lib/raven/interfaces/http.rb000066400000000000000000000005001357613622200212010ustar00rootroot00000000000000module Raven class HttpInterface < Interface attr_accessor :url, :method, :data, :query_string, :cookies, :headers, :env def initialize(*arguments) self.headers = {} self.env = {} self.cookies = nil super(*arguments) end def self.sentry_alias :request end end end raven-ruby-2.13.0/lib/raven/interfaces/message.rb000066400000000000000000000005421357613622200216540ustar00rootroot00000000000000require 'raven/interface' module Raven class MessageInterface < Interface attr_accessor :message, :params def initialize(*arguments) self.params = [] super(*arguments) end def unformatted_message Array(params).empty? ? message : message % params end def self.sentry_alias :logentry end end end raven-ruby-2.13.0/lib/raven/interfaces/single_exception.rb000066400000000000000000000004731357613622200235720ustar00rootroot00000000000000module Raven class SingleExceptionInterface < Interface attr_accessor :type attr_accessor :value attr_accessor :module attr_accessor :stacktrace def to_hash(*args) data = super(*args) data[:stacktrace] = data[:stacktrace].to_hash if data[:stacktrace] data end end end raven-ruby-2.13.0/lib/raven/interfaces/stack_trace.rb000066400000000000000000000035141357613622200225150ustar00rootroot00000000000000module Raven class StacktraceInterface < Interface attr_accessor :frames def initialize(*arguments) super(*arguments) end def self.sentry_alias :stacktrace end def to_hash(*args) data = super(*args) data[:frames] = data[:frames].map(&:to_hash) data end # Not actually an interface, but I want to use the same style class Frame < Interface attr_accessor :abs_path, :context_line, :function, :in_app, :lineno, :module, :pre_context, :post_context, :vars def initialize(*arguments) super(*arguments) end def filename return if abs_path.nil? return @filename if instance_variable_defined?(:@filename) prefix = if under_project_root? && in_app project_root elsif under_project_root? longest_load_path || project_root else longest_load_path end @filename = prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path end def to_hash(*args) data = super(*args) data[:filename] = filename data.delete(:vars) unless vars && !vars.empty? data.delete(:pre_context) unless pre_context && !pre_context.empty? data.delete(:post_context) unless post_context && !post_context.empty? data.delete(:context_line) unless context_line && !context_line.empty? data end private def under_project_root? project_root && abs_path.start_with?(project_root) end def project_root @project_root ||= Raven.configuration.project_root && Raven.configuration.project_root.to_s end def longest_load_path $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size) end end end end raven-ruby-2.13.0/lib/raven/linecache.rb000066400000000000000000000020161357613622200200160ustar00rootroot00000000000000module Raven class LineCache def initialize @cache = {} end # Any linecache you provide to Raven must implement this method. # Returns an Array of Strings representing the lines in the source # file. The number of lines retrieved is (2 * context) + 1, the middle # line should be the line requested by lineno. See specs for more information. def get_file_context(filename, lineno, context) return nil, nil, nil unless valid_path?(filename) lines = Array.new(2 * context + 1) do |i| getline(filename, lineno - context + i) end [lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]] end private def valid_path?(path) lines = getlines(path) !lines.nil? end def getlines(path) @cache[path] ||= begin IO.readlines(path) rescue nil end end def getline(path, n) return nil if n < 1 lines = getlines(path) return nil if lines.nil? lines[n - 1] end end end raven-ruby-2.13.0/lib/raven/logger.rb000066400000000000000000000007351357613622200173700ustar00rootroot00000000000000# frozen_string_literal: true require 'logger' module Raven class Logger < ::Logger LOG_PREFIX = "** [Raven] ".freeze PROGNAME = "sentry".freeze def initialize(*) super @level = ::Logger::INFO original_formatter = ::Logger::Formatter.new @default_formatter = proc do |severity, datetime, _progname, msg| msg = "#{LOG_PREFIX}#{msg}" original_formatter.call(severity, datetime, PROGNAME, msg) end end end end raven-ruby-2.13.0/lib/raven/processor.rb000066400000000000000000000004371357613622200201270ustar00rootroot00000000000000module Raven class Processor STRING_MASK = '********'.freeze INT_MASK = 0 REGEX_SPECIAL_CHARACTERS = %w(. $ ^ { [ ( | ) * + ?).freeze def initialize(client = nil) @client = client end def process(_data) raise NotImplementedError end end end raven-ruby-2.13.0/lib/raven/processor/000077500000000000000000000000001357613622200175765ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/processor/cookies.rb000066400000000000000000000013561357613622200215640ustar00rootroot00000000000000module Raven class Processor::Cookies < Processor def process(data) process_if_symbol_keys(data) if data[:request] process_if_string_keys(data) if data["request"] data end private def process_if_symbol_keys(data) data[:request][:cookies] = STRING_MASK if data[:request][:cookies] return unless data[:request][:headers] && data[:request][:headers]["Cookie"] data[:request][:headers]["Cookie"] = STRING_MASK end def process_if_string_keys(data) data["request"]["cookies"] = STRING_MASK if data["request"]["cookies"] return unless data["request"]["headers"] && data["request"]["headers"]["Cookie"] data["request"]["headers"]["Cookie"] = STRING_MASK end end end raven-ruby-2.13.0/lib/raven/processor/http_headers.rb000066400000000000000000000025501357613622200225770ustar00rootroot00000000000000module Raven class Processor::HTTPHeaders < Processor DEFAULT_FIELDS = ["Authorization"].freeze attr_accessor :sanitize_http_headers def initialize(client) super self.sanitize_http_headers = client.configuration.sanitize_http_headers end def process(data) process_if_symbol_keys(data) if data[:request] process_if_string_keys(data) if data["request"] data end private def process_if_symbol_keys(data) return unless data[:request][:headers] data[:request][:headers].keys.select { |k| fields_re.match(k.to_s) }.each do |k| data[:request][:headers][k] = STRING_MASK end end def process_if_string_keys(data) return unless data["request"]["headers"] data["request"]["headers"].keys.select { |k| fields_re.match(k) }.each do |k| data["request"]["headers"][k] = STRING_MASK end end def matches_regexes?(k) fields_re.match(k.to_s) end def fields_re @fields_re ||= /#{(DEFAULT_FIELDS | sanitize_http_headers).map do |f| use_boundary?(f) ? "\\b#{f}\\b" : f end.join("|")}/i end def use_boundary?(string) !DEFAULT_FIELDS.include?(string) && !special_characters?(string) end def special_characters?(string) REGEX_SPECIAL_CHARACTERS.select { |r| string.include?(r) }.any? end end end raven-ruby-2.13.0/lib/raven/processor/post_data.rb000066400000000000000000000010011357613622200220710ustar00rootroot00000000000000module Raven class Processor::PostData < Processor def process(data) process_if_symbol_keys(data) if data[:request] process_if_string_keys(data) if data["request"] data end private def process_if_symbol_keys(data) return unless data[:request][:method] == "POST" data[:request][:data] = STRING_MASK end def process_if_string_keys(data) return unless data["request"]["method"] == "POST" data["request"]["data"] = STRING_MASK end end end raven-ruby-2.13.0/lib/raven/processor/removecircularreferences.rb000066400000000000000000000010661357613622200252120ustar00rootroot00000000000000module Raven class Processor::RemoveCircularReferences < Processor def process(value, visited = []) return "(...)" if visited.include?(value.__id__) visited << value.__id__ if value.is_a?(Array) || value.is_a?(Hash) case value when Hash !value.frozen? ? value.merge!(value) { |_, v| process v, visited } : value.merge(value) { |_, v| process v, visited } when Array !value.frozen? ? value.map! { |v| process v, visited } : value.map { |v| process v, visited } else value end end end end raven-ruby-2.13.0/lib/raven/processor/removestacktrace.rb000066400000000000000000000011611357613622200234640ustar00rootroot00000000000000module Raven class Processor::RemoveStacktrace < Processor def process(data) process_if_symbol_keys(data) if data[:exception] process_if_string_keys(data) if data["exception"] data end private def process_if_symbol_keys(data) data[:exception][:values].map do |single_exception| single_exception.delete(:stacktrace) if single_exception[:stacktrace] end end def process_if_string_keys(data) data["exception"]["values"].map do |single_exception| single_exception.delete("stacktrace") if single_exception["stacktrace"] end end end end raven-ruby-2.13.0/lib/raven/processor/sanitizedata.rb000066400000000000000000000053731357613622200226130ustar00rootroot00000000000000# frozen_string_literal: true require 'json' module Raven class Processor::SanitizeData < Processor DEFAULT_FIELDS = %w(authorization password passwd secret ssn social(.*)?sec).freeze CREDIT_CARD_RE = /\b(?:3[47]\d|(?:4\d|5[1-5]|65)\d{2}|6011)\d{12}\b/ QUERY_STRING = ['query_string', :query_string].freeze JSON_STARTS_WITH = ["[", "{"].freeze attr_accessor :sanitize_fields, :sanitize_credit_cards, :sanitize_fields_excluded def initialize(client) super self.sanitize_fields = client.configuration.sanitize_fields self.sanitize_credit_cards = client.configuration.sanitize_credit_cards self.sanitize_fields_excluded = client.configuration.sanitize_fields_excluded end def process(value, key = nil) case value when Hash !value.frozen? ? value.merge!(value) { |k, v| process v, k } : value.merge(value) { |k, v| process v, k } when Array !value.frozen? ? value.map! { |v| process v, key } : value.map { |v| process v, key } when Integer matches_regexes?(key, value.to_s) ? INT_MASK : value when String if value =~ fields_re && (json = parse_json_or_nil(value)) # if this string is actually a json obj, convert and sanitize process(json).to_json elsif matches_regexes?(key, value) STRING_MASK elsif QUERY_STRING.include?(key) sanitize_query_string(value) else value end else value end end private # CGI.parse takes our nice UTF-8 strings and converts them back to ASCII, # so we have to convert them back, again. def utf8_processor @utf8_processor ||= Processor::UTF8Conversion.new end def sanitize_query_string(query_string) query_hash = CGI.parse(query_string) sanitized = utf8_processor.process(query_hash) processed_query_hash = process(sanitized) URI.encode_www_form(processed_query_hash) end def matches_regexes?(k, v) (sanitize_credit_cards && v =~ CREDIT_CARD_RE) || k =~ fields_re end def fields_re return @fields_re if instance_variable_defined?(:@fields_re) fields = DEFAULT_FIELDS | sanitize_fields fields -= sanitize_fields_excluded @fields_re = /#{fields.map do |f| use_boundary?(f) ? "\\b#{f}\\b" : f end.join("|")}/i end def use_boundary?(string) !DEFAULT_FIELDS.include?(string) && !special_characters?(string) end def special_characters?(string) REGEX_SPECIAL_CHARACTERS.select { |r| string.include?(r) }.any? end def parse_json_or_nil(string) return unless string.start_with?(*JSON_STARTS_WITH) JSON.parse(string) rescue JSON::ParserError, NoMethodError nil end end end raven-ruby-2.13.0/lib/raven/processor/utf8conversion.rb000066400000000000000000000036341357613622200231250ustar00rootroot00000000000000module Raven class Processor::UTF8Conversion < Processor # Slightly misnamed - actually just removes any bytes with invalid encoding # Previously, our JSON backend required UTF-8. Since we now use the built-in # JSON, we can use any encoding, but it must be valid anyway so we can do # things like call #match and #slice on strings REPLACE = "".freeze def process(value) case value when Hash !value.frozen? ? value.merge!(value) { |_, v| process v } : value.merge(value) { |_, v| process v } when Array !value.frozen? ? value.map! { |v| process v } : value.map { |v| process v } when Exception return value if value.message.valid_encoding? clean_exc = value.class.new(remove_invalid_bytes(value.message)) clean_exc.set_backtrace(value.backtrace) clean_exc when String # Encoding::BINARY / Encoding::ASCII_8BIT is a special binary encoding. # valid_encoding? will always return true because it contains all codepoints, # so instead we check if it only contains actual ASCII codepoints, and if # not we assume it's actually just UTF8 and scrub accordingly. if value.encoding == Encoding::BINARY && !value.ascii_only? value = value.dup value.force_encoding(Encoding::UTF_8) end return value if value.valid_encoding? remove_invalid_bytes(value) else value end end private # Stolen from RSpec # https://github.com/rspec/rspec-support/blob/f0af3fd74a94ff7bb700f6ba06dbdc67bba17fbf/lib/rspec/support/encoded_string.rb#L120-L139 if String.method_defined?(:scrub) # 2.1+ def remove_invalid_bytes(string) string.scrub(REPLACE) end else def remove_invalid_bytes(string) string.chars.map do |char| char.valid_encoding? ? char : REPLACE end.join end end end end raven-ruby-2.13.0/lib/raven/transports.rb000066400000000000000000000005111357613622200203200ustar00rootroot00000000000000module Raven module Transports class Transport attr_accessor :configuration def initialize(configuration) @configuration = configuration end def send_event # (auth_header, data, options = {}) raise NotImplementedError, 'Abstract method not implemented' end end end end raven-ruby-2.13.0/lib/raven/transports/000077500000000000000000000000001357613622200177765ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/transports/dummy.rb000066400000000000000000000004421357613622200214560ustar00rootroot00000000000000module Raven module Transports class Dummy < Transport attr_accessor :events def initialize(*) super @events = [] end def send_event(auth_header, data, options = {}) @events << [auth_header, data, options] end end end end raven-ruby-2.13.0/lib/raven/transports/http.rb000066400000000000000000000041431357613622200213040ustar00rootroot00000000000000require 'faraday' require 'raven/transports' module Raven module Transports class HTTP < Transport attr_accessor :conn, :adapter def initialize(*args) super self.adapter = configuration.http_adapter || Faraday.default_adapter self.conn = set_conn end def send_event(auth_header, data, options = {}) unless configuration.sending_allowed? logger.debug("Event not sent: #{configuration.error_messages}") end project_id = configuration[:project_id] path = configuration[:path] + "/" conn.post "#{path}api/#{project_id}/store/" do |req| req.headers['Content-Type'] = options[:content_type] req.headers['X-Sentry-Auth'] = auth_header req.body = data end rescue Faraday::Error => ex error_info = ex.message if ex.response && ex.response[:headers]['x-sentry-error'] error_info += " Error in headers is: #{ex.response[:headers]['x-sentry-error']}" end raise Raven::Error, error_info end private def set_conn configuration.logger.debug "Raven HTTP Transport connecting to #{configuration.server}" proxy = configuration.public_send(:proxy) Faraday.new(configuration.server, :ssl => ssl_configuration, :proxy => proxy) do |builder| configuration.faraday_builder.call(builder) if configuration.faraday_builder builder.response :raise_error builder.options.merge! faraday_opts builder.headers[:user_agent] = "sentry-ruby/#{Raven::VERSION}" builder.adapter(*adapter) end end # TODO: deprecate and replace where possible w/Faraday Builder def faraday_opts [:timeout, :open_timeout].each_with_object({}) do |opt, memo| memo[opt] = configuration.public_send(opt) if configuration.public_send(opt) end end def ssl_configuration (configuration.ssl || {}).merge( :verify => configuration.ssl_verification, :ca_file => configuration.ssl_ca_file ) end end end end raven-ruby-2.13.0/lib/raven/transports/stdout.rb000066400000000000000000000006251357613622200216500ustar00rootroot00000000000000module Raven module Transports class Stdout < Transport attr_accessor :events def initialize(*) super end def send_event(_auth_header, data, _options = {}) unless configuration.sending_allowed? logger.debug("Event not sent: #{configuration.error_messages}") end $stdout.puts data $stdout.flush end end end end raven-ruby-2.13.0/lib/raven/utils/000077500000000000000000000000001357613622200167175ustar00rootroot00000000000000raven-ruby-2.13.0/lib/raven/utils/deep_merge.rb000066400000000000000000000011151357613622200213360ustar00rootroot00000000000000module Raven module Utils # ported from ActiveSupport module DeepMergeHash def self.deep_merge(hash, other_hash, &block) deep_merge!(hash, other_hash, &block) end def self.deep_merge!(hash, other_hash, &block) hash.merge!(other_hash) do |key, this_val, other_val| if this_val.is_a?(Hash) && other_val.is_a?(Hash) deep_merge(this_val, other_val, &block) elsif block_given? block.call(key, this_val, other_val) else other_val end end end end end end raven-ruby-2.13.0/lib/raven/utils/exception_cause_chain.rb000066400000000000000000000007611357613622200235700ustar00rootroot00000000000000module Raven module Utils module ExceptionCauseChain def self.exception_to_array(exception) if exception.respond_to?(:cause) && exception.cause exceptions = [exception] while exception.cause exception = exception.cause break if exceptions.any? { |e| e.object_id == exception.object_id } exceptions << exception end exceptions else [exception] end end end end end raven-ruby-2.13.0/lib/raven/utils/real_ip.rb000066400000000000000000000042111357613622200206550ustar00rootroot00000000000000require 'ipaddr' # Based on ActionDispatch::RemoteIp. All security-related precautions from that # middleware have been removed, because the Event IP just needs to be accurate, # and spoofing an IP here only makes data inaccurate, not insecure. Don't re-use # this module if you have to *trust* the IP address. module Raven module Utils class RealIp LOCAL_ADDRESSES = [ "127.0.0.1", # localhost IPv4 "::1", # localhost IPv6 "fc00::/7", # private IPv6 range fc00::/7 "10.0.0.0/8", # private IPv4 range 10.x.x.x "172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255 "192.168.0.0/16", # private IPv4 range 192.168.x.x ].map { |proxy| IPAddr.new(proxy) } attr_accessor :ip, :ip_addresses def initialize(ip_addresses) self.ip_addresses = ip_addresses end def calculate_ip # CGI environment variable set by Rack remote_addr = ips_from(ip_addresses[:remote_addr]).last # Could be a CSV list and/or repeated headers that were concatenated. client_ips = ips_from(ip_addresses[:client_ip]) real_ips = ips_from(ip_addresses[:real_ip]) forwarded_ips = ips_from(ip_addresses[:forwarded_for]) ips = [client_ips, real_ips, forwarded_ips, remote_addr].flatten.compact # If every single IP option is in the trusted list, just return REMOTE_ADDR self.ip = filter_local_addresses(ips).first || remote_addr end protected def ips_from(header) # Split the comma-separated list into an array of strings ips = header ? header.strip.split(/[,\s]+/) : [] ips.select do |ip| begin # Only return IPs that are valid according to the IPAddr#new method range = IPAddr.new(ip).to_range # we want to make sure nobody is sneaking a netmask in range.begin == range.end rescue ArgumentError nil end end end def filter_local_addresses(ips) ips.reject { |ip| LOCAL_ADDRESSES.any? { |proxy| proxy === ip } } end end end end raven-ruby-2.13.0/lib/raven/version.rb000066400000000000000000000002271357613622200175720ustar00rootroot00000000000000# frozen_string_literal: true module Raven # Freezing this constant breaks in 1.9.x VERSION = "2.13.0" # rubocop:disable Style/MutableConstant end raven-ruby-2.13.0/lib/sentry-raven-without-integrations.rb000066400000000000000000000000251357613622200236300ustar00rootroot00000000000000require 'raven/base' raven-ruby-2.13.0/lib/sentry-raven.rb000066400000000000000000000000201357613622200174160ustar00rootroot00000000000000require "raven" raven-ruby-2.13.0/sentry-raven.gemspec000066400000000000000000000013531357613622200177020ustar00rootroot00000000000000$LOAD_PATH.unshift File.expand_path('../lib', __FILE__) require 'raven/version' Gem::Specification.new do |gem| gem.name = "sentry-raven" gem.authors = ["Sentry Team"] gem.description = gem.summary = "A gem that provides a client interface for the Sentry error logger" gem.email = "accounts@sentry.io" gem.license = 'Apache-2.0' gem.homepage = "https://github.com/getsentry/raven-ruby" gem.version = Raven::VERSION gem.platform = Gem::Platform::RUBY gem.required_ruby_version = '>= 1.9.0' gem.extra_rdoc_files = ["README.md", "LICENSE"] gem.files = `git ls-files | grep -Ev '^(spec|benchmarks|examples)'`.split("\n") gem.bindir = "exe" gem.executables = "raven" gem.add_dependency "faraday", ">= 0.7.6", "< 1.0" end raven-ruby-2.13.0/spec/000077500000000000000000000000001357613622200146305ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/000077500000000000000000000000001357613622200157435ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/backtrace_spec.rb000066400000000000000000000010251357613622200212170ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Backtrace do before(:each) do @backtrace = Raven::Backtrace.parse(Thread.current.backtrace) end it "#lines" do expect(@backtrace.lines.first).to be_a(Raven::Backtrace::Line) end it "#inspect" do expect(@backtrace.inspect).to match(/Backtrace: .*>$/) end it "#to_s" do expect(@backtrace.to_s).to match(/backtrace_spec.rb:5/) end it "==" do @backtrace2 = Raven::Backtrace.new(@backtrace.lines) expect(@backtrace).to be == @backtrace2 end end raven-ruby-2.13.0/spec/raven/breadcrumbs_spec.rb000066400000000000000000000033611357613622200215760ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::BreadcrumbBuffer do before(:each) do @breadcrumbs = Raven::BreadcrumbBuffer.new(10) end it "records breadcrumbs w/a block" do expect(@breadcrumbs.empty?).to be true @breadcrumbs.record do Raven::Breadcrumb.new.tap { |b| b.message = "test" } end expect(@breadcrumbs.members.size).to eq(1) expect(@breadcrumbs.empty?).to be false end it "records breadcrumbs w/o block" do crumb = Raven::Breadcrumb.new.tap { |b| b.message = "test" } @breadcrumbs.record(crumb) expect(@breadcrumbs.members[0]).to eq(crumb) end it "allows peeking" do expect(@breadcrumbs.peek).to eq(nil) crumb = Raven::Breadcrumb.new.tap { |b| b.message = "test" } @breadcrumbs.record(crumb) expect(@breadcrumbs.peek).to eq(crumb) end it "is enumerable" do (0..10).each do |i| @breadcrumbs.record(Raven::Breadcrumb.new.tap { |b| b.message = i }) end expect(@breadcrumbs.each).to be_a Enumerator end it "evicts when buffer exceeded" do (0..10).each do |i| @breadcrumbs.record(Raven::Breadcrumb.new.tap { |b| b.message = i }) end expect(@breadcrumbs.members[0].message).to eq(1) expect(@breadcrumbs.members[-1].message).to eq(10) end it "converts to a hash" do expect(@breadcrumbs.peek).to eq(nil) crumb = Raven::Breadcrumb.new.tap { |b| b.message = "test" } @breadcrumbs.record(crumb) expect(@breadcrumbs.to_hash[:values]).to eq([crumb.to_hash]) end it "clears in a threaded context" do crumb = Raven::Breadcrumb.new.tap { |b| b.message = "test" } Raven::BreadcrumbBuffer.current.record(crumb) Raven::BreadcrumbBuffer.clear! expect(Raven::BreadcrumbBuffer.current.empty?).to be true end end raven-ruby-2.13.0/spec/raven/cli_spec.rb000066400000000000000000000006301357613622200200500ustar00rootroot00000000000000require 'spec_helper' require 'raven/cli' RSpec.describe "CLI tests" do it "posting an exception" do event = Raven::CLI.test(Raven.configuration.server, true, Raven.configuration) expect(event).to be_a(Raven::Event) hash = event.to_hash expect(hash[:exception][:values][0][:type]).to eq("ZeroDivisionError") expect(hash[:exception][:values][0][:value]).to eq("divided by 0") end end raven-ruby-2.13.0/spec/raven/client_spec.rb000066400000000000000000000027021357613622200205610ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Client do let(:configuration) do Raven::Configuration.new.tap do |config| config.server = 'http://12345:67890@sentry.localdomain/sentry/42' end end let(:client) { Raven::Client.new(configuration) } before do @fake_time = Time.now allow(Time).to receive(:now).and_return @fake_time end it "generates an auth header" do expect(client.send(:generate_auth_header)).to eq( "Sentry sentry_version=5, sentry_client=raven-ruby/#{Raven::VERSION}, sentry_timestamp=#{@fake_time.to_i}, " \ "sentry_key=12345, sentry_secret=67890" ) end it "generates a message with exception" do event = Raven::CLI.test(Raven.configuration.server, true, Raven.configuration).to_hash expect(client.send(:get_message_from_exception, event)).to eq("ZeroDivisionError: divided by 0") end it "generates a message without exception" do event = Raven::Event.from_message("this is an STDOUT transport test").to_hash expect(client.send(:get_message_from_exception, event)).to eq(nil) end it "generates an auth header without a secret (Sentry 9)" do client.configuration.server = "https://66260460f09b5940498e24bb7ce093a0@sentry.io/42" expect(client.send(:generate_auth_header)).to eq( "Sentry sentry_version=5, sentry_client=raven-ruby/#{Raven::VERSION}, sentry_timestamp=#{@fake_time.to_i}, " \ "sentry_key=66260460f09b5940498e24bb7ce093a0" ) end end raven-ruby-2.13.0/spec/raven/client_state_spec.rb000066400000000000000000000022531357613622200217620ustar00rootroot00000000000000require 'spec_helper' require 'timecop' RSpec.describe Raven::ClientState do let(:state) { Raven::ClientState.new } it 'should try when online' do expect(state.should_try?).to eq(true) end it 'should not try with a new error' do state.failure expect(state.should_try?).to eq(false) end it 'should try again after time passes' do Timecop.freeze(-10) { state.failure } expect(state.should_try?).to eq(true) end it 'should try again after success' do state.failure state.success expect(state.should_try?).to eq(true) end it 'should try again after retry_after' do Timecop.freeze(-2) { state.failure(1) } expect(state.should_try?).to eq(true) end it 'should exponentially backoff' do Timecop.freeze do state.failure Timecop.travel(2) expect(state.should_try?).to eq(true) state.failure Timecop.travel(3) expect(state.should_try?).to eq(false) Timecop.travel(2) expect(state.should_try?).to eq(true) state.failure Timecop.travel(8) expect(state.should_try?).to eq(false) Timecop.travel(2) expect(state.should_try?).to eq(true) end end end raven-ruby-2.13.0/spec/raven/configuration_spec.rb000066400000000000000000000220711357613622200221530ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Configuration do before do # Make sure we reset the env in case something leaks in ENV.delete('SENTRY_DSN') ENV.delete('SENTRY_CURRENT_ENV') ENV.delete('SENTRY_ENVIRONMENT') ENV.delete('SENTRY_RELEASE') ENV.delete('RAILS_ENV') ENV.delete('RACK_ENV') end it "should set some attributes when server is set" do subject.server = "http://12345:67890@sentry.localdomain:3000/sentry/42" expect(subject.project_id).to eq("42") expect(subject.public_key).to eq("12345") expect(subject.secret_key).to eq("67890") expect(subject.scheme).to eq("http") expect(subject.host).to eq("sentry.localdomain") expect(subject.port).to eq(3000) expect(subject.path).to eq("/sentry") expect(subject.server).to eq("http://sentry.localdomain:3000/sentry") end it "doesnt accept invalid encodings" do expect { subject.encoding = "apple" }.to raise_error(Raven::Error, 'Unsupported encoding') end it "has hashlike attribute accessors" do expect(subject.encoding).to eq("gzip") expect(subject[:encoding]).to eq("gzip") end context 'configuring for async' do it 'should be configurable to send events async' do subject.async = ->(_e) { :ok } expect(subject.async.call('event')).to eq(:ok) end it 'should raise when setting async to anything other than callable or false' do subject.transport_failure_callback = -> {} subject.transport_failure_callback = false expect { subject.async = true }.to raise_error(ArgumentError) end end it 'should raise when setting transport_failure_callback to anything other than callable or false' do subject.transport_failure_callback = -> {} subject.transport_failure_callback = false expect { subject.transport_failure_callback = true }.to raise_error(ArgumentError) end it 'should raise when setting should_capture to anything other than callable or false' do subject.should_capture = -> {} subject.should_capture = false expect { subject.should_capture = true }.to raise_error(ArgumentError) end it 'should raise when setting before_send to anything other than callable or false' do subject.before_send = -> {} subject.before_send = false expect { subject.before_send = true }.to raise_error(ArgumentError) end context 'being initialized with a current environment' do before(:each) do subject.current_environment = 'test' subject.server = 'http://12345:67890@sentry.localdomain:3000/sentry/42' end it 'should send events if test is whitelisted' do subject.environments = %w(test) subject.capture_allowed? puts subject.errors expect(subject.capture_allowed?).to eq(true) end it 'should not send events if test is not whitelisted' do subject.environments = %w(not_test) expect(subject.capture_allowed?).to eq(false) expect(subject.errors).to eq(["Not configured to send/capture in environment 'test'"]) end end context 'being initialized without a current environment' do after do ENV.delete('SENTRY_CURRENT_ENV') ENV.delete('SENTRY_ENVIRONMENT') ENV.delete('RAILS_ENV') ENV.delete('RACK_ENV') end it 'defaults to "default"' do expect(subject.current_environment).to eq('default') end it 'uses `SENTRY_CURRENT_ENV` env variable' do ENV['SENTRY_CURRENT_ENV'] = 'set-with-sentry-current-env' ENV['SENTRY_ENVIRONMENT'] = 'set-with-sentry-environment' ENV['RAILS_ENV'] = 'set-with-rails-env' ENV['RACK_ENV'] = 'set-with-rack-env' expect(subject.current_environment).to eq('set-with-sentry-current-env') end it 'uses `SENTRY_ENVIRONMENT` env variable' do ENV['SENTRY_ENVIRONMENT'] = 'set-with-sentry-environment' ENV['RAILS_ENV'] = 'set-with-rails-env' ENV['RACK_ENV'] = 'set-with-rack-env' expect(subject.current_environment).to eq('set-with-sentry-environment') end it 'uses `RAILS_ENV` env variable' do ENV['SENTRY_CURRENT_ENV'] = nil ENV['RAILS_ENV'] = 'set-with-rails-env' ENV['RACK_ENV'] = 'set-with-rack-env' expect(subject.current_environment).to eq('set-with-rails-env') end it 'uses `RACK_ENV` env variable' do ENV['SENTRY_CURRENT_ENV'] = nil ENV['RAILS_ENV'] = nil ENV['RACK_ENV'] = 'set-with-rack-env' expect(subject.current_environment).to eq('set-with-rack-env') end end context 'being initialized without a release' do before do allow(File).to receive(:directory?).with(".git").and_return(false) allow(File).to receive(:directory?).with("/etc/heroku").and_return(false) end it 'defaults to nil' do expect(subject.release).to eq(nil) end it 'uses `SENTRY_RELEASE` env variable' do ENV['SENTRY_RELEASE'] = 'v1' expect(subject.release).to eq('v1') ENV.delete('SENTRY_CURRENT_ENV') end end context 'with a should_capture callback configured' do before(:each) do subject.should_capture = ->(exc_or_msg) { exc_or_msg != "dont send me" } subject.server = 'http://12345:67890@sentry.localdomain:3000/sentry/42' end it 'should not send events if should_capture returns false' do expect(subject.capture_allowed?("dont send me")).to eq(false) expect(subject.errors).to eq(["should_capture returned false"]) expect(subject.capture_allowed?("send me")).to eq(true) end end context "with an invalid server" do before(:each) do subject.server = 'dummy://trololo' end it 'captured_allowed returns false' do expect(subject.capture_allowed?).to eq(false) expect(subject.errors).to eq(["No public_key specified", "No project_id specified"]) end end context "with the new Sentry 9 DSN format" do # Basically the same as before, without a secret before(:each) do subject.server = "https://66260460f09b5940498e24bb7ce093a0@sentry.io/42" end it 'captured_allowed is true' do expect(subject.capture_allowed?).to eq(true) end it "sets the DSN in the way we expect" do expect(subject.server).to eq("https://sentry.io") expect(subject.project_id).to eq("42") expect(subject.public_key).to eq("66260460f09b5940498e24bb7ce093a0") expect(subject.secret_key).to be_nil end end context "with a sample rate" do before(:each) do subject.server = 'http://12345:67890@sentry.localdomain:3000/sentry/42' subject.sample_rate = 0.75 end it 'captured_allowed false when sampled' do allow(Random::DEFAULT).to receive(:rand).and_return(0.76) expect(subject.capture_allowed?).to eq(false) expect(subject.errors).to eq(["Excluded by random sample"]) end it 'captured_allowed true when not sampled' do allow(Random::DEFAULT).to receive(:rand).and_return(0.74) expect(subject.capture_allowed?).to eq(true) end end describe '#exception_class_allowed?' do class MyTestException < RuntimeError; end context 'with custom excluded_exceptions' do before do subject.excluded_exceptions = ['MyTestException'] end context 'when the raised exception is a Raven::Error' do let(:incoming_exception) { Raven::Error.new } it 'returns false' do expect(subject.exception_class_allowed?(incoming_exception)).to eq false end end context 'when the raised exception is not in excluded_exceptions' do let(:incoming_exception) { RuntimeError.new } it 'returns true' do expect(subject.exception_class_allowed?(incoming_exception)).to eq true end end context 'when the raised exception has a cause that is in excluded_exceptions' do let(:incoming_exception) { build_exception_with_cause(MyTestException.new) } context 'when inspect_exception_causes_for_exclusion is false' do it 'returns true' do expect(subject.exception_class_allowed?(incoming_exception)).to eq true end end # Only check causes when they're supported by the ruby version context 'when inspect_exception_causes_for_exclusion is true' do before do subject.inspect_exception_causes_for_exclusion = true end if Exception.new.respond_to? :cause context 'when the language version supports exception causes' do it 'returns false' do expect(subject.exception_class_allowed?(incoming_exception)).to eq false end end else context 'when the language version does not support exception causes' do it 'returns true' do expect(subject.exception_class_allowed?(incoming_exception)).to eq true end end end end end context 'when the raised exception is in excluded_exceptions' do let(:incoming_exception) { MyTestException.new } it 'returns false' do expect(subject.exception_class_allowed?(incoming_exception)).to eq false end end end end end raven-ruby-2.13.0/spec/raven/event_spec.rb000066400000000000000000000560051357613622200204310ustar00rootroot00000000000000require 'spec_helper' require 'raven/integrations/rack' RSpec.describe Raven::Event do before do Raven::Context.clear! Raven::BreadcrumbBuffer.clear! end context 'a fully implemented event' do let(:hash) do Raven::Event.new(:message => 'test', :level => 'warn', :logger => 'foo', :tags => { 'foo' => 'bar' }, :extra => { 'my_custom_variable' => 'value' }, :server_name => 'foo.local', :release => '721e41770371db95eee98ca2707686226b993eda', :environment => 'production').to_hash end it 'has message' do expect(hash[:message]).to eq('test') end it 'has level' do expect(hash[:level]).to eq(:warning) end it 'has logger' do expect(hash[:logger]).to eq('foo') end it 'has server name' do expect(hash[:server_name]).to eq('foo.local') end it 'has release' do expect(hash[:release]).to eq('721e41770371db95eee98ca2707686226b993eda') end it 'has environment' do expect(hash[:environment]).to eq('production') end it 'has tag data' do expect(hash[:tags]).to eq('foo' => 'bar') end it 'has extra data' do expect(hash[:extra]["my_custom_variable"]).to eq('value') end it 'has platform' do expect(hash[:platform]).to eq(:ruby) end it 'has SDK' do expect(hash[:sdk]).to eq("name" => "raven-ruby", "version" => Raven::VERSION) end it 'has server os' do expect(hash[:extra][:server][:os].keys).to eq([:name, :version, :build, :kernel_version]) end it 'has runtime' do expect(hash[:extra][:server][:runtime][:version]).to match(/ruby/) end end context 'parameter entries are nil' do let(:hash) do Raven::Event.new(:message => 'test', :level => 'warn', :logger => 'foo', :tags => nil, :extra => nil, :user => nil, :server_name => 'foo.local', :release => '721e41770371db95eee98ca2707686226b993eda', :environment => 'production').to_hash end it "skips nil values" do expect(hash[:extra]).to eq(Raven.context.extra) expect(hash[:user]).to eq(Raven.context.user) expect(hash[:tags]).to eq(Raven.configuration.tags) end end context 'user context specified' do let(:hash) do Raven.user_context('id' => 'hello') Raven::Event.new(:level => 'warning', :logger => 'foo', :tags => { 'foo' => 'bar' }, :extra => { 'my_custom_variable' => 'value' }, :server_name => 'foo.local').to_hash end it "adds user data" do expect(hash[:user]).to eq('id' => 'hello') end end context 'tags context specified' do let(:hash) do Raven.tags_context('key' => 'value') Raven::Event.new(:level => 'warning', :logger => 'foo', :tags => { 'foo' => 'bar' }, :extra => { 'my_custom_variable' => 'value' }, :server_name => 'foo.local').to_hash end it "merges tags data" do expect(hash[:tags]).to eq('key' => 'value', 'foo' => 'bar') end end context 'extra context specified' do let(:hash) do Raven.extra_context('key' => 'value') Raven::Event.new(:level => 'warning', :logger => 'foo', :tags => { 'foo' => 'bar' }, :extra => { 'my_custom_variable' => 'value' }, :server_name => 'foo.local').to_hash end it "merges extra data" do expect(hash[:extra]['key']).to eq('value') expect(hash[:extra]['my_custom_variable']).to eq('value') end end context 'rack context specified' do require 'stringio' let(:hash) do Raven.rack_context('REQUEST_METHOD' => 'POST', 'QUERY_STRING' => 'biz=baz', 'HTTP_HOST' => 'localhost', 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => '80', 'HTTP_X_FORWARDED_FOR' => '1.1.1.1, 2.2.2.2', 'REMOTE_ADDR' => '192.168.1.1', 'PATH_INFO' => '/lol', 'rack.url_scheme' => 'http', 'rack.input' => StringIO.new('foo=bar')) Raven::Event.new(:level => 'warning', :logger => 'foo', :tags => { 'foo' => 'bar' }, :extra => { 'my_custom_variable' => 'value' }, :server_name => 'foo.local').to_hash end it "adds http data" do expect(hash[:request]).to eq(:data => { 'foo' => 'bar' }, :env => { 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => '80', "REMOTE_ADDR" => "192.168.1.1" }, :headers => { 'Host' => 'localhost', "X-Forwarded-For" => "1.1.1.1, 2.2.2.2" }, :method => 'POST', :query_string => 'biz=baz', :url => 'http://localhost/lol', :cookies => {}) end it "sets user context ip address correctly" do expect(hash[:user][:ip_address]).to eq("1.1.1.1") end end context "rack context, long body" do let(:hash) do Raven.rack_context('REQUEST_METHOD' => 'GET', 'rack.url_scheme' => 'http', 'rack.input' => StringIO.new('a' * 4096 * 5)) Raven::Event.new.to_hash end it "truncates http data" do expect(hash[:request][:data]).to eq("a" * 4096 * 4) end end context 'configuration tags specified' do let(:hash) do config = Raven::Configuration.new config.tags = { 'key' => 'value' } config.release = "custom" config.current_environment = "custom" Raven::Event.new( :level => 'warning', :logger => 'foo', :tags => { 'foo' => 'bar' }, :server_name => 'foo.local', :configuration => config ).to_hash end it 'merges tags data' do expect(hash[:tags]).to eq('key' => 'value', 'foo' => 'bar') expect(hash[:release]).to eq("custom") expect(hash[:environment]).to eq("custom") end end context 'configuration tags unspecified' do it 'should not persist tags between unrelated events' do config = Raven::Configuration.new config.logger = Logger.new(nil) Raven::Event.new( :level => 'warning', :logger => 'foo', :tags => { 'foo' => 'bar' }, :server_name => 'foo.local', :configuration => config ) hash = Raven::Event.new( :level => 'warning', :logger => 'foo', :server_name => 'foo.local', :configuration => config ).to_hash expect(hash[:tags]).to eq({}) end end context 'tags hierarchy respected' do let(:hash) do config = Raven::Configuration.new config.logger = Logger.new(nil) config.tags = { 'configuration_context_event_key' => 'configuration_value', 'configuration_context_key' => 'configuration_value', 'configuration_event_key' => 'configuration_value', 'configuration_key' => 'configuration_value' } Raven.tags_context('configuration_context_event_key' => 'context_value', 'configuration_context_key' => 'context_value', 'context_event_key' => 'context_value', 'context_key' => 'context_value') Raven::Event.new( :level => 'warning', :logger => 'foo', :tags => { 'configuration_context_event_key' => 'event_value', 'configuration_event_key' => 'event_value', 'context_event_key' => 'event_value', 'event_key' => 'event_value' }, :server_name => 'foo.local', :configuration => config ).to_hash end it 'merges tags data' do expect(hash[:tags]).to eq('configuration_context_event_key' => 'event_value', 'configuration_context_key' => 'context_value', 'configuration_event_key' => 'event_value', 'context_event_key' => 'event_value', 'configuration_key' => 'configuration_value', 'context_key' => 'context_value', 'event_key' => 'event_value') end end context 'merging user context' do before do Raven.user_context('context_event_key' => 'context_value', 'context_key' => 'context_value') end let(:hash) do Raven::Event.new(:user => { 'context_event_key' => 'event_value', 'event_key' => 'event_value' }).to_hash end it 'prioritizes event context over request context' do expect(hash[:user]).to eq('context_event_key' => 'event_value', 'context_key' => 'context_value', 'event_key' => 'event_value') end end context 'merging extra context' do before do Raven.extra_context('context_event_key' => 'context_value', 'context_key' => 'context_value') end let(:hash) do Raven::Event.new(:extra => { 'context_event_key' => 'event_value', 'event_key' => 'event_value' }).to_hash end it 'prioritizes event context over request context' do expect(hash[:extra]['context_event_key']).to eq('event_value') expect(hash[:extra]['context_key']).to eq('context_value') expect(hash[:extra]['event_key']).to eq('event_value') end end context 'merging exception context' do class ExceptionWithContext < StandardError def raven_context { :extra => { 'context_event_key' => 'context_value', 'context_key' => 'context_value' } } end end let(:hash) do Raven::Event.from_exception(ExceptionWithContext.new, :extra => { 'context_event_key' => 'event_value', 'event_key' => 'event_value' }).to_hash end it 'prioritizes event context over request context' do expect(hash[:extra]['context_event_key']).to eq('event_value') expect(hash[:extra]['context_key']).to eq('context_value') expect(hash[:extra]['event_key']).to eq('event_value') end end describe '.to_json_compatible' do subject do Raven::Event.new(:extra => { 'my_custom_variable' => 'value', 'date' => Time.utc(0), 'anonymous_module' => Class.new }) end it "should coerce non-JSON-compatible types" do json = subject.to_json_compatible expect(json["extra"]['my_custom_variable']).to eq('value') expect(json["extra"]['date']).to be_a(String) expect(json["extra"]['anonymous_module']).not_to be_a(Class) end context "with bad data" do subject do data = {} data['data'] = data data['ary'] = [] data['ary'].push('x' => data['ary']) data['ary2'] = data['ary'] Raven::Event.new(:extra => { :invalid => "invalid\255".force_encoding('UTF-8'), :circular => data }) end it "should remove bad UTF-8" do json = subject.to_json_compatible expect(json["extra"]["invalid"]).to eq("invalid") end it "should remove circular references" do json = subject.to_json_compatible expect(json["extra"]["circular"]["ary2"]).to eq("(...)") end end context "with sensitive data" do subject do Raven::Event.new(:extra => { 'password' => 'secretpassword' }) end it "should sanitize password" do json = subject.to_json_compatible expect(json["extra"]["password"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) end end end describe '.capture_message' do let(:message) { 'This is a message' } let(:hash) { Raven::Event.capture_message(message).to_hash } context 'for a Message' do it 'returns an event' do expect(Raven::Event.capture_message(message)).to be_a(Raven::Event) end it "sets the message to the value passed" do expect(hash[:message]).to eq(message) end it 'has level ERROR' do expect(hash[:level]).to eq(:error) end it 'accepts an options hash' do expect(Raven::Event.capture_message(message, :logger => 'logger').logger).to eq('logger') end it 'accepts a stacktrace' do backtrace = ["/path/to/some/file:22:in `function_name'", "/some/other/path:1412:in `other_function'"] evt = Raven::Event.capture_message(message, :backtrace => backtrace) expect(evt[:stacktrace]).to be_a(Raven::StacktraceInterface) frames = evt[:stacktrace].to_hash[:frames] expect(frames.length).to eq(2) expect(frames[0][:lineno]).to eq(1412) expect(frames[0][:function]).to eq('other_function') expect(frames[0][:filename]).to eq('/some/other/path') expect(frames[1][:lineno]).to eq(22) expect(frames[1][:function]).to eq('function_name') expect(frames[1][:filename]).to eq('/path/to/some/file') end end end describe '.capture_exception' do let(:message) { 'This is a message' } let(:exception) { Exception.new(message) } let(:hash) { Raven::Event.capture_exception(exception).to_hash } context 'for an Exception' do it 'returns an event' do expect(Raven::Event.capture_exception(exception)).to be_a(Raven::Event) end it "sets the message to the exception's value and type" do expect(hash[:exception][:values][0][:type]).to eq("Exception") expect(hash[:exception][:values][0][:value]).to eq(message) end it 'has level ERROR' do expect(hash[:level]).to eq(:error) end it 'uses the exception class name as the exception type' do expect(hash[:exception][:values][0][:type]).to eq('Exception') end it 'uses the exception message as the exception value' do expect(hash[:exception][:values][0][:value]).to eq(message) end it 'does not belong to a module' do expect(hash[:exception][:values][0][:module]).to eq('') end end context 'for a nested exception type' do module Raven::Test class Exception < RuntimeError; end end let(:exception) { Raven::Test::Exception.new(message) } it 'sends the module name as part of the exception info' do expect(hash[:exception][:values][0][:module]).to eq('Raven::Test') end end context 'for a Raven::Error' do let(:exception) { Raven::Error.new } it 'does not create an event' do expect(Raven::Event.capture_exception(exception)).to be_nil end end context 'for an excluded exception type' do module Raven::Test class BaseExc < RuntimeError; end class SubExc < BaseExc; end module ExcTag; end end let(:config) do config = Raven::Configuration.new config.logger = Logger.new(nil) config end context "invalid exclusion type" do it 'returns Raven::Event' do config.excluded_exceptions << nil config.excluded_exceptions << 1 config.excluded_exceptions << {} expect(Raven::Event.capture_exception(Raven::Test::BaseExc.new, :configuration => config)).to be_a(Raven::Event) end end context "defined by string type" do it 'returns nil for a class match' do config.excluded_exceptions << 'Raven::Test::BaseExc' expect(Raven::Event.capture_exception(Raven::Test::BaseExc.new, :configuration => config)).to be_nil end it 'returns nil for a top class match' do config.excluded_exceptions << '::Raven::Test::BaseExc' expect(Raven::Event.capture_exception(Raven::Test::BaseExc.new, :configuration => config)).to be_nil end it 'returns nil for a sub class match' do config.excluded_exceptions << 'Raven::Test::BaseExc' expect(Raven::Event.capture_exception(Raven::Test::SubExc.new, :configuration => config)).to be_nil end it 'returns nil for a tagged class match' do config.excluded_exceptions << 'Raven::Test::ExcTag' expect(Raven::Event.capture_exception(Raven::Test::SubExc.new.tap { |x| x.extend(Raven::Test::ExcTag) }, :configuration => config)).to be_nil end it 'returns Raven::Event for an undefined exception class' do config.excluded_exceptions << 'Raven::Test::NonExistentExc' expect(Raven::Event.capture_exception(Raven::Test::BaseExc.new, :configuration => config)).to be_a(Raven::Event) end end context "defined by class type" do it 'returns nil for a class match' do config.excluded_exceptions << Raven::Test::BaseExc expect(Raven::Event.capture_exception(Raven::Test::BaseExc.new, :configuration => config)).to be_nil end it 'returns nil for a sub class match' do config.excluded_exceptions << Raven::Test::BaseExc expect(Raven::Event.capture_exception(Raven::Test::SubExc.new, :configuration => config)).to be_nil end it 'returns nil for a tagged class match' do config.excluded_exceptions << Raven::Test::ExcTag expect(Raven::Event.capture_exception(Raven::Test::SubExc.new.tap { |x| x.extend(Raven::Test::ExcTag) }, :configuration => config)).to be_nil end end end # Only check causes when they're supported if Exception.new.respond_to? :cause context 'when the exception has a cause' do let(:exception) { build_exception_with_cause } it 'captures the cause' do expect(hash[:exception][:values].length).to eq(2) end end context 'when the exception has nested causes' do let(:exception) { build_exception_with_two_causes } it 'captures nested causes' do expect(hash[:exception][:values].length).to eq(3) end end end context 'when the exception has a recursive cause' do let(:exception) { build_exception_with_recursive_cause } it 'should handle it gracefully' do expect(hash[:exception][:values].length).to eq(1) end end if RUBY_PLATFORM == "java" context 'when running under jRuby' do let(:exception) do begin raise java.lang.OutOfMemoryError, "A Java error" rescue Exception => e return e end end it 'should have a backtrace' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames.length).not_to eq(0) end end end context 'when the exception has a backtrace' do let(:exception) do e = Exception.new(message) allow(e).to receive(:backtrace).and_return [ "/path/to/some/file:22:in `function_name'", "/some/other/path:1412:in `other_function'" ] e end it 'parses the backtrace' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames.length).to eq(2) expect(frames[0][:lineno]).to eq(1412) expect(frames[0][:function]).to eq('other_function') expect(frames[0][:filename]).to eq('/some/other/path') expect(frames[1][:lineno]).to eq(22) expect(frames[1][:function]).to eq('function_name') expect(frames[1][:filename]).to eq('/path/to/some/file') end context 'with internal backtrace' do let(:exception) do e = Exception.new(message) allow(e).to receive(:backtrace).and_return([":10:in `synchronize'"]) e end it 'marks filename and in_app correctly' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[0][:lineno]).to eq(10) expect(frames[0][:function]).to eq("synchronize") expect(frames[0][:filename]).to eq("") end end context 'when a path in the stack trace is on the load path' do before do $LOAD_PATH << '/some' end after do $LOAD_PATH.delete('/some') end it 'strips prefixes in the load path from frame filenames' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[0][:filename]).to eq('other/path') end end end it 'accepts an options hash' do expect(Raven::Event.capture_exception(exception, :logger => 'logger').logger).to eq('logger') end it 'uses an annotation if one exists' do Raven.annotate_exception(exception, :logger => 'logger') expect(Raven::Event.capture_exception(exception).logger).to eq('logger') end it 'accepts a checksum' do expect(Raven::Event.capture_exception(exception, :checksum => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa').checksum).to eq('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') end it 'accepts a release' do expect(Raven::Event.capture_exception(exception, :release => '1.0').release).to eq('1.0') end it 'accepts a fingerprint' do expect(Raven::Event.capture_exception(exception, :fingerprint => ['{{ default }}', 'foo']).fingerprint).to eq(['{{ default }}', 'foo']) end it 'accepts a logger' do expect(Raven::Event.capture_exception(exception, :logger => 'root').logger).to eq('root') end end end raven-ruby-2.13.0/spec/raven/instance_spec.rb000066400000000000000000000240521357613622200211110ustar00rootroot00000000000000require 'spec_helper' require 'raven/instance' RSpec.describe Raven::Instance do let(:event) { Raven::Event.new(:id => "event_id") } let(:options) { { :key => "value" } } let(:context) { nil } let(:configuration) do config = Raven::Configuration.new config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42" config.logger = Logger.new(nil) config end subject { described_class.new(context, configuration) } before do allow(subject).to receive(:send_event) allow(Raven::Event).to receive(:from_message) { event } allow(Raven::Event).to receive(:from_exception) { event } end describe '#context' do it 'is Raven.context by default' do expect(subject.context).to equal(Raven.context) end context 'initialized with a context' do let(:context) { :explicit } it 'is not Raven.context' do expect(subject.context).to_not equal(Raven.context) end end end describe '#capture_type' do describe 'as #capture_message' do before do expect(Raven::Event).to receive(:from_message).with(message, options) expect(subject).to receive(:send_event).with(event, :exception => nil, :message => message) end let(:message) { "Test message" } it 'sends the result of Event.capture_message' do subject.capture_type(message, options) end it 'yields the event to a passed block' do expect { |b| subject.capture_type(message, options, &b) }.to yield_with_args(event) end end describe 'as #capture_message when async' do let(:message) { "Test message" } around do |example| prior_async = subject.configuration.async subject.configuration.async = proc { :ok } example.run subject.configuration.async = prior_async end it 'sends the result of Event.capture_type' do expect(Raven::Event).to receive(:from_message).with(message, options) expect(subject).not_to receive(:send_event).with(event) expect(subject.configuration.async).to receive(:call).with(event.to_json_compatible) subject.capture_message(message, options) end it 'returns the generated event' do returned = subject.capture_message(message, options) expect(returned).to eq(event) end end describe 'as #capture_exception' do let(:exception) { build_exception } it 'sends the result of Event.capture_exception' do expect(Raven::Event).to receive(:from_exception).with(exception, options) expect(subject).to receive(:send_event).with(event, :exception => exception, :message => nil) subject.capture_exception(exception, options) end it 'has an alias' do expect(Raven::Event).to receive(:from_exception).with(exception, options) expect(subject).to receive(:send_event).with(event, :exception => exception, :message => nil) subject.capture_exception(exception, options) end end describe 'as #capture_exception when async' do let(:exception) { build_exception } context "when async" do around do |example| prior_async = subject.configuration.async subject.configuration.async = proc { :ok } example.run subject.configuration.async = prior_async end it 'sends the result of Event.capture_exception' do expect(Raven::Event).to receive(:from_exception).with(exception, options) expect(subject).not_to receive(:send_event).with(event) expect(subject.configuration.async).to receive(:call).with(event.to_json_compatible) subject.capture_exception(exception, options) end it 'returns the generated event' do returned = subject.capture_exception(exception, options) expect(returned).to eq(event) end end context "when async raises an exception" do around do |example| prior_async = subject.configuration.async subject.configuration.async = proc { raise TypeError } example.run subject.configuration.async = prior_async end it 'sends the result of Event.capture_exception via fallback' do expect(Raven::Event).to receive(:from_exception).with(exception, options) expect(subject.configuration.async).to receive(:call).with(event.to_json_compatible) subject.capture_exception(exception, options) end end end describe 'as #capture_exception with a should_capture callback' do let(:exception) { build_exception } it 'sends the result of Event.capture_exception according to the result of should_capture' do expect(subject).not_to receive(:send_event).with(event) subject.configuration.should_capture = proc { false } expect(subject.configuration.should_capture).to receive(:call).with(exception) expect(subject.capture_exception(exception, options)).to be false end end end describe '#capture' do context 'given a block' do it 'yields to the given block' do expect { |b| subject.capture(&b) }.to yield_with_no_args end end it 'does not install an at_exit hook' do expect(Kernel).not_to receive(:at_exit) subject.capture {} end end describe '#annotate_exception' do let(:exception) { build_exception } def ivars(object) object.instance_variables.map(&:to_s) end it 'adds an annotation to the exception' do expect(ivars(exception)).not_to include("@__raven_context") subject.annotate_exception(exception, {}) expect(ivars(exception)).to include("@__raven_context") expect(exception.instance_variable_get(:@__raven_context)).to \ be_kind_of Hash end context 'when the exception already has context' do it 'does a deep merge of options' do subject.annotate_exception(exception, :extra => { :language => "ruby" }) subject.annotate_exception(exception, :extra => { :job_title => "engineer" }) expected_hash = { :extra => { :language => "ruby", :job_title => "engineer" } } expect(exception.instance_variable_get(:@__raven_context)).to \ eq expected_hash end end end describe '#report_status' do let(:ready_message) do "Raven #{Raven::VERSION} ready to catch errors" end let(:not_ready_message) do "Raven #{Raven::VERSION} configured not to capture errors." end it 'logs a ready message when configured' do subject.configuration.silence_ready = false expect(subject.logger).to receive(:info).with(ready_message) subject.report_status end it 'logs not ready message if the config does not send in current environment' do subject.configuration.silence_ready = false subject.configuration.environments = ["production"] expect(subject.logger).to receive(:info).with( "Raven #{Raven::VERSION} configured not to capture errors: Not configured to send/capture in environment 'default'" ) subject.report_status end it 'logs nothing if "silence_ready" configuration is true' do subject.configuration.silence_ready = true expect(subject.logger).not_to receive(:info) subject.report_status end end describe '.last_event_id' do let(:message) { "Test message" } it 'sends the result of Event.capture_type' do expect(subject).to receive(:send_event).with(event, :exception => nil, :message => message) subject.capture_type("Test message", options) expect(subject.last_event_id).to eq(event.id) end end describe "#tags_context" do let(:default) { { :foo => :bar } } let(:additional) { { :baz => :qux } } before do subject.context.tags = default end it "returns the tags" do expect(subject.tags_context).to eq default end it "returns the tags" do expect(subject.tags_context(additional)).to eq default.merge(additional) end it "doesn't set anything if the tags is empty" do subject.tags_context({}) expect(subject.context.tags).to eq default end it "adds tags" do subject.tags_context(additional) expect(subject.context.tags).to eq default.merge(additional) end context 'when block given' do it "returns the tags" do tags = subject.tags_context(additional) do # do nothing end expect(tags).to eq default end it "adds tags only in the block" do subject.tags_context(additional) do expect(subject.context.tags).to eq default.merge(additional) end expect(subject.context.tags).to eq default end end end describe "#extra_context" do let(:default) { { :foo => :bar } } let(:additional) { { :baz => :qux } } before do subject.context.extra = default end it "returns the extra" do expect(subject.extra_context).to eq default end it "returns the extra" do expect(subject.extra_context(additional)).to eq default.merge(additional) end it "doesn't set anything if the extra is empty" do subject.extra_context({}) expect(subject.context.extra).to eq default end it "adds extra" do subject.extra_context(additional) expect(subject.context.extra).to eq default.merge(additional) end context 'when block given' do it "returns the extra" do extra = subject.extra_context(additional) do # do nothing end expect(extra).to eq default end it "adds extra only in the block" do subject.extra_context(additional) do expect(subject.context.extra).to eq default.merge(additional) end expect(subject.context.extra).to eq default end end end describe "#rack_context" do it "doesn't set anything if the context is empty" do subject.rack_context({}) expect(subject.context.rack_env).to be_nil end it "sets arbitrary rack context" do subject.rack_context(:foo => :bar) expect(subject.context.rack_env[:foo]).to eq(:bar) end end end raven-ruby-2.13.0/spec/raven/integration_spec.rb000066400000000000000000000071511357613622200216310ustar00rootroot00000000000000require 'spec_helper' RSpec.describe "Integration tests" do before(:each) do @io = StringIO.new @logger = Logger.new(@io) @instance = Raven::Instance.new @stubs = Faraday::Adapter::Test::Stubs.new @instance.configuration = Raven::Configuration.new.tap do |config| config.server = 'http://12345:67890@sentry.localdomain/sentry/42' config.http_adapter = [:test, @stubs] config.logger = @logger end end it "posting an exception" do @stubs.post('sentry/api/42/store/') { [200, {}, 'ok'] } @instance.capture_exception(build_exception) @stubs.verify_stubbed_calls expect(@io.string).to match(/Sending event [0-9a-f]+ to Sentry$/) end it "posting an exception to a prefixed DSN" do @stubs.post('/prefix/sentry/api/42/store/') { [200, {}, 'ok'] } @instance.configuration.server = 'http://12345:67890@sentry.localdomain/prefix/sentry/42' @instance.capture_exception(build_exception) @stubs.verify_stubbed_calls end # TODO: Not a very good test # it "hitting quota limit shouldn't swallow exception" do # @stubs.post('sentry/api/42/store/') { [403, {}, 'Creation of this event was blocked'] } # # # sentry error and original error # expect(@logger).not_to receive(:error) # @instance.capture_exception(build_exception) # # @stubs.verify_stubbed_calls # end it "timed backoff should prevent sends" do expect(@instance.client.transport).to receive(:send_event).exactly(1).times.and_raise(Faraday::Error::ConnectionFailed, "conn failed") 2.times { @instance.capture_exception(build_exception) } expect(@io.string).to match(/Failed to submit event: ZeroDivisionError: divided by 0$/) end it "transport failure should call transport_failure_callback" do @instance.configuration.transport_failure_callback = proc { |_e| @io.puts "OK!" } expect(@instance.client.transport).to receive(:send_event).exactly(1).times.and_raise(Faraday::Error::ConnectionFailed, "conn failed") @instance.capture_exception(build_exception) expect(@io.string).to match(/OK!$/) end describe '#before_send' do it "change event before sending (capture_exception)" do @stubs.post('/prefix/sentry/api/42/store/') { [200, {}, 'ok'] } @instance.configuration.server = 'http://12345:67890@sentry.localdomain/prefix/sentry/42' @instance.configuration.before_send = lambda { |event, hint| expect(hint[:exception]).not_to be nil expect(hint[:message]).to be nil event.environment = 'testxx' event } event = @instance.capture_exception(build_exception) expect(event.environment).to eq('testxx') @stubs.verify_stubbed_calls end it "change event before sending (capture_message)" do @stubs.post('/prefix/sentry/api/42/store/') { [200, {}, 'ok'] } @instance.configuration.server = 'http://12345:67890@sentry.localdomain/prefix/sentry/42' @instance.configuration.before_send = lambda { |event, hint| expect(hint[:exception]).to be nil expect(hint[:message]).not_to be nil expect(event.message).to eq('xyz') event.message = 'abc' event } event = @instance.capture_message('xyz') expect(event.message).to eq('abc') @stubs.verify_stubbed_calls end it "return nil" do @instance.configuration.server = 'http://12345:67890@sentry.localdomain/prefix/sentry/42' @instance.configuration.before_send = lambda { |_event, _hint| nil } @instance.capture_exception(build_exception) expect(@instance.client.transport).to receive(:send_event).exactly(0) end end end raven-ruby-2.13.0/spec/raven/integrations/000077500000000000000000000000001357613622200204515ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/integrations/rack_spec.rb000066400000000000000000000063631357613622200227400ustar00rootroot00000000000000require 'spec_helper' require 'raven/integrations/rack' RSpec.describe Raven::Rack do let(:exception) { build_exception } let(:env) { Rack::MockRequest.env_for("/test") } context "when we expect to capture an exception" do before do expect(Raven::Rack).to receive(:capture_exception).with(exception, env) end it 'should capture exceptions' do app = ->(_e) { raise exception } stack = Raven::Rack.new(app) expect { stack.call(env) }.to raise_error(ZeroDivisionError) end it 'should capture rack.exception' do app = lambda do |e| e['rack.exception'] = exception [200, {}, ['okay']] end stack = Raven::Rack.new(app) stack.call(env) end it 'should capture sinatra errors' do app = lambda do |e| e['sinatra.error'] = exception [200, {}, ['okay']] end stack = Raven::Rack.new(app) stack.call(env) end end it 'should capture context and clear after app is called' do Raven::Context.current.tags[:environment] = :test app = ->(_e) { :ok } stack = Raven::Rack.new(app) stack.call(env) expect(Raven::Context.current.tags).to eq({}) end it 'sets transaction' do app = lambda do |_e| expect(Raven.context.transaction.last).to eq "/test" end stack = Raven::Rack.new(app) stack.call(env) expect(Raven.context.transaction.last).to be_nil end it 'should allow empty rack env in rspec tests' do Raven.rack_context({}) # the rack env is empty when running rails/rspec tests Raven.capture_exception(build_exception) end it 'should bind request context' do Raven::Context.current.rack_env = nil app = lambda do |env| expect(Raven::Context.current.rack_env).to eq(env) ['response', {}, env] end stack = Raven::Rack.new(app) stack.call({}) end it 'transforms headers to conform with the interface' do interface = Raven::HttpInterface.new new_env = env.merge("HTTP_VERSION" => "HTTP/1.1", "HTTP_COOKIE" => "test") interface.from_rack(new_env) expect(interface.headers).to eq("Content-Length" => "0", "Version" => "HTTP/1.1") end it 'puts cookies into the cookies attribute' do interface = Raven::HttpInterface.new new_env = env.merge("HTTP_COOKIE" => "test") interface.from_rack(new_env) expect(interface.cookies).to eq("test" => nil) end it 'does not ignore version headers which do not match SERVER_PROTOCOL' do new_env = env.merge("SERVER_PROTOCOL" => "HTTP/1.1", "HTTP_VERSION" => "HTTP/2.0") interface = Raven::HttpInterface.new interface.from_rack(new_env) expect(interface.headers["Version"]).to eq("HTTP/2.0") end it 'does not fail if an object in the env cannot be cast to string' do obj = Class.new do def to_s raise 'Could not stringify object!' end end.new new_env = env.merge("HTTP_FOO" => "BAR", "rails_object" => obj) interface = Raven::HttpInterface.new expect { interface.from_rack(new_env) }.to_not raise_error end it 'should pass rack/lint' do app = proc do [200, { 'Content-Type' => 'text/plain' }, ['OK']] end stack = Raven::Rack.new(Rack::Lint.new(app)) expect { stack.call(env) }.to_not raise_error end end raven-ruby-2.13.0/spec/raven/integrations/rack_timeout_spec.rb000066400000000000000000000005531357613622200245010ustar00rootroot00000000000000require "spec_helper" require "rack/timeout/base" require "raven/integrations/rack-timeout" RSpec.describe "Rack timeout" do it "should have a raven_context method defined" do exc = Rack::Timeout::RequestTimeoutException.new("REQUEST_URI" => "This is a URI") expect(exc.raven_context[:fingerprint]).to eq(["{{ default }}", "This is a URI"]) end end raven-ruby-2.13.0/spec/raven/integrations/rails/000077500000000000000000000000001357613622200215635ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/integrations/rails/activejob_spec.rb000066400000000000000000000037741357613622200251030ustar00rootroot00000000000000require "spec_helper" if defined? ActiveJob class MyActiveJob < ActiveJob::Base self.logger = nil class TestError < RuntimeError end def perform raise TestError, "Boom!" end end class RescuedActiveJob < MyActiveJob rescue_from TestError, :with => :rescue_callback def rescue_callback(error) end end end RSpec.describe "ActiveJob integration", :rails => true do before(:all) do require "rspec/rails" require "raven/integrations/rails" require "raven/integrations/rails/active_job" end before(:each) do Raven.client.transport.events = [] MyActiveJob.queue_adapter = :inline end it_should_behave_like "Raven default capture behavior" do let(:block) { MyActiveJob.new.perform_now } let(:captured_class) { MyActiveJob::TestError } let(:captured_message) { "Boom!" } end it "clears context" do Raven.extra_context(:foo => :bar) job = MyActiveJob.new expect { job.perform_now }.to raise_error(MyActiveJob::TestError) event = JSON.parse!(Raven.client.transport.events.first[1]) expect(event["extra"]["foo"]).to eq("bar") Raven.client.transport.events = [] expect { job.perform_now }.to raise_error(MyActiveJob::TestError) event = JSON.parse!(Raven.client.transport.events.first[1]) expect(event["extra"]["foo"]).to eq(nil) end context 'using rescue_from' do it 'does not trigger Sentry' do job = RescuedActiveJob.new allow(job).to receive(:rescue_callback) expect { job.perform_now }.not_to raise_error expect(Raven.client.transport.events.size).to eq(0) expect(job).to have_received(:rescue_callback).once end end context "when we are using an adapter which has a specific integration" do it "does not trigger sentry and re-raises" do MyActiveJob.queue_adapter = :sidekiq job = MyActiveJob.new expect { job.perform_now }.to raise_error(MyActiveJob::TestError) expect(Raven.client.transport.events.size).to eq(0) end end end raven-ruby-2.13.0/spec/raven/integrations/rails/controller_methods_spec.rb000066400000000000000000000016341357613622200270340ustar00rootroot00000000000000require 'spec_helper' RSpec.describe "Raven::Rails::ControllerMethods", :rails => true do include Raven::Rails::ControllerMethods if defined?(Rails) before(:all) do require 'raven/integrations/rails/controller_methods' end let(:env) { { "foo" => "bar" } } let(:request) { double('request', :env => env) } let(:options) { double('options') } describe "#capture_message" do let(:message) { double('message') } it "captures a message with the request environment" do expect(Raven::Rack).to receive(:capture_message).with(message, env, options) capture_message(message, options) end end describe "#capture_exception" do let(:exception) { double('exception') } it "captures a exception with the request environment" do expect(Raven::Rack).to receive(:capture_exception).with(exception, env, options) capture_exception(exception, options) end end end raven-ruby-2.13.0/spec/raven/integrations/rails/event_spec.rb000066400000000000000000000055701357613622200242520ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Event, :rails => true do context 'in a rails environment' do let(:configuration) do config = Raven::Configuration.new config.dsn = "dummy://12345:67890@sentry.localdomain:3000/sentry/42" config.logger = Logger.new(nil) config end let(:instance) { Raven::Instance.new(nil, configuration) } context 'with an application stacktrace' do let(:exception) do e = Exception.new("Oh no!") allow(e).to receive(:backtrace).and_return [ "#{Rails.root}/vendor/bundle/cache/other_gem.rb:10:in `public_method'", "vendor/bundle/some_gem.rb:10:in `a_method'", "#{Rails.root}/app/models/user.rb:132:in `new_function'", "/gem/lib/path:87:in `a_function'", "/app/some/other/path:1412:in `other_function'", "test/some/other/path:1412:in `other_function'" ] e end let(:hash) { instance.capture_exception(exception).to_hash } it 'marks in_app correctly' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[0][:filename]).to eq("test/some/other/path") expect(frames[0][:in_app]).to eq(true) expect(frames[1][:filename]).to eq("/app/some/other/path") expect(frames[1][:in_app]).to eq(false) expect(frames[2][:filename]).to eq("/gem/lib/path") expect(frames[2][:in_app]).to eq(false) expect(frames[3][:filename]).to eq("app/models/user.rb") expect(frames[3][:in_app]).to eq(true) expect(frames[4][:filename]).to eq("vendor/bundle/some_gem.rb") expect(frames[4][:in_app]).to eq(false) expect(frames[5][:filename]).to eq("vendor/bundle/cache/other_gem.rb") expect(frames[5][:in_app]).to eq(false) end context 'when an in_app path under project_root is on the load path' do it 'normalizes the filename using project_root' do $LOAD_PATH << "#{Rails.root}/app/models" frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[3][:filename]).to eq("app/models/user.rb") $LOAD_PATH.delete("#{Rails.root}/app/models") end end context 'when a non-in_app path under project_root is on the load path' do it 'normalizes the filename using the load path' do $LOAD_PATH.push "#{Rails.root}/vendor/bundle" frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[5][:filename]).to eq("cache/other_gem.rb") $LOAD_PATH.pop end end context "when a non-in_app path under project_root isn't on the load path" do it 'normalizes the filename using project_root' do frames = hash[:exception][:values][0][:stacktrace][:frames] expect(frames[5][:filename]).to eq("vendor/bundle/cache/other_gem.rb") end end end end end raven-ruby-2.13.0/spec/raven/integrations/rails/overrides/000077500000000000000000000000001357613622200235655ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/integrations/rails/overrides/debug_exceptions_catcher_spec.rb000066400000000000000000000032111357613622200321410ustar00rootroot00000000000000require 'spec_helper' RSpec.shared_examples "exception catching middleware" do let(:middleware) do Class.new do def initialize(app) @app = app end def call(env) @app.call(env) rescue => e render_exception(env, e) end def render_exception(_, exception) [500, exception.message, {}] end end end let(:app) do lambda { |_| raise "app error" } # rubocop:disable Style/Lambda end let(:env) { {} } it "shows the exception" do expect(middleware.new(app).call(env)).to eq([500, "app error", {}]) end it "captures the exception" do expect(Raven::Rack).to receive(:capture_exception) middleware.new(app).call(env) end context "when an error is raised" do it "shows the original exception" do allow(Raven::Rack).to receive(:capture_exception).and_raise("raven error") expect(middleware.new(app).call(env)).to eq([500, "app error", {}]) end end end RSpec.describe "Raven::Rails::Overrides::DebugExceptionsCatcher", :rails => true do before(:all) do require 'raven/integrations/rails/overrides/debug_exceptions_catcher' end if Class.respond_to?(:alias_method_chain) context "using include" do before do middleware.send(:include, Raven::Rails::Overrides::OldDebugExceptionsCatcher) end include_examples "exception catching middleware" end end if Class.respond_to?(:prepend) context "using prepend" do before do middleware.send(:prepend, Raven::Rails::Overrides::DebugExceptionsCatcher) end include_examples "exception catching middleware" end end end raven-ruby-2.13.0/spec/raven/integrations/rails_spec.rb000066400000000000000000000031121357613622200231170ustar00rootroot00000000000000require "spec_helper" RSpec.describe "Rails Integration", :type => :request, :rails => true do before(:all) do TestApp.initialize! end after(:each) do Raven.client.transport.events = [] end it "inserts middleware" do expect(TestApp.middleware).to include(Raven::Rack) end it "doesn't do anything on a normal route" do get "/" expect(response.status).to eq(200) expect(Raven.client.transport.events.size).to eq(0) end it "should capture exceptions in production" do get "/exception" expect(response.status).to eq(500) event = JSON.parse!(Raven.client.transport.events.first[1]) expect(event["exception"]["values"][0]["type"]).to eq("RuntimeError") expect(event["exception"]["values"][0]["value"]).to eq("An unhandled exception!") end it "should properly set the exception's URL" do get "/exception" event = JSON.parse!(Raven.client.transport.events.first[1]) expect(event['request']['url']).to eq("http://www.example.com/exception") end it "sets transaction to ControllerName#method" do get "/exception" event = JSON.parse!(Raven.client.transport.events.first[1]) expect(event['transaction']).to eq("HelloController#exception") end it "sets Raven.configuration.logger correctly" do expect(Raven.configuration.logger).to eq(Rails.logger) end it "sets Raven.configuration.project_root correctly" do expect(Raven.configuration.project_root).to eq(Rails.root.to_s) end it "doesn't clobber a manually configured release" do expect(Raven.configuration.release).to eq('beta') end end raven-ruby-2.13.0/spec/raven/integrations/rake_spec.rb000066400000000000000000000003521357613622200227320ustar00rootroot00000000000000require 'spec_helper' RSpec.describe 'Rake tasks' do it "should capture exceptions in Rake tasks" do expect(`cd spec/support && bundle exec rake raise_exception 2>&1`).to match(/Sending event [abcdef0-9]+ to Sentry/) end end raven-ruby-2.13.0/spec/raven/integrations/sidekiq_spec.rb000066400000000000000000000130201357613622200234350ustar00rootroot00000000000000if RUBY_VERSION > '2.0' require 'spec_helper' require 'raven/integrations/sidekiq' require 'sidekiq/processor' RSpec.describe "Raven::SidekiqErrorHandler" do let(:context) do { "args" => [true, true], "class" => "HardWorker", "created_at" => 1_474_922_824.910579, "enqueued_at" => 1_474_922_824.910665, "error_class" => "RuntimeError", "error_message" => "a wild exception appeared", "failed_at" => 1_474_922_825.158953, "jid" => "701ed9cfa51c84a763d56bc4", "queue" => "default", "retry" => true, "retry_count" => 0 } end it "should capture exceptions based on Sidekiq context" do exception = build_exception expected_options = { :message => exception.message, :extra => { :sidekiq => context } } expect(Raven).to receive(:capture_exception).with(exception, expected_options) Raven::SidekiqErrorHandler.new.call(exception, context) end context "when the captured exception is already annotated" do it "does a deep merge of options" do exception = build_exception Raven.annotate_exception(exception, :extra => { :job_title => "engineer" }) expected_options = { :message => exception.message, :extra => { :sidekiq => context, :job_title => "engineer" } } expect(Raven::Event).to receive(:new).with(hash_including(expected_options)) Raven::SidekiqErrorHandler.new.call(exception, context) end end it "filters out ActiveJob keys", :rails => true do exception = build_exception aj_context = context aj_context["_aj_globalid"] = GlobalID.new('gid://app/model/id') expected_context = aj_context.dup expected_context.delete("_aj_globalid") expected_context["_globalid"] = "gid://app/model/id" expected_options = { :message => exception.message, :extra => { :sidekiq => expected_context } } expect(Raven).to receive(:capture_exception).with(exception, expected_options) Raven::SidekiqErrorHandler.new.call(exception, aj_context) end end class HappyWorker include Sidekiq::Worker def perform Raven.breadcrumbs.record do |crumb| crumb.message = "I'm happy!" end Raven.tags_context :mood => 'happy' end end class SadWorker include Sidekiq::Worker def perform Raven.breadcrumbs.record do |crumb| crumb.message = "I'm sad!" end Raven.tags_context :mood => 'sad' raise "I'm sad!" end end class VerySadWorker include Sidekiq::Worker def perform Raven.breadcrumbs.record do |crumb| crumb.message = "I'm very sad!" end Raven.tags_context :mood => 'very sad' raise "I'm very sad!" end end class ReportingWorker include Sidekiq::Worker def perform Raven.capture_message("I have something to say!") end end RSpec.describe "Sidekiq full-stack integration" do before(:all) do Sidekiq.error_handlers << Raven::SidekiqErrorHandler.new Sidekiq.server_middleware do |chain| chain.add Raven::SidekiqCleanupMiddleware end Sidekiq.logger = Logger.new(nil) end before do @mgr = double('manager') allow(@mgr).to receive(:options).and_return(:queues => ['default']) @processor = ::Sidekiq::Processor.new(@mgr) end def process_job(klass) msg = Sidekiq.dump_json("class" => klass) job = Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg) @processor.instance_variable_set(:'@job', job) @processor.send(:process, job) rescue # rubocop:disable Lint/HandleExceptions # do nothing end it "actually captures an exception" do redis_on = Sidekiq.redis(&:info) rescue nil skip("No Redis server online") unless redis_on expect { process_job("SadWorker") }.to change { Raven.client.transport.events.size }.by(1) event = JSON.parse(Raven.client.transport.events.last[1]) expect(event["logentry"]["message"]).to eq("I'm sad!") end it "clears context from other workers and captures its own" do process_job("HappyWorker") process_job("SadWorker") event = JSON.parse(Raven.client.transport.events.last[1]) expect(event["tags"]).to eq("mood" => "sad") expect(event["transaction"]).to eq("Sidekiq/SadWorker") expect(event["breadcrumbs"]["values"][0]["message"]).to eq("I'm sad!") end it "clears context after raising" do process_job("SadWorker") process_job("VerySadWorker") event = JSON.parse(Raven.client.transport.events.last[1]) expect(event["tags"]).to eq("mood" => "very sad") expect(event["breadcrumbs"]["values"][0]["message"]).to eq("I'm very sad!") end it "captures exceptions raised during events" do Sidekiq.options[:lifecycle_events][:startup] = [proc { raise "Uhoh!" }] @processor.fire_event(:startup) event = JSON.parse(Raven.client.transport.events.last[1]) expect(event["logentry"]["message"]).to eq "Uhoh!" expect(event["transaction"]).to eq "Sidekiq/startup" end it "has some context when capturing, even if no exception raised" do process_job("ReportingWorker") event = JSON.parse(Raven.client.transport.events.last[1]) expect(event["logentry"]["message"]).to eq "I have something to say!" expect(event["extra"]["sidekiq"]).to eq("class" => "ReportingWorker", "queue" => "default") end end end raven-ruby-2.13.0/spec/raven/interface_spec.rb000066400000000000000000000023041357613622200212410ustar00rootroot00000000000000require 'spec_helper' class TestInterface < Raven::Interface attr_accessor :some_attr end RSpec.describe Raven::Interface do it "should register an interface when a new class is defined" do expect(Raven::Interface.registered[:test]).to eq(TestInterface) end it "can be initialized with some attributes" do interface = TestInterface.new(:some_attr => "test") expect(interface.some_attr).to eq("test") end it "can initialize with a block" do interface = TestInterface.new { |int| int.some_attr = "test" } expect(interface.some_attr).to eq("test") end it "serializes to a Hash" do interface = TestInterface.new(:some_attr => "test") expect(interface.to_hash).to eq(:some_attr => "test") end end RSpec.describe Raven::MessageInterface do it "supports invalid format string message when params is not defined" do interface = Raven::MessageInterface.new(:params => nil, :message => "test '%'") expect(interface.unformatted_message).to eq("test '%'") end it "supports invalid format string message when params is empty" do interface = Raven::MessageInterface.new(:message => "test '%'") expect(interface.unformatted_message).to eq("test '%'") end end raven-ruby-2.13.0/spec/raven/interfaces/000077500000000000000000000000001357613622200200665ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/interfaces/stack_trace_spec.rb000066400000000000000000000005561357613622200237160ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::StacktraceInterface::Frame do it "should convert pathnames to strings" do frame = Raven::StacktraceInterface::Frame.new $LOAD_PATH.unshift Pathname.pwd # Oh no, a Pathname in the $LOAD_PATH! frame.abs_path = __FILE__ expect(frame.filename).to match(/stack_trace_spec.rb/) $LOAD_PATH.shift end end raven-ruby-2.13.0/spec/raven/json_spec.rb000066400000000000000000000047311357613622200202600ustar00rootroot00000000000000# Raven sometimes has to deal with some weird JSON. This makes sure whatever # JSON impl we use handles it in the way that we expect. require 'spec_helper' RSpec.describe JSON do data = [ OpenStruct.new(:key => 'foo', :val => 'bar', :enc_key => '"foo"', :enc_val => '"bar"'), OpenStruct.new(:key => :foo, :val => :bar, :enc_key => '"foo"', :enc_val => '"bar"'), OpenStruct.new(:key => 1, :val => 1, :enc_key => '"1"', :enc_val => '1') ] data.each do |obj| it "works with #{obj.key.class} keys" do expect(JSON.dump(obj.key => 'bar')).to eq "{#{obj.enc_key}:\"bar\"}" end it "works with #{obj.val.class} values" do expect(JSON.dump('bar' => obj.val)).to eq "{\"bar\":#{obj.enc_val}}" end it "works with an array of #{obj.val.class}s" do expect(JSON.dump('bar' => [obj.val])).to eq "{\"bar\":[#{obj.enc_val}]}" end it "works with a hash of #{obj.val.class}s" do expect(JSON.dump('bar' => { obj.key => obj.val })).to eq "{\"bar\":{#{obj.enc_key}:#{obj.enc_val}}}" end end it 'encodes anything that responds to to_s' do data = [ :symbol, 1 / 0.0, 0 / 0.0 ] expect(JSON.dump(data)).to eq "[\"symbol\",Infinity,NaN]" end it 'resolves large numbers to Infinity' do expect(JSON.parse("[123e090000000]")).to eq [+1.0 / 0.0] end if RUBY_VERSION.to_f >= 2.0 # 1.9 just hangs on this. it 'it raises the correct error on strings that look like incomplete objects' do expect { JSON.parse("{") }.to raise_error(JSON::ParserError) expect { JSON.parse("[") }.to raise_error(JSON::ParserError) end it "accepts any encoding which is internally valid" do expect do JSON.parse(%({"example": "this is a utf8 or ASCII string"})) end.not_to raise_error expect do JSON.parse(%({"example": "this is a utf8 or ASCII string"}).encode("utf-16")) end.not_to raise_error expect do JSON.parse(%({"example": "this is a utf8 or ASCII string"}).encode("US-ASCII")) end.not_to raise_error end it "blows up on circular references" do data = {} data['data'] = data data['ary'] = [] data['ary'].push('x' => data['ary']) data['ary2'] = data['ary'] data['leave intact'] = { 'not a circular reference' => true } if RUBY_PLATFORM == 'java' expect { JSON.dump(data) }.to raise_error else expect { JSON.dump(data) }.to raise_error(SystemStackError) end end end end raven-ruby-2.13.0/spec/raven/linecache_spec.rb000066400000000000000000000020711357613622200212150ustar00rootroot00000000000000require 'spec_helper' # rubocop:disable Style/WordArray RSpec.describe Raven::LineCache do describe "#get_file_context" do it "returns an array of nils if the path is not valid" do expect(subject.get_file_context("/nonexist", 1, 10)).to eq([nil, nil, nil]) end it "returns a variable size depending on context" do expect(subject.get_file_context("spec/support/linecache.txt", 3, 2)).to eq( [ ["foo\n", "bar\n"], "baz\n", ["qux\n", "lorem\n"] ] ) end it "returns nil if line doesnt exist" do expect(subject.get_file_context("spec/support/linecache.txt", 1, 2)).to eq( [ [nil, nil], "foo\n", ["bar\n", "baz\n"] ] ) end it "returns a different section of the file based on lineno" do expect(subject.get_file_context("./spec/support/linecache.txt", 4, 2)).to eq( [ ["bar\n", "baz\n"], "qux\n", ["lorem\n", "ipsum\n"] ] ) end end end # rubocop:enable Style/WordArray raven-ruby-2.13.0/spec/raven/logger_spec.rb000066400000000000000000000010231357613622200205550ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Logger do it "should log to a given IO" do stringio = StringIO.new log = Raven::Logger.new(stringio) log.fatal("Oh noes!") expect(stringio.string).to end_with("FATAL -- sentry: ** [Raven] Oh noes!\n") end it "should allow exceptions to be logged" do stringio = StringIO.new log = Raven::Logger.new(stringio) log.fatal(Exception.new("Oh exceptions")) expect(stringio.string).to end_with("FATAL -- sentry: ** [Raven] Oh exceptions\n") end end raven-ruby-2.13.0/spec/raven/processors/000077500000000000000000000000001357613622200201455ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/processors/cookies_spec.rb000066400000000000000000000027461357613622200231510ustar00rootroot00000000000000# Encoding: utf-8 require 'spec_helper' RSpec.describe Raven::Processor::Cookies do before do @client = double("client") @processor = Raven::Processor::Cookies.new(@client) end it 'should remove cookies' do test_data = { :request => { :headers => { "Cookie" => "_sentry-testapp_session=SlRKVnNha2Z", "AnotherHeader" => "still_here" }, :cookies => "_sentry-testapp_session=SlRKVnNha2Z", :some_other_data => "still_here" } } result = @processor.process(test_data) expect(result[:request][:cookies]).to eq("********") expect(result[:request][:headers]["Cookie"]).to eq("********") expect(result[:request][:some_other_data]).to eq("still_here") expect(result[:request][:headers]["AnotherHeader"]).to eq("still_here") end it 'should remove cookies even if keys are strings' do test_data = { "request" => { "headers" => { "Cookie" => "_sentry-testapp_session=SlRKVnNha2Z", "AnotherHeader" => "still_here" }, "cookies" => "_sentry-testapp_session=SlRKVnNha2Z", "some_other_data" => "still_here" } } result = @processor.process(test_data) expect(result["request"]["cookies"]).to eq("********") expect(result["request"]["headers"]["Cookie"]).to eq("********") expect(result["request"]["some_other_data"]).to eq("still_here") expect(result["request"]["headers"]["AnotherHeader"]).to eq("still_here") end end raven-ruby-2.13.0/spec/raven/processors/http_headers_spec.rb000066400000000000000000000030021357613622200241510ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Processor::HTTPHeaders do before do @client = double("client") allow(@client).to receive_message_chain(:configuration, :sanitize_http_headers) { ['User-Defined-Header'] } @processor = Raven::Processor::HTTPHeaders.new(@client) end it 'should remove HTTP headers we dont like' do data = { :request => { :headers => { "Authorization" => "dontseeme", "AnotherHeader" => "still_here" } } } result = @processor.process(data) expect(result[:request][:headers]["Authorization"]).to eq("********") expect(result[:request][:headers]["AnotherHeader"]).to eq("still_here") end it 'should be configurable' do data = { :request => { :headers => { "User-Defined-Header" => "dontseeme", "AnotherHeader" => "still_here" } } } result = @processor.process(data) expect(result[:request][:headers]["User-Defined-Header"]).to eq("********") expect(result[:request][:headers]["AnotherHeader"]).to eq("still_here") end it "should remove headers even if the keys are strings" do data = { "request" => { "headers" => { "Authorization" => "dontseeme", "AnotherHeader" => "still_here" } } } result = @processor.process(data) expect(result["request"]["headers"]["Authorization"]).to eq("********") expect(result["request"]["headers"]["AnotherHeader"]).to eq("still_here") end end raven-ruby-2.13.0/spec/raven/processors/post_data_spec.rb000066400000000000000000000022561357613622200234670ustar00rootroot00000000000000# Encoding: utf-8 require 'spec_helper' RSpec.describe Raven::Processor::PostData do before do @client = double("client") @processor = Raven::Processor::PostData.new(@client) end it 'should remove post data when HTTP method is POST' do data = { :request => { :method => "POST", :data => { "sensitive_stuff" => "TOP_SECRET-GAMMA" } } } result = @processor.process(data) expect(result[:request][:data]).to eq("********") end it 'should NOT remove post data when HTTP method is not POST' do data = { :request => { :method => "GET", :data => { "sensitive_stuff" => "TOP_SECRET-GAMMA" } } } result = @processor.process(data) expect(result[:request][:data]).to eq("sensitive_stuff" => "TOP_SECRET-GAMMA") end it 'should remove post data when HTTP method is POST and keys are strings' do data = { "request" => { "method" => "POST", "data" => { "sensitive_stuff" => "TOP_SECRET-GAMMA" } } } result = @processor.process(data) expect(result["request"]["data"]).to eq("********") end end raven-ruby-2.13.0/spec/raven/processors/removecirculareferences_spec.rb000066400000000000000000000013321357613622200264050ustar00rootroot00000000000000# Encoding: utf-8 require 'spec_helper' RSpec.describe Raven::Processor::RemoveCircularReferences do before do @client = double("client") @processor = Raven::Processor::RemoveCircularReferences.new(@client) end it 'should cleanup circular references' do data = {} data['data'] = data data['ary'] = [] data['ary'].push('x' => data['ary']) data['ary2'] = data['ary'] data['leave intact'] = { 'not a circular reference' => true } result = @processor.process(data) expect(result['data']).to eq('(...)') expect(result['ary'].first['x']).to eq('(...)') expect(result['ary2']).to eq("(...)") expect(result['leave intact']).to eq('not a circular reference' => true) end end raven-ruby-2.13.0/spec/raven/processors/removestacktrace_spec.rb000066400000000000000000000040531357613622200250500ustar00rootroot00000000000000require 'spec_helper' require 'raven/processor/removestacktrace' RSpec.describe Raven::Processor::RemoveStacktrace do before do @client = double("client") @processor = Raven::Processor::RemoveStacktrace.new(@client) end it 'should remove stacktraces' do data = Raven::Event.capture_exception(build_exception).to_hash expect(data[:exception][:values][0][:stacktrace]).to_not eq(nil) result = @processor.process(data) expect(result[:exception][:values][0][:stacktrace]).to eq(nil) end # Only check causes when they're supported if Exception.new.respond_to? :cause it 'should remove stacktraces from causes' do data = Raven::Event.capture_exception(build_exception_with_cause).to_hash expect(data[:exception][:values][0][:stacktrace]).to_not eq(nil) expect(data[:exception][:values][1][:stacktrace]).to_not eq(nil) result = @processor.process(data) expect(result[:exception][:values][0][:stacktrace]).to eq(nil) expect(result[:exception][:values][1][:stacktrace]).to eq(nil) end it 'should remove stacktraces from nested causes' do data = Raven::Event.capture_exception(build_exception_with_two_causes).to_hash expect(data[:exception][:values][0][:stacktrace]).to_not eq(nil) expect(data[:exception][:values][1][:stacktrace]).to_not eq(nil) expect(data[:exception][:values][2][:stacktrace]).to_not eq(nil) result = @processor.process(data) expect(result[:exception][:values][0][:stacktrace]).to eq(nil) expect(result[:exception][:values][1][:stacktrace]).to eq(nil) expect(result[:exception][:values][2][:stacktrace]).to eq(nil) end end if defined?(Rails) # depends on activesupport it 'should remove stacktraces even when keys are strings' do data = Raven::Event.capture_exception(build_exception).to_hash.deep_stringify_keys expect(data["exception"]["values"][0]["stacktrace"]).to_not eq(nil) result = @processor.process(data) expect(result["exception"]["values"][0]["stacktrace"]).to eq(nil) end end end raven-ruby-2.13.0/spec/raven/processors/sanitizedata_processor_spec.rb000066400000000000000000000175121357613622200262710ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Processor::SanitizeData do before do config = Struct.new(:sanitize_fields, :sanitize_credit_cards, :sanitize_fields_excluded).new([], true, []) client = Struct.new(:configuration).new(config) @processor = Raven::Processor::SanitizeData.new(client) end context 'configuration for sanitize fields' do it 'should union default sanitize fields with user-defined sanitize fields' do fields = Raven::Processor::SanitizeData::DEFAULT_FIELDS | %w(test monkeybutt) @processor.sanitize_fields = fields expected_fields_re = /authorization|password|passwd|secret|ssn|social(.*)?sec|\btest\b|\bmonkeybutt\b/i expect(@processor.send(:fields_re)).to eq(expected_fields_re) end it 'should remove default fields if specified by sanitize_fields_excluded' do @processor.sanitize_fields_excluded = %w(authorization) expected_fields_re = /password|passwd|secret|ssn|social(.*)?sec/i expect(@processor.send(:fields_re)).to eq(expected_fields_re) end it 'accepts regex-like strings' do @processor.sanitize_fields = ["foo(.*)?bar"] expected_fields_re = /authorization|password|passwd|secret|ssn|social(.*)?sec|foo(.*)?bar/i expect(@processor.send(:fields_re)).to eq(expected_fields_re) end end it 'should filter http data' do @processor.sanitize_fields = ['user_field'] data = { 'sentry.interfaces.Http' => { 'data' => { 'foo' => 'bar', 'password' => 'hello', 'the_secret' => 'hello', 'a_password_here' => 'hello', 'mypasswd' => 'hello', 'test' => 1, :ssn => '123-45-6789', # test symbol handling 'social_security_number' => 123456789, 'user_field' => 'user', 'user_field_foo' => 'hello', 'query_string' => 'foo=bar%E9' # test utf8 handling } } } result = @processor.process(data) vars = result["sentry.interfaces.Http"]["data"] expect(vars["foo"]).to eq("bar") expect(vars["password"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["the_secret"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["a_password_here"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["mypasswd"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["test"]).to eq(1) expect(vars[:ssn]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["social_security_number"]).to eq(Raven::Processor::SanitizeData::INT_MASK) expect(vars["user_field"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["user_field_foo"]).to eq('hello') expect(vars["query_string"]).to match('foo=bar') end it 'should filter json data' do @processor.sanitize_fields = ['user_field'] data_with_json = { 'json' => { 'foo' => 'bar', 'password' => 'hello', 'the_secret' => 'hello', 'a_password_here' => 'hello', 'mypasswd' => 'hello', 'test' => 1, 'ssn' => '123-45-6789', 'social_security_number' => 123456789, 'user_field' => 'user', 'user_field_foo' => 'hello' }.to_json } result = JSON.parse(@processor.process(data_with_json)['json']) vars = result expect(vars["foo"]).to eq("bar") expect(vars["password"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["the_secret"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["a_password_here"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["mypasswd"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["test"]).to eq(1) expect(vars["ssn"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["social_security_number"]).to eq(Raven::Processor::SanitizeData::INT_MASK) expect(vars["user_field"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(vars["user_field_foo"]).to eq('hello') end it 'should filter json embedded in a ruby object' do data_with_embedded_json = { 'data' => { 'json' => %w(foo bar).to_json, 'json_hash' => { 'foo' => 'bar' }.to_json, 'sensitive' => { 'password' => 'secret' }.to_json } } result = @processor.process(data_with_embedded_json) expect(JSON.parse(result["data"]["json"])).to eq(%w(foo bar)) expect(JSON.parse(result["data"]["json_hash"])).to eq('foo' => 'bar') expect(JSON.parse(result["data"]["sensitive"])).to eq('password' => Raven::Processor::SanitizeData::STRING_MASK) end it 'should not fail when json is invalid' do data_with_invalid_json = { 'data' => { 'invalid' => "{\r\n\"key\":\"value\",\r\n \"foo\":{\"bar\":\"baz\"}\r\n" } } result = @processor.process(data_with_invalid_json) expect { JSON.parse(result["data"]["invalid"]) }.to raise_exception(JSON::ParserError) end it 'should filter credit card values' do data = { 'ccnumba' => '4242424242424242', 'ccnumba_int' => 4242424242424242 } result = @processor.process(data) expect(result["ccnumba"]).to eq(Raven::Processor::SanitizeData::STRING_MASK) expect(result["ccnumba_int"]).to eq(Raven::Processor::SanitizeData::INT_MASK) end it 'should pass through credit card values if configured' do @processor.sanitize_credit_cards = false data = { 'ccnumba' => '4242424242424242', 'ccnumba_int' => 4242424242424242 } result = @processor.process(data) expect(result["ccnumba"]).to eq('4242424242424242') expect(result["ccnumba_int"]).to eq(4242424242424242) end it 'sanitizes hashes nested in arrays' do data = { "empty_array" => [], "array" => [{ 'password' => 'secret' }] } result = @processor.process(data) expect(result["array"][0]['password']).to eq(Raven::Processor::SanitizeData::STRING_MASK) end context "query strings" do it 'sanitizes' do data = { 'sentry.interfaces.Http' => { 'data' => { 'query_string' => 'foo=bar&password=secret' } } } result = @processor.process(data) vars = result["sentry.interfaces.Http"]["data"] expect(vars["query_string"]).to_not include("secret") end it 'handles :query_string as symbol' do data = { 'sentry.interfaces.Http' => { 'data' => { :query_string => 'foo=bar&password=secret' } } } result = @processor.process(data) vars = result["sentry.interfaces.Http"]["data"] expect(vars[:query_string]).to_not include("secret") end it 'handles multiple values for a key' do data = { 'sentry.interfaces.Http' => { 'data' => { 'query_string' => 'foo=bar&foo=fubar&foo=barfoo' } } } result = @processor.process(data) vars = result["sentry.interfaces.Http"]["data"] query_string = vars["query_string"].split('&') expect(query_string).to include("foo=bar") expect(query_string).to include("foo=fubar") expect(query_string).to include("foo=barfoo") end it 'handles url encoded keys and values' do encoded_query_string = 'Bio+4%24=cA%24%7C-%7C+M%28%29n3%5E' data = { 'sentry.interfaces.Http' => { 'data' => { 'query_string' => encoded_query_string } } } result = @processor.process(data) vars = result["sentry.interfaces.Http"]["data"] expect(vars["query_string"]).to eq(encoded_query_string) end # Sometimes this sort of thing can show up in request headers, e.g. # X-REQUEST-START on Heroku it 'does not censor milliseconds since the epoch' do result = @processor.process(:millis_since_epoch => 1507671610403.to_s) expect(result).to eq(:millis_since_epoch => 1507671610403.to_s) end end end raven-ruby-2.13.0/spec/raven/processors/utf8conversion_spec.rb000066400000000000000000000047461357613622200245130ustar00rootroot00000000000000# Encoding: utf-8 require 'spec_helper' RSpec.describe Raven::Processor::UTF8Conversion do before do @client = double("client") @processor = Raven::Processor::UTF8Conversion.new(@client) @bad_utf8_string = "invalid utf8 string goes here\255".force_encoding('UTF-8') end it "has a utf8 fixture which is not valid utf-8" do expect(@bad_utf8_string.valid_encoding?).to eq(false) expect { @bad_utf8_string.match("") }.to raise_error(ArgumentError) end it 'should cleanup invalid UTF-8 bytes' do data = {} data['invalid'] = @bad_utf8_string results = @processor.process(data) expect(results['invalid']).to eq("invalid utf8 string goes here") end it "should cleanup invalid UTF-8 bytes in Exception messages" do data = Exception.new(@bad_utf8_string) results = @processor.process(data) expect(results.message).to eq("invalid utf8 string goes here") end it 'should keep valid UTF-8 bytes after cleaning' do data = {} data['invalid'] = "한국, 中國, 日本(にっぽん)\255".force_encoding('UTF-8') results = @processor.process(data) expect(results['invalid']).to eq("한국, 中國, 日本(にっぽん)") end it 'should work recursively on hashes' do data = { 'nested' => {} } data['nested']['invalid'] = @bad_utf8_string results = @processor.process(data) expect(results['nested']['invalid']).to eq("invalid utf8 string goes here") end it 'should work recursively on arrays' do data = ['good string', 'good string', ['good string', @bad_utf8_string]] results = @processor.process(data) expect(results[2][1]).to eq("invalid utf8 string goes here") end it 'should not blow up on symbols' do data = { :key => :value } results = @processor.process(data) expect(results[:key]).to eq(:value) end it "deals with unicode hidden in ASCII_8BIT" do data = ["\xE2\x9C\x89 Hello".force_encoding(Encoding::ASCII_8BIT)] results = @processor.process(data) # Calling JSON.generate here to simulate this value eventually being fed # to JSON generator in the client for transport, we're looking to see # if encoding errors are raised expect(JSON.generate(results)).to eq("[\"✉ Hello\"]") end it "deals with unicode hidden in ASCII_8BIT when the string is frozen" do data = ["\xE2\x9C\x89 Hello".force_encoding(Encoding::ASCII_8BIT).freeze] results = @processor.process(data) expect(JSON.generate(results)).to eq("[\"✉ Hello\"]") end end raven-ruby-2.13.0/spec/raven/raven_spec.rb000066400000000000000000000074421357613622200204240ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven do let(:event) { Raven::Event.new(:id => "event_id") } let(:options) { double("options") } before do allow(Raven.instance).to receive(:send_event) allow(Raven::Event).to receive(:from_message) { event } allow(Raven::Event).to receive(:from_exception) { event } end describe '.capture' do context 'not given a block' do let(:options) { { :key => 'value' } } def capture_in_separate_process pipe_in, pipe_out = IO.pipe fork do pipe_in.close described_class.capture(options) allow(Raven.instance).to receive(:capture_type) do |exception, _options| pipe_out.puts exception.message end # silence process $stderr.reopen('/dev/null', 'w') $stdout.reopen('/dev/null', 'w') yield exit end pipe_out.close captured_messages = pipe_in.read pipe_in.close # sometimes the at_exit hook was registered multiple times captured_messages.split("\n").last end it 'does not yield' do # As there is no yield matcher that does not require a probe (e.g. this # is not valid: expect { |b| described_class.capture }.to_not yield_control), # expect that a LocalJumpError, which is raised when yielding when no # block is defined, is not raised. described_class.capture end it 'installs an at exit hook that will capture exceptions' do skip('fork not supported in jruby') if RUBY_PLATFORM == 'java' captured_message = capture_in_separate_process { raise 'test error' } expect(captured_message).to eq('test error') end end end describe '.inject_only' do before do allow(Gem.loaded_specs).to receive(:keys).and_return(%w(railties rack sidekiq)) end it 'loads integrations when they are valid configurations' do expect(Raven).to receive(:load_integration).once.with('railties') expect(Raven).to receive(:load_integration).once.with('sidekiq') Raven.inject_only(:railties, :sidekiq) end it 'skips any integrations that are not supported' do expect(Raven).to receive(:load_integration).once.with('railties') expect(Raven.logger).to receive(:warn).with('Integrations do not exist: doesnot, exist') Raven.inject_only(:railties, :doesnot, :exist) end it 'skips any integrations that are not loaded in the gemspec' do expect(Raven).to receive(:load_integration).once.with('railties') Raven.inject_only(:railties, :delayed_job) end end describe '.inject_without' do before do allow(Gem.loaded_specs).to receive(:keys).and_return(Raven::AVAILABLE_INTEGRATIONS) end it 'injects all integrations except those passed as an argument' do expect(Raven).to receive(:load_integration).once.with('rake') Raven.inject_without(:delayed_job, :logger, :railties, :sidekiq, :rack, :"rack-timeout") end end describe "#sys_command" do it "should execute system commands" do expect(Raven.sys_command("echo 'Sentry'")).to eq("Sentry") end it "should return nil if a system command doesn't exist" do expect(Raven.sys_command("asdasdasdsa")).to eq(nil) end it "should return nil if the process exits with a non-zero exit status" do expect(Raven.sys_command("uname -c")).to eq(nil) # non-existent uname option end it "should not output to stdout on failure" do expect { Raven.sys_command("asdasdasdsa") }.to_not output.to_stdout expect { Raven.sys_command("uname -c") }.to_not output.to_stdout end it "should tolerate a missing $CHILD_STATUS" do Signal.trap('CLD', 'DEFAULT') expect(Raven.sys_command("echo 'Sentry'")).to eq("Sentry") end end end raven-ruby-2.13.0/spec/raven/transports/000077500000000000000000000000001357613622200201625ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/transports/http_spec.rb000066400000000000000000000041361357613622200225040ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Transports::HTTP do let(:config) { Raven::Configuration.new.tap { |c| c.dsn = 'http://12345@sentry.localdomain/sentry/42' } } let(:client) { Raven::Client.new(config) } it 'should set a custom User-Agent' do expect(client.send(:transport).conn.headers[:user_agent]).to eq("sentry-ruby/#{Raven::VERSION}") end it 'should raise an error on 4xx responses' do stubs = Faraday::Adapter::Test::Stubs.new do |stub| stub.post('sentry/api/42/store/') { [404, {}, 'not found'] } end client.configuration.http_adapter = [:test, stubs] event = JSON.generate(Raven::Event.from_message("test").to_hash) expect { client.send(:transport).send_event("test", event) }.to raise_error(Raven::Error, /the server responded with status 404/) stubs.verify_stubbed_calls end it 'should raise an error on 5xx responses' do stubs = Faraday::Adapter::Test::Stubs.new do |stub| stub.post('sentry/api/42/store/') { [500, {}, 'error'] } end client.configuration.http_adapter = [:test, stubs] event = JSON.generate(Raven::Event.from_message("test").to_hash) expect { client.send(:transport).send_event("test", event) }.to raise_error(Raven::Error, /the server responded with status 500/) stubs.verify_stubbed_calls end it 'should add header info message to the error' do stubs = Faraday::Adapter::Test::Stubs.new do |stub| stub.post('sentry/api/42/store/') { [400, { 'x-sentry-error' => 'error_in_header' }, 'error'] } end client.configuration.http_adapter = [:test, stubs] event = JSON.generate(Raven::Event.from_message("test").to_hash) expect { client.send(:transport).send_event("test", event) }.to raise_error(Raven::Error, /error_in_header/) stubs.verify_stubbed_calls end it 'allows to customise faraday' do builder = spy('faraday_builder') expect(Faraday).to receive(:new).and_yield(builder) client.configuration.faraday_builder = proc { |b| b.request :instrumentation } client.send(:transport) expect(builder).to have_received(:request).with(:instrumentation) end end raven-ruby-2.13.0/spec/raven/transports/stdout_spec.rb000066400000000000000000000010011357613622200230330ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Transports::Stdout do let(:config) { Raven::Configuration.new.tap { |c| c.dsn = 'stdout://12345:67890@sentry.localdomain/sentry/42' } } let(:client) { Raven::Client.new(config) } it 'should write to stdout' do event = JSON.generate(Raven::Event.from_message("this is an STDOUT transport test").to_hash) expect { client.send(:transport).send_event("stdout test", event) }.to output(/\"message\":\"this is an STDOUT transport test\"/).to_stdout end end raven-ruby-2.13.0/spec/raven/utils/000077500000000000000000000000001357613622200171035ustar00rootroot00000000000000raven-ruby-2.13.0/spec/raven/utils/exception_cause_chain_spec.rb000066400000000000000000000025711357613622200247670ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Utils::ExceptionCauseChain do describe '.exception_to_array' do # Only check causes when they're supported if Exception.new.respond_to? :cause context 'when the ruby version supports exception causes' do context 'when the exception has a cause' do let(:exception) { build_exception_with_cause } it 'captures the cause' do expect(described_class.exception_to_array(exception).length).to eq(2) end end context 'when the exception has nested causes' do let(:exception) { build_exception_with_two_causes } it 'captures nested causes' do expect(described_class.exception_to_array(exception).length).to eq(3) end end context 'when the exception has a recursive cause' do let(:exception) { build_exception_with_recursive_cause } it 'should handle it gracefully' do expect(described_class.exception_to_array(exception).length).to eq(1) end end end else context 'when the ruby version does not support exception causes' do let(:exception) { build_exception_with_two_causes } it 'returns the passed in exception' do expect(described_class.exception_to_array(exception)).to eq [exception] end end end end end raven-ruby-2.13.0/spec/raven/utils/real_ip_spec.rb000066400000000000000000000037431357613622200220640ustar00rootroot00000000000000require 'spec_helper' RSpec.describe Raven::Utils::RealIp do context "when no ip addresses are provided other than REMOTE_ADDR" do subject { Raven::Utils::RealIp.new(:remote_addr => "1.1.1.1") } it "should return the remote_addr" do expect(subject.calculate_ip).to eq("1.1.1.1") end end context "when a list of x-forwarded-for ips is provided" do subject do Raven::Utils::RealIp.new( :forwarded_for => "192.168.0.2, 2.2.2.2, 3.3.3.3, 4.4.4.4", :remote_addr => "192.168.0.1" ) end it "should return the oldest ancestor that is not a local IP" do expect(subject.calculate_ip).to eq("2.2.2.2") end end context "when client/real ips are provided" do subject do Raven::Utils::RealIp.new( :forwarded_for => "2.2.2.2", :real_ip => "4.4.4.4", :client_ip => "3.3.3.3", :remote_addr => "192.168.0.1" ) end it "should return the oldest ancestor, preferring client/real ips first" do expect(subject.calculate_ip).to eq("3.3.3.3") end end context "all provided ip addresses are actually local addresses" do subject do Raven::Utils::RealIp.new( :forwarded_for => "127.0.0.1, ::1, 10.0.0.0", :remote_addr => "192.168.0.1" ) end it "should return REMOTE_ADDR" do expect(subject.calculate_ip).to eq("192.168.0.1") end end context "when an invalid IP is provided" do subject do Raven::Utils::RealIp.new( :forwarded_for => "4.4.4.4.4, 2.2.2.2", :remote_addr => "192.168.0.1" ) end it "return the eldest valid IP" do expect(subject.calculate_ip).to eq("2.2.2.2") end end context "with IPv6 ips" do subject do Raven::Utils::RealIp.new( :forwarded_for => "2001:db8:a0b:12f0::1", :remote_addr => "192.168.0.1" ) end it "return the eldest valid IP" do expect(subject.calculate_ip).to eq("2001:db8:a0b:12f0::1") end end end raven-ruby-2.13.0/spec/spec_helper.rb000066400000000000000000000036551357613622200174570ustar00rootroot00000000000000require 'sentry-raven-without-integrations' require 'raven/transports/dummy' require 'raven/transports/stdout' Raven.configure do |config| config.dsn = "dummy://12345:67890@sentry.localdomain/sentry/42" config.encoding = "json" config.silence_ready = true config.logger = Logger.new(nil) end if ENV["RAILS_VERSION"] && (ENV["RAILS_VERSION"].to_i == 0) RSpec.configure do |config| config.filter_run_excluding :rails => true end else require File.dirname(__FILE__) + "/support/test_rails_app/app.rb" require "rspec/rails" end RSpec.configure do |config| config.mock_with(:rspec) { |mocks| mocks.verify_partial_doubles = true } config.raise_errors_for_deprecations! config.disable_monkey_patching! Kernel.srand config.seed end RSpec.shared_examples "Raven default capture behavior" do it "captures exceptions" do expect { block }.to raise_error(captured_class) expect(Raven.client.transport.events.size).to eq(1) event = JSON.parse!(Raven.client.transport.events.first[1]) expect(event["exception"]["values"][0]["type"]).to eq(captured_class.name) expect(event["exception"]["values"][0]["value"]).to eq(captured_message) end end def build_exception 1 / 0 rescue ZeroDivisionError => exception return exception end def build_exception_with_cause(cause = "exception a") begin raise cause rescue raise "exception b" end rescue RuntimeError => exception return exception end def build_exception_with_two_causes begin begin raise "exception a" rescue raise "exception b" end rescue raise "exception c" end rescue RuntimeError => exception return exception end def build_exception_with_recursive_cause backtrace = [] exception = double("Exception") allow(exception).to receive(:cause).and_return(exception) allow(exception).to receive(:message).and_return("example") allow(exception).to receive(:backtrace).and_return(backtrace) exception end raven-ruby-2.13.0/spec/support/000077500000000000000000000000001357613622200163445ustar00rootroot00000000000000raven-ruby-2.13.0/spec/support/Rakefile000066400000000000000000000003341357613622200200110ustar00rootroot00000000000000require 'rake' require 'rubygems' require 'raven' require 'raven/transports/dummy' Raven.configure do |config| config.dsn = 'dummy://12345:67890@sentry.localdomain/sentry/42' end task :raise_exception do 1 / 0 end raven-ruby-2.13.0/spec/support/linecache.txt000066400000000000000000000000341357613622200210150ustar00rootroot00000000000000foo bar baz qux lorem ipsum raven-ruby-2.13.0/spec/support/test_rails_app/000077500000000000000000000000001357613622200213555ustar00rootroot00000000000000raven-ruby-2.13.0/spec/support/test_rails_app/app.rb000066400000000000000000000015571357613622200224720ustar00rootroot00000000000000require 'rails' # require "active_record/railtie" require "action_view/railtie" require "action_controller/railtie" # require "action_mailer/railtie" require "active_job/railtie" # require "action_cable/engine" # require "sprockets/railtie" # require "rails/test_unit/railtie" require 'raven/integrations/rails' ActiveSupport::Deprecation.silenced = true class TestApp < Rails::Application config.secret_key_base = "test" # Usually set for us in production.rb config.eager_load = true routes.append do get "/exception", :to => "hello#exception" root :to => "hello#world" end initializer :configure_release do Raven.configure do |config| config.release = 'beta' end end end class HelloController < ActionController::Base def exception raise "An unhandled exception!" end def world render :plain => "Hello World!" end end