opbeat 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/.travis.yml +19 -28
  4. data/.yardopts +3 -0
  5. data/Gemfile +4 -2
  6. data/HISTORY.md +3 -0
  7. data/LICENSE +7 -196
  8. data/README.md +96 -177
  9. data/Rakefile +19 -13
  10. data/gemfiles/Gemfile.base +28 -0
  11. data/gemfiles/Gemfile.rails-3.2.x +3 -0
  12. data/gemfiles/Gemfile.rails-4.0.x +3 -0
  13. data/gemfiles/Gemfile.rails-4.1.x +3 -0
  14. data/gemfiles/Gemfile.rails-4.2.x +3 -0
  15. data/lib/opbeat.rb +113 -93
  16. data/lib/opbeat/capistrano.rb +3 -4
  17. data/lib/opbeat/client.rb +243 -82
  18. data/lib/opbeat/configuration.rb +51 -64
  19. data/lib/opbeat/data_builders.rb +16 -0
  20. data/lib/opbeat/data_builders/error.rb +27 -0
  21. data/lib/opbeat/data_builders/transactions.rb +85 -0
  22. data/lib/opbeat/error.rb +1 -2
  23. data/lib/opbeat/error_message.rb +71 -0
  24. data/lib/opbeat/error_message/exception.rb +12 -0
  25. data/lib/opbeat/error_message/http.rb +62 -0
  26. data/lib/opbeat/error_message/stacktrace.rb +75 -0
  27. data/lib/opbeat/error_message/user.rb +23 -0
  28. data/lib/opbeat/filter.rb +53 -43
  29. data/lib/opbeat/http_client.rb +141 -0
  30. data/lib/opbeat/injections.rb +83 -0
  31. data/lib/opbeat/injections/json.rb +19 -0
  32. data/lib/opbeat/injections/net_http.rb +43 -0
  33. data/lib/opbeat/injections/redis.rb +23 -0
  34. data/lib/opbeat/injections/sequel.rb +32 -0
  35. data/lib/opbeat/injections/sinatra.rb +56 -0
  36. data/lib/opbeat/{capistrano → integration}/capistrano2.rb +6 -6
  37. data/lib/opbeat/{capistrano → integration}/capistrano3.rb +3 -3
  38. data/lib/opbeat/{integrations → integration}/delayed_job.rb +6 -11
  39. data/lib/opbeat/integration/rails/inject_exceptions_catcher.rb +23 -0
  40. data/lib/opbeat/integration/railtie.rb +53 -0
  41. data/lib/opbeat/integration/resque.rb +16 -0
  42. data/lib/opbeat/integration/sidekiq.rb +38 -0
  43. data/lib/opbeat/line_cache.rb +21 -0
  44. data/lib/opbeat/logging.rb +37 -0
  45. data/lib/opbeat/middleware.rb +59 -0
  46. data/lib/opbeat/normalizers.rb +65 -0
  47. data/lib/opbeat/normalizers/action_controller.rb +21 -0
  48. data/lib/opbeat/normalizers/action_view.rb +71 -0
  49. data/lib/opbeat/normalizers/active_record.rb +41 -0
  50. data/lib/opbeat/sql_summarizer.rb +27 -0
  51. data/lib/opbeat/subscriber.rb +80 -0
  52. data/lib/opbeat/tasks.rb +20 -18
  53. data/lib/opbeat/trace.rb +47 -0
  54. data/lib/opbeat/trace_helpers.rb +29 -0
  55. data/lib/opbeat/transaction.rb +99 -0
  56. data/lib/opbeat/util.rb +26 -0
  57. data/lib/opbeat/util/constantize.rb +54 -0
  58. data/lib/opbeat/util/inspector.rb +75 -0
  59. data/lib/opbeat/version.rb +1 -1
  60. data/lib/opbeat/worker.rb +55 -0
  61. data/opbeat.gemspec +6 -14
  62. data/spec/opbeat/client_spec.rb +216 -29
  63. data/spec/opbeat/configuration_spec.rb +34 -38
  64. data/spec/opbeat/data_builders/error_spec.rb +43 -0
  65. data/spec/opbeat/data_builders/transactions_spec.rb +51 -0
  66. data/spec/opbeat/error_message/exception_spec.rb +22 -0
  67. data/spec/opbeat/error_message/http_spec.rb +65 -0
  68. data/spec/opbeat/error_message/stacktrace_spec.rb +56 -0
  69. data/spec/opbeat/error_message/user_spec.rb +28 -0
  70. data/spec/opbeat/error_message_spec.rb +78 -0
  71. data/spec/opbeat/filter_spec.rb +21 -99
  72. data/spec/opbeat/http_client_spec.rb +64 -0
  73. data/spec/opbeat/injections/net_http_spec.rb +37 -0
  74. data/spec/opbeat/injections/sequel_spec.rb +33 -0
  75. data/spec/opbeat/injections/sinatra_spec.rb +13 -0
  76. data/spec/opbeat/injections_spec.rb +49 -0
  77. data/spec/opbeat/integration/delayed_job_spec.rb +35 -0
  78. data/spec/opbeat/integration/json_spec.rb +41 -0
  79. data/spec/opbeat/integration/rails_spec.rb +88 -0
  80. data/spec/opbeat/integration/redis_spec.rb +20 -0
  81. data/spec/opbeat/integration/resque_spec.rb +42 -0
  82. data/spec/opbeat/integration/sidekiq_spec.rb +40 -0
  83. data/spec/opbeat/integration/sinatra_spec.rb +66 -0
  84. data/spec/opbeat/line_cache_spec.rb +38 -0
  85. data/spec/opbeat/logging_spec.rb +47 -0
  86. data/spec/opbeat/middleware_spec.rb +32 -0
  87. data/spec/opbeat/normalizers/action_controller_spec.rb +32 -0
  88. data/spec/opbeat/normalizers/action_view_spec.rb +77 -0
  89. data/spec/opbeat/normalizers/active_record_spec.rb +70 -0
  90. data/spec/opbeat/normalizers_spec.rb +16 -0
  91. data/spec/opbeat/sql_summarizer_spec.rb +6 -0
  92. data/spec/opbeat/subscriber_spec.rb +83 -0
  93. data/spec/opbeat/trace_spec.rb +43 -0
  94. data/spec/opbeat/transaction_spec.rb +98 -0
  95. data/spec/opbeat/util/inspector_spec.rb +40 -0
  96. data/spec/opbeat/util_spec.rb +20 -0
  97. data/spec/opbeat/worker_spec.rb +54 -0
  98. data/spec/opbeat_spec.rb +49 -0
  99. data/spec/spec_helper.rb +79 -6
  100. metadata +89 -149
  101. data/Makefile +0 -3
  102. data/gemfiles/rails30.gemfile +0 -9
  103. data/gemfiles/rails31.gemfile +0 -9
  104. data/gemfiles/rails32.gemfile +0 -9
  105. data/gemfiles/rails40.gemfile +0 -9
  106. data/gemfiles/rails41.gemfile +0 -9
  107. data/gemfiles/rails42.gemfile +0 -9
  108. data/gemfiles/ruby192_rails31.gemfile +0 -10
  109. data/gemfiles/ruby192_rails32.gemfile +0 -10
  110. data/gemfiles/sidekiq31.gemfile +0 -11
  111. data/lib/opbeat/better_attr_accessor.rb +0 -44
  112. data/lib/opbeat/event.rb +0 -223
  113. data/lib/opbeat/integrations/resque.rb +0 -22
  114. data/lib/opbeat/integrations/sidekiq.rb +0 -32
  115. data/lib/opbeat/interfaces.rb +0 -35
  116. data/lib/opbeat/interfaces/exception.rb +0 -16
  117. data/lib/opbeat/interfaces/http.rb +0 -57
  118. data/lib/opbeat/interfaces/message.rb +0 -19
  119. data/lib/opbeat/interfaces/stack_trace.rb +0 -50
  120. data/lib/opbeat/linecache.rb +0 -25
  121. data/lib/opbeat/logger.rb +0 -21
  122. data/lib/opbeat/rack.rb +0 -46
  123. data/lib/opbeat/rails/middleware/debug_exceptions_catcher.rb +0 -22
  124. data/lib/opbeat/railtie.rb +0 -26
  125. data/spec/opbeat/better_attr_accessor_spec.rb +0 -99
  126. data/spec/opbeat/event_spec.rb +0 -138
  127. data/spec/opbeat/integrations/delayed_job_spec.rb +0 -38
  128. data/spec/opbeat/logger_spec.rb +0 -55
  129. data/spec/opbeat/opbeat_spec.rb +0 -64
  130. data/spec/opbeat/rack_spec.rb +0 -117
@@ -0,0 +1,26 @@
1
+ module Opbeat
2
+ # @api private
3
+ module Util
4
+ def self.nearest_minute
5
+ now = Time.now.utc
6
+ now - now.to_i % 60
7
+ end
8
+
9
+ def self.nanos
10
+ now = Time.now.utc
11
+ now.to_i * 1_000_000_000 + now.usec * 1_000
12
+ end
13
+ end
14
+
15
+ require 'opbeat/util/inspector'
16
+ end
17
+
18
+ # TODO: Maybe move this some place more explicit as we're extending
19
+ # a pretty widely used class. Or maybe don't extend at all.
20
+ if RUBY_VERSION.to_i <= 1
21
+ class Struct
22
+ def to_h
23
+ Hash[self.each_pair.to_a]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ module Opbeat
2
+ module Util
3
+ # From https://github.com/rails/rails/blob/861b70e92f4a1fc0e465ffcf2ee62680519c8f6f/activesupport/lib/active_support/inflector/methods.rb#L249
4
+ #
5
+ # Tries to find a constant with the name specified in the argument string.
6
+ #
7
+ # 'Module'.constantize # => Module
8
+ # 'Test::Unit'.constantize # => Test::Unit
9
+ #
10
+ # The name is assumed to be the one of a top-level constant, no matter
11
+ # whether it starts with "::" or not. No lexical context is taken into
12
+ # account:
13
+ #
14
+ # C = 'outside'
15
+ # module M
16
+ # C = 'inside'
17
+ # C # => 'inside'
18
+ # 'C'.constantize # => 'outside', same as ::C
19
+ # end
20
+ #
21
+ # NameError is raised when the name is not in CamelCase or the constant is
22
+ # unknown.
23
+ def self.constantize(camel_cased_word)
24
+ names = camel_cased_word.split('::')
25
+
26
+ # Trigger a built-in NameError exception including the ill-formed constant in the message.
27
+ Object.const_get(camel_cased_word) if names.empty?
28
+
29
+ # Remove the first blank element in case of '::ClassName' notation.
30
+ names.shift if names.size > 1 && names.first.empty?
31
+
32
+ names.inject(Object) do |constant, name|
33
+ if constant == Object
34
+ constant.const_get(name)
35
+ else
36
+ candidate = constant.const_get(name)
37
+ next candidate if constant.const_defined?(name, false)
38
+ next candidate unless Object.const_defined?(name)
39
+
40
+ # Go down the ancestors to check if it is owned directly. The check
41
+ # stops when we reach Object or the end of ancestors tree.
42
+ constant = constant.ancestors.inject do |const, ancestor|
43
+ break const if ancestor == Object
44
+ break ancestor if ancestor.const_defined?(name, false)
45
+ const
46
+ end
47
+
48
+ # owner is in Object, so raise
49
+ constant.const_get(name, false)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+
3
+ module Opbeat
4
+ module Util
5
+ class Inspector
6
+
7
+ DEFAULTS = {
8
+ width: 120
9
+ }.freeze
10
+
11
+ NEWLINE = "\n".freeze
12
+ SPACE = " ".freeze
13
+
14
+ def initialize config = {}
15
+ @config = DEFAULTS.merge(config)
16
+ end
17
+
18
+ def ms nanos
19
+ nanos.to_f / 1_000_000
20
+ end
21
+
22
+ def transaction transaction, opts = {}
23
+ w = @config[:width].to_f
24
+ f = w / ms(transaction.duration)
25
+
26
+ traces = transaction.traces
27
+
28
+ traces = traces.reduce([]) do |state, trace|
29
+ descriptions = [
30
+ "#{trace.signature} - #{trace.kind}",
31
+ "transaction:#{trace.transaction.endpoint}"
32
+ ]
33
+
34
+ if opts[:include_parents]
35
+ descriptions << "parents:#{trace.parents.map(&:signature).join(',')}"
36
+ end
37
+
38
+ descriptions << "duration:#{ms trace.duration}ms - rel:#{ms trace.relative_start}ms"
39
+
40
+ start_diff = ms(trace.start_time) - ms(transaction.start_time)
41
+ indent = (start_diff.floor * f).to_i
42
+
43
+ longest_desc_length = descriptions.map(&:length).max
44
+ desc_indent = [[indent, w - longest_desc_length].min, 0].max
45
+
46
+ lines = descriptions.map do |desc|
47
+ "#{SPACE * desc_indent}#{desc}"
48
+ end
49
+
50
+ if trace.duration
51
+ span = (ms(trace.duration) * f).ceil.to_i
52
+ lines << "#{SPACE * indent}+#{"-" * [(span - 2), 0].max}+"
53
+ else
54
+ lines << "#{SPACE * indent}UNFINISHED"
55
+ end
56
+
57
+ state << lines.join("\n")
58
+ state
59
+ end.join("\n")
60
+
61
+ <<-STR.gsub(/^\s{8}/, '')
62
+ \n#{"=" * (w.to_i)}
63
+ #{transaction.endpoint} - kind:#{transaction.kind} - #{transaction.duration.to_f / 1_000_000}ms
64
+ +#{"-" * (w.to_i - 2)}+
65
+ #{traces}
66
+ STR
67
+ rescue => e
68
+ puts e
69
+ puts e.backtrace.join("\n")
70
+ transaction.inspect
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
1
  module Opbeat
2
- VERSION = "2.0.0"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -0,0 +1,55 @@
1
+ module Opbeat
2
+ # @api private
3
+ class Worker
4
+ include Logging
5
+
6
+ class PostRequest < Struct.new(:path, :data)
7
+ # require all parameters
8
+ def initialize path, data
9
+ super(path, data)
10
+ end
11
+ end
12
+
13
+ class StopMessage; end
14
+
15
+ def initialize config, queue, http_client
16
+ @config = config
17
+ @queue = queue
18
+ @http_client = http_client
19
+ end
20
+
21
+ attr_reader :config
22
+
23
+ def run
24
+ loop do
25
+ while action = @queue.pop
26
+ case action
27
+ when PostRequest
28
+ process_request action
29
+ when StopMessage
30
+ Thread.exit
31
+ else
32
+ raise Error.new("Unknown entity in worker queue: #{action.inspect}")
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def process_request req
41
+ unless config.validate!
42
+ info "Invalid config - Skipping posting to Opbeat"
43
+ return
44
+ end
45
+
46
+ begin
47
+ @http_client.post(req.path, req.data)
48
+ rescue => e
49
+ fatal "Failed POST: #{e.inspect}"
50
+ debug e.backtrace.join("\n")
51
+ end
52
+ end
53
+
54
+ end
55
+ end
data/opbeat.gemspec CHANGED
@@ -1,28 +1,20 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ $:.unshift(lib) unless $:.include?(lib)
4
4
  require 'opbeat/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "opbeat"
8
8
  gem.version = Opbeat::VERSION
9
- gem.authors = ["Thomas Watson Steen", "Ron Cohen", "Noah Kantrowitz"]
9
+ gem.authors = ["Mikkel Malmberg"]
10
10
  gem.email = "support@opbeat.com"
11
- gem.summary = "The official Opbeat Ruby client"
12
- gem.homepage = "https://github.com/opbeat/opbeat_ruby"
13
- gem.license = "Apache-2.0"
11
+ gem.summary = "The official Opbeat Ruby client library"
12
+ gem.homepage = "https://github.com/opbeat/opbeat-ruby"
13
+ gem.license = "BSD-3-Clause"
14
14
 
15
15
  gem.files = `git ls-files -z`.split("\x0")
16
16
  gem.require_paths = ["lib"]
17
17
  gem.extra_rdoc_files = ["README.md", "LICENSE"]
18
18
 
19
- gem.add_dependency "faraday", [">= 0.7.6", "< 0.10"]
20
- gem.add_dependency "multi_json", "~> 1.0"
21
-
22
- gem.add_development_dependency "bundler", "~> 1.7"
23
- gem.add_development_dependency "rake", "~> 10.0"
24
- gem.add_development_dependency "rspec", ">= 2.14"
25
- gem.add_development_dependency "simplecov"
26
- gem.add_development_dependency "delayed_job"
27
- gem.add_development_dependency "sidekiq", "~> 2.17.0"
19
+ gem.add_dependency('activesupport', '>= 3.0.0')
28
20
  end
@@ -1,35 +1,222 @@
1
- require File::expand_path('../../spec_helper', __FILE__)
2
- require 'opbeat'
3
- require 'faraday'
1
+ require 'spec_helper'
4
2
 
5
- http = Faraday.new do |builder|
6
- builder.adapter :test do |stub|
7
- stub.get('/') { |env| [ 200, {}, 'foo' ]}
8
- end
9
- end
3
+ module Opbeat
4
+ RSpec.describe Client do
10
5
 
11
- describe Opbeat::Client do
12
- before do
13
- @configuration = Opbeat::Configuration.new
14
- @configuration.environments = ["test"]
15
- @configuration.current_environment = :test
16
- @configuration.secret_token = 'test'
17
- @configuration.organization_id = 'test'
18
- @configuration.app_id = 'test'
19
- @client = Opbeat::Client.new(@configuration)
20
- allow(@client).to receive(:send)
21
- end
6
+ let(:config) { Configuration.new app_id: 'x', organization_id: 'y', secret_token: 'z' }
22
7
 
23
- it 'send_release should send' do
24
- message = "Test message"
25
- expect(@client).to receive(:send).with("/releases/", message)
26
- @client.send_release(message)
27
- end
8
+ describe ".start!" do
9
+ it "set's up an instance and only one" do
10
+ first_instance = Client.start! config
11
+ expect(Client.inst).to_not be_nil
12
+ expect(Client.start! config).to be first_instance
13
+ end
14
+ end
15
+
16
+ describe ".stop!" do
17
+ it "kills the instance but flushes before" do
18
+ Client.start! config
19
+ Client.inst.submit_transaction Transaction.new(Client.inst, 'Test').done(200)
20
+ Client.stop!
21
+ expect(WebMock).to have_requested(:post, %r{/transactions/$})
22
+ expect(Client.inst).to be_nil
23
+ end
24
+ end
25
+
26
+ context "without worker spec setting", start_without_worker: true do
27
+ it "doesn't start a Worker" do
28
+ expect(Thread).to_not receive(:new)
29
+ Client.start! config
30
+ expect(Client.inst).to_not be_nil
31
+ end
32
+ end
33
+
34
+ context "with a running client", start_without_worker: true do
35
+ subject { Client.inst }
36
+
37
+ describe "#transaction" do
38
+ it "returns a new transaction and sets it as current" do
39
+ transaction = subject.transaction 'Test'
40
+ expect(transaction).to_not be_nil
41
+ expect(subject.current_transaction).to be transaction
42
+ end
43
+ it "returns the current transaction if present" do
44
+ transaction = subject.transaction 'Test'
45
+ expect(subject.transaction 'Test').to eq transaction
46
+ end
47
+ context "with a block" do
48
+ it "yields transaction" do
49
+ blck = lambda { |*args| }
50
+ allow(blck).to receive(:call)
51
+ subject.transaction('Test') { |t| blck.(t) }
52
+ expect(blck).to have_received(:call).with(Transaction)
53
+ end
54
+ it "returns transaction" do
55
+ result = subject.transaction('Test') { "DON'T RETURN ME" }
56
+ expect(result).to be_a Transaction
57
+ end
58
+ end
59
+ end
60
+
61
+ describe "#trace" do
62
+ it "delegates to current transaction" do
63
+ subject.current_transaction = double('transaction', trace: true)
64
+ subject.trace 1, 2, 3
65
+ expect(subject.current_transaction).to have_received(:trace).with(1, 2, 3)
66
+ subject.current_transaction = nil
67
+ end
68
+
69
+ it "ignores when outside transaction" do
70
+ blk = Proc.new {}
71
+ allow(blk).to receive(:call)
72
+ subject.trace { blk.call }
73
+ expect(blk).to have_received(:call)
74
+ end
75
+ end
76
+
77
+ describe "#submit_transaction" do
78
+ it "doesn't send right away" do
79
+ transaction = Transaction.new(subject, 'test')
80
+
81
+ subject.submit_transaction transaction
82
+
83
+ expect(subject.queue.length).to be 0
84
+ expect(WebMock).to_not have_requested(:post, %r{/transactions/$})
85
+ end
86
+
87
+ it "sends if it's long enough ago that we sent last" do
88
+ transaction = Transaction.new(subject, 'test')
89
+ subject.instance_variable_set :@last_sent_transactions, Time.now.utc - 61
90
+
91
+ subject.submit_transaction transaction
92
+
93
+ expect(subject.queue.length).to be 1
94
+ expect(subject.queue.pop).to be_a Worker::PostRequest
95
+ end
96
+
97
+ it "sends if interval is disabled" do
98
+ transaction = Transaction.new(subject, 'test')
99
+ subject.config.transaction_post_interval = nil
100
+ subject.submit_transaction transaction
101
+ expect(subject.queue.length).to be 1
102
+ end
103
+ end
104
+
105
+ describe "#report" do
106
+ it "builds and posts an exception" do
107
+ exception = Exception.new('BOOM')
108
+
109
+ subject.report exception
110
+
111
+ expect(subject.queue.length).to be 1
112
+ expect(subject.queue.pop).to be_a Worker::PostRequest
113
+ end
114
+
115
+ it "skips nil exceptions" do
116
+ subject.report nil
117
+ expect(WebMock).to_not have_requested(:post, %r{/errors/$})
118
+ end
119
+ end
120
+
121
+ describe "#report_message" do
122
+ it "builds and posts an exception" do
123
+ subject.report_message "Massage message"
124
+
125
+ expect(subject.queue.length).to be 1
126
+ expect(subject.queue.pop).to be_a Worker::PostRequest
127
+ end
128
+ end
129
+
130
+ describe "#capture" do
131
+ it "captures exceptions and sends them off then raises them again" do
132
+ exception = Exception.new("BOOM")
133
+
134
+ expect do
135
+ subject.capture do
136
+ raise exception
137
+ end
138
+ end.to raise_exception(Exception)
139
+
140
+ expect(subject.queue.length).to be 1
141
+ expect(subject.queue.pop).to be_a Worker::PostRequest
142
+ end
143
+ end
144
+
145
+ describe "#release" do
146
+ it "notifies Opbeat of a release" do
147
+ release = { rev: "abc123", status: 'completed' }
148
+
149
+ subject.release release
150
+
151
+ expect(subject.queue.length).to be 1
152
+ expect(subject.queue.pop).to be_a Worker::PostRequest
153
+ end
154
+
155
+ it "may send inline" do
156
+ release = { rev: "abc123", status: 'completed' }
157
+
158
+ subject.release release, inline: true
159
+
160
+ expect(WebMock).to have_requested(:post, %r{/releases/$}).with(body: release)
161
+ end
162
+ end
163
+ end
164
+
165
+ context "with performance disabled" do
166
+ subject do
167
+ Opbeat::Client.inst
168
+ end
169
+
170
+ before do
171
+ config.disable_performance = true
172
+ Opbeat.start! config
173
+ end
174
+ after { Opbeat.stop! }
175
+
176
+ describe "#transaction" do
177
+ it "yields" do
178
+ block = lambda { }
179
+ expect(block).to receive(:call)
180
+ Client.inst.transaction('Test') { block.call }
181
+ end
182
+ it "returns nil" do
183
+ expect(Client.inst.transaction 'Test').to be_nil
184
+ end
185
+ end
186
+
187
+ describe "#trace" do
188
+ it "yields" do
189
+ block = lambda { }
190
+ expect(block).to receive(:call)
191
+ Client.inst.trace('Test', 'trace') { block.call }
192
+ end
193
+ it "returns nil" do
194
+ expect(Client.inst.trace 'Test', 'test').to be_nil
195
+ end
196
+ end
197
+ end
198
+
199
+ context "with errors disabled" do
200
+ subject do
201
+ Opbeat::Client.inst
202
+ end
203
+
204
+ before do
205
+ config.disable_errors = true
206
+ Opbeat.start! config
207
+ end
208
+ after { Opbeat.stop! }
209
+
210
+ describe "#report" do
211
+ it "doesn't do anything" do
212
+ exception = Exception.new('BOOM')
213
+
214
+ Client.inst.report exception
215
+
216
+ expect(Client.inst.queue.length).to be 0
217
+ end
218
+ end
219
+ end
28
220
 
29
- it 'send_message should send' do
30
- event = Opbeat::Event.new :message => "my message"
31
- req = http.get '/'
32
- expect(@client).to receive(:send).with("/errors/", event).and_return(req)
33
- @client.send_event(event)
34
221
  end
35
222
  end