appsignal 3.4.12 → 3.4.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23564a15fbad1ecb68987675c925a81b0e423ffa66a3481563999f97db10ef79
4
- data.tar.gz: a42321ba0bc9809e2b4b26a3c7e3707e5c06941a30ed6187cba491cbc76b9cfd
3
+ metadata.gz: da9d753b6bb738432dde776aac3404c660df7362d6fff5612ceb4535ab8dd00f
4
+ data.tar.gz: 712225f476fd4e66c83bc2b59f605eca653228fa75551f34c8210206bb87aea9
5
5
  SHA512:
6
- metadata.gz: ff4db633c340cf16fc0cfb3b154f4b754ef3416d3e56077203b7a298851457624dba934576c634b56bad599199fe427d1200dfa019f3bcfab67a9aa7349a0591
7
- data.tar.gz: 811176ae1f6735a901e1b0b822b4956aa5a0ca86efd2fbc8cc969afde01510022d3d2adf4fe11de50609f324df4dab0c699dbf84ca120ab27556d18735e7748b
6
+ metadata.gz: 7fcd4d3b278f44dc3033393708923819dce551f5bacb1e890c674cb332351bf1d756c882d05315b47582750d7370de5e2c729088b565cf0b3807ce977bd03631
7
+ data.tar.gz: 8980095a2da7d7f044e68fa02600a73ad48c584e1a450e2dca4be2e7fc4cc2579a7bb5a627d9ee691e0bac1f7065f9d100f705437df99c0875bcb34182da8eaf
@@ -583,6 +583,24 @@ blocks:
583
583
  value: latest
584
584
  commands:
585
585
  - "./support/bundler_wrapper exec rake test"
586
+ - name: Ruby 3.0.5 for dry-monitor
587
+ env_vars:
588
+ - *2
589
+ - *3
590
+ - *4
591
+ - *5
592
+ - name: RUBY_VERSION
593
+ value: 3.0.5
594
+ - name: GEMSET
595
+ value: dry-monitor
596
+ - name: BUNDLE_GEMFILE
597
+ value: gemfiles/dry-monitor.gemfile
598
+ - name: _RUBYGEMS_VERSION
599
+ value: latest
600
+ - name: _BUNDLER_VERSION
601
+ value: latest
602
+ commands:
603
+ - "./support/bundler_wrapper exec rake test"
586
604
  - name: Ruby 3.0.5 for grape
587
605
  env_vars:
588
606
  - *2
@@ -781,6 +799,24 @@ blocks:
781
799
  value: latest
782
800
  commands:
783
801
  - "./support/bundler_wrapper exec rake test"
802
+ - name: Ruby 3.0.5 for rails-7.1
803
+ env_vars:
804
+ - *2
805
+ - *3
806
+ - *4
807
+ - *5
808
+ - name: RUBY_VERSION
809
+ value: 3.0.5
810
+ - name: GEMSET
811
+ value: rails-7.1
812
+ - name: BUNDLE_GEMFILE
813
+ value: gemfiles/rails-7.1.gemfile
814
+ - name: _RUBYGEMS_VERSION
815
+ value: latest
816
+ - name: _BUNDLER_VERSION
817
+ value: latest
818
+ commands:
819
+ - "./support/bundler_wrapper exec rake test"
784
820
  - name: Ruby 3.0.5 for sequel
785
821
  env_vars:
786
822
  - *2
@@ -940,6 +976,24 @@ blocks:
940
976
  value: latest
941
977
  commands:
942
978
  - "./support/bundler_wrapper exec rake test"
979
+ - name: Ruby 3.1.3 for dry-monitor
980
+ env_vars:
981
+ - *2
982
+ - *3
983
+ - *4
984
+ - *5
985
+ - name: RUBY_VERSION
986
+ value: 3.1.3
987
+ - name: GEMSET
988
+ value: dry-monitor
989
+ - name: BUNDLE_GEMFILE
990
+ value: gemfiles/dry-monitor.gemfile
991
+ - name: _RUBYGEMS_VERSION
992
+ value: latest
993
+ - name: _BUNDLER_VERSION
994
+ value: latest
995
+ commands:
996
+ - "./support/bundler_wrapper exec rake test"
943
997
  - name: Ruby 3.1.3 for grape
944
998
  env_vars:
945
999
  - *2
@@ -1120,6 +1174,24 @@ blocks:
1120
1174
  value: latest
1121
1175
  commands:
1122
1176
  - "./support/bundler_wrapper exec rake test"
1177
+ - name: Ruby 3.1.3 for rails-7.1
1178
+ env_vars:
1179
+ - *2
1180
+ - *3
1181
+ - *4
1182
+ - *5
1183
+ - name: RUBY_VERSION
1184
+ value: 3.1.3
1185
+ - name: GEMSET
1186
+ value: rails-7.1
1187
+ - name: BUNDLE_GEMFILE
1188
+ value: gemfiles/rails-7.1.gemfile
1189
+ - name: _RUBYGEMS_VERSION
1190
+ value: latest
1191
+ - name: _BUNDLER_VERSION
1192
+ value: latest
1193
+ commands:
1194
+ - "./support/bundler_wrapper exec rake test"
1123
1195
  - name: Ruby 3.1.3 for sequel
1124
1196
  env_vars:
1125
1197
  - *2
@@ -1279,6 +1351,24 @@ blocks:
1279
1351
  value: latest
1280
1352
  commands:
1281
1353
  - "./support/bundler_wrapper exec rake test"
1354
+ - name: Ruby 3.2.1 for dry-monitor
1355
+ env_vars:
1356
+ - *2
1357
+ - *3
1358
+ - *4
1359
+ - *5
1360
+ - name: RUBY_VERSION
1361
+ value: 3.2.1
1362
+ - name: GEMSET
1363
+ value: dry-monitor
1364
+ - name: BUNDLE_GEMFILE
1365
+ value: gemfiles/dry-monitor.gemfile
1366
+ - name: _RUBYGEMS_VERSION
1367
+ value: latest
1368
+ - name: _BUNDLER_VERSION
1369
+ value: latest
1370
+ commands:
1371
+ - "./support/bundler_wrapper exec rake test"
1282
1372
  - name: Ruby 3.2.1 for grape
1283
1373
  env_vars:
1284
1374
  - *2
@@ -1459,6 +1549,24 @@ blocks:
1459
1549
  value: latest
1460
1550
  commands:
1461
1551
  - "./support/bundler_wrapper exec rake test"
1552
+ - name: Ruby 3.2.1 for rails-7.1
1553
+ env_vars:
1554
+ - *2
1555
+ - *3
1556
+ - *4
1557
+ - *5
1558
+ - name: RUBY_VERSION
1559
+ value: 3.2.1
1560
+ - name: GEMSET
1561
+ value: rails-7.1
1562
+ - name: BUNDLE_GEMFILE
1563
+ value: gemfiles/rails-7.1.gemfile
1564
+ - name: _RUBYGEMS_VERSION
1565
+ value: latest
1566
+ - name: _BUNDLER_VERSION
1567
+ value: latest
1568
+ commands:
1569
+ - "./support/bundler_wrapper exec rake test"
1462
1570
  - name: Ruby 3.2.1 for sequel
1463
1571
  env_vars:
1464
1572
  - *2
@@ -1636,3 +1744,21 @@ blocks:
1636
1744
  value: latest
1637
1745
  commands:
1638
1746
  - "./support/bundler_wrapper exec rake test"
1747
+ - name: Ruby jruby-9.4.1.0 for rails-7.1
1748
+ env_vars:
1749
+ - *2
1750
+ - *3
1751
+ - *4
1752
+ - *5
1753
+ - name: RUBY_VERSION
1754
+ value: jruby-9.4.1.0
1755
+ - name: GEMSET
1756
+ value: rails-7.1
1757
+ - name: BUNDLE_GEMFILE
1758
+ value: gemfiles/rails-7.1.gemfile
1759
+ - name: _RUBYGEMS_VERSION
1760
+ value: latest
1761
+ - name: _BUNDLER_VERSION
1762
+ value: latest
1763
+ commands:
1764
+ - "./support/bundler_wrapper exec rake test"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 3.4.13
4
+
5
+ ### Added
6
+
7
+ - [29970d93](https://github.com/appsignal/appsignal-ruby/commit/29970d93a63aa174fbc4a41b29eff996ef0ede5e) patch - Events from `dry-monitor` are now supported. There's also native support for `rom-sql` instrumentation events if they're configured.
8
+ - [27656744](https://github.com/appsignal/appsignal-ruby/commit/27656744d5d5657d120b4fcd97857c17421d8dfd) patch - Support Rails 7.1 ActiveSupport Notifications handler.
9
+
10
+ ### Changed
11
+
12
+ - [6932bb3f](https://github.com/appsignal/appsignal-ruby/commit/6932bb3f7eae75beeb86e29ddc16dc16f9da4428) patch - Add configuration load modifiers to diagnose report. Track if the `APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR` environment variable was set.
13
+
3
14
  ## 3.4.12
4
15
 
5
16
  ### Added
@@ -11,9 +22,12 @@
11
22
  ### Changed
12
23
 
13
24
  - [a42da92b](https://github.com/appsignal/appsignal-ruby/commit/a42da92b1ff16c48eb40dc081d3b4fbd6480c7c0) patch - Log an error when sample data is of an invalid type. Accepted types are Array and Hash. If any other types are given, it will log an error to the `appsignal.log` file.
25
+
26
+ ### Fixed
27
+
14
28
  - [8e636323](https://github.com/appsignal/appsignal-ruby/commit/8e6363232dc7fabe5f1aeae5758802e4c8d6cbfa) patch - Bump agent to 6133900.
15
29
 
16
- - Fix `disk_inodes_usage` metric name format to not be interpreted as a JSON object.
30
+ - Fix `disk_inode_usage` metric name format to not be interpreted as a JSON object.
17
31
 
18
32
  ## 3.4.11
19
33
 
data/README.md CHANGED
@@ -231,6 +231,7 @@ configurations you need to run the spec suite with a specific Gemfile.
231
231
  ```
232
232
  BUNDLE_GEMFILE=gemfiles/capistrano2.gemfile bundle exec rspec
233
233
  BUNDLE_GEMFILE=gemfiles/capistrano3.gemfile bundle exec rspec
234
+ BUNDLE_GEMFILE=gemfiles/dry-monitor.gemfile bundle exec rspec
234
235
  BUNDLE_GEMFILE=gemfiles/grape.gemfile bundle exec rspec
235
236
  BUNDLE_GEMFILE=gemfiles/hanami.gemfile bundle exec rspec
236
237
  BUNDLE_GEMFILE=gemfiles/http5.gemfile bundle exec rspec
data/build_matrix.yml CHANGED
@@ -170,6 +170,7 @@ matrix:
170
170
  - "rails-6.0"
171
171
  - "rails-6.1"
172
172
  - "rails-7.0"
173
+ - "rails-7.1"
173
174
 
174
175
  ruby:
175
176
  - ruby: "2.7.8"
@@ -182,6 +183,12 @@ matrix:
182
183
  - gem: "no_dependencies"
183
184
  - gem: "capistrano2"
184
185
  - gem: "capistrano3"
186
+ - gem: "dry-monitor"
187
+ only:
188
+ ruby:
189
+ - "3.0.5"
190
+ - "3.1.3"
191
+ - "3.2.1"
185
192
  - gem: "grape"
186
193
  - gem: "hanami"
187
194
  only:
@@ -229,6 +236,13 @@ matrix:
229
236
  - "3.1.3"
230
237
  - "3.2.1"
231
238
  - "jruby-9.4.1.0"
239
+ - gem: "rails-7.1"
240
+ only:
241
+ ruby:
242
+ - "3.0.5"
243
+ - "3.1.3"
244
+ - "3.2.1"
245
+ - "jruby-9.4.1.0"
232
246
  - gem: "sequel"
233
247
  - gem: "sinatra"
234
248
  - gem: "webmachine1"
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "dry-monitor", "~> 1.0.1"
4
+
5
+ gemspec :path => '../'
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rails", "~> 7.1.0"
4
+ gem "rake", "> 12.2"
5
+ gem "sidekiq"
6
+
7
+ gemspec :path => "../"
@@ -477,6 +477,10 @@ module Appsignal
477
477
  :file => config.file_config,
478
478
  :env => config.env_config,
479
479
  :override => config.override_config
480
+ },
481
+ :modifiers => {
482
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" =>
483
+ ENV.fetch("APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR", "")
480
484
  }
481
485
  }
482
486
  print_config_options(config)
@@ -519,6 +523,11 @@ module Appsignal
519
523
  end
520
524
  end
521
525
 
526
+ puts
527
+ puts "Configuration modifiers"
528
+ puts " APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR: " \
529
+ "#{data[:config][:modifiers]["APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR"].inspect}"
530
+
522
531
  puts "\nRead more about how the diagnose config output is rendered\n" \
523
532
  "https://docs.appsignal.com/ruby/command-line/diagnose.html"
524
533
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ class EventFormatter
5
+ module Rom
6
+ class SqlFormatter
7
+ def format(payload)
8
+ ["query.#{payload[:name]}", payload[:query], SQL_BODY_FORMAT]
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ Appsignal::EventFormatter.register(
16
+ "sql.dry",
17
+ Appsignal::EventFormatter::Rom::SqlFormatter
18
+ )
@@ -22,21 +22,30 @@ module Appsignal
22
22
  end
23
23
 
24
24
  require "appsignal/integrations/active_support_notifications"
25
- instrumenter = ::ActiveSupport::Notifications::Instrumenter
26
25
  parent_integration_module = Appsignal::Integrations::ActiveSupportNotificationsIntegration
27
- if instrumenter.method_defined?(:start) && instrumenter.method_defined?(:finish)
28
- install_module(parent_integration_module::StartFinishIntegration)
26
+
27
+ if defined?(::ActiveSupport::Notifications::Fanout::Handle)
28
+ install_module(
29
+ parent_integration_module::StartFinishHandlerIntegration,
30
+ ::ActiveSupport::Notifications::Fanout::Handle
31
+ )
29
32
  else
30
- install_module(parent_integration_module::InstrumentIntegration)
31
- end
33
+ instrumenter = ::ActiveSupport::Notifications::Instrumenter
32
34
 
33
- return unless instrumenter.method_defined?(:finish_with_state)
35
+ if instrumenter.method_defined?(:start) && instrumenter.method_defined?(:finish)
36
+ install_module(parent_integration_module::StartFinishIntegration, instrumenter)
37
+ else
38
+ install_module(parent_integration_module::InstrumentIntegration, instrumenter)
39
+ end
34
40
 
35
- install_module(parent_integration_module::FinishStateIntegration)
41
+ return unless instrumenter.method_defined?(:finish_with_state)
42
+
43
+ install_module(parent_integration_module::FinishStateIntegration, instrumenter)
44
+ end
36
45
  end
37
46
 
38
- def install_module(mod)
39
- ::ActiveSupport::Notifications::Instrumenter.send(:prepend, mod)
47
+ def install_module(mod, instrumenter)
48
+ instrumenter.send(:prepend, mod)
40
49
  end
41
50
  end
42
51
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ class Hooks
5
+ # @api private
6
+ class DryMonitorHook < Appsignal::Hooks::Hook
7
+ register :dry_monitor
8
+
9
+ def dependencies_present?
10
+ defined?(::Dry::Monitor::Notifications)
11
+ end
12
+
13
+ def install
14
+ require "appsignal/integrations/dry_monitor"
15
+
16
+ ::Dry::Monitor::Notifications.prepend(Appsignal::Integrations::DryMonitorIntegration)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -95,6 +95,7 @@ require "appsignal/hooks/active_support_notifications"
95
95
  require "appsignal/hooks/celluloid"
96
96
  require "appsignal/hooks/delayed_job"
97
97
  require "appsignal/hooks/gvl"
98
+ require "appsignal/hooks/dry_monitor"
98
99
  require "appsignal/hooks/http"
99
100
  require "appsignal/hooks/mri"
100
101
  require "appsignal/hooks/net_http"
@@ -54,6 +54,32 @@ module Appsignal
54
54
  end
55
55
  end
56
56
 
57
+ module StartFinishHandlerIntegration
58
+ def start
59
+ instrument_this = @name[0] != ActiveSupportNotificationsIntegration::BANG
60
+
61
+ Appsignal::Transaction.current.start_event if instrument_this
62
+ super
63
+ end
64
+
65
+ def finish_with_values(name, id, payload = {})
66
+ # Events that start with a bang are internal to Rails
67
+ instrument_this = name[0] != ActiveSupportNotificationsIntegration::BANG
68
+
69
+ if instrument_this
70
+ title, body, body_format = Appsignal::EventFormatter.format(name, payload)
71
+ Appsignal::Transaction.current.finish_event(
72
+ name.to_s,
73
+ title,
74
+ body,
75
+ body_format
76
+ )
77
+ end
78
+
79
+ super
80
+ end
81
+ end
82
+
57
83
  module FinishStateIntegration
58
84
  def finish_with_state(listeners_state, name, payload = {})
59
85
  # Events that start with a bang are internal to Rails
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appsignal
4
+ module Integrations
5
+ module DryMonitorIntegration
6
+ def instrument(event_id, payload = {}, &block)
7
+ Appsignal::Transaction.current.start_event
8
+
9
+ super
10
+ ensure
11
+ title, body, body_format = Appsignal::EventFormatter.format("#{event_id}.dry", payload)
12
+
13
+ Appsignal::Transaction.current.finish_event(
14
+ title || event_id.to_s,
15
+ title,
16
+ body,
17
+ body_format
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -36,9 +36,14 @@ module Appsignal
36
36
 
37
37
  Appsignal.start
38
38
 
39
- if Appsignal.config[:enable_rails_error_reporter] && Rails.respond_to?(:error) # rubocop:disable Style/GuardClause
40
- Rails.error.subscribe(Appsignal::Integrations::RailsErrorReporterSubscriber)
41
- end
39
+ initialize_error_reporter
40
+ end
41
+
42
+ def self.initialize_error_reporter
43
+ return unless Appsignal.config[:enable_rails_error_reporter]
44
+ return unless Rails.respond_to?(:error)
45
+
46
+ Rails.error.subscribe(Appsignal::Integrations::RailsErrorReporterSubscriber)
42
47
  end
43
48
  end
44
49
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.4.12"
4
+ VERSION = "3.4.13"
5
5
  end
@@ -781,6 +781,9 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
781
781
  "file" => {},
782
782
  "env" => {},
783
783
  "override" => { "send_session_data" => true }
784
+ },
785
+ "modifiers" => {
786
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => ""
784
787
  }
785
788
  )
786
789
  end
@@ -912,6 +915,28 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
912
915
  end
913
916
  end
914
917
 
918
+ describe "modifiers" do
919
+ before do
920
+ ENV["APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR"] = "1"
921
+ run
922
+ end
923
+
924
+ it "outputs config modifiers" do
925
+ expect(output).to include(
926
+ "Configuration modifiers\n" \
927
+ " APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR: \"1\""
928
+ )
929
+ end
930
+
931
+ it "transmits config modifiers in report" do
932
+ expect(received_report["config"]).to include(
933
+ "modifiers" => {
934
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => "1"
935
+ }
936
+ )
937
+ end
938
+ end
939
+
915
940
  it "transmits config in report" do
916
941
  run
917
942
  additional_initial_config = {}
@@ -935,6 +960,9 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
935
960
  "file" => hash_with_string_keys(config.file_config),
936
961
  "env" => {},
937
962
  "override" => { "send_session_data" => true }
963
+ },
964
+ "modifiers" => {
965
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => ""
938
966
  }
939
967
  )
940
968
  end
@@ -963,6 +991,9 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
963
991
  "file" => hash_with_string_keys(config.file_config),
964
992
  "env" => {},
965
993
  "override" => { "send_session_data" => true }
994
+ },
995
+ "modifiers" => {
996
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => ""
966
997
  }
967
998
  )
968
999
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Appsignal::EventFormatter::Rom::SqlFormatter do
4
+ let(:klass) { described_class }
5
+ let(:formatter) { klass.new }
6
+
7
+ it "registers the sql event formatter" do
8
+ expect(Appsignal::EventFormatter.registered?("sql.dry", klass)).to be_truthy
9
+ end
10
+
11
+ describe "#format" do
12
+ let(:payload) do
13
+ {
14
+ :name => "postgres",
15
+ :query => "SELECT * FROM users"
16
+ }
17
+ end
18
+ subject { formatter.format(payload) }
19
+
20
+ it { is_expected.to eq ["query.postgres", "SELECT * FROM users", 1] }
21
+ end
22
+ end
@@ -22,6 +22,12 @@ describe Appsignal::Hooks::ActiveSupportNotificationsHook do
22
22
 
23
23
  it_behaves_like "activesupport instrument override"
24
24
 
25
+ if defined?(::ActiveSupport::Notifications::Fanout::Handle)
26
+ require_relative "./active_support_notifications/start_finish_shared_examples"
27
+
28
+ it_behaves_like "activesupport start finish override"
29
+ end
30
+
25
31
  if ::ActiveSupport::Notifications::Instrumenter.method_defined?(:start)
26
32
  require_relative "./active_support_notifications/start_finish_shared_examples"
27
33
 
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ if DependencyHelper.dry_monitor_present?
4
+ require "dry-monitor"
5
+
6
+ describe Appsignal::Hooks::DryMonitorHook do
7
+ describe "#dependencies_present?" do
8
+ subject { described_class.new.dependencies_present? }
9
+
10
+ context "when Dry::Monitor::Notifications constant is found" do
11
+ before { stub_const "Dry::Monitor::Notifications", Class.new }
12
+
13
+ it { is_expected.to be_truthy }
14
+ end
15
+
16
+ context "when Dry::Monitor::Notifications constant is not found" do
17
+ before { hide_const "Dry::Monitor::Notifications" }
18
+
19
+ it { is_expected.to be_falsy }
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "#install" do
25
+ it "installs the dry-monitor hook" do
26
+ start_agent
27
+
28
+ expect(Dry::Monitor::Notifications.included_modules).to include(
29
+ Appsignal::Integrations::DryMonitorIntegration
30
+ )
31
+ end
32
+ end
33
+
34
+ describe "Dry Monitor Integration" do
35
+ before :context do
36
+ start_agent
37
+ end
38
+
39
+ let!(:transaction) do
40
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
41
+ end
42
+
43
+ let(:notifications) { Dry::Monitor::Notifications.new(:test) }
44
+
45
+ context "when is a dry-sql event" do
46
+ let(:event_id) { :sql }
47
+ let(:payload) do
48
+ {
49
+ :name => "postgres",
50
+ :query => "SELECT * FROM users"
51
+ }
52
+ end
53
+
54
+ it "creates an sql event" do
55
+ notifications.instrument(event_id, payload)
56
+ expect(transaction.to_h["events"]).to match([
57
+ {
58
+ "allocation_count" => kind_of(Integer),
59
+ "body" => "SELECT * FROM users",
60
+ "body_format" => Appsignal::EventFormatter::SQL_BODY_FORMAT,
61
+ "child_allocation_count" => kind_of(Integer),
62
+ "child_duration" => kind_of(Float),
63
+ "child_gc_duration" => kind_of(Float),
64
+ "count" => 1,
65
+ "duration" => kind_of(Float),
66
+ "gc_duration" => kind_of(Float),
67
+ "name" => "query.postgres",
68
+ "start" => kind_of(Float),
69
+ "title" => "query.postgres"
70
+ }
71
+ ])
72
+ end
73
+ end
74
+
75
+ context "when is an unregistered formatter event" do
76
+ let(:event_id) { :foo }
77
+ let(:payload) do
78
+ {
79
+ :name => "foo"
80
+ }
81
+ end
82
+
83
+ it "creates a generic event" do
84
+ notifications.instrument(event_id, payload)
85
+ expect(transaction.to_h["events"]).to match([
86
+ {
87
+ "allocation_count" => kind_of(Integer),
88
+ "body" => "",
89
+ "body_format" => Appsignal::EventFormatter::DEFAULT,
90
+ "child_allocation_count" => kind_of(Integer),
91
+ "child_duration" => kind_of(Float),
92
+ "child_gc_duration" => kind_of(Float),
93
+ "count" => 1,
94
+ "duration" => kind_of(Float),
95
+ "gc_duration" => kind_of(Float),
96
+ "name" => "foo",
97
+ "start" => kind_of(Float),
98
+ "title" => ""
99
+ }
100
+ ])
101
+ end
102
+ end
103
+ end
104
+ end
@@ -2,6 +2,10 @@ if DependencyHelper.rails_present?
2
2
  require "action_mailer"
3
3
 
4
4
  describe Appsignal::Integrations::Railtie do
5
+ include RailsHelper
6
+
7
+ after { clear_rails_error_reporter! }
8
+
5
9
  context "after initializing the app" do
6
10
  it "should call initialize_appsignal" do
7
11
  expect(Appsignal::Integrations::Railtie).to receive(:initialize_appsignal)
@@ -125,17 +129,16 @@ if DependencyHelper.rails_present?
125
129
 
126
130
  if Rails.respond_to?(:error)
127
131
  describe "Rails error reporter" do
128
- before do
129
- Appsignal::Integrations::Railtie.initialize_appsignal(app)
130
- start_agent
131
- end
132
+ before { start_agent }
132
133
  around { |example| keep_transactions { example.run } }
133
134
 
134
135
  context "when error is not handled (reraises the error)" do
135
136
  it "does nothing" do
136
- expect do
137
- Rails.error.record { raise ExampleStandardError }
138
- end.to raise_error(ExampleStandardError)
137
+ with_rails_error_reporter do
138
+ expect do
139
+ Rails.error.record { raise ExampleStandardError }
140
+ end.to raise_error(ExampleStandardError)
141
+ end
139
142
 
140
143
  expect(created_transactions).to be_empty
141
144
  end
@@ -151,26 +154,28 @@ if DependencyHelper.rails_present?
151
154
  :duplicated_tag => "duplicated value"
152
155
  )
153
156
 
154
- with_current_transaction current_transaction do
155
- Rails.error.handle { raise ExampleStandardError }
156
-
157
- transaction = last_transaction
158
- transaction_hash = transaction.to_h
159
- expect(transaction_hash).to include(
160
- "action" => "CustomAction",
161
- "namespace" => "custom",
162
- "error" => {
163
- "name" => "ExampleStandardError",
164
- "message" => "ExampleStandardError",
165
- "backtrace" => kind_of(String)
166
- },
167
- "sample_data" => hash_including(
168
- "tags" => {
169
- "duplicated_tag" => "duplicated value",
170
- "severity" => "warning"
171
- }
157
+ with_rails_error_reporter do
158
+ with_current_transaction current_transaction do
159
+ Rails.error.handle { raise ExampleStandardError }
160
+
161
+ transaction = last_transaction
162
+ transaction_hash = transaction.to_h
163
+ expect(transaction_hash).to include(
164
+ "action" => "CustomAction",
165
+ "namespace" => "custom",
166
+ "error" => {
167
+ "name" => "ExampleStandardError",
168
+ "message" => "ExampleStandardError",
169
+ "backtrace" => kind_of(String)
170
+ },
171
+ "sample_data" => hash_including(
172
+ "tags" => hash_including(
173
+ "duplicated_tag" => "duplicated value",
174
+ "severity" => "warning"
175
+ )
176
+ )
172
177
  )
173
- )
178
+ end
174
179
  end
175
180
  end
176
181
 
@@ -178,48 +183,52 @@ if DependencyHelper.rails_present?
178
183
  current_transaction = http_request_transaction
179
184
  current_transaction.set_tags(:tag1 => "duplicated value")
180
185
 
181
- with_current_transaction current_transaction do
182
- given_context = { :tag1 => "value1", :tag2 => "value2" }
183
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
184
-
185
- transaction = last_transaction
186
- transaction_hash = transaction.to_h
187
- expect(transaction_hash).to include(
188
- "sample_data" => hash_including(
189
- "tags" => {
190
- "tag1" => "value1",
191
- "tag2" => "value2",
192
- "severity" => "warning"
193
- }
186
+ with_rails_error_reporter do
187
+ with_current_transaction current_transaction do
188
+ given_context = { :tag1 => "value1", :tag2 => "value2" }
189
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
190
+
191
+ transaction = last_transaction
192
+ transaction_hash = transaction.to_h
193
+ expect(transaction_hash).to include(
194
+ "sample_data" => hash_including(
195
+ "tags" => hash_including(
196
+ "tag1" => "value1",
197
+ "tag2" => "value2",
198
+ "severity" => "warning"
199
+ )
200
+ )
194
201
  )
195
- )
202
+ end
196
203
  end
197
204
  end
198
205
 
199
206
  it "sends tags stored in :appsignal -> :custom_data as custom data" do
200
207
  current_transaction = http_request_transaction
201
208
 
202
- with_current_transaction current_transaction do
203
- given_context = {
204
- :appsignal => {
205
- :custom_data => {
206
- :array => [1, 2],
207
- :hash => { :one => 1, :two => 2 }
209
+ with_rails_error_reporter do
210
+ with_current_transaction current_transaction do
211
+ given_context = {
212
+ :appsignal => {
213
+ :custom_data => {
214
+ :array => [1, 2],
215
+ :hash => { :one => 1, :two => 2 }
216
+ }
208
217
  }
209
218
  }
210
- }
211
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
212
-
213
- transaction = last_transaction
214
- transaction_hash = transaction.to_h
215
- expect(transaction_hash).to include(
216
- "sample_data" => hash_including(
217
- "custom_data" => {
218
- "array" => [1, 2],
219
- "hash" => { "one" => 1, "two" => 2 }
220
- }
219
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
220
+
221
+ transaction = last_transaction
222
+ transaction_hash = transaction.to_h
223
+ expect(transaction_hash).to include(
224
+ "sample_data" => hash_including(
225
+ "custom_data" => {
226
+ "array" => [1, 2],
227
+ "hash" => { "one" => 1, "two" => 2 }
228
+ }
229
+ )
221
230
  )
222
- )
231
+ end
223
232
  end
224
233
  end
225
234
 
@@ -228,18 +237,20 @@ if DependencyHelper.rails_present?
228
237
  current_transaction.set_namespace "custom"
229
238
  current_transaction.set_action "CustomAction"
230
239
 
231
- with_current_transaction current_transaction do
232
- given_context = {
233
- :appsignal => { :namespace => "context", :action => "ContextAction" }
234
- }
235
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
240
+ with_rails_error_reporter do
241
+ with_current_transaction current_transaction do
242
+ given_context = {
243
+ :appsignal => { :namespace => "context", :action => "ContextAction" }
244
+ }
245
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
236
246
 
237
- transaction = last_transaction
238
- transaction_hash = transaction.to_h
239
- expect(transaction_hash).to include(
240
- "namespace" => "context",
241
- "action" => "ContextAction"
242
- )
247
+ transaction = last_transaction
248
+ transaction_hash = transaction.to_h
249
+ expect(transaction_hash).to include(
250
+ "namespace" => "context",
251
+ "action" => "ContextAction"
252
+ )
253
+ end
243
254
  end
244
255
  end
245
256
  end
@@ -267,7 +278,9 @@ if DependencyHelper.rails_present?
267
278
  it "fetches the action from the controller in the context" do
268
279
  # The controller key is set by Rails when raised in a controller
269
280
  given_context = { :controller => ExampleRailsControllerMock.new }
270
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
281
+ with_rails_error_reporter do
282
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
283
+ end
271
284
 
272
285
  transaction = last_transaction
273
286
  transaction_hash = transaction.to_h
@@ -278,7 +291,9 @@ if DependencyHelper.rails_present?
278
291
 
279
292
  it "sets no action if no execution context is present" do
280
293
  # The controller key is set by Rails when raised in a controller
281
- Rails.error.handle { raise ExampleStandardError }
294
+ with_rails_error_reporter do
295
+ Rails.error.handle { raise ExampleStandardError }
296
+ end
282
297
 
283
298
  transaction = last_transaction
284
299
  transaction_hash = transaction.to_h
@@ -296,17 +311,19 @@ if DependencyHelper.rails_present?
296
311
  :tag1 => "value1",
297
312
  :tag2 => "value2"
298
313
  }
299
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
314
+ with_rails_error_reporter do
315
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
316
+ end
300
317
 
301
318
  transaction = last_transaction
302
319
  transaction_hash = transaction.to_h
303
320
  expect(transaction_hash).to include(
304
321
  "sample_data" => hash_including(
305
- "tags" => {
322
+ "tags" => hash_including(
306
323
  "tag1" => "value1",
307
324
  "tag2" => "value2",
308
325
  "severity" => "warning"
309
- }
326
+ )
310
327
  )
311
328
  )
312
329
  end
@@ -266,13 +266,16 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
266
266
 
267
267
  if DependencyHelper.rails7_present?
268
268
  context "with Rails error reporter" do
269
+ include RailsHelper
270
+
269
271
  it "reports the worker name as the action, copies the namespace and tags" do
270
- Appsignal::Integrations::Railtie.initialize_appsignal(MyApp::Application.new)
271
272
  Appsignal.config = project_fixture_config("production")
272
- perform_job do
273
- Appsignal.tag_job("test_tag" => "value")
274
- Rails.error.handle do
275
- raise error, "uh oh"
273
+ with_rails_error_reporter do
274
+ perform_job do
275
+ Appsignal.tag_job("test_tag" => "value")
276
+ Rails.error.handle do
277
+ raise ExampleStandardError, "uh oh"
278
+ end
276
279
  end
277
280
  end
278
281
 
@@ -363,7 +366,9 @@ if DependencyHelper.active_job_present?
363
366
  require "sidekiq/testing"
364
367
 
365
368
  describe "Sidekiq ActiveJob integration" do
369
+ include RailsHelper
366
370
  include ActiveJobHelpers
371
+
367
372
  let(:namespace) { Appsignal::Transaction::BACKGROUND_JOB }
368
373
  let(:time) { Time.parse("2001-01-01 10:00:00UTC") }
369
374
  let(:log) { StringIO.new }
@@ -416,7 +421,7 @@ if DependencyHelper.active_job_present?
416
421
  ["perform_job.sidekiq", "perform_start.active_job", "perform.active_job"]
417
422
  end
418
423
  end
419
- before do
424
+ around do |example|
420
425
  start_agent
421
426
  Appsignal.logger = test_logger(log)
422
427
  ActiveJob::Base.queue_adapter = :sidekiq
@@ -441,11 +446,11 @@ if DependencyHelper.active_job_present?
441
446
  Sidekiq::Testing.server_middleware do |chain|
442
447
  chain.add Appsignal::Integrations::SidekiqMiddleware
443
448
  end
444
- end
445
- around do |example|
446
- keep_transactions do
447
- Sidekiq::Testing.fake! do
448
- example.run
449
+ with_rails_error_reporter do
450
+ keep_transactions do
451
+ Sidekiq::Testing.fake! do
452
+ example.run
453
+ end
449
454
  end
450
455
  end
451
456
  end
@@ -115,6 +115,10 @@ module DependencyHelper
115
115
  dependency_present? "hanami"
116
116
  end
117
117
 
118
+ def dry_monitor_present?
119
+ dependency_present? "dry-monitor"
120
+ end
121
+
118
122
  def hanami2_present?
119
123
  hanami_present? && Gem.loaded_specs["hanami"].version >= Gem::Version.new("2.0")
120
124
  end
@@ -0,0 +1,28 @@
1
+ module RailsHelper
2
+ def with_railtie(app)
3
+ clear_rails_error_reporter! if Rails.respond_to? :error
4
+ Appsignal::Integrations::Railtie.initialize_appsignal(app)
5
+ yield
6
+ ensure
7
+ clear_rails_error_reporter!
8
+ end
9
+
10
+ def with_rails_error_reporter
11
+ if Rails.respond_to? :error
12
+ clear_rails_error_reporter!
13
+ Appsignal::Integrations::Railtie.initialize_error_reporter
14
+ end
15
+ yield
16
+ ensure
17
+ clear_rails_error_reporter!
18
+ end
19
+
20
+ def clear_rails_error_reporter!
21
+ return unless Rails.respond_to? :error
22
+
23
+ Rails
24
+ .error
25
+ .instance_variable_get(:@subscribers)
26
+ .reject! { |s| s == Appsignal::Integrations::RailsErrorReporterSubscriber }
27
+ end
28
+ 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: 3.4.12
4
+ version: 3.4.13
5
5
  platform: ruby
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: 2023-08-30 00:00:00.000000000 Z
13
+ date: 2023-10-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -160,6 +160,7 @@ files:
160
160
  - ext/extconf.rb
161
161
  - gemfiles/capistrano2.gemfile
162
162
  - gemfiles/capistrano3.gemfile
163
+ - gemfiles/dry-monitor.gemfile
163
164
  - gemfiles/grape.gemfile
164
165
  - gemfiles/hanami.gemfile
165
166
  - gemfiles/http5.gemfile
@@ -172,6 +173,7 @@ files:
172
173
  - gemfiles/rails-6.0.gemfile
173
174
  - gemfiles/rails-6.1.gemfile
174
175
  - gemfiles/rails-7.0.gemfile
176
+ - gemfiles/rails-7.1.gemfile
175
177
  - gemfiles/resque-2.gemfile
176
178
  - gemfiles/sequel.gemfile
177
179
  - gemfiles/sinatra.gemfile
@@ -197,6 +199,7 @@ files:
197
199
  - lib/appsignal/event_formatter/elastic_search/search_formatter.rb
198
200
  - lib/appsignal/event_formatter/faraday/request_formatter.rb
199
201
  - lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb
202
+ - lib/appsignal/event_formatter/rom/sql_formatter.rb
200
203
  - lib/appsignal/event_formatter/sequel/sql_formatter.rb
201
204
  - lib/appsignal/extension.rb
202
205
  - lib/appsignal/extension/jruby.rb
@@ -211,6 +214,7 @@ files:
211
214
  - lib/appsignal/hooks/celluloid.rb
212
215
  - lib/appsignal/hooks/data_mapper.rb
213
216
  - lib/appsignal/hooks/delayed_job.rb
217
+ - lib/appsignal/hooks/dry_monitor.rb
214
218
  - lib/appsignal/hooks/excon.rb
215
219
  - lib/appsignal/hooks/gvl.rb
216
220
  - lib/appsignal/hooks/http.rb
@@ -234,6 +238,7 @@ files:
234
238
  - lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb
235
239
  - lib/appsignal/integrations/data_mapper.rb
236
240
  - lib/appsignal/integrations/delayed_job_plugin.rb
241
+ - lib/appsignal/integrations/dry_monitor.rb
237
242
  - lib/appsignal/integrations/excon.rb
238
243
  - lib/appsignal/integrations/grape.rb
239
244
  - lib/appsignal/integrations/hanami.rb
@@ -302,6 +307,7 @@ files:
302
307
  - spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb
303
308
  - spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb
304
309
  - spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb
310
+ - spec/lib/appsignal/event_formatter/rom/sql_formatter_spec.rb
305
311
  - spec/lib/appsignal/event_formatter/sequel/sql_formatter_spec.rb
306
312
  - spec/lib/appsignal/event_formatter_spec.rb
307
313
  - spec/lib/appsignal/extension/jruby_spec.rb
@@ -318,6 +324,7 @@ files:
318
324
  - spec/lib/appsignal/hooks/celluloid_spec.rb
319
325
  - spec/lib/appsignal/hooks/data_mapper_spec.rb
320
326
  - spec/lib/appsignal/hooks/delayed_job_spec.rb
327
+ - spec/lib/appsignal/hooks/dry_monitor_spec.rb
321
328
  - spec/lib/appsignal/hooks/excon_spec.rb
322
329
  - spec/lib/appsignal/hooks/gvl_spec.rb
323
330
  - spec/lib/appsignal/hooks/http_spec.rb
@@ -392,6 +399,7 @@ files:
392
399
  - spec/support/helpers/example_exception.rb
393
400
  - spec/support/helpers/example_standard_error.rb
394
401
  - spec/support/helpers/log_helpers.rb
402
+ - spec/support/helpers/rails_helper.rb
395
403
  - spec/support/helpers/std_streams_helper.rb
396
404
  - spec/support/helpers/system_helpers.rb
397
405
  - spec/support/helpers/time_helpers.rb