appsignal 3.7.0 → 3.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -87,7 +87,7 @@ describe Appsignal do
87
87
  end
88
88
 
89
89
  it "should start minutely" do
90
- expect(Appsignal::Minutely).to receive(:start)
90
+ expect(Appsignal::Probes).to receive(:start)
91
91
  Appsignal.start
92
92
  end
93
93
  end
@@ -98,7 +98,7 @@ describe Appsignal do
98
98
  end
99
99
 
100
100
  it "should not start minutely" do
101
- expect(Appsignal::Minutely).to_not receive(:start)
101
+ expect(Appsignal::Probes).to_not receive(:start)
102
102
  Appsignal.start
103
103
  end
104
104
  end
@@ -151,13 +151,20 @@ describe Appsignal do
151
151
  end
152
152
 
153
153
  describe ".stop" do
154
- it "should call stop on the extension" do
154
+ it "calls stop on the extension" do
155
155
  expect(Appsignal.internal_logger).to receive(:debug).with("Stopping appsignal")
156
156
  expect(Appsignal::Extension).to receive(:stop)
157
157
  Appsignal.stop
158
158
  expect(Appsignal.active?).to be_falsy
159
159
  end
160
160
 
161
+ it "stops the minutely probes" do
162
+ Appsignal::Probes.start
163
+ expect(Appsignal::Probes.started?).to be_truthy
164
+ Appsignal.stop
165
+ expect(Appsignal::Probes.started?).to be_falsy
166
+ end
167
+
161
168
  context "with context specified" do
162
169
  it "should log the context" do
163
170
  expect(Appsignal.internal_logger).to receive(:debug).with("Stopping appsignal (something)")
@@ -1121,7 +1128,14 @@ describe Appsignal do
1121
1128
  let(:log_path) { File.join(tmp_dir, "log") }
1122
1129
  let(:log_file) { File.join(log_path, "appsignal.log") }
1123
1130
 
1124
- before { FileUtils.mkdir_p(log_path) }
1131
+ before do
1132
+ FileUtils.mkdir_p(log_path)
1133
+ # Clear state from previous test
1134
+ Appsignal.internal_logger = nil
1135
+ if Appsignal.instance_variable_defined?(:@in_memory_log)
1136
+ Appsignal.remove_instance_variable(:@in_memory_log)
1137
+ end
1138
+ end
1125
1139
  after { FileUtils.rm_rf(log_path) }
1126
1140
 
1127
1141
  def initialize_config
@@ -1130,6 +1144,7 @@ describe Appsignal do
1130
1144
  :log_path => log_path
1131
1145
  )
1132
1146
  Appsignal.internal_logger.error("Log in memory")
1147
+ expect(Appsignal.in_memory_log.string).to_not be_empty
1133
1148
  end
1134
1149
 
1135
1150
  context "when the log path is writable" do
@@ -1154,6 +1169,10 @@ describe Appsignal do
1154
1169
  it "amends in memory log to log file" do
1155
1170
  expect(log_file_contents).to include "[ERROR] appsignal: Log in memory"
1156
1171
  end
1172
+
1173
+ it "clears the in memory log after writing to the new logger" do
1174
+ expect(Appsignal.in_memory_log.string).to be_empty
1175
+ end
1157
1176
  end
1158
1177
 
1159
1178
  context "when the log file is not writable" do
@@ -1178,8 +1197,11 @@ describe Appsignal do
1178
1197
  expect(output).to include "[ERROR] appsignal: Log in memory"
1179
1198
  end
1180
1199
 
1200
+ it "clears the in memory log after writing to the new logger" do
1201
+ expect(Appsignal.in_memory_log.string).to be_empty
1202
+ end
1203
+
1181
1204
  it "outputs a warning" do
1182
- puts output
1183
1205
  expect(output).to include \
1184
1206
  "[WARN] appsignal: Unable to start internal logger with log path '#{log_file}'.",
1185
1207
  "[WARN] appsignal: Permission denied"
@@ -1237,6 +1259,10 @@ describe Appsignal do
1237
1259
  it "amends in memory log to stdout" do
1238
1260
  expect(output).to include "[ERROR] appsignal: Log in memory"
1239
1261
  end
1262
+
1263
+ it "clears the in memory log after writing to the new logger" do
1264
+ expect(Appsignal.in_memory_log.string).to be_empty
1265
+ end
1240
1266
  end
1241
1267
 
1242
1268
  describe "#logger#level" do
@@ -32,10 +32,14 @@ RSpec.describe "Puma plugin" do
32
32
  # StatsD server used for these tests.
33
33
  # Open a UDPSocket and listen for messages sent by the AppSignal Puma plugin.
34
34
  class StatsdServer
35
+ def initialize(statsd_port)
36
+ @statsd_port = statsd_port
37
+ end
38
+
35
39
  def start
36
40
  stop
37
41
  @socket = UDPSocket.new
38
- @socket.bind("127.0.0.1", 8125)
42
+ @socket.bind("127.0.0.1", @statsd_port)
39
43
 
40
44
  loop do
41
45
  # Listen for messages and track them on the messages Array.
@@ -115,13 +119,15 @@ RSpec.describe "Puma plugin" do
115
119
 
116
120
  def run_plugin(stats_data, plugin, &block)
117
121
  Puma._set_stats = stats_data
118
- @statsd = StatsdServer.new
122
+ ENV["APPSIGNAL_STATSD_PORT"] = "8126"
123
+ @statsd = StatsdServer.new(ENV.fetch("APPSIGNAL_STATSD_PORT"))
119
124
  @server_thread = Thread.new { @statsd.start }
120
125
  @server_thread.abort_on_exception = true
121
126
  @client_thread = Thread.new { start_plugin(plugin) }
122
127
  @client_thread.abort_on_exception = true
123
128
  wait_for(:puma_client_wait, &block)
124
129
  ensure
130
+ ENV["APPSIGNAL_STATSD_PORT"] = nil
125
131
  Puma._set_stats = nil
126
132
  # Stop all threads in test and stop listening on the UDPSocket
127
133
  @client_thread.kill if defined?(@client_thread) && @client_thread
data/spec/spec_helper.rb CHANGED
@@ -171,11 +171,11 @@ RSpec.configure do |config|
171
171
  def stop_minutely_probes
172
172
  thread =
173
173
  begin
174
- Appsignal::Minutely.class_variable_get(:@@thread) # Fetch old thread
174
+ Appsignal::Probes.class_variable_get(:@@thread) # Fetch old thread
175
175
  rescue NameError
176
176
  nil
177
177
  end
178
- Appsignal::Minutely.stop
178
+ Appsignal::Probes.stop
179
179
  thread&.join # Wait for old thread to exit
180
180
  end
181
181
  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.7.0
4
+ version: 3.7.2
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: 2024-04-22 00:00:00.000000000 Z
13
+ date: 2024-05-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack
@@ -263,7 +263,6 @@ files:
263
263
  - lib/appsignal/integrations/webmachine.rb
264
264
  - lib/appsignal/logger.rb
265
265
  - lib/appsignal/marker.rb
266
- - lib/appsignal/minutely.rb
267
266
  - lib/appsignal/probes.rb
268
267
  - lib/appsignal/probes/gvl.rb
269
268
  - lib/appsignal/probes/helpers.rb
@@ -279,12 +278,12 @@ files:
279
278
  - lib/appsignal/transmitter.rb
280
279
  - lib/appsignal/utils.rb
281
280
  - lib/appsignal/utils/data.rb
282
- - lib/appsignal/utils/deprecation_message.rb
283
281
  - lib/appsignal/utils/hash_sanitizer.rb
284
282
  - lib/appsignal/utils/integration_logger.rb
285
283
  - lib/appsignal/utils/json.rb
286
284
  - lib/appsignal/utils/query_params_sanitizer.rb
287
285
  - lib/appsignal/utils/rails_helper.rb
286
+ - lib/appsignal/utils/stdout_and_logger_message.rb
288
287
  - lib/appsignal/version.rb
289
288
  - lib/puma/plugin/appsignal.rb
290
289
  - lib/sequel/extensions/appsignal_integration.rb
@@ -364,10 +363,10 @@ files:
364
363
  - spec/lib/appsignal/integrations/webmachine_spec.rb
365
364
  - spec/lib/appsignal/logger_spec.rb
366
365
  - spec/lib/appsignal/marker_spec.rb
367
- - spec/lib/appsignal/minutely_spec.rb
368
366
  - spec/lib/appsignal/probes/gvl_spec.rb
369
367
  - spec/lib/appsignal/probes/mri_spec.rb
370
368
  - spec/lib/appsignal/probes/sidekiq_spec.rb
369
+ - spec/lib/appsignal/probes_spec.rb
371
370
  - spec/lib/appsignal/rack/generic_instrumentation_spec.rb
372
371
  - spec/lib/appsignal/rack/rails_instrumentation_spec.rb
373
372
  - spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb
@@ -453,7 +452,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
453
452
  - !ruby/object:Gem::Version
454
453
  version: '0'
455
454
  requirements: []
456
- rubygems_version: 3.3.7
455
+ rubygems_version: 3.5.9
457
456
  signing_key:
458
457
  specification_version: 4
459
458
  summary: Logs performance and exception data from your app to appsignal.com
@@ -1,206 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Appsignal
4
- class Minutely
5
- class ProbeCollection
6
- def initialize
7
- @probes = {}
8
- end
9
-
10
- # @return [Integer] Number of probes that are registered.
11
- def count
12
- probes.count
13
- end
14
-
15
- # Clears all probes from the list.
16
- # @return [void]
17
- def clear
18
- probes.clear
19
- end
20
-
21
- # Fetch a probe using its name.
22
- # @param key [Symbol/String] The name of the probe to fetch.
23
- # @return [Object] Returns the registered probe.
24
- def [](key)
25
- probes[key]
26
- end
27
-
28
- # Register a new minutely probe.
29
- #
30
- # Supported probe types are:
31
- #
32
- # - Lambda - A lambda is an object that listens to a `call` method call.
33
- # This `call` method is called every minute.
34
- # - Class - A class object is an object that listens to a `new` and
35
- # `call` method call. The `new` method is called when the Minutely
36
- # probe thread is started to initialize all probes. This allows probes
37
- # to load dependencies once beforehand. Their `call` method is called
38
- # every minute.
39
- # - Class instance - A class instance object is an object that listens to
40
- # a `call` method call. The `call` method is called every minute.
41
- #
42
- # @example Register a new probe
43
- # Appsignal::Minutely.probes.register :my_probe, lambda {}
44
- #
45
- # @example Overwrite an existing registered probe
46
- # Appsignal::Minutely.probes.register :my_probe, lambda {}
47
- # Appsignal::Minutely.probes.register :my_probe, lambda { puts "hello" }
48
- #
49
- # @example Add a lambda as a probe
50
- # Appsignal::Minutely.probes.register :my_probe, lambda { puts "hello" }
51
- # # "hello" # printed every minute
52
- #
53
- # @example Add a probe instance
54
- # class MyProbe
55
- # def initialize
56
- # puts "started"
57
- # end
58
- #
59
- # def call
60
- # puts "called"
61
- # end
62
- # end
63
- #
64
- # Appsignal::Minutely.probes.register :my_probe, MyProbe.new
65
- # # "started" # printed immediately
66
- # # "called" # printed every minute
67
- #
68
- # @example Add a probe class
69
- # class MyProbe
70
- # def initialize
71
- # # Add things that only need to be done on start up for this probe
72
- # require "some/library/dependency"
73
- # @cache = {} # initialize a local cache variable
74
- # puts "started"
75
- # end
76
- #
77
- # def call
78
- # puts "called"
79
- # end
80
- # end
81
- #
82
- # Appsignal::Minutely.probes.register :my_probe, MyProbe
83
- # Appsignal::Minutely.start # This is called for you
84
- # # "started" # Printed on Appsignal::Minutely.start
85
- # # "called" # Repeated every minute
86
- #
87
- # @param name [Symbol/String] Name of the probe. Can be used with {[]}.
88
- # This name will be used in errors in the log and allows overwriting of
89
- # probes by registering new ones with the same name.
90
- # @param probe [Object] Any object that listens to the `call` method will
91
- # be used as a probe.
92
- # @return [void]
93
- def register(name, probe)
94
- if probes.key?(name)
95
- logger.debug "A probe with the name `#{name}` is already " \
96
- "registered. Overwriting the entry with the new probe."
97
- end
98
- probes[name] = probe
99
- end
100
-
101
- # @api private
102
- def each(&block)
103
- probes.each(&block)
104
- end
105
-
106
- private
107
-
108
- attr_reader :probes
109
-
110
- def logger
111
- Appsignal.internal_logger
112
- end
113
- end
114
-
115
- class << self
116
- # @see ProbeCollection
117
- # @return [ProbeCollection] Returns list of probes.
118
- def probes
119
- @probes ||= ProbeCollection.new
120
- end
121
-
122
- # @api private
123
- def start
124
- stop
125
- @thread = Thread.new do
126
- # Advise multi-threaded app servers to ignore this thread
127
- # for the purposes of fork safety warnings
128
- if Thread.current.respond_to?(:thread_variable_set)
129
- Thread.current.thread_variable_set(:fork_safe, true)
130
- end
131
-
132
- sleep initial_wait_time
133
- initialize_probes
134
- loop do
135
- logger = Appsignal.internal_logger
136
- logger.debug("Gathering minutely metrics with #{probe_instances.count} probes")
137
- probe_instances.each do |name, probe|
138
- logger.debug("Gathering minutely metrics with '#{name}' probe")
139
- probe.call
140
- rescue => ex
141
- logger.error "Error in minutely probe '#{name}': #{ex}"
142
- logger.debug ex.backtrace.join("\n")
143
- end
144
- sleep wait_time
145
- end
146
- end
147
- end
148
-
149
- # @api private
150
- def stop
151
- defined?(@thread) && @thread.kill
152
- probe_instances.clear
153
- end
154
-
155
- # @api private
156
- def wait_time
157
- 60 - Time.now.sec
158
- end
159
-
160
- private
161
-
162
- def initial_wait_time
163
- remaining_seconds = 60 - Time.now.sec
164
- return remaining_seconds if remaining_seconds > 30
165
-
166
- remaining_seconds + 60
167
- end
168
-
169
- def initialize_probes
170
- probes.each do |name, probe|
171
- initialize_probe(name, probe)
172
- end
173
- end
174
-
175
- def initialize_probe(name, probe)
176
- if probe.respond_to? :new
177
- instance = probe.new
178
- klass = probe
179
- else
180
- instance = probe
181
- klass = instance.class
182
- end
183
- unless dependencies_present?(klass)
184
- Appsignal.internal_logger.debug "Skipping '#{name}' probe, " \
185
- "#{klass}.dependency_present? returned falsy"
186
- return
187
- end
188
- probe_instances[name] = instance
189
- rescue => error
190
- logger = Appsignal.internal_logger
191
- logger.error "Error while initializing minutely probe '#{name}': #{error}"
192
- logger.debug error.backtrace.join("\n")
193
- end
194
-
195
- def dependencies_present?(probe)
196
- return true unless probe.respond_to? :dependencies_present?
197
-
198
- probe.dependencies_present?
199
- end
200
-
201
- def probe_instances
202
- @probe_instances ||= {}
203
- end
204
- end
205
- end
206
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Appsignal
4
- module Utils
5
- module DeprecationMessage
6
- def self.message(message, logger = Appsignal.internal_logger)
7
- Kernel.warn "appsignal WARNING: #{message}"
8
- logger.warn message
9
- end
10
-
11
- def deprecation_message(message, logger = Appsignal.internal_logger)
12
- Appsignal::Utils::DeprecationMessage.message(message, logger)
13
- end
14
- end
15
- end
16
- end