appsignal 4.0.4 → 4.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +151 -16
  3. data/CHANGELOG.md +42 -0
  4. data/build_matrix.yml +2 -1
  5. data/ext/agent.rb +27 -27
  6. data/gemfiles/que-1.gemfile +5 -0
  7. data/gemfiles/que-2.gemfile +5 -0
  8. data/lib/appsignal/check_in/scheduler.rb +3 -4
  9. data/lib/appsignal/config.rb +7 -0
  10. data/lib/appsignal/hooks/at_exit.rb +1 -0
  11. data/lib/appsignal/hooks/puma.rb +5 -1
  12. data/lib/appsignal/integrations/puma.rb +45 -0
  13. data/lib/appsignal/integrations/que.rb +8 -2
  14. data/lib/appsignal/rack/abstract_middleware.rb +3 -47
  15. data/lib/appsignal/rack/event_handler.rb +2 -0
  16. data/lib/appsignal/rack/hanami_middleware.rb +5 -1
  17. data/lib/appsignal/rack.rb +68 -0
  18. data/lib/appsignal/version.rb +1 -1
  19. data/spec/lib/appsignal/check_in/cron_spec.rb +134 -134
  20. data/spec/lib/appsignal/check_in/scheduler_spec.rb +297 -224
  21. data/spec/lib/appsignal/config_spec.rb +13 -0
  22. data/spec/lib/appsignal/hooks/at_exit_spec.rb +11 -0
  23. data/spec/lib/appsignal/hooks/puma_spec.rb +31 -23
  24. data/spec/lib/appsignal/integrations/puma_spec.rb +150 -0
  25. data/spec/lib/appsignal/integrations/que_spec.rb +56 -21
  26. data/spec/lib/appsignal/probes_spec.rb +4 -6
  27. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +41 -122
  28. data/spec/lib/appsignal/rack_spec.rb +180 -0
  29. data/spec/lib/appsignal/transaction_spec.rb +96 -92
  30. data/spec/spec_helper.rb +6 -7
  31. data/spec/support/helpers/api_request_helper.rb +40 -0
  32. data/spec/support/helpers/config_helpers.rb +2 -1
  33. data/spec/support/helpers/dependency_helper.rb +5 -0
  34. data/spec/support/matchers/contains_log.rb +10 -3
  35. data/spec/support/mocks/hash_like.rb +10 -0
  36. data/spec/support/mocks/puma_mock.rb +43 -0
  37. data/spec/support/testing.rb +9 -0
  38. metadata +8 -3
  39. data/gemfiles/que.gemfile +0 -5
@@ -61,3 +61,183 @@ describe Appsignal::Rack::Utils do
61
61
  end
62
62
  end
63
63
  end
64
+
65
+ describe Appsignal::Rack::ApplyRackRequest do
66
+ describe "#apply_to" do
67
+ let(:merged_env) do
68
+ Rack::MockRequest.env_for(
69
+ "/some/path",
70
+ {
71
+ "REQUEST_METHOD" => "GET",
72
+ :params => { "page" => 2, "query" => "lorem" },
73
+ "rack.session" => { "session" => "data", "user_id" => 123 }
74
+ }.merge(env)
75
+ )
76
+ end
77
+ let(:env) { {} }
78
+ let(:request) { ::Rack::Request.new(merged_env) }
79
+ let(:options) { {} }
80
+ let(:helper) { described_class.new(request, options) }
81
+ let(:transaction) { http_request_transaction }
82
+ before { start_agent }
83
+
84
+ def apply_to(transaction)
85
+ helper.apply_to(transaction)
86
+ transaction._sample
87
+ end
88
+
89
+ it "sets request metadata" do
90
+ apply_to(transaction)
91
+
92
+ expect(transaction).to include_metadata(
93
+ "method" => "GET",
94
+ "path" => "/some/path"
95
+ )
96
+ expect(transaction).to include_environment(
97
+ "REQUEST_METHOD" => "GET",
98
+ "PATH_INFO" => "/some/path"
99
+ # and more, but we don't need to test Rack mock defaults
100
+ )
101
+ end
102
+
103
+ context "with an invalid HTTP request method" do
104
+ let(:env) { { "REQUEST_METHOD" => "FOO" } }
105
+
106
+ it "stores the invalid HTTP request method" do
107
+ apply_to(transaction)
108
+
109
+ expect(transaction).to include_metadata("method" => "FOO")
110
+ end
111
+ end
112
+
113
+ context "when fetching the request method raises an error" do
114
+ class BrokenRequestMethodRequest < Rack::Request
115
+ def request_method
116
+ raise "uh oh!"
117
+ end
118
+ end
119
+
120
+ let(:env) { { "REQUEST_METHOD" => "FOO" } }
121
+ let(:request) { BrokenRequestMethodRequest.new(merged_env) }
122
+
123
+ it "does not store the invalid HTTP request method" do
124
+ logs = capture_logs { apply_to(transaction) }
125
+
126
+ expect(transaction).to_not include_metadata("method" => anything)
127
+ expect(logs).to contains_log(
128
+ :error,
129
+ "Exception while fetching the HTTP request method: RuntimeError: uh oh"
130
+ )
131
+ end
132
+ end
133
+
134
+ it "sets request parameters" do
135
+ apply_to(transaction)
136
+
137
+ expect(transaction).to include_params(
138
+ "page" => "2",
139
+ "query" => "lorem"
140
+ )
141
+ end
142
+
143
+ context "when params_method isn't set" do
144
+ let(:options) { { :params_method => nil } }
145
+
146
+ it "reports no params" do
147
+ apply_to(transaction)
148
+
149
+ expect(transaction).to_not include_params
150
+ end
151
+ end
152
+
153
+ context "when fetching the request method raises an error" do
154
+ class BrokenRequestParamsRequest < Rack::Request
155
+ def params
156
+ raise "uh oh!"
157
+ end
158
+ end
159
+
160
+ let(:request) { BrokenRequestParamsRequest.new(merged_env) }
161
+ let(:options) { { :params_method => :params } }
162
+
163
+ it "does not store the invalid HTTP request method" do
164
+ logs = capture_logs { apply_to(transaction) }
165
+
166
+ expect(transaction).to_not include_params
167
+ expect(logs).to contains_log(
168
+ :error,
169
+ "Exception while fetching params " \
170
+ "from 'BrokenRequestParamsRequest#params': RuntimeError uh oh!"
171
+ )
172
+ end
173
+ end
174
+
175
+ it "sets session data" do
176
+ apply_to(transaction)
177
+
178
+ expect(transaction).to include_session_data("session" => "data", "user_id" => 123)
179
+ end
180
+
181
+ context "with Hash-like session data" do
182
+ let(:env) { { "rack.session" => HashLike.new("hash-like" => "value", "user_id" => 123) } }
183
+
184
+ it "sets session data" do
185
+ apply_to(transaction)
186
+
187
+ expect(transaction).to include_session_data("hash-like" => "value", "user_id" => 123)
188
+ end
189
+ end
190
+
191
+ context "with queue start header" do
192
+ let(:queue_start_time) { fixed_time * 1_000 }
193
+ let(:env) { { "HTTP_X_REQUEST_START" => "t=#{queue_start_time.to_i}" } } # in milliseconds
194
+
195
+ it "sets the queue start" do
196
+ apply_to(transaction)
197
+
198
+ expect(transaction).to have_queue_start(queue_start_time)
199
+ end
200
+ end
201
+
202
+ class RackFilteredRequest
203
+ attr_reader :env
204
+
205
+ def initialize(env)
206
+ @env = env
207
+ end
208
+
209
+ def path
210
+ "/static/path"
211
+ end
212
+
213
+ def request_method
214
+ "GET"
215
+ end
216
+
217
+ def filtered_params
218
+ { "abc" => "123" }
219
+ end
220
+
221
+ def session
222
+ { "data" => "value" }
223
+ end
224
+ end
225
+
226
+ context "with overridden request class and params method" do
227
+ let(:request) { RackFilteredRequest.new(env) }
228
+ let(:options) { { :params_method => :filtered_params } }
229
+
230
+ it "uses the overridden request class and params method to fetch params" do
231
+ apply_to(transaction)
232
+
233
+ expect(transaction).to include_params("abc" => "123")
234
+ end
235
+
236
+ it "uses the overridden request class to fetch session data" do
237
+ apply_to(transaction)
238
+
239
+ expect(transaction).to include_session_data("data" => "value")
240
+ end
241
+ end
242
+ end
243
+ end
@@ -211,15 +211,15 @@ describe Appsignal::Transaction do
211
211
 
212
212
  context "when a transaction has errors" do
213
213
  let(:error) do
214
- e = ExampleStandardError.new("test message")
215
- allow(e).to receive(:backtrace).and_return(["line 1"])
216
- e
214
+ ExampleStandardError.new("test message").tap do |e|
215
+ e.set_backtrace(["line 1"])
216
+ end
217
217
  end
218
218
 
219
219
  let(:other_error) do
220
- e = ExampleStandardError.new("other test message")
221
- allow(e).to receive(:backtrace).and_return(["line 2"])
222
- e
220
+ ExampleStandardError.new("other test message").tap do |e|
221
+ e.set_backtrace(["line 2"])
222
+ end
223
223
  end
224
224
 
225
225
  context "when an error is already set on the transaction" do
@@ -1526,9 +1526,9 @@ describe Appsignal::Transaction do
1526
1526
  let(:transaction) { create_transaction }
1527
1527
 
1528
1528
  let(:error) do
1529
- e = ExampleStandardError.new("test message")
1530
- allow(e).to receive(:backtrace).and_return(["line 1"])
1531
- e
1529
+ ExampleStandardError.new("test message").tap do |e|
1530
+ e.set_backtrace(["line 1"])
1531
+ end
1532
1532
  end
1533
1533
 
1534
1534
  context "when error argument is not an error" do
@@ -1588,9 +1588,9 @@ describe Appsignal::Transaction do
1588
1588
 
1589
1589
  context "when an error is already set in the transaction" do
1590
1590
  let(:other_error) do
1591
- e = ExampleStandardError.new("other test message")
1592
- allow(e).to receive(:backtrace).and_return(["line 2"])
1593
- e
1591
+ ExampleStandardError.new("other test message").tap do |e|
1592
+ e.set_backtrace(["line 2"])
1593
+ end
1594
1594
  end
1595
1595
 
1596
1596
  before { transaction.set_error(other_error) }
@@ -1697,12 +1697,92 @@ describe Appsignal::Transaction do
1697
1697
  end
1698
1698
  end
1699
1699
  end
1700
+
1701
+ context "with a PG::UniqueViolation" do
1702
+ let(:error) do
1703
+ PG::UniqueViolation.new(
1704
+ "ERROR: duplicate key value violates unique constraint " \
1705
+ "\"index_users_on_email\" DETAIL: Key (email)=(test@test.com) already exists."
1706
+ )
1707
+ end
1708
+ before do
1709
+ stub_const("PG::UniqueViolation", Class.new(StandardError))
1710
+ transaction.add_error(error)
1711
+ end
1712
+
1713
+ it "returns a sanizited error message" do
1714
+ expect(transaction).to have_error(
1715
+ "PG::UniqueViolation",
1716
+ "ERROR: duplicate key value violates unique constraint " \
1717
+ "\"index_users_on_email\" DETAIL: Key (email)=(?) already exists."
1718
+ )
1719
+ end
1720
+ end
1721
+
1722
+ context "with a ActiveRecord::RecordNotUnique" do
1723
+ let(:error) do
1724
+ ActiveRecord::RecordNotUnique.new(
1725
+ "PG::UniqueViolation: ERROR: duplicate key value violates unique constraint " \
1726
+ "\"example_constraint\"\nDETAIL: Key (email)=(foo@example.com) already exists."
1727
+ )
1728
+ end
1729
+ before do
1730
+ stub_const("ActiveRecord::RecordNotUnique", Class.new(StandardError))
1731
+ transaction.add_error(error)
1732
+ end
1733
+
1734
+ it "returns a sanizited error message" do
1735
+ expect(transaction).to have_error(
1736
+ "ActiveRecord::RecordNotUnique",
1737
+ "PG::UniqueViolation: ERROR: duplicate key value violates unique constraint " \
1738
+ "\"example_constraint\"\nDETAIL: Key (email)=(?) already exists."
1739
+ )
1740
+ end
1741
+ end
1742
+
1743
+ context "with Rails module but without backtrace_cleaner method" do
1744
+ it "returns the backtrace uncleaned" do
1745
+ stub_const("Rails", Module.new)
1746
+ error = ExampleStandardError.new("error message")
1747
+ error.set_backtrace(["line 1", "line 2"])
1748
+ transaction.add_error(error)
1749
+
1750
+ expect(last_transaction).to have_error(
1751
+ "ExampleStandardError",
1752
+ "error message",
1753
+ ["line 1", "line 2"]
1754
+ )
1755
+ end
1756
+ end
1757
+
1758
+ if rails_present?
1759
+ context "with Rails" do
1760
+ it "cleans the backtrace with the Rails backtrace cleaner" do
1761
+ ::Rails.backtrace_cleaner.add_filter do |line|
1762
+ line.tr("2", "?")
1763
+ end
1764
+
1765
+ error = ExampleStandardError.new("error message")
1766
+ error.set_backtrace(["line 1", "line 2"])
1767
+ transaction.add_error(error)
1768
+ expect(last_transaction).to have_error(
1769
+ "ExampleStandardError",
1770
+ "error message",
1771
+ ["line 1", "line ?"]
1772
+ )
1773
+ end
1774
+ end
1775
+ end
1700
1776
  end
1701
1777
 
1702
1778
  describe "#_set_error" do
1703
1779
  let(:transaction) { new_transaction }
1704
1780
  let(:env) { http_request_env_with_data }
1705
- let(:error) { ExampleStandardError.new("test message") }
1781
+ let(:error) do
1782
+ ExampleStandardError.new("test message").tap do |e|
1783
+ e.set_backtrace(["line 1"])
1784
+ end
1785
+ end
1706
1786
 
1707
1787
  it "responds to add_exception for backwards compatibility" do
1708
1788
  expect(transaction).to respond_to(:add_exception)
@@ -1716,7 +1796,6 @@ describe Appsignal::Transaction do
1716
1796
 
1717
1797
  context "for a http request" do
1718
1798
  it "sets an error on the transaction" do
1719
- allow(error).to receive(:backtrace).and_return(["line 1"])
1720
1799
  transaction.send(:_set_error, error)
1721
1800
 
1722
1801
  expect(transaction).to have_error(
@@ -1738,9 +1817,9 @@ describe Appsignal::Transaction do
1738
1817
  context "when the error has multiple causes" do
1739
1818
  let(:error) do
1740
1819
  e = ExampleStandardError.new("test message")
1820
+ e.set_backtrace(["line 1"])
1741
1821
  e2 = RuntimeError.new("cause message")
1742
1822
  e3 = StandardError.new("cause message 2")
1743
- allow(e).to receive(:backtrace).and_return(["line 1"])
1744
1823
  allow(e).to receive(:cause).and_return(e2)
1745
1824
  allow(e2).to receive(:cause).and_return(e3)
1746
1825
  e
@@ -1795,8 +1874,7 @@ describe Appsignal::Transaction do
1795
1874
  allow(next_e).to receive(:cause).and_return(e)
1796
1875
  e = next_e
1797
1876
  end
1798
-
1799
- allow(e).to receive(:backtrace).and_return(["line 1"])
1877
+ e.set_backtrace(["line 1"])
1800
1878
  e
1801
1879
  end
1802
1880
 
@@ -1831,7 +1909,7 @@ describe Appsignal::Transaction do
1831
1909
  let(:error) do
1832
1910
  e = ExampleStandardError.new
1833
1911
  allow(e).to receive(:message).and_return(nil)
1834
- allow(e).to receive(:backtrace).and_return(["line 1"])
1912
+ e.set_backtrace(["line 1"])
1835
1913
  e
1836
1914
  end
1837
1915
 
@@ -1985,80 +2063,6 @@ describe Appsignal::Transaction do
1985
2063
 
1986
2064
  # private
1987
2065
 
1988
- describe "#cleaned_backtrace" do
1989
- let(:transaction) { new_transaction }
1990
- subject { transaction.send(:cleaned_backtrace, ["line 1", "line 2"]) }
1991
-
1992
- it "returns the backtrace" do
1993
- expect(subject).to eq ["line 1", "line 2"]
1994
- end
1995
-
1996
- context "with Rails module but without backtrace_cleaner method" do
1997
- it "returns the backtrace uncleaned" do
1998
- stub_const("Rails", Module.new)
1999
- expect(subject).to eq ["line 1", "line 2"]
2000
- end
2001
- end
2002
-
2003
- if rails_present?
2004
- context "with rails" do
2005
- it "cleans the backtrace with the Rails backtrace cleaner" do
2006
- ::Rails.backtrace_cleaner.add_filter do |line|
2007
- line.tr("2", "?")
2008
- end
2009
- expect(subject).to eq ["line 1", "line ?"]
2010
- end
2011
- end
2012
- end
2013
- end
2014
-
2015
- describe "#cleaned_error_message" do
2016
- let(:transaction) { new_transaction }
2017
- let(:error) { StandardError.new("Error message") }
2018
- subject { transaction.send(:cleaned_error_message, error) }
2019
-
2020
- it "returns the error message" do
2021
- expect(subject).to eq "Error message"
2022
- end
2023
-
2024
- context "with a PG::UniqueViolation" do
2025
- before do
2026
- stub_const("PG::UniqueViolation", Class.new(StandardError))
2027
- end
2028
-
2029
- let(:error) do
2030
- PG::UniqueViolation.new(
2031
- "ERROR: duplicate key value violates unique constraint " \
2032
- "\"index_users_on_email\" DETAIL: Key (email)=(test@test.com) already exists."
2033
- )
2034
- end
2035
-
2036
- it "returns a sanizited error message" do
2037
- expect(subject).to eq "ERROR: duplicate key value violates unique constraint " \
2038
- "\"index_users_on_email\" DETAIL: Key (email)=(?) already exists."
2039
- end
2040
- end
2041
-
2042
- context "with a ActiveRecord::RecordNotUnique" do
2043
- before do
2044
- stub_const("ActiveRecord::RecordNotUnique", Class.new(StandardError))
2045
- end
2046
-
2047
- let(:error) do
2048
- ActiveRecord::RecordNotUnique.new(
2049
- "PG::UniqueViolation: ERROR: duplicate key value violates unique constraint " \
2050
- "\"example_constraint\"\nDETAIL: Key (email)=(foo@example.com) already exists."
2051
- )
2052
- end
2053
-
2054
- it "returns a sanizited error message" do
2055
- expect(subject).to eq \
2056
- "PG::UniqueViolation: ERROR: duplicate key value violates unique constraint " \
2057
- "\"example_constraint\"\nDETAIL: Key (email)=(?) already exists."
2058
- end
2059
- end
2060
- end
2061
-
2062
2066
  describe ".to_hash / .to_h" do
2063
2067
  let(:transaction) { new_transaction }
2064
2068
  subject { transaction.to_hash }
data/spec/spec_helper.rb CHANGED
@@ -85,6 +85,10 @@ RSpec.configure do |config|
85
85
  File.join(tmp_dir, "system-tmp")
86
86
  end
87
87
 
88
+ config.before :suite do
89
+ WebMock.disable_net_connect!
90
+ end
91
+
88
92
  config.before :context do
89
93
  FileUtils.rm_rf(tmp_dir)
90
94
  FileUtils.mkdir_p(spec_system_tmp_dir)
@@ -94,6 +98,8 @@ RSpec.configure do |config|
94
98
  Appsignal.clear!
95
99
  Appsignal::Testing.clear!
96
100
  Appsignal::Loaders.clear!
101
+ Appsignal::CheckIn.clear!
102
+
97
103
  clear_current_transaction!
98
104
  stop_minutely_probes
99
105
  ENV["RAILS_ENV"] ||= "test"
@@ -168,13 +174,6 @@ RSpec.configure do |config|
168
174
  end
169
175
 
170
176
  def stop_minutely_probes
171
- thread =
172
- begin
173
- Appsignal::Probes.class_variable_get(:@@thread) # Fetch old thread
174
- rescue NameError
175
- nil
176
- end
177
177
  Appsignal::Probes.stop
178
- thread&.join # Wait for old thread to exit
179
178
  end
180
179
  end
@@ -17,4 +17,44 @@ module ApiRequestHelper
17
17
  endpoint = config[:endpoint] || Appsignal::Config::DEFAULT_CONFIG[:endpoint]
18
18
  stub_request(:post, "#{endpoint}/1/#{path}").with(options)
19
19
  end
20
+
21
+ def stub_check_in_request(events:, response: { :status => 200 })
22
+ config = Appsignal.config
23
+ options = {
24
+ :query => {
25
+ :api_key => config[:push_api_key],
26
+ :name => config[:name],
27
+ :environment => config.respond_to?(:env) ? config.env : config[:environment],
28
+ :hostname => config[:hostname],
29
+ :gem_version => Appsignal::VERSION
30
+ },
31
+ :headers => { "Content-Type" => "application/x-ndjson; charset=UTF-8" }
32
+ }
33
+
34
+ request_stub =
35
+ stub_request(
36
+ :post,
37
+ "#{config[:logging_endpoint]}/check_ins/json"
38
+ ).with(options) do |request|
39
+ # Parse each line as JSON per the NDJSON format
40
+ payloads = request.body.split("\n").map { |line| JSON.parse(line) }
41
+ formatted_events =
42
+ events.map do |event|
43
+ {
44
+ "identifier" => nil,
45
+ "digest" => kind_of(String),
46
+ "kind" => "start",
47
+ "timestamp" => kind_of(Integer),
48
+ "check_in_type" => "cron"
49
+ }.merge(event)
50
+ end
51
+ expect(payloads).to include(*formatted_events)
52
+ end
53
+
54
+ if response.is_a?(Exception)
55
+ request_stub.to_raise(response)
56
+ else
57
+ request_stub.to_return(response)
58
+ end
59
+ end
20
60
  end
@@ -46,7 +46,7 @@ module ConfigHelpers
46
46
  end
47
47
  module_function :build_config
48
48
 
49
- def start_agent(env: "production", options: {})
49
+ def start_agent(env: "production", options: {}, internal_logger: nil)
50
50
  env = "production" if env == :default
51
51
  env ||= "production"
52
52
  Appsignal.configure(env, :root_path => project_fixture_path) do |config|
@@ -55,6 +55,7 @@ module ConfigHelpers
55
55
  end
56
56
  end
57
57
  Appsignal.start
58
+ Appsignal.internal_logger = internal_logger if internal_logger
58
59
  end
59
60
 
60
61
  def clear_integration_env_vars!
@@ -127,6 +127,11 @@ module DependencyHelper
127
127
  dependency_present? "que"
128
128
  end
129
129
 
130
+ def que2_present?
131
+ que_present? &&
132
+ Gem.loaded_specs["que"].version >= Gem::Version.new("2.0.0")
133
+ end
134
+
130
135
  def hanami_present?
131
136
  dependency_present? "hanami"
132
137
  end
@@ -1,14 +1,21 @@
1
1
  RSpec::Matchers.define :contains_log do |level, message|
2
- expected_log_line = "[#{level.upcase}] #{message}"
2
+ log_level_prefix = level.upcase
3
3
 
4
4
  match do |actual|
5
- actual.include?(expected_log_line)
5
+ case message
6
+ when Regexp
7
+ /\[#{log_level_prefix}\] #{message}/.match?(actual)
8
+ else
9
+ expected_log_line = "[#{log_level_prefix}] #{message}"
10
+ actual.include?(expected_log_line)
11
+ end
6
12
  end
7
13
 
8
14
  failure_message do |actual|
9
15
  <<~MESSAGE
10
16
  Did not contain log line:
11
- #{expected_log_line}
17
+ Log level: #{log_level_prefix}
18
+ Message: #{message}
12
19
 
13
20
  Received logs:
14
21
  #{actual}
@@ -0,0 +1,10 @@
1
+ class HashLike < Hash
2
+ def initialize(value)
3
+ super
4
+ @value = value
5
+ end
6
+
7
+ def to_h
8
+ @value
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ class PumaMock
2
+ module MiniSSL
3
+ class SSLError < StandardError
4
+ def self.to_s
5
+ "Puma::MiniSSL::SSLError"
6
+ end
7
+ end
8
+ end
9
+
10
+ class HttpParserError < StandardError
11
+ def self.to_s
12
+ "Puma::HttpParserError"
13
+ end
14
+ end
15
+
16
+ class HttpParserError501 < StandardError
17
+ def self.to_s
18
+ "Puma::HttpParserError501"
19
+ end
20
+ end
21
+
22
+ def self.stats
23
+ end
24
+
25
+ def self.cli_config
26
+ @cli_config ||= CliConfig.new
27
+ end
28
+
29
+ class Server
30
+ end
31
+
32
+ module Const
33
+ VERSION = "6.0.0".freeze
34
+ end
35
+
36
+ class CliConfig
37
+ attr_accessor :options
38
+
39
+ def initialize
40
+ @options = {}
41
+ end
42
+ end
43
+ end
@@ -47,6 +47,15 @@ module Appsignal
47
47
  end
48
48
  end
49
49
 
50
+ module CheckIn
51
+ class << self
52
+ def clear!
53
+ @transmitter = nil
54
+ @scheduler = nil
55
+ end
56
+ end
57
+ end
58
+
50
59
  # @api private
51
60
  module Testing
52
61
  class << self