appsignal 3.0.15-java → 3.0.19-java
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -3
- data/.semaphore/semaphore.yml +513 -104
- data/CHANGELOG.md +57 -0
- data/appsignal.gemspec +0 -2
- data/build_matrix.yml +45 -17
- data/ext/agent.yml +25 -25
- data/ext/appsignal_extension.c +201 -0
- data/ext/base.rb +2 -1
- data/gemfiles/rails-6.1.gemfile +7 -0
- data/gemfiles/rails-7.0.gemfile +7 -0
- data/lib/appsignal/cli/diagnose/utils.rb +0 -14
- data/lib/appsignal/cli/diagnose.rb +19 -8
- data/lib/appsignal/config.rb +89 -57
- data/lib/appsignal/event_formatter/sequel/sql_formatter.rb +24 -0
- data/lib/appsignal/extension/jruby.rb +147 -0
- data/lib/appsignal/extension.rb +5 -0
- data/lib/appsignal/integrations/sidekiq.rb +5 -1
- data/lib/appsignal/span.rb +92 -0
- data/lib/appsignal/system.rb +0 -4
- data/lib/appsignal/transaction.rb +12 -1
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +4 -10
- data/script/lint_git +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +18 -13
- data/spec/lib/appsignal/config_spec.rb +104 -20
- data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +2 -2
- data/spec/lib/appsignal/event_formatter/sequel/sql_formatter_spec.rb +30 -0
- data/spec/lib/appsignal/event_formatter_spec.rb +2 -2
- data/spec/lib/appsignal/hooks/activejob_spec.rb +17 -6
- data/spec/lib/appsignal/hooks/sequel_spec.rb +1 -1
- data/spec/lib/appsignal/integrations/padrino_spec.rb +8 -2
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +23 -5
- data/spec/lib/appsignal/span_spec.rb +141 -0
- data/spec/lib/appsignal/transaction_spec.rb +25 -0
- data/spec/lib/appsignal/utils/data_spec.rb +0 -2
- data/spec/lib/appsignal/utils/json_spec.rb +0 -2
- data/spec/lib/appsignal_spec.rb +2 -3
- data/spec/support/helpers/activejob_helpers.rb +27 -0
- data/spec/support/helpers/dependency_helper.rb +13 -1
- metadata +13 -3
@@ -251,7 +251,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
251
251
|
|
252
252
|
it "adds the installation report to the diagnostics report" do
|
253
253
|
run
|
254
|
-
jruby =
|
254
|
+
jruby = Appsignal::System.jruby?
|
255
255
|
expect(received_report["installation"]).to match(
|
256
256
|
"result" => {
|
257
257
|
"status" => "success"
|
@@ -321,7 +321,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
321
321
|
expect(File).to receive(:read)
|
322
322
|
.with(File.expand_path("../../../../../ext/install.report", __FILE__))
|
323
323
|
.and_return(
|
324
|
-
|
324
|
+
JSON.generate(
|
325
325
|
"result" => {
|
326
326
|
"status" => "error",
|
327
327
|
"error" => "RuntimeError: some error",
|
@@ -384,8 +384,8 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
384
384
|
end
|
385
385
|
end
|
386
386
|
|
387
|
-
context "when report is invalid
|
388
|
-
let(:raw_report) { "
|
387
|
+
context "when report is invalid JSON" do
|
388
|
+
let(:raw_report) { "{}-" }
|
389
389
|
before do
|
390
390
|
allow(File).to receive(:read).and_call_original
|
391
391
|
expect(File).to receive(:read)
|
@@ -750,13 +750,13 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
750
750
|
end
|
751
751
|
|
752
752
|
it "outputs a warning that no config is loaded" do
|
753
|
-
expect(output).to include "
|
753
|
+
expect(output).to include "environment: \"\"\n#{warning_message}"
|
754
754
|
expect(output).to_not have_color_markers
|
755
755
|
end
|
756
756
|
|
757
757
|
context "with color", :color => true do
|
758
758
|
it "outputs a warning that no config is loaded in color" do
|
759
|
-
expect(output).to include "
|
759
|
+
expect(output).to include "environment: \"\"\n"
|
760
760
|
expect(output).to have_colorized_text :red, warning_message
|
761
761
|
end
|
762
762
|
end
|
@@ -785,7 +785,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
785
785
|
describe "environment" do
|
786
786
|
it "outputs environment" do
|
787
787
|
run
|
788
|
-
expect(output).to include(%(
|
788
|
+
expect(output).to include(%(environment: "production"))
|
789
789
|
end
|
790
790
|
|
791
791
|
context "when the source is a single source" do
|
@@ -793,7 +793,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
793
793
|
|
794
794
|
it "outputs the label source after the value" do
|
795
795
|
expect(output).to include(
|
796
|
-
%(
|
796
|
+
%(environment: "#{Appsignal.config.env}" (Loaded from: initial)\n)
|
797
797
|
)
|
798
798
|
end
|
799
799
|
end
|
@@ -810,7 +810,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
810
810
|
|
811
811
|
it "outputs a list of sources with their values" do
|
812
812
|
expect(output).to include(
|
813
|
-
%(
|
813
|
+
%( environment: "production"\n) +
|
814
814
|
%( Sources:\n) +
|
815
815
|
%( initial: "development"\n) +
|
816
816
|
%( env: "production"\n)
|
@@ -904,7 +904,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
904
904
|
before { run_within_dir tmp_dir }
|
905
905
|
|
906
906
|
it "outputs environment" do
|
907
|
-
expect(output).to include(%(
|
907
|
+
expect(output).to include(%(environment: "foobar"))
|
908
908
|
end
|
909
909
|
|
910
910
|
it "outputs config defaults" do
|
@@ -1007,7 +1007,7 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
1007
1007
|
|
1008
1008
|
it "outputs failure with status code" do
|
1009
1009
|
expect(output).to include "Validation",
|
1010
|
-
"Validating Push API key: Failed
|
1010
|
+
"Validating Push API key: Failed to validate: status 500\n" +
|
1011
1011
|
%("Could not confirm authorization: 500")
|
1012
1012
|
end
|
1013
1013
|
|
@@ -1015,14 +1015,19 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
|
|
1015
1015
|
it "outputs error in color" do
|
1016
1016
|
expect(output).to include "Validation",
|
1017
1017
|
"Validating Push API key: " +
|
1018
|
-
colorize(
|
1018
|
+
colorize(
|
1019
|
+
"Failed to validate: status 500\n" +
|
1020
|
+
%("Could not confirm authorization: 500"),
|
1021
|
+
:red
|
1022
|
+
)
|
1019
1023
|
end
|
1020
1024
|
end
|
1021
1025
|
|
1022
1026
|
it "transmits validation in report" do
|
1023
1027
|
expect(received_report).to include(
|
1024
1028
|
"validation" => {
|
1025
|
-
"push_api_key" =>
|
1029
|
+
"push_api_key" => "Failed to validate: status 500\n" +
|
1030
|
+
%("Could not confirm authorization: 500")
|
1026
1031
|
}
|
1027
1032
|
)
|
1028
1033
|
end
|
@@ -151,34 +151,34 @@ describe Appsignal::Config do
|
|
151
151
|
|
152
152
|
it "merges with the default config" do
|
153
153
|
expect(config.config_hash).to eq(
|
154
|
+
:active => true,
|
155
|
+
:ca_file_path => File.join(resources_dir, "cacert.pem"),
|
154
156
|
:debug => false,
|
155
|
-
:
|
157
|
+
:dns_servers => [],
|
158
|
+
:enable_allocation_tracking => true,
|
159
|
+
:enable_gc_instrumentation => false,
|
160
|
+
:enable_host_metrics => true,
|
161
|
+
:enable_minutely_probes => true,
|
162
|
+
:enable_statsd => true,
|
163
|
+
:endpoint => "https://push.appsignal.com",
|
164
|
+
:files_world_accessible => true,
|
165
|
+
:filter_parameters => [],
|
166
|
+
:filter_session_data => [],
|
156
167
|
:ignore_actions => [],
|
157
168
|
:ignore_errors => [],
|
158
169
|
:ignore_namespaces => [],
|
159
|
-
:filter_parameters => [],
|
160
|
-
:filter_session_data => [],
|
161
170
|
:instrument_net_http => true,
|
162
171
|
:instrument_redis => true,
|
163
172
|
:instrument_sequel => true,
|
164
|
-
:
|
165
|
-
:send_environment_metadata => true,
|
166
|
-
:send_params => true,
|
167
|
-
:endpoint => "https://push.appsignal.com",
|
168
|
-
:push_api_key => "abc",
|
173
|
+
:log => "file",
|
169
174
|
:name => "TestApp",
|
170
|
-
:
|
171
|
-
:
|
172
|
-
:enable_gc_instrumentation => false,
|
173
|
-
:enable_host_metrics => true,
|
174
|
-
:enable_minutely_probes => true,
|
175
|
-
:enable_statsd => true,
|
176
|
-
:ca_file_path => File.join(resources_dir, "cacert.pem"),
|
177
|
-
:dns_servers => [],
|
178
|
-
:files_world_accessible => true,
|
179
|
-
:transaction_debug_mode => false,
|
175
|
+
:push_api_key => "abc",
|
176
|
+
:request_headers => [],
|
180
177
|
:revision => "v2.5.1",
|
181
|
-
:
|
178
|
+
:send_environment_metadata => true,
|
179
|
+
:send_params => true,
|
180
|
+
:skip_session_data => false,
|
181
|
+
:transaction_debug_mode => false
|
182
182
|
)
|
183
183
|
end
|
184
184
|
|
@@ -319,13 +319,15 @@ describe Appsignal::Config do
|
|
319
319
|
"non-existing-path",
|
320
320
|
"production",
|
321
321
|
:running_in_container => true,
|
322
|
-
:debug => true
|
322
|
+
:debug => true,
|
323
|
+
:log_level => "debug"
|
323
324
|
)
|
324
325
|
end
|
325
326
|
|
326
327
|
it "overrides system detected and defaults config" do
|
327
328
|
expect(config[:running_in_container]).to be_truthy
|
328
329
|
expect(config[:debug]).to be_truthy
|
330
|
+
expect(config[:log_level]).to eq("debug")
|
329
331
|
end
|
330
332
|
end
|
331
333
|
|
@@ -502,6 +504,7 @@ describe Appsignal::Config do
|
|
502
504
|
config[:log] = "stdout"
|
503
505
|
config[:log_path] = "/tmp"
|
504
506
|
config[:filter_parameters] = %w[password confirm_password]
|
507
|
+
config[:filter_session_data] = %w[key1 key2]
|
505
508
|
config[:running_in_container] = false
|
506
509
|
config[:dns_servers] = ["8.8.8.8", "8.8.4.4"]
|
507
510
|
config[:transaction_debug_mode] = true
|
@@ -535,6 +538,8 @@ describe Appsignal::Config do
|
|
535
538
|
expect(ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"]).to eq "true"
|
536
539
|
expect(ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"]).to eq "true"
|
537
540
|
expect(ENV["_APPSIGNAL_SEND_ENVIRONMENT_METADATA"]).to eq "false"
|
541
|
+
expect(ENV["_APPSIGNAL_FILTER_PARAMETERS"]).to eq "password,confirm_password"
|
542
|
+
expect(ENV["_APPSIGNAL_FILTER_SESSION_DATA"]).to eq "key1,key2"
|
538
543
|
expect(ENV["_APP_REVISION"]).to eq "v2.5.1"
|
539
544
|
expect(ENV).to_not have_key("_APPSIGNAL_WORKING_DIR_PATH")
|
540
545
|
expect(ENV).to_not have_key("_APPSIGNAL_WORKING_DIRECTORY_PATH")
|
@@ -781,4 +786,83 @@ describe Appsignal::Config do
|
|
781
786
|
end
|
782
787
|
end
|
783
788
|
end
|
789
|
+
|
790
|
+
describe "#log_level" do
|
791
|
+
let(:options) { {} }
|
792
|
+
let(:config) { described_class.new("", nil, options) }
|
793
|
+
subject { config.log_level }
|
794
|
+
|
795
|
+
context "without any config" do
|
796
|
+
it "returns info by default" do
|
797
|
+
is_expected.to eq(Logger::INFO)
|
798
|
+
end
|
799
|
+
end
|
800
|
+
|
801
|
+
context "with debug set to true" do
|
802
|
+
let(:options) { { :debug => true } }
|
803
|
+
it { is_expected.to eq(Logger::DEBUG) }
|
804
|
+
end
|
805
|
+
|
806
|
+
context "with transaction_debug_mode set to true" do
|
807
|
+
let(:options) { { :transaction_debug_mode => true } }
|
808
|
+
it { is_expected.to eq(Logger::DEBUG) }
|
809
|
+
end
|
810
|
+
|
811
|
+
context "with log_level set to error" do
|
812
|
+
let(:options) { { :log_level => "error" } }
|
813
|
+
it { is_expected.to eq(Logger::ERROR) }
|
814
|
+
end
|
815
|
+
|
816
|
+
context "with log_level set to warn" do
|
817
|
+
let(:options) { { :log_level => "warn" } }
|
818
|
+
it { is_expected.to eq(Logger::WARN) }
|
819
|
+
end
|
820
|
+
|
821
|
+
context "with log_level set to info" do
|
822
|
+
let(:options) { { :log_level => "info" } }
|
823
|
+
it { is_expected.to eq(Logger::INFO) }
|
824
|
+
end
|
825
|
+
|
826
|
+
context "with log_level set to debug" do
|
827
|
+
let(:options) { { :log_level => "debug" } }
|
828
|
+
it { is_expected.to eq(Logger::DEBUG) }
|
829
|
+
end
|
830
|
+
|
831
|
+
context "with log_level set to trace" do
|
832
|
+
let(:options) { { :log_level => "trace" } }
|
833
|
+
it { is_expected.to eq(Logger::DEBUG) }
|
834
|
+
end
|
835
|
+
|
836
|
+
context "with debug and log_level set" do
|
837
|
+
let(:options) { { :log_level => "error", :debug => true } }
|
838
|
+
|
839
|
+
it "the log_level option is leading" do
|
840
|
+
is_expected.to eq(Logger::ERROR)
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
context "with transaction_debug_mode and log_level set" do
|
845
|
+
let(:options) { { :log_level => "error", :transaction_debug_mode => true } }
|
846
|
+
|
847
|
+
it "the log_level option is leading" do
|
848
|
+
is_expected.to eq(Logger::ERROR)
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
context "with log level set to an unknown value" do
|
853
|
+
let(:options) { { :log_level => "fatal" } }
|
854
|
+
|
855
|
+
it "prints a warning and doesn't use the log_level" do
|
856
|
+
is_expected.to eql(Logger::INFO)
|
857
|
+
end
|
858
|
+
|
859
|
+
context "with debug option set to true" do
|
860
|
+
let(:options) { { :log_level => "fatal", :debug => true } }
|
861
|
+
|
862
|
+
it "prints a warning and sets it to debug" do
|
863
|
+
is_expected.to eql(Logger::DEBUG)
|
864
|
+
end
|
865
|
+
end
|
866
|
+
end
|
867
|
+
end
|
784
868
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
describe Appsignal::EventFormatter::ActiveRecord::
|
2
|
-
let(:klass) {
|
1
|
+
describe Appsignal::EventFormatter::ActiveRecord::SqlFormatter do
|
2
|
+
let(:klass) { described_class }
|
3
3
|
let(:formatter) { klass.new }
|
4
4
|
|
5
5
|
it "should register sql.active_record" do
|
@@ -0,0 +1,30 @@
|
|
1
|
+
describe Appsignal::EventFormatter::Sequel::SqlFormatter do
|
2
|
+
let(:klass) { described_class }
|
3
|
+
let(:formatter) { klass.new }
|
4
|
+
|
5
|
+
it "registers the sql.sequel event formatter" do
|
6
|
+
expect(Appsignal::EventFormatter.registered?("sql.sequel", klass)).to be_truthy
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#format" do
|
10
|
+
before do
|
11
|
+
stub_const(
|
12
|
+
"SequelDatabaseTypeClass",
|
13
|
+
Class.new do
|
14
|
+
def self.to_s
|
15
|
+
"SequelDatabaseTypeClassToString"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
)
|
19
|
+
end
|
20
|
+
let(:payload) do
|
21
|
+
{
|
22
|
+
:name => SequelDatabaseTypeClass,
|
23
|
+
:sql => "SELECT * FROM users"
|
24
|
+
}
|
25
|
+
end
|
26
|
+
subject { formatter.format(payload) }
|
27
|
+
|
28
|
+
it { is_expected.to eq ["SequelDatabaseTypeClassToString", "SELECT * FROM users", 1] }
|
29
|
+
end
|
30
|
+
end
|
@@ -28,7 +28,7 @@ end
|
|
28
28
|
|
29
29
|
class MockDependentFormatter < Appsignal::EventFormatter
|
30
30
|
def initialize
|
31
|
-
|
31
|
+
raise "There is an error"
|
32
32
|
end
|
33
33
|
|
34
34
|
def format(_payload)
|
@@ -72,7 +72,7 @@ describe Appsignal::EventFormatter do
|
|
72
72
|
end
|
73
73
|
expect(klass.registered?("mock.dependent")).to be_falsy
|
74
74
|
expect(logs).to contains_log :error, \
|
75
|
-
"'
|
75
|
+
"'There is an error' " \
|
76
76
|
"when initializing mock.dependent event formatter"
|
77
77
|
end
|
78
78
|
end
|
@@ -30,6 +30,7 @@ if DependencyHelper.active_job_present?
|
|
30
30
|
end
|
31
31
|
|
32
32
|
describe Appsignal::Hooks::ActiveJobHook::ActiveJobClassInstrumentation do
|
33
|
+
include ActiveJobHelpers
|
33
34
|
let(:time) { Time.parse("2001-01-01 10:00:00UTC") }
|
34
35
|
let(:namespace) { Appsignal::Transaction::BACKGROUND_JOB }
|
35
36
|
let(:queue) { "default" }
|
@@ -64,6 +65,13 @@ if DependencyHelper.active_job_present?
|
|
64
65
|
parameterized_expected_args
|
65
66
|
]
|
66
67
|
end
|
68
|
+
let(:expected_perform_events) do
|
69
|
+
if DependencyHelper.rails7_present?
|
70
|
+
["perform.active_job", "perform_start.active_job"]
|
71
|
+
else
|
72
|
+
["perform_start.active_job", "perform.active_job"]
|
73
|
+
end
|
74
|
+
end
|
67
75
|
before do
|
68
76
|
ActiveJob::Base.queue_adapter = :inline
|
69
77
|
|
@@ -119,7 +127,8 @@ if DependencyHelper.active_job_present?
|
|
119
127
|
events = transaction_hash["events"]
|
120
128
|
.sort_by { |e| e["start"] }
|
121
129
|
.map { |event| event["name"] }
|
122
|
-
|
130
|
+
|
131
|
+
expect(events).to eq(expected_perform_events)
|
123
132
|
end
|
124
133
|
|
125
134
|
context "with custom queue" do
|
@@ -208,7 +217,8 @@ if DependencyHelper.active_job_present?
|
|
208
217
|
events = transaction_hash["events"]
|
209
218
|
.sort_by { |e| e["start"] }
|
210
219
|
.map { |event| event["name"] }
|
211
|
-
|
220
|
+
|
221
|
+
expect(events).to eq(expected_perform_events)
|
212
222
|
end
|
213
223
|
|
214
224
|
if DependencyHelper.rails_version >= Gem::Version.new("5.0.0")
|
@@ -286,7 +296,8 @@ if DependencyHelper.active_job_present?
|
|
286
296
|
.reject { |e| e["name"] == "enqueue.active_job" }
|
287
297
|
.sort_by { |e| e["start"] }
|
288
298
|
.map { |event| event["name"] }
|
289
|
-
|
299
|
+
|
300
|
+
expect(events).to eq(expected_perform_events)
|
290
301
|
end
|
291
302
|
end
|
292
303
|
|
@@ -414,7 +425,7 @@ if DependencyHelper.active_job_present?
|
|
414
425
|
expect(transaction_hash).to include(
|
415
426
|
"action" => "ActionMailerTestJob#welcome",
|
416
427
|
"sample_data" => hash_including(
|
417
|
-
"params" => ["ActionMailerTestJob", "welcome", "deliver_now"],
|
428
|
+
"params" => ["ActionMailerTestJob", "welcome", "deliver_now"] + active_job_args_wrapper,
|
418
429
|
"tags" => {
|
419
430
|
"active_job_id" => kind_of(String),
|
420
431
|
"queue" => "mailers"
|
@@ -433,7 +444,7 @@ if DependencyHelper.active_job_present?
|
|
433
444
|
expect(transaction_hash).to include(
|
434
445
|
"action" => "ActionMailerTestJob#welcome",
|
435
446
|
"sample_data" => hash_including(
|
436
|
-
"params" => ["ActionMailerTestJob", "welcome", "deliver_now"] + method_expected_args,
|
447
|
+
"params" => ["ActionMailerTestJob", "welcome", "deliver_now"] + active_job_args_wrapper(:args => method_expected_args),
|
437
448
|
"tags" => {
|
438
449
|
"active_job_id" => kind_of(String),
|
439
450
|
"queue" => "mailers"
|
@@ -453,7 +464,7 @@ if DependencyHelper.active_job_present?
|
|
453
464
|
expect(transaction_hash).to include(
|
454
465
|
"action" => "ActionMailerTestJob#welcome",
|
455
466
|
"sample_data" => hash_including(
|
456
|
-
"params" => ["ActionMailerTestJob", "welcome", "deliver_now"
|
467
|
+
"params" => ["ActionMailerTestJob", "welcome", "deliver_now"] + active_job_args_wrapper(:params => parameterized_expected_args),
|
457
468
|
"tags" => {
|
458
469
|
"active_job_id" => kind_of(String),
|
459
470
|
"queue" => "mailers"
|
@@ -98,7 +98,13 @@ if DependencyHelper.padrino_present?
|
|
98
98
|
RSpec::Matchers.define :match_response do |expected_status, expected_content|
|
99
99
|
match do |response|
|
100
100
|
status, _headers, content = response
|
101
|
-
|
101
|
+
matches_content =
|
102
|
+
if expected_content.is_a?(Regexp)
|
103
|
+
content.join =~ expected_content
|
104
|
+
else
|
105
|
+
content == [expected_content].compact
|
106
|
+
end
|
107
|
+
status == expected_status && matches_content
|
102
108
|
end
|
103
109
|
end
|
104
110
|
|
@@ -142,7 +148,7 @@ if DependencyHelper.padrino_present?
|
|
142
148
|
expect_a_transaction_to_be_created
|
143
149
|
# Uses path for action name
|
144
150
|
expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp#unknown")
|
145
|
-
expect(response).to match_response(404,
|
151
|
+
expect(response).to match_response(404, %r{^GET /404})
|
146
152
|
end
|
147
153
|
end
|
148
154
|
|
@@ -339,6 +339,7 @@ if DependencyHelper.active_job_present?
|
|
339
339
|
require "sidekiq/testing"
|
340
340
|
|
341
341
|
describe "Sidekiq ActiveJob integration" do
|
342
|
+
include ActiveJobHelpers
|
342
343
|
let(:namespace) { Appsignal::Transaction::BACKGROUND_JOB }
|
343
344
|
let(:time) { Time.parse("2001-01-01 10:00:00UTC") }
|
344
345
|
let(:log) { StringIO.new }
|
@@ -366,6 +367,16 @@ if DependencyHelper.active_job_present?
|
|
366
367
|
}
|
367
368
|
]
|
368
369
|
end
|
370
|
+
let(:expected_wrapped_args) do
|
371
|
+
if (DependencyHelper.rails6_1_present? && DependencyHelper.ruby_3_1_or_newer?) || DependencyHelper.rails7_present?
|
372
|
+
[{
|
373
|
+
"_aj_ruby2_keywords" => ["args"],
|
374
|
+
"args" => expected_args
|
375
|
+
}]
|
376
|
+
else
|
377
|
+
expected_args
|
378
|
+
end
|
379
|
+
end
|
369
380
|
let(:expected_tags) do
|
370
381
|
{}.tap do |hash|
|
371
382
|
hash["active_job_id"] = kind_of(String)
|
@@ -374,6 +385,13 @@ if DependencyHelper.active_job_present?
|
|
374
385
|
end
|
375
386
|
end
|
376
387
|
end
|
388
|
+
let(:expected_perform_events) do
|
389
|
+
if DependencyHelper.rails7_present?
|
390
|
+
["perform_job.sidekiq", "perform.active_job", "perform_start.active_job"]
|
391
|
+
else
|
392
|
+
["perform_job.sidekiq", "perform_start.active_job", "perform.active_job"]
|
393
|
+
end
|
394
|
+
end
|
377
395
|
before do
|
378
396
|
start_agent
|
379
397
|
Appsignal.logger = test_logger(log)
|
@@ -434,8 +452,8 @@ if DependencyHelper.active_job_present?
|
|
434
452
|
events = transaction_hash["events"]
|
435
453
|
.sort_by { |e| e["start"] }
|
436
454
|
.map { |event| event["name"] }
|
437
|
-
|
438
|
-
|
455
|
+
|
456
|
+
expect(events).to eq(expected_perform_events)
|
439
457
|
end
|
440
458
|
|
441
459
|
context "with error" do
|
@@ -467,8 +485,8 @@ if DependencyHelper.active_job_present?
|
|
467
485
|
events = transaction_hash["events"]
|
468
486
|
.sort_by { |e| e["start"] }
|
469
487
|
.map { |event| event["name"] }
|
470
|
-
|
471
|
-
|
488
|
+
|
489
|
+
expect(events).to eq(expected_perform_events)
|
472
490
|
end
|
473
491
|
end
|
474
492
|
|
@@ -490,7 +508,7 @@ if DependencyHelper.active_job_present?
|
|
490
508
|
expect(transaction_hash).to include(
|
491
509
|
"action" => "ActionMailerSidekiqTestJob#welcome",
|
492
510
|
"sample_data" => hash_including(
|
493
|
-
"params" => ["ActionMailerSidekiqTestJob", "welcome", "deliver_now"] +
|
511
|
+
"params" => ["ActionMailerSidekiqTestJob", "welcome", "deliver_now"] + expected_wrapped_args
|
494
512
|
)
|
495
513
|
)
|
496
514
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require "appsignal/span"
|
2
|
+
|
3
|
+
describe Appsignal::Span do
|
4
|
+
before :context do
|
5
|
+
start_agent
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:namespace) { "web" }
|
9
|
+
let(:root) { Appsignal::Span.new(namespace) }
|
10
|
+
|
11
|
+
describe "creating a span" do
|
12
|
+
it "creates an empty span" do
|
13
|
+
expect(root.to_h["namespace"]).to eq "web"
|
14
|
+
expect(root.to_h["trace_id"].length).to eq 16
|
15
|
+
expect(root.to_h["span_id"].length).to eq 8
|
16
|
+
expect(root.to_h["parent_span_id"]).to be_empty
|
17
|
+
expect(root.to_h["name"]).to be_empty
|
18
|
+
expect(root.to_h["start_time"]).to be > 1_600_000_000
|
19
|
+
expect(root.to_h["closed"]).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#child" do
|
24
|
+
let(:child) { root.child }
|
25
|
+
|
26
|
+
it "creates a child span" do
|
27
|
+
expect(child.to_h["namespace"]).to be_empty
|
28
|
+
expect(child.to_h["trace_id"].length).to eq 16
|
29
|
+
expect(child.to_h["span_id"].length).to eq 8
|
30
|
+
expect(child.to_h["parent_span_id"]).to eq root.to_h["span_id"]
|
31
|
+
expect(child.to_h["name"]).to be_empty
|
32
|
+
expect(child.to_h["start_time"]).to be > 1_600_000_000
|
33
|
+
expect(child.to_h["closed"]).to be false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#add_error" do
|
38
|
+
it "adds an error" do
|
39
|
+
begin
|
40
|
+
raise "Error"
|
41
|
+
rescue => error
|
42
|
+
root.add_error(error)
|
43
|
+
end
|
44
|
+
|
45
|
+
error = root.to_h["error"]
|
46
|
+
expect(error["name"]).to eq "RuntimeError"
|
47
|
+
expect(error["message"]).to eq "Error"
|
48
|
+
expect(error["backtrace"]).not_to be_empty
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "set_sample_data" do
|
53
|
+
it "sets sample data" do
|
54
|
+
root.set_sample_data(:params, "key" => "value")
|
55
|
+
|
56
|
+
sample_data = root.to_h["sample_data"]
|
57
|
+
expect(sample_data["params"]).to eq "{\"key\":\"value\"}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#name=" do
|
62
|
+
it "sets the name" do
|
63
|
+
root.name = "Span name"
|
64
|
+
|
65
|
+
expect(root.to_h["name"]).to eq "Span name"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#[]=" do
|
70
|
+
let(:attributes) { root.to_h["attributes"] }
|
71
|
+
|
72
|
+
it "sets a string attribute" do
|
73
|
+
root["string"] = "attribute"
|
74
|
+
|
75
|
+
expect(attributes["string"]).to eq "attribute"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "sets an integer attribute" do
|
79
|
+
root["integer"] = 1001
|
80
|
+
|
81
|
+
expect(attributes["integer"]).to eq 1001
|
82
|
+
end
|
83
|
+
|
84
|
+
it "sets a bigint attribute" do
|
85
|
+
root["bigint"] = 1 << 64
|
86
|
+
|
87
|
+
expect(attributes["bigint"]).to eq "bigint:#{1 << 64}"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "sets a boolean attribute" do
|
91
|
+
root["true"] = true
|
92
|
+
root["false"] = false
|
93
|
+
|
94
|
+
expect(attributes["true"]).to eq true
|
95
|
+
expect(attributes["false"]).to eq false
|
96
|
+
end
|
97
|
+
|
98
|
+
it "sets a float attribute" do
|
99
|
+
root["float"] = 10.01
|
100
|
+
|
101
|
+
expect(attributes["float"]).to eq 10.01
|
102
|
+
end
|
103
|
+
|
104
|
+
it "raises an error for other types" do
|
105
|
+
expect do
|
106
|
+
root["something"] = Object.new
|
107
|
+
end.to raise_error TypeError
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#instrument" do
|
112
|
+
it "closes the span after yielding" do
|
113
|
+
root.instrument do
|
114
|
+
# Nothing happening
|
115
|
+
end
|
116
|
+
expect(root.closed?).to eq true
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with an error raised in the passed block" do
|
120
|
+
it "closes the span after yielding" do
|
121
|
+
expect do
|
122
|
+
root.instrument do
|
123
|
+
raise ExampleException, "foo"
|
124
|
+
end
|
125
|
+
end.to raise_error(ExampleException, "foo")
|
126
|
+
expect(root.closed?).to eq true
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#close" do
|
132
|
+
it "closes a span" do
|
133
|
+
expect(root.closed?).to eq false
|
134
|
+
|
135
|
+
root.close
|
136
|
+
|
137
|
+
expect(root.to_h).to be_nil
|
138
|
+
expect(root.closed?).to eq true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|