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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -0
- data/ext/agent.rb +27 -27
- data/lib/appsignal/check_in/cron.rb +2 -34
- data/lib/appsignal/check_in/scheduler.rb +192 -0
- data/lib/appsignal/check_in.rb +18 -0
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +7 -0
- data/lib/appsignal/hooks/at_exit.rb +3 -1
- data/lib/appsignal/hooks/puma.rb +5 -1
- data/lib/appsignal/integrations/puma.rb +45 -0
- data/lib/appsignal/rack/abstract_middleware.rb +3 -47
- data/lib/appsignal/rack/body_wrapper.rb +15 -0
- data/lib/appsignal/rack/event_handler.rb +2 -0
- data/lib/appsignal/rack/hanami_middleware.rb +5 -1
- data/lib/appsignal/rack.rb +68 -0
- data/lib/appsignal/transmitter.rb +30 -7
- data/lib/appsignal/utils/ndjson.rb +15 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +1 -0
- data/spec/lib/appsignal/check_in/cron_spec.rb +202 -0
- data/spec/lib/appsignal/check_in/scheduler_spec.rb +443 -0
- data/spec/lib/appsignal/config_spec.rb +13 -0
- data/spec/lib/appsignal/environment_spec.rb +1 -1
- data/spec/lib/appsignal/hooks/at_exit_spec.rb +22 -0
- data/spec/lib/appsignal/hooks/puma_spec.rb +31 -23
- data/spec/lib/appsignal/integrations/puma_spec.rb +150 -0
- data/spec/lib/appsignal/probes_spec.rb +1 -6
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +41 -122
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +29 -21
- data/spec/lib/appsignal/rack_spec.rb +180 -0
- data/spec/lib/appsignal/transmitter_spec.rb +48 -2
- data/spec/lib/appsignal_spec.rb +5 -0
- data/spec/spec_helper.rb +0 -7
- data/spec/support/helpers/config_helpers.rb +2 -1
- data/spec/support/helpers/take_at_most_helper.rb +21 -0
- data/spec/support/matchers/contains_log.rb +10 -3
- data/spec/support/mocks/hash_like.rb +10 -0
- data/spec/support/mocks/puma_mock.rb +43 -0
- metadata +11 -3
- 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
|
-
|
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
|
data/spec/lib/appsignal_spec.rb
CHANGED
@@ -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
|
-
|
2
|
+
log_level_prefix = level.upcase
|
3
3
|
|
4
4
|
match do |actual|
|
5
|
-
|
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
|
-
#{
|
17
|
+
Log level: #{log_level_prefix}
|
18
|
+
Message: #{message}
|
12
19
|
|
13
20
|
Received logs:
|
14
21
|
#{actual}
|
@@ -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.
|
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-
|
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/
|
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
|