appsignal 4.0.3-java → 4.0.5-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -0
  3. data/ext/agent.rb +27 -27
  4. data/lib/appsignal/check_in/cron.rb +2 -34
  5. data/lib/appsignal/check_in/scheduler.rb +192 -0
  6. data/lib/appsignal/check_in.rb +18 -0
  7. data/lib/appsignal/cli/diagnose.rb +1 -1
  8. data/lib/appsignal/config.rb +7 -0
  9. data/lib/appsignal/hooks/at_exit.rb +3 -1
  10. data/lib/appsignal/hooks/puma.rb +5 -1
  11. data/lib/appsignal/integrations/puma.rb +45 -0
  12. data/lib/appsignal/rack/abstract_middleware.rb +3 -47
  13. data/lib/appsignal/rack/body_wrapper.rb +15 -0
  14. data/lib/appsignal/rack/event_handler.rb +2 -0
  15. data/lib/appsignal/rack/hanami_middleware.rb +5 -1
  16. data/lib/appsignal/rack.rb +68 -0
  17. data/lib/appsignal/transmitter.rb +30 -7
  18. data/lib/appsignal/utils/ndjson.rb +15 -0
  19. data/lib/appsignal/utils.rb +1 -0
  20. data/lib/appsignal/version.rb +1 -1
  21. data/lib/appsignal.rb +1 -0
  22. data/spec/lib/appsignal/check_in/cron_spec.rb +202 -0
  23. data/spec/lib/appsignal/check_in/scheduler_spec.rb +443 -0
  24. data/spec/lib/appsignal/config_spec.rb +13 -0
  25. data/spec/lib/appsignal/environment_spec.rb +1 -1
  26. data/spec/lib/appsignal/hooks/at_exit_spec.rb +22 -0
  27. data/spec/lib/appsignal/hooks/puma_spec.rb +31 -23
  28. data/spec/lib/appsignal/integrations/puma_spec.rb +150 -0
  29. data/spec/lib/appsignal/probes_spec.rb +1 -6
  30. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +41 -122
  31. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +29 -21
  32. data/spec/lib/appsignal/rack_spec.rb +180 -0
  33. data/spec/lib/appsignal/transmitter_spec.rb +48 -2
  34. data/spec/lib/appsignal_spec.rb +5 -0
  35. data/spec/spec_helper.rb +0 -7
  36. data/spec/support/helpers/config_helpers.rb +2 -1
  37. data/spec/support/helpers/take_at_most_helper.rb +21 -0
  38. data/spec/support/matchers/contains_log.rb +10 -3
  39. data/spec/support/mocks/hash_like.rb +10 -0
  40. data/spec/support/mocks/puma_mock.rb +43 -0
  41. metadata +11 -3
  42. data/spec/lib/appsignal/check_in_spec.rb +0 -136
@@ -52,13 +52,41 @@ describe Appsignal::Transmitter do
52
52
  }
53
53
  ).to_return(:status => 200)
54
54
  end
55
- let(:response) { instance.transmit(:the => :payload) }
55
+
56
+ let(:response) { instance.transmit({ :the => :payload }) }
56
57
 
57
58
  it "returns Net::HTTP response" do
58
59
  expect(response).to be_kind_of(Net::HTTPResponse)
59
60
  expect(response.code).to eq "200"
60
61
  end
61
62
 
63
+ describe "with :ndjson format" do
64
+ before do
65
+ stub_request(:post, "https://push.appsignal.com/1/action").with(
66
+ :query => {
67
+ :api_key => "abc",
68
+ :environment => "production",
69
+ :gem_version => Appsignal::VERSION,
70
+ :hostname => config[:hostname],
71
+ :name => "TestApp"
72
+ },
73
+ :body => "{\"the\":\"payload\"}\n{\"part\":\"two\"}",
74
+ :headers => {
75
+ "Content-Type" => "application/x-ndjson; charset=UTF-8"
76
+ }
77
+ ).to_return(:status => 200)
78
+ end
79
+
80
+ let(:response) do
81
+ instance.transmit([{ :the => :payload }, { :part => :two }], :format => :ndjson)
82
+ end
83
+
84
+ it "returns Net::HTTP response" do
85
+ expect(response).to be_kind_of(Net::HTTPResponse)
86
+ expect(response.code).to eq "200"
87
+ end
88
+ end
89
+
62
90
  context "with ca_file_path config option set" do
63
91
  context "when file does not exist" do
64
92
  before do
@@ -106,7 +134,7 @@ describe Appsignal::Transmitter do
106
134
  end
107
135
 
108
136
  describe "#http_post" do
109
- subject { instance.send(:http_post, "the" => "payload") }
137
+ subject { instance.send(:http_post, { "the" => "payload" }, :format => :json) }
110
138
 
111
139
  it "sets the path" do
112
140
  expect(subject.path).to eq instance.uri.request_uri
@@ -115,6 +143,24 @@ describe Appsignal::Transmitter do
115
143
  it "sets the correct headers" do
116
144
  expect(subject["Content-Type"]).to eq "application/json; charset=UTF-8"
117
145
  end
146
+
147
+ it "serialises the payload to JSON" do
148
+ expect(subject.body).to eq "{\"the\":\"payload\"}"
149
+ end
150
+
151
+ describe "with :ndjson format" do
152
+ subject do
153
+ instance.send(:http_post, [{ "the" => "payload" }, { "part" => "two" }], :format => :ndjson)
154
+ end
155
+
156
+ it "sets the correct headers" do
157
+ expect(subject["Content-Type"]).to eq "application/x-ndjson; charset=UTF-8"
158
+ end
159
+
160
+ it "serialises the payload to NDJSON" do
161
+ expect(subject.body).to eq "{\"the\":\"payload\"}\n{\"part\":\"two\"}"
162
+ end
163
+ end
118
164
  end
119
165
 
120
166
  describe "#http_client" do
@@ -581,6 +581,11 @@ describe Appsignal do
581
581
  expect(Appsignal.active?).to be_falsy
582
582
  end
583
583
  end
584
+
585
+ it "calls stop on the check-in scheduler" do
586
+ expect(Appsignal::CheckIn.scheduler).to receive(:stop)
587
+ Appsignal.stop
588
+ end
584
589
  end
585
590
 
586
591
  describe ".started?" do
data/spec/spec_helper.rb CHANGED
@@ -168,13 +168,6 @@ RSpec.configure do |config|
168
168
  end
169
169
 
170
170
  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
171
  Appsignal::Probes.stop
178
- thread&.join # Wait for old thread to exit
179
172
  end
180
173
  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!
@@ -0,0 +1,21 @@
1
+ module TakeAtMostHelper
2
+ # Assert that it takes at most a certain amount of time to run a block.
3
+ #
4
+ # @example
5
+ # # Assert that it takes at most 1 second to run the block
6
+ # take_at_most(1) { sleep 0.5 }
7
+ #
8
+ # @param time [Integer, Float] The maximum amount of time the block is allowed to
9
+ # run in seconds.
10
+ # @yield Block to run.
11
+ # @raise [StandardError] Raises error if the block takes longer than the
12
+ # specified time to run.
13
+ def take_at_most(time)
14
+ start = Time.now
15
+ yield
16
+ elapsed = Time.now - start
17
+ return if elapsed <= time
18
+
19
+ raise "Expected block to take at most #{time} seconds, but took #{elapsed}"
20
+ end
21
+ 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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 4.0.5
5
5
  platform: java
6
6
  authors:
7
7
  - Robert Beekman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-08-26 00:00:00.000000000 Z
13
+ date: 2024-09-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -202,6 +202,7 @@ files:
202
202
  - lib/appsignal/capistrano.rb
203
203
  - lib/appsignal/check_in.rb
204
204
  - lib/appsignal/check_in/cron.rb
205
+ - lib/appsignal/check_in/scheduler.rb
205
206
  - lib/appsignal/cli.rb
206
207
  - lib/appsignal/cli/demo.rb
207
208
  - lib/appsignal/cli/diagnose.rb
@@ -267,6 +268,7 @@ files:
267
268
  - lib/appsignal/integrations/mongo_ruby_driver.rb
268
269
  - lib/appsignal/integrations/net_http.rb
269
270
  - lib/appsignal/integrations/object.rb
271
+ - lib/appsignal/integrations/puma.rb
270
272
  - lib/appsignal/integrations/que.rb
271
273
  - lib/appsignal/integrations/railtie.rb
272
274
  - lib/appsignal/integrations/rake.rb
@@ -309,6 +311,7 @@ files:
309
311
  - lib/appsignal/utils/integration_logger.rb
310
312
  - lib/appsignal/utils/integration_memory_logger.rb
311
313
  - lib/appsignal/utils/json.rb
314
+ - lib/appsignal/utils/ndjson.rb
312
315
  - lib/appsignal/utils/query_params_sanitizer.rb
313
316
  - lib/appsignal/utils/rails_helper.rb
314
317
  - lib/appsignal/utils/stdout_and_logger_message.rb
@@ -322,7 +325,8 @@ files:
322
325
  - spec/lib/appsignal/auth_check_spec.rb
323
326
  - spec/lib/appsignal/capistrano2_spec.rb
324
327
  - spec/lib/appsignal/capistrano3_spec.rb
325
- - spec/lib/appsignal/check_in_spec.rb
328
+ - spec/lib/appsignal/check_in/cron_spec.rb
329
+ - spec/lib/appsignal/check_in/scheduler_spec.rb
326
330
  - spec/lib/appsignal/cli/demo_spec.rb
327
331
  - spec/lib/appsignal/cli/diagnose/paths_spec.rb
328
332
  - spec/lib/appsignal/cli/diagnose/utils_spec.rb
@@ -384,6 +388,7 @@ files:
384
388
  - spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb
385
389
  - spec/lib/appsignal/integrations/net_http_spec.rb
386
390
  - spec/lib/appsignal/integrations/object_spec.rb
391
+ - spec/lib/appsignal/integrations/puma_spec.rb
387
392
  - spec/lib/appsignal/integrations/que_spec.rb
388
393
  - spec/lib/appsignal/integrations/railtie_spec.rb
389
394
  - spec/lib/appsignal/integrations/resque_spec.rb
@@ -450,6 +455,7 @@ files:
450
455
  - spec/support/helpers/rails_helper.rb
451
456
  - spec/support/helpers/std_streams_helper.rb
452
457
  - spec/support/helpers/system_helpers.rb
458
+ - spec/support/helpers/take_at_most_helper.rb
453
459
  - spec/support/helpers/time_helpers.rb
454
460
  - spec/support/helpers/transaction_helpers.rb
455
461
  - spec/support/helpers/wait_for_helper.rb
@@ -460,7 +466,9 @@ files:
460
466
  - spec/support/mocks/dummy_app.rb
461
467
  - spec/support/mocks/fake_gc_profiler.rb
462
468
  - spec/support/mocks/fake_gvl_tools.rb
469
+ - spec/support/mocks/hash_like.rb
463
470
  - spec/support/mocks/mock_probe.rb
471
+ - spec/support/mocks/puma_mock.rb
464
472
  - spec/support/shared_examples/instrument.rb
465
473
  - spec/support/stubs/appsignal/loaders/loader_stub.rb
466
474
  - spec/support/stubs/delayed_job.rb
@@ -1,136 +0,0 @@
1
- describe Appsignal::CheckIn::Cron do
2
- let(:config) { project_fixture_config }
3
- let(:cron_checkin) { described_class.new(:identifier => "cron-checkin-name") }
4
- let(:transmitter) { Appsignal::Transmitter.new("http://cron_checkins/", config) }
5
-
6
- before(:each) do
7
- allow(Appsignal).to receive(:active?).and_return(true)
8
- config.logger = Logger.new(StringIO.new)
9
- allow(Appsignal::CheckIn::Cron).to receive(:transmitter).and_return(transmitter)
10
- end
11
-
12
- describe "when Appsignal is not active" do
13
- it "should not transmit any events" do
14
- allow(Appsignal).to receive(:active?).and_return(false)
15
- expect(transmitter).not_to receive(:transmit)
16
-
17
- cron_checkin.start
18
- cron_checkin.finish
19
- end
20
- end
21
-
22
- describe "#start" do
23
- it "should send a cron check-in start" do
24
- expect(transmitter).to receive(:transmit).with(hash_including(
25
- :identifier => "cron-checkin-name",
26
- :kind => "start",
27
- :check_in_type => "cron"
28
- )).and_return(Net::HTTPResponse.new(nil, "200", nil))
29
-
30
- expect(Appsignal.internal_logger).to receive(:debug).with(
31
- "Transmitted cron check-in `cron-checkin-name` (#{cron_checkin.digest}) start event"
32
- )
33
- expect(Appsignal.internal_logger).not_to receive(:error)
34
-
35
- cron_checkin.start
36
- end
37
-
38
- it "should log an error if it fails" do
39
- expect(transmitter).to receive(:transmit).with(hash_including(
40
- :identifier => "cron-checkin-name",
41
- :kind => "start",
42
- :check_in_type => "cron"
43
- )).and_return(Net::HTTPResponse.new(nil, "499", nil))
44
-
45
- expect(Appsignal.internal_logger).not_to receive(:debug)
46
- expect(Appsignal.internal_logger).to receive(:error).with(
47
- "Failed to transmit cron check-in start event: status code was 499"
48
- )
49
-
50
- cron_checkin.start
51
- end
52
- end
53
-
54
- describe "#finish" do
55
- it "should send a cron check-in finish" do
56
- expect(transmitter).to receive(:transmit).with(hash_including(
57
- :identifier => "cron-checkin-name",
58
- :kind => "finish",
59
- :check_in_type => "cron"
60
- )).and_return(Net::HTTPResponse.new(nil, "200", nil))
61
-
62
- expect(Appsignal.internal_logger).to receive(:debug).with(
63
- "Transmitted cron check-in `cron-checkin-name` (#{cron_checkin.digest}) finish event"
64
- )
65
- expect(Appsignal.internal_logger).not_to receive(:error)
66
-
67
- cron_checkin.finish
68
- end
69
-
70
- it "should log an error if it fails" do
71
- expect(transmitter).to receive(:transmit).with(hash_including(
72
- :identifier => "cron-checkin-name",
73
- :kind => "finish",
74
- :check_in_type => "cron"
75
- )).and_return(Net::HTTPResponse.new(nil, "499", nil))
76
-
77
- expect(Appsignal.internal_logger).not_to receive(:debug)
78
- expect(Appsignal.internal_logger).to receive(:error).with(
79
- "Failed to transmit cron check-in finish event: status code was 499"
80
- )
81
-
82
- cron_checkin.finish
83
- end
84
- end
85
-
86
- describe ".cron" do
87
- describe "when a block is given" do
88
- it "should send a cron check-in start and finish and return the block output" do
89
- expect(transmitter).to receive(:transmit).with(hash_including(
90
- :kind => "start",
91
- :identifier => "cron-checkin-with-block",
92
- :check_in_type => "cron"
93
- )).and_return(nil)
94
-
95
- expect(transmitter).to receive(:transmit).with(hash_including(
96
- :kind => "finish",
97
- :identifier => "cron-checkin-with-block",
98
- :check_in_type => "cron"
99
- )).and_return(nil)
100
-
101
- output = Appsignal::CheckIn.cron("cron-checkin-with-block") { "output" }
102
- expect(output).to eq("output")
103
- end
104
-
105
- it "should not send a cron check-in finish event when an error is raised" do
106
- expect(transmitter).to receive(:transmit).with(hash_including(
107
- :kind => "start",
108
- :identifier => "cron-checkin-with-block",
109
- :check_in_type => "cron"
110
- )).and_return(nil)
111
-
112
- expect(transmitter).not_to receive(:transmit).with(hash_including(
113
- :kind => "finish",
114
- :identifier => "cron-checkin-with-block",
115
- :check_in_type => "cron"
116
- ))
117
-
118
- expect do
119
- Appsignal::CheckIn.cron("cron-checkin-with-block") { raise "error" }
120
- end.to raise_error(RuntimeError, "error")
121
- end
122
- end
123
-
124
- describe "when no block is given" do
125
- it "should only send a cron check-in finish event" do
126
- expect(transmitter).to receive(:transmit).with(hash_including(
127
- :kind => "finish",
128
- :identifier => "cron-checkin-without-block",
129
- :check_in_type => "cron"
130
- )).and_return(nil)
131
-
132
- Appsignal::CheckIn.cron("cron-checkin-without-block")
133
- end
134
- end
135
- end
136
- end