appsignal 4.0.5 → 4.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/Rakefile +9 -9
  4. data/appsignal.gemspec +22 -1
  5. data/build_matrix.yml +2 -1
  6. data/ext/agent.rb +27 -27
  7. data/lib/appsignal/check_in/scheduler.rb +3 -4
  8. data/lib/appsignal/check_in.rb +1 -1
  9. data/lib/appsignal/config.rb +1 -3
  10. data/lib/appsignal/integrations/que.rb +8 -2
  11. data/lib/appsignal/integrations/resque.rb +1 -6
  12. data/lib/appsignal/utils/hash_sanitizer.rb +4 -0
  13. data/lib/appsignal/version.rb +1 -1
  14. metadata +2 -191
  15. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -31
  16. data/.github/ISSUE_TEMPLATE/chore.md +0 -14
  17. data/.github/workflows/ci.yml +0 -3150
  18. data/.github/workflows/create_release_from_tag.yml +0 -62
  19. data/.gitignore +0 -35
  20. data/.gitmodules +0 -3
  21. data/.rspec +0 -4
  22. data/.yardopts +0 -8
  23. data/benchmark.rake +0 -139
  24. data/gemfiles/capistrano2.gemfile +0 -6
  25. data/gemfiles/capistrano3.gemfile +0 -7
  26. data/gemfiles/dry-monitor.gemfile +0 -5
  27. data/gemfiles/grape.gemfile +0 -5
  28. data/gemfiles/hanami-2.0.gemfile +0 -7
  29. data/gemfiles/hanami-2.1.gemfile +0 -7
  30. data/gemfiles/http5.gemfile +0 -5
  31. data/gemfiles/no_dependencies.gemfile +0 -10
  32. data/gemfiles/padrino.gemfile +0 -7
  33. data/gemfiles/psych-3.gemfile +0 -5
  34. data/gemfiles/psych-4.gemfile +0 -5
  35. data/gemfiles/que.gemfile +0 -5
  36. data/gemfiles/rails-6.0.gemfile +0 -10
  37. data/gemfiles/rails-6.1.gemfile +0 -11
  38. data/gemfiles/rails-7.0.gemfile +0 -11
  39. data/gemfiles/rails-7.1.gemfile +0 -11
  40. data/gemfiles/rails-7.2.gemfile +0 -11
  41. data/gemfiles/redis-4.gemfile +0 -5
  42. data/gemfiles/redis-5.gemfile +0 -6
  43. data/gemfiles/resque-2.gemfile +0 -6
  44. data/gemfiles/sequel.gemfile +0 -10
  45. data/gemfiles/sinatra.gemfile +0 -5
  46. data/gemfiles/webmachine1.gemfile +0 -7
  47. data/gemfiles/webmachine2.gemfile +0 -6
  48. data/mono.yml +0 -16
  49. data/spec/.rubocop.yml +0 -7
  50. data/spec/lib/appsignal/auth_check_spec.rb +0 -84
  51. data/spec/lib/appsignal/capistrano2_spec.rb +0 -227
  52. data/spec/lib/appsignal/capistrano3_spec.rb +0 -284
  53. data/spec/lib/appsignal/check_in/cron_spec.rb +0 -202
  54. data/spec/lib/appsignal/check_in/scheduler_spec.rb +0 -443
  55. data/spec/lib/appsignal/cli/demo_spec.rb +0 -46
  56. data/spec/lib/appsignal/cli/diagnose/paths_spec.rb +0 -16
  57. data/spec/lib/appsignal/cli/diagnose/utils_spec.rb +0 -86
  58. data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -1553
  59. data/spec/lib/appsignal/cli/helpers_spec.rb +0 -179
  60. data/spec/lib/appsignal/cli/install_spec.rb +0 -848
  61. data/spec/lib/appsignal/cli_spec.rb +0 -56
  62. data/spec/lib/appsignal/config_spec.rb +0 -1380
  63. data/spec/lib/appsignal/demo_spec.rb +0 -83
  64. data/spec/lib/appsignal/environment_spec.rb +0 -190
  65. data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +0 -60
  66. data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +0 -21
  67. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +0 -21
  68. data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +0 -52
  69. data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +0 -21
  70. data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +0 -84
  71. data/spec/lib/appsignal/event_formatter/rom/sql_formatter_spec.rb +0 -22
  72. data/spec/lib/appsignal/event_formatter/sequel/sql_formatter_spec.rb +0 -30
  73. data/spec/lib/appsignal/event_formatter/view_component/render_formatter_spec.rb +0 -41
  74. data/spec/lib/appsignal/event_formatter_spec.rb +0 -193
  75. data/spec/lib/appsignal/extension/jruby_spec.rb +0 -46
  76. data/spec/lib/appsignal/extension_install_failure_spec.rb +0 -20
  77. data/spec/lib/appsignal/extension_spec.rb +0 -178
  78. data/spec/lib/appsignal/garbage_collection_spec.rb +0 -98
  79. data/spec/lib/appsignal/hooks/action_cable_spec.rb +0 -345
  80. data/spec/lib/appsignal/hooks/action_mailer_spec.rb +0 -55
  81. data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +0 -23
  82. data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +0 -99
  83. data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +0 -47
  84. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +0 -47
  85. data/spec/lib/appsignal/hooks/activejob_spec.rb +0 -650
  86. data/spec/lib/appsignal/hooks/at_exit_spec.rb +0 -105
  87. data/spec/lib/appsignal/hooks/celluloid_spec.rb +0 -40
  88. data/spec/lib/appsignal/hooks/data_mapper_spec.rb +0 -40
  89. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +0 -38
  90. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +0 -83
  91. data/spec/lib/appsignal/hooks/excon_spec.rb +0 -67
  92. data/spec/lib/appsignal/hooks/gvl_spec.rb +0 -145
  93. data/spec/lib/appsignal/hooks/http_spec.rb +0 -37
  94. data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +0 -46
  95. data/spec/lib/appsignal/hooks/mri_spec.rb +0 -23
  96. data/spec/lib/appsignal/hooks/net_http_spec.rb +0 -18
  97. data/spec/lib/appsignal/hooks/passenger_spec.rb +0 -30
  98. data/spec/lib/appsignal/hooks/puma_spec.rb +0 -80
  99. data/spec/lib/appsignal/hooks/que_spec.rb +0 -19
  100. data/spec/lib/appsignal/hooks/rake_spec.rb +0 -144
  101. data/spec/lib/appsignal/hooks/redis_client_spec.rb +0 -218
  102. data/spec/lib/appsignal/hooks/redis_spec.rb +0 -124
  103. data/spec/lib/appsignal/hooks/resque_spec.rb +0 -27
  104. data/spec/lib/appsignal/hooks/sequel_spec.rb +0 -44
  105. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -29
  106. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +0 -115
  107. data/spec/lib/appsignal/hooks/unicorn_spec.rb +0 -63
  108. data/spec/lib/appsignal/hooks/webmachine_spec.rb +0 -24
  109. data/spec/lib/appsignal/hooks_spec.rb +0 -124
  110. data/spec/lib/appsignal/integrations/data_mapper_spec.rb +0 -74
  111. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +0 -454
  112. data/spec/lib/appsignal/integrations/http_spec.rb +0 -111
  113. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +0 -154
  114. data/spec/lib/appsignal/integrations/net_http_spec.rb +0 -33
  115. data/spec/lib/appsignal/integrations/object_spec.rb +0 -347
  116. data/spec/lib/appsignal/integrations/puma_spec.rb +0 -150
  117. data/spec/lib/appsignal/integrations/que_spec.rb +0 -152
  118. data/spec/lib/appsignal/integrations/railtie_spec.rb +0 -457
  119. data/spec/lib/appsignal/integrations/resque_spec.rb +0 -155
  120. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +0 -165
  121. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +0 -640
  122. data/spec/lib/appsignal/integrations/webmachine_spec.rb +0 -136
  123. data/spec/lib/appsignal/loaders/grape_spec.rb +0 -12
  124. data/spec/lib/appsignal/loaders/hanami_spec.rb +0 -92
  125. data/spec/lib/appsignal/loaders/padrino_spec.rb +0 -273
  126. data/spec/lib/appsignal/loaders/sinatra_spec.rb +0 -44
  127. data/spec/lib/appsignal/loaders_spec.rb +0 -144
  128. data/spec/lib/appsignal/logger_spec.rb +0 -205
  129. data/spec/lib/appsignal/marker_spec.rb +0 -51
  130. data/spec/lib/appsignal/probes/gvl_spec.rb +0 -164
  131. data/spec/lib/appsignal/probes/mri_spec.rb +0 -162
  132. data/spec/lib/appsignal/probes/sidekiq_spec.rb +0 -333
  133. data/spec/lib/appsignal/probes_spec.rb +0 -411
  134. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +0 -370
  135. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +0 -319
  136. data/spec/lib/appsignal/rack/event_handler_spec.rb +0 -441
  137. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +0 -201
  138. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +0 -36
  139. data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +0 -38
  140. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +0 -126
  141. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +0 -217
  142. data/spec/lib/appsignal/rack_spec.rb +0 -243
  143. data/spec/lib/appsignal/sample_data_spec.rb +0 -238
  144. data/spec/lib/appsignal/span_spec.rb +0 -141
  145. data/spec/lib/appsignal/system_spec.rb +0 -126
  146. data/spec/lib/appsignal/transaction_spec.rb +0 -2111
  147. data/spec/lib/appsignal/transmitter_spec.rb +0 -198
  148. data/spec/lib/appsignal/utils/data_spec.rb +0 -166
  149. data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +0 -182
  150. data/spec/lib/appsignal/utils/integration_logger_spec.rb +0 -21
  151. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -153
  152. data/spec/lib/appsignal/utils/json_spec.rb +0 -44
  153. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +0 -192
  154. data/spec/lib/appsignal_spec.rb +0 -1919
  155. data/spec/lib/puma/appsignal_spec.rb +0 -334
  156. data/spec/spec_helper.rb +0 -173
  157. data/spec/support/fixtures/generated_config.yml +0 -24
  158. data/spec/support/fixtures/projects/broken/config/appsignal.yml +0 -1
  159. data/spec/support/fixtures/projects/valid/config/appsignal.yml +0 -57
  160. data/spec/support/fixtures/projects/valid/log/.gitkeep +0 -0
  161. data/spec/support/fixtures/projects/valid_with_rails_app/config/application.rb +0 -16
  162. data/spec/support/fixtures/projects/valid_with_rails_app/config/appsignal.yml +0 -56
  163. data/spec/support/fixtures/projects/valid_with_rails_app/config/environment.rb +0 -10
  164. data/spec/support/fixtures/projects/valid_with_rails_app/log/.gitkeep +0 -0
  165. data/spec/support/fixtures/uploaded_file.txt +0 -0
  166. data/spec/support/hanami/hanami_app.rb +0 -29
  167. data/spec/support/helpers/action_mailer_helpers.rb +0 -25
  168. data/spec/support/helpers/activejob_helpers.rb +0 -27
  169. data/spec/support/helpers/api_request_helper.rb +0 -20
  170. data/spec/support/helpers/cli_helpers.rb +0 -40
  171. data/spec/support/helpers/config_helpers.rb +0 -66
  172. data/spec/support/helpers/dependency_helper.rb +0 -150
  173. data/spec/support/helpers/directory_helper.rb +0 -27
  174. data/spec/support/helpers/env_helpers.rb +0 -41
  175. data/spec/support/helpers/environment_metdata_helper.rb +0 -16
  176. data/spec/support/helpers/example_exception.rb +0 -13
  177. data/spec/support/helpers/example_standard_error.rb +0 -13
  178. data/spec/support/helpers/loader_helper.rb +0 -21
  179. data/spec/support/helpers/log_helpers.rb +0 -36
  180. data/spec/support/helpers/rails_helper.rb +0 -28
  181. data/spec/support/helpers/std_streams_helper.rb +0 -94
  182. data/spec/support/helpers/system_helpers.rb +0 -8
  183. data/spec/support/helpers/take_at_most_helper.rb +0 -21
  184. data/spec/support/helpers/time_helpers.rb +0 -11
  185. data/spec/support/helpers/transaction_helpers.rb +0 -122
  186. data/spec/support/helpers/wait_for_helper.rb +0 -39
  187. data/spec/support/matchers/contains_log.rb +0 -26
  188. data/spec/support/matchers/have_colorized_text.rb +0 -28
  189. data/spec/support/matchers/transaction.rb +0 -200
  190. data/spec/support/mocks/appsignal_mock.rb +0 -18
  191. data/spec/support/mocks/dummy_app.rb +0 -20
  192. data/spec/support/mocks/fake_gc_profiler.rb +0 -19
  193. data/spec/support/mocks/fake_gvl_tools.rb +0 -28
  194. data/spec/support/mocks/hash_like.rb +0 -10
  195. data/spec/support/mocks/mock_probe.rb +0 -13
  196. data/spec/support/mocks/puma_mock.rb +0 -43
  197. data/spec/support/shared_examples/instrument.rb +0 -48
  198. data/spec/support/stubs/appsignal/loaders/loader_stub.rb +0 -7
  199. data/spec/support/stubs/delayed_job.rb +0 -0
  200. data/spec/support/stubs/sidekiq/api.rb +0 -4
  201. data/spec/support/testing.rb +0 -194
  202. data/support/bundler_wrapper +0 -12
  203. data/support/install_deps +0 -33
@@ -1,205 +0,0 @@
1
- describe Appsignal::Logger do
2
- let(:log_stream) { StringIO.new }
3
- let(:logs) { log_contents(log_stream) }
4
- let(:logger) { Appsignal::Logger.new("group", :level => ::Logger::DEBUG) }
5
-
6
- before do
7
- Appsignal.internal_logger = test_logger(log_stream)
8
- end
9
-
10
- it "should not create a logger with a nil group" do
11
- expect do
12
- Appsignal::Logger.new(nil)
13
- end.to raise_error(TypeError)
14
- end
15
-
16
- describe "#add" do
17
- it "should log with a level and message" do
18
- expect(Appsignal::Extension).to receive(:log)
19
- .with("group", 3, 0, "Log message", instance_of(Appsignal::Extension::Data))
20
- logger.add(::Logger::INFO, "Log message")
21
- end
22
-
23
- it "does not log a message that's not a String" do
24
- expect(Appsignal::Extension).to_not receive(:log)
25
- logger.add(::Logger::INFO, 123)
26
- logger.add(::Logger::INFO, {})
27
- logger.add(::Logger::INFO, [])
28
- expect(logs)
29
- .to contains_log(:warn, "Logger message was ignored, because it was not a String: 123")
30
- expect(logs)
31
- .to contains_log(:warn, "Logger message was ignored, because it was not a String: []")
32
- expect(logs)
33
- .to contains_log(:warn, "Logger message was ignored, because it was not a String: {}")
34
- end
35
-
36
- it "should log with a block" do
37
- expect(Appsignal::Extension).to receive(:log)
38
- .with("group", 3, 0, "Log message", instance_of(Appsignal::Extension::Data))
39
- logger.add(::Logger::INFO) do
40
- "Log message"
41
- end
42
- end
43
-
44
- it "should log with a level, message and group" do
45
- expect(Appsignal::Extension).to receive(:log)
46
- .with("other_group", 3, 0, "Log message", instance_of(Appsignal::Extension::Data))
47
- logger.add(::Logger::INFO, "Log message", "other_group")
48
- end
49
-
50
- it "should log when using `group` for the log message" do
51
- expect(Appsignal::Extension).to receive(:log)
52
- .with("group", 3, 0, "Log message", instance_of(Appsignal::Extension::Data))
53
- logger.add(::Logger::INFO, nil, "Log message")
54
- end
55
-
56
- context "with info log level" do
57
- let(:logger) { Appsignal::Logger.new("group", :level => ::Logger::INFO) }
58
-
59
- it "should skip logging if the level is too low" do
60
- expect(Appsignal::Extension).not_to receive(:log)
61
- logger.add(::Logger::DEBUG, "Log message")
62
- end
63
- end
64
-
65
- context "with a format set" do
66
- let(:logger) { Appsignal::Logger.new("group", :format => Appsignal::Logger::LOGFMT) }
67
-
68
- it "should log and pass the format flag" do
69
- expect(Appsignal::Extension).to receive(:log)
70
- .with("group", 3, 1, "Log message", instance_of(Appsignal::Extension::Data))
71
- logger.add(::Logger::INFO, "Log message")
72
- end
73
- end
74
-
75
- context "with a formatter set" do
76
- before do
77
- logger.formatter = proc do |_level, _timestamp, _appname, message|
78
- "formatted: '#{message}'"
79
- end
80
- end
81
-
82
- it "should log with a level, message and group" do
83
- expect(Appsignal::Extension).to receive(:log).with(
84
- "other_group",
85
- 3,
86
- 0,
87
- "formatted: 'Log message'",
88
- instance_of(Appsignal::Extension::Data)
89
- )
90
- logger.add(::Logger::INFO, "Log message", "other_group")
91
- end
92
- end
93
- end
94
-
95
- describe "#silence" do
96
- it "calls the given block" do
97
- num = 1
98
-
99
- logger.silence do
100
- num += 1
101
- end
102
-
103
- expect(num).to eq(2)
104
- expect(Appsignal::Extension).not_to receive(:log)
105
- end
106
- end
107
-
108
- [
109
- ["debug", 2, ::Logger::INFO],
110
- ["info", 3, ::Logger::WARN],
111
- ["warn", 5, ::Logger::ERROR],
112
- ["error", 6, ::Logger::FATAL],
113
- ["fatal", 7, nil]
114
- ].each do |method|
115
- describe "##{method[0]}" do
116
- it "should log with a message" do
117
- expect(Appsignal::Utils::Data).to receive(:generate)
118
- .with({ :attribute => "value" })
119
- .and_call_original
120
- expect(Appsignal::Extension).to receive(:log)
121
- .with("group", method[1], 0, "Log message", instance_of(Appsignal::Extension::Data))
122
-
123
- logger.send(method[0], "Log message", :attribute => "value")
124
- end
125
-
126
- it "should log with a block" do
127
- expect(Appsignal::Utils::Data).to receive(:generate)
128
- .with({})
129
- .and_call_original
130
- expect(Appsignal::Extension).to receive(:log)
131
- .with("group", method[1], 0, "Log message", instance_of(Appsignal::Extension::Data))
132
-
133
- logger.send(method[0]) do
134
- "Log message"
135
- end
136
- end
137
-
138
- it "should return with a nil message" do
139
- expect(Appsignal::Extension).not_to receive(:log)
140
- logger.send(method[0])
141
- end
142
-
143
- if method[2]
144
- context "with a lower log level" do
145
- let(:logger) { Appsignal::Logger.new("group", :level => method[2]) }
146
-
147
- it "should skip logging if the level is too low" do
148
- expect(Appsignal::Extension).not_to receive(:log)
149
- logger.send(method[0], "Log message")
150
- end
151
- end
152
- end
153
-
154
- context "with a formatter set" do
155
- before do
156
- Timecop.freeze(Time.local(2023))
157
- logger.formatter = logger.formatter = proc do |_level, timestamp, _appname, message|
158
- # This line replicates the behaviour of the Ruby default Logger::Formatter
159
- # which expects a timestamp object as a second argument
160
- # https://github.com/ruby/ruby/blob/master/lib/logger/formatter.rb#L15-L17
161
- time = timestamp.strftime("%Y-%m-%dT%H:%M:%S.%6N")
162
- "formatted: #{time} '#{message}'"
163
- end
164
- end
165
-
166
- after do
167
- Timecop.return
168
- end
169
-
170
- it "should log with a level, message and group" do
171
- expect(Appsignal::Extension).to receive(:log)
172
- .with(
173
- "group",
174
- method[1],
175
- 0,
176
- "formatted: 2023-01-01T00:00:00.000000 'Log message'",
177
- instance_of(Appsignal::Extension::Data)
178
- )
179
- logger.send(method[0], "Log message")
180
- end
181
- end
182
- end
183
- end
184
-
185
- describe "#error with exception object" do
186
- it "logs the exception class and its message" do
187
- error =
188
- begin
189
- raise ExampleStandardError, "oh no!"
190
- rescue => e
191
- # This makes the exception include a backtrace, so we can assert it's NOT included
192
- e
193
- end
194
- expect(Appsignal::Extension).to receive(:log)
195
- .with(
196
- "group",
197
- 6,
198
- 0,
199
- "ExampleStandardError: oh no!",
200
- instance_of(Appsignal::Extension::Data)
201
- )
202
- logger.error(error)
203
- end
204
- end
205
- end
@@ -1,51 +0,0 @@
1
- describe Appsignal::Marker do
2
- let(:config) { build_config }
3
- let(:marker) do
4
- described_class.new(
5
- {
6
- :revision => "503ce0923ed177a3ce000005",
7
- :repository => "main",
8
- :user => "batman",
9
- :rails_env => "production"
10
- },
11
- config
12
- )
13
- end
14
- let(:out_stream) { std_stream }
15
- let(:output) { out_stream.read }
16
-
17
- describe "#transmit" do
18
- def stub_marker_request
19
- stub_api_request config, "markers", marker.marker_data
20
- end
21
-
22
- def run
23
- capture_stdout(out_stream) { marker.transmit }
24
- end
25
-
26
- context "when request is valid" do
27
- before { stub_marker_request.to_return(:status => 200) }
28
-
29
- it "outputs success" do
30
- run
31
- expect(output).to include \
32
- "Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman",
33
- "AppSignal has been notified of this deploy!"
34
- end
35
- end
36
-
37
- context "when request is invalid" do
38
- before { stub_marker_request.to_return(:status => 500) }
39
-
40
- it "outputs failure" do
41
- run
42
- expect(output).to include \
43
- "Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman",
44
- "Something went wrong while trying to notify AppSignal: 500 at " \
45
- "#{config[:endpoint]}/1/markers"
46
- expect(output).to_not include \
47
- "AppSignal has been notified of this deploy!"
48
- end
49
- end
50
- end
51
- end
@@ -1,164 +0,0 @@
1
- describe Appsignal::Probes::GvlProbe do
2
- let(:appsignal_mock) { AppsignalMock.new(:hostname => hostname) }
3
- let(:probe) { described_class.new(:appsignal => appsignal_mock, :gvl_tools => FakeGVLTools) }
4
-
5
- let(:hostname) { "some-host" }
6
-
7
- around do |example|
8
- real_program_name = $PROGRAM_NAME
9
- example.run
10
- ensure
11
- $PROGRAM_NAME = real_program_name
12
- end
13
-
14
- def gauges_for(metric)
15
- gauges = appsignal_mock.gauges.select do |gauge|
16
- gauge[0] == metric
17
- end
18
-
19
- gauges.map do |gauge|
20
- gauge.drop(1)
21
- end
22
- end
23
-
24
- after { FakeGVLTools.reset }
25
-
26
- it "gauges the global timer delta" do
27
- FakeGVLTools::GlobalTimer.monotonic_time = 100_000_000
28
- probe.call
29
-
30
- expect(gauges_for("gvl_global_timer")).to be_empty
31
-
32
- FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
33
- probe.call
34
-
35
- expect(gauges_for("gvl_global_timer")).to eq [
36
- [200, {
37
- :hostname => hostname,
38
- :process_name => "rspec",
39
- :process_id => Process.pid
40
- }],
41
- [200, { :hostname => hostname }]
42
- ]
43
- end
44
-
45
- context "when the delta is negative" do
46
- it "does not gauge the global timer delta" do
47
- FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
48
- probe.call
49
-
50
- expect(gauges_for("gvl_global_timer")).to be_empty
51
-
52
- FakeGVLTools::GlobalTimer.monotonic_time = 0
53
- probe.call
54
-
55
- expect(gauges_for("gvl_global_timer")).to be_empty
56
- end
57
- end
58
-
59
- context "when the delta is zero" do
60
- it "does not gauge the global timer delta" do
61
- FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
62
- probe.call
63
-
64
- expect(gauges_for("gvl_global_timer")).to be_empty
65
-
66
- probe.call
67
-
68
- expect(gauges_for("gvl_global_timer")).to be_empty
69
- end
70
- end
71
-
72
- context "when the waiting threads count is enabled" do
73
- before do
74
- FakeGVLTools::WaitingThreads.enabled = true
75
- end
76
-
77
- it "gauges the waiting threads count" do
78
- FakeGVLTools::WaitingThreads.count = 3
79
- probe.call
80
-
81
- expect(gauges_for("gvl_waiting_threads")).to eq [
82
- [3, {
83
- :hostname => hostname,
84
- :process_name => "rspec",
85
- :process_id => Process.pid
86
- }],
87
- [3, { :hostname => hostname }]
88
- ]
89
- end
90
- end
91
-
92
- context "when the waiting threads count is disabled" do
93
- before do
94
- FakeGVLTools::WaitingThreads.enabled = false
95
- end
96
-
97
- it "does not gauge the waiting threads count" do
98
- FakeGVLTools::WaitingThreads.count = 3
99
- probe.call
100
-
101
- expect(gauges_for("gvl_waiting_threads")).to be_empty
102
- end
103
- end
104
-
105
- context "when the process name is a custom value" do
106
- before do
107
- FakeGVLTools::WaitingThreads.enabled = true
108
- end
109
-
110
- it "uses only the first word as the process name" do
111
- $PROGRAM_NAME = "sidekiq 7.1.6 app [0 of 5 busy]"
112
- probe.call
113
-
114
- expect(gauges_for("gvl_waiting_threads")).to eq [
115
- [0, {
116
- :hostname => hostname,
117
- :process_name => "sidekiq",
118
- :process_id => Process.pid
119
- }],
120
- [0, { :hostname => hostname }]
121
- ]
122
- end
123
- end
124
-
125
- context "when the process name is a path" do
126
- before do
127
- FakeGVLTools::WaitingThreads.enabled = true
128
- end
129
-
130
- it "uses only the binary name as the process name" do
131
- $PROGRAM_NAME = "/foo/folder with spaces/bin/rails"
132
- probe.call
133
-
134
- expect(gauges_for("gvl_waiting_threads")).to eq [
135
- [0, {
136
- :hostname => hostname,
137
- :process_name => "rails",
138
- :process_id => Process.pid
139
- }],
140
- [0, { :hostname => hostname }]
141
- ]
142
- end
143
- end
144
-
145
- context "when the process name is an empty string" do
146
- before do
147
- FakeGVLTools::WaitingThreads.enabled = true
148
- end
149
-
150
- it "uses [unknown process] as the process name" do
151
- $PROGRAM_NAME = ""
152
- probe.call
153
-
154
- expect(gauges_for("gvl_waiting_threads")).to eq [
155
- [0, {
156
- :hostname => hostname,
157
- :process_name => "[unknown process]",
158
- :process_id => Process.pid
159
- }],
160
- [0, { :hostname => hostname }]
161
- ]
162
- end
163
- end
164
- end
@@ -1,162 +0,0 @@
1
- describe Appsignal::Probes::MriProbe do
2
- let(:appsignal_mock) { AppsignalMock.new(:hostname => hostname) }
3
- let(:gc_profiler_mock) { instance_double("Appsignal::GarbageCollectionProfiler") }
4
- let(:probe) do
5
- described_class.new(:appsignal => appsignal_mock, :gc_profiler => gc_profiler_mock)
6
- end
7
-
8
- describe ".dependencies_present?" do
9
- if DependencyHelper.running_jruby?
10
- it "should not be present" do
11
- expect(described_class.dependencies_present?).to be_falsy
12
- end
13
- else
14
- it "should be present" do
15
- expect(described_class.dependencies_present?).to be_truthy
16
- end
17
- end
18
- end
19
-
20
- unless DependencyHelper.running_jruby?
21
- describe "#call" do
22
- let(:hostname) { nil }
23
- before do
24
- allow(gc_profiler_mock).to receive(:total_time)
25
- allow(GC::Profiler).to receive(:enabled?).and_return(true)
26
- end
27
-
28
- it "should track vm cache metrics" do
29
- probe.call
30
- if DependencyHelper.ruby_3_2_or_newer?
31
- expect_gauge_value("ruby_vm", :tags => { :metric => :constant_cache_invalidations })
32
- expect_gauge_value("ruby_vm", :tags => { :metric => :constant_cache_misses })
33
- else
34
- expect_gauge_value("ruby_vm", :tags => { :metric => :class_serial })
35
- expect_gauge_value("ruby_vm", :tags => { :metric => :global_constant_state })
36
- end
37
- end
38
-
39
- it "tracks thread counts" do
40
- probe.call
41
- expect_gauge_value("thread_count")
42
- end
43
-
44
- it "tracks GC time between measurements" do
45
- expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15)
46
- probe.call
47
- probe.call
48
- expect_gauge_value("gc_time", 5)
49
- end
50
-
51
- context "when GC total time overflows" do
52
- it "skips one report" do
53
- expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15, 0, 10)
54
- probe.call # Normal call, create a cache
55
- probe.call # Report delta value based on cached value
56
- probe.call # The value overflows and reports no value. Then stores 0 in the cache
57
- probe.call # Report new value based on cache of 0
58
- expect_gauges([["gc_time", 5], ["gc_time", 10]])
59
- end
60
- end
61
-
62
- context "when GC profiling is disabled" do
63
- it "does not report a gc_time metric" do
64
- allow(GC::Profiler).to receive(:enabled?).and_return(false)
65
- expect(gc_profiler_mock).to_not receive(:total_time)
66
- probe.call # Normal call, create a cache
67
- probe.call # Report delta value based on cached value
68
- metrics = appsignal_mock.gauges.map { |(key)| key }
69
- expect(metrics).to_not include("gc_time")
70
- end
71
-
72
- it "does not report a gc_time metric while temporarily disabled" do
73
- # While enabled
74
- allow(GC::Profiler).to receive(:enabled?).and_return(true)
75
- expect(gc_profiler_mock).to receive(:total_time).and_return(10, 15)
76
- probe.call # Normal call, create a cache
77
- probe.call # Report delta value based on cached value
78
- expect_gauges([["gc_time", 5]])
79
-
80
- # While disabled
81
- allow(GC::Profiler).to receive(:enabled?).and_return(false)
82
- probe.call # Call twice to make sure any caches resets wouldn't mess up the assertion
83
- probe.call
84
- # Does not include any newly reported metrics
85
- expect_gauges([["gc_time", 5]])
86
-
87
- # When enabled after being disabled for a while, it only reports the
88
- # newly reported time since it was renabled
89
- allow(GC::Profiler).to receive(:enabled?).and_return(true)
90
- expect(gc_profiler_mock).to receive(:total_time).and_return(25)
91
- probe.call
92
- expect_gauges([["gc_time", 5], ["gc_time", 10]])
93
- end
94
- end
95
-
96
- it "tracks GC run count" do
97
- expect(GC).to receive(:count).and_return(10, 15)
98
- expect(GC).to receive(:stat).and_return(
99
- { :minor_gc_count => 10, :major_gc_count => 10 },
100
- :minor_gc_count => 16, :major_gc_count => 17
101
- )
102
- probe.call
103
- probe.call
104
- expect_gauge_value("gc_count", 5, :tags => { :metric => :gc_count })
105
- expect_gauge_value("gc_count", 6, :tags => { :metric => :minor_gc_count })
106
- expect_gauge_value("gc_count", 7, :tags => { :metric => :major_gc_count })
107
- end
108
-
109
- it "tracks object allocation" do
110
- expect(GC).to receive(:stat).and_return(
111
- { :total_allocated_objects => 10 },
112
- :total_allocated_objects => 15
113
- )
114
- # Only tracks delta value so the needs to be called twice
115
- probe.call
116
- probe.call
117
- expect_gauge_value("allocated_objects", 5)
118
- end
119
-
120
- it "tracks heap slots" do
121
- probe.call
122
- expect_gauge_value("heap_slots", :tags => { :metric => :heap_live })
123
- expect_gauge_value("heap_slots", :tags => { :metric => :heap_free })
124
- end
125
-
126
- context "with custom hostname" do
127
- let(:hostname) { "my hostname" }
128
-
129
- it "reports custom hostname tag value" do
130
- probe.call
131
- expect_gauge_value("heap_slots",
132
- :tags => { :metric => :heap_live, :hostname => hostname })
133
- end
134
- end
135
- end
136
- end
137
-
138
- def expect_gauge_value(expected_key, expected_value = nil, tags: {})
139
- expected_tags = { :hostname => Socket.gethostname }.merge(tags)
140
- expect(appsignal_mock.gauges).to satisfy do |gauges|
141
- gauges.any? do |distribution_value|
142
- key, value, tags = distribution_value
143
- next unless key == expected_key
144
- next unless expected_value ? expected_value == value : !value.nil?
145
- next unless tags == expected_tags
146
-
147
- true
148
- end
149
- end
150
- end
151
-
152
- def expect_gauges(expected_metrics)
153
- default_tags = { :hostname => Socket.gethostname }
154
- keys = expected_metrics.map { |(key)| key }
155
- metrics = expected_metrics.map do |metric|
156
- key, value, tags = metric
157
- [key, value, default_tags.merge(tags || {})]
158
- end
159
- found_gauges = appsignal_mock.gauges.select { |(key)| keys.include? key }
160
- expect(found_gauges).to eq(metrics)
161
- end
162
- end