appsignal 2.10.12-java → 2.11.0.alpha.1-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.
@@ -60,6 +60,9 @@ module Appsignal
60
60
  [:appsignal_string],
61
61
  :appsignal_string
62
62
  attach_function :appsignal_running_in_container, [], :bool
63
+ attach_function :appsignal_set_environment_metadata,
64
+ [:appsignal_string, :appsignal_string],
65
+ :void
63
66
 
64
67
  # Metrics methods
65
68
  attach_function :appsignal_set_gauge,
@@ -224,6 +227,13 @@ module Appsignal
224
227
  appsignal_running_in_container
225
228
  end
226
229
 
230
+ def set_environment_metadata(key, value)
231
+ appsignal_set_environment_metadata(
232
+ make_appsignal_string(key),
233
+ make_appsignal_string(value)
234
+ )
235
+ end
236
+
227
237
  def set_gauge(key, value, tags)
228
238
  appsignal_set_gauge(make_appsignal_string(key), value, tags.pointer)
229
239
  end
@@ -25,6 +25,8 @@ module Appsignal
25
25
  end
26
26
  end
27
27
  end
28
+
29
+ Appsignal::Environment.report_enabled("net_http")
28
30
  end
29
31
  end
30
32
  end
@@ -26,6 +26,8 @@ module Appsignal
26
26
  end
27
27
  end
28
28
  end
29
+
30
+ Appsignal::Environment.report_enabled("redis")
29
31
  end
30
32
  end
31
33
  end
@@ -56,6 +56,8 @@ module Appsignal
56
56
 
57
57
  # ... and automatically add it to future instances.
58
58
  ::Sequel::Database.extension(:appsignal_integration)
59
+
60
+ Appsignal::Environment.report_enabled("sequel")
59
61
  end
60
62
  end
61
63
  end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ if defined?(Appsignal)
4
+ Appsignal::Environment.report_enabled("object_instrumentation")
5
+ end
6
+
3
7
  class Object
4
8
  def self.appsignal_instrument_class_method(method_name, options = {})
5
9
  singleton_class.send \
@@ -34,6 +34,8 @@ module Appsignal
34
34
  end
35
35
  end
36
36
  end
37
+
38
+ Appsignal::Environment.report("ruby_active_job_resque_enabled") { true }
37
39
  end
38
40
  end
39
41
  end
@@ -29,11 +29,8 @@ module Appsignal
29
29
  Appsignal.logger.debug \
30
30
  "Initializing Appsignal::Rack::JSExceptionCatcher"
31
31
  deprecation_message "The Appsignal::Rack::JSExceptionCatcher is " \
32
- "deprecated and will be removed in a future version. Please use " \
33
- "the official AppSignal JavaScript integration by disabling " \
34
- "`enable_frontend_error_catching` in your configuration and " \
35
- "installing AppSignal for JavaScript instead. " \
36
- "(https://docs.appsignal.com/front-end/)"
32
+ "deprecated. Please use the official AppSignal JavaScript " \
33
+ "integration instead. https://docs.appsignal.com/front-end/"
37
34
  @app = app
38
35
  end
39
36
 
@@ -228,12 +228,27 @@ module Appsignal
228
228
  Appsignal.logger.warn("Queue start value #{start} is too big")
229
229
  end
230
230
 
231
+ # Set the queue time based on the HTTP header or `:queue_start` env key
232
+ # value.
233
+ #
234
+ # This method will first try to read the queue time from the HTTP headers
235
+ # `X-Request-Start` or `X-Queue-Start`. Which are parsed by Rack as
236
+ # `HTTP_X_QUEUE_START` and `HTTP_X_REQUEST_START`.
237
+ # The header value is parsed by AppSignal as either milliseconds or
238
+ # microseconds.
239
+ #
240
+ # If no headers are found, or the value could not be parsed, it falls back
241
+ # on the `:queue_start` env key on this Transaction's {request} environment
242
+ # (called like `request.env[:queue_start]`). This value is parsed by
243
+ # AppSignal as seconds.
244
+ #
245
+ # @see https://docs.appsignal.com/ruby/instrumentation/request-queue-time.html
246
+ # @return [void]
231
247
  def set_http_or_background_queue_start
232
- if namespace == HTTP_REQUEST
233
- set_queue_start(http_queue_start)
234
- elsif namespace == BACKGROUND_JOB
235
- set_queue_start(background_queue_start)
236
- end
248
+ start = http_queue_start || background_queue_start
249
+ return unless start
250
+
251
+ set_queue_start(start)
237
252
  end
238
253
 
239
254
  def set_metadata(key, value)
@@ -346,14 +361,14 @@ module Appsignal
346
361
  #
347
362
  # @return [nil] if no {#environment} is present.
348
363
  # @return [nil] if there is no `:queue_start` in the {#environment}.
349
- # @return [Integer]
364
+ # @return [Integer] `:queue_start` time (in seconds) converted to milliseconds
350
365
  def background_queue_start
351
366
  env = environment
352
367
  return unless env
353
368
  queue_start = env[:queue_start]
354
369
  return unless queue_start
355
370
 
356
- (queue_start.to_f * 1000.0).to_i
371
+ (queue_start.to_f * 1000.0).to_i # Convert seconds to milliseconds
357
372
  end
358
373
 
359
374
  # Returns HTTP queue start time in milliseconds.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "2.10.12".freeze
4
+ VERSION = "2.11.0.alpha.1".freeze
5
5
  end
@@ -10,7 +10,7 @@ if DependencyHelper.capistrano2_present?
10
10
  let(:capistrano_config) do
11
11
  Capistrano::Configuration.new.tap do |c|
12
12
  c.set(:rails_env, "production")
13
- c.set(:repository, "main")
13
+ c.set(:repository, "master")
14
14
  c.set(:deploy_to, "/home/username/app")
15
15
  c.set(:current_release, "")
16
16
  c.set(:current_revision, "503ce0923ed177a3ce000005")
@@ -15,7 +15,7 @@ if DependencyHelper.capistrano3_present?
15
15
  c.set(:log_level, :error)
16
16
  c.set(:logger, logger)
17
17
  c.set(:rails_env, "production")
18
- c.set(:repository, "main")
18
+ c.set(:repository, "master")
19
19
  c.set(:deploy_to, "/home/username/app")
20
20
  c.set(:current_release, "")
21
21
  c.set(:current_revision, "503ce0923ed177a3ce000005")
@@ -290,8 +290,6 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
290
290
  jruby = Appsignal::System.jruby?
291
291
  expect(output).to include(
292
292
  "Extension installation report",
293
- "Installation result",
294
- " Status: success",
295
293
  "Language details",
296
294
  " Implementation: #{jruby ? "jruby" : "ruby"}",
297
295
  " Ruby version: #{"#{rbconfig["ruby_version"]}-p#{rbconfig["PATCHLEVEL"]}"}",
@@ -312,46 +310,6 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
312
310
  )
313
311
  end
314
312
 
315
- context "with error in install report" do
316
- let(:error) { RuntimeError.new("some error") }
317
- before do
318
- allow(File).to receive(:read).and_call_original
319
- expect(File).to receive(:read)
320
- .with(File.expand_path("../../../../../ext/install.report", __FILE__))
321
- .and_return(
322
- YAML.dump(
323
- "result" => {
324
- "status" => "error",
325
- "error" => "RuntimeError: some error",
326
- "backtrace" => error.backtrace
327
- }
328
- )
329
- )
330
- end
331
-
332
- it "sends an error" do
333
- run
334
- expect(received_report["installation"]).to match(
335
- "result" => {
336
- "status" => "error",
337
- "error" => "RuntimeError: some error",
338
- "backtrace" => error.backtrace
339
- }
340
- )
341
- end
342
-
343
- it "prints the error" do
344
- run
345
-
346
- expect(output).to include(
347
- "Extension installation report",
348
- "Installation result",
349
- "Status: error\n Error: RuntimeError: some error"
350
- )
351
- expect(output).to_not include("Raw report:")
352
- end
353
- end
354
-
355
313
  context "without install report" do
356
314
  let(:error) { RuntimeError.new("foo") }
357
315
  before do
@@ -148,6 +148,7 @@ describe Appsignal::Config do
148
148
  :instrument_redis => true,
149
149
  :instrument_sequel => true,
150
150
  :skip_session_data => false,
151
+ :send_environment_metadata => true,
151
152
  :send_params => true,
152
153
  :endpoint => "https://push.appsignal.com",
153
154
  :push_api_key => "abc",
@@ -243,27 +244,6 @@ describe Appsignal::Config do
243
244
  end
244
245
  end
245
246
 
246
- context "with an overriden config file" do
247
- let(:config) do
248
- project_fixture_config("production", {}, Appsignal.logger, File.join(project_fixture_path, "config", "appsignal.yml"))
249
- end
250
-
251
- it "is valid and active" do
252
- expect(config.valid?).to be_truthy
253
- expect(config.active?).to be_truthy
254
- end
255
-
256
- context "with an invalid overriden config file" do
257
- let(:config) do
258
- project_fixture_config("production", {}, Appsignal.logger, File.join(project_fixture_path, "config", "missing.yml"))
259
- end
260
-
261
- it "is not valid" do
262
- expect(config.valid?).to be_falsy
263
- end
264
- end
265
- end
266
-
267
247
  context "with the config file causing an error" do
268
248
  let(:config_path) do
269
249
  File.expand_path(
@@ -417,7 +397,6 @@ describe Appsignal::Config do
417
397
  :debug => true
418
398
  )
419
399
  end
420
- let(:working_directory_path) { File.join(tmp_dir, "test_working_directory_path") }
421
400
  let(:env_config) do
422
401
  {
423
402
  :running_in_container => true,
@@ -434,7 +413,7 @@ describe Appsignal::Config do
434
413
  :files_world_accessible => false,
435
414
  :request_headers => %w[accept accept-charset],
436
415
  :revision => "v2.5.1",
437
- :working_directory_path => working_directory_path
416
+ :send_environment_metadata => false
438
417
  }
439
418
  end
440
419
  before do
@@ -451,7 +430,7 @@ describe Appsignal::Config do
451
430
  ENV["APPSIGNAL_INSTRUMENT_SEQUEL"] = "false"
452
431
  ENV["APPSIGNAL_FILES_WORLD_ACCESSIBLE"] = "false"
453
432
  ENV["APPSIGNAL_REQUEST_HEADERS"] = "accept,accept-charset"
454
- ENV["APPSIGNAL_WORKING_DIRECTORY_PATH"] = working_directory_path
433
+ ENV["APPSIGNAL_SEND_ENVIRONMENT_METADATA"] = "false"
455
434
  ENV["APP_REVISION"] = "v2.5.1"
456
435
  end
457
436
 
@@ -551,6 +530,7 @@ describe Appsignal::Config do
551
530
  config[:running_in_container] = false
552
531
  config[:dns_servers] = ["8.8.8.8", "8.8.4.4"]
553
532
  config[:transaction_debug_mode] = true
533
+ config[:send_environment_metadata] = false
554
534
  config[:revision] = "v2.5.1"
555
535
  config.write_to_environment
556
536
  end
@@ -579,6 +559,7 @@ describe Appsignal::Config do
579
559
  expect(ENV["_APPSIGNAL_DNS_SERVERS"]).to eq "8.8.8.8,8.8.4.4"
580
560
  expect(ENV["_APPSIGNAL_FILES_WORLD_ACCESSIBLE"]).to eq "true"
581
561
  expect(ENV["_APPSIGNAL_TRANSACTION_DEBUG_MODE"]).to eq "true"
562
+ expect(ENV["_APPSIGNAL_SEND_ENVIRONMENT_METADATA"]).to eq "false"
582
563
  expect(ENV["_APP_REVISION"]).to eq "v2.5.1"
583
564
  expect(ENV).to_not have_key("_APPSIGNAL_WORKING_DIR_PATH")
584
565
  expect(ENV).to_not have_key("_APPSIGNAL_WORKING_DIRECTORY_PATH")
@@ -0,0 +1,167 @@
1
+ describe Appsignal::Environment do
2
+ include EnvironmentMetadataHelper
3
+
4
+ before(:context) { start_agent }
5
+ before { capture_environment_metadata_report_calls }
6
+
7
+ def report(key, &value_block)
8
+ described_class.report(key, &value_block)
9
+ end
10
+
11
+ describe ".report" do
12
+ it "sends environment metadata to the extension" do
13
+ logs =
14
+ capture_logs do
15
+ report("_test_ruby_version") { "1.0.0" }
16
+ expect_environment_metadata("_test_ruby_version", "1.0.0")
17
+ end
18
+ expect(logs).to be_empty
19
+ end
20
+
21
+ context "when the key is a non String type" do
22
+ it "does not set the value" do
23
+ logs =
24
+ capture_logs do
25
+ report(:_test_symbol) { "1.0.0" }
26
+ expect_not_environment_metadata(:_test_symbol)
27
+ expect_not_environment_metadata("_test_symbol")
28
+ end
29
+ expect(logs).to contains_log(
30
+ :error,
31
+ "Unable to report on environment metadata: Unsupported value type for :_test_symbol"
32
+ )
33
+ end
34
+ end
35
+
36
+ context "when the key is nil" do
37
+ it "does not set the value" do
38
+ logs =
39
+ capture_logs do
40
+ report(nil) { "1" }
41
+ expect_not_environment_metadata(nil)
42
+ end
43
+ expect(logs).to contains_log(
44
+ :error,
45
+ "Unable to report on environment metadata: Unsupported value type for nil"
46
+ )
47
+ end
48
+ end
49
+
50
+ context "when the value is true or false" do
51
+ it "reports true or false as Strings" do
52
+ logs =
53
+ capture_logs do
54
+ report("_test_true") { true }
55
+ report("_test_false") { false }
56
+ expect_environment_metadata("_test_true", "true")
57
+ expect_environment_metadata("_test_false", "false")
58
+ end
59
+ expect(logs).to be_empty
60
+ end
61
+ end
62
+
63
+ context "when the value is nil" do
64
+ it "does not set the value" do
65
+ logs =
66
+ capture_logs do
67
+ report("_test_ruby_version") { nil }
68
+ expect_not_environment_metadata("_test_ruby_version")
69
+ end
70
+ expect(logs).to contains_log(
71
+ :error,
72
+ "Unable to report on environment metadata \"_test_ruby_version\": " \
73
+ "Unsupported value type for nil"
74
+ )
75
+ end
76
+ end
77
+
78
+ context "when the value block raises an error" do
79
+ it "does not re-raise the error and writes it to the log" do
80
+ logs =
81
+ capture_logs do
82
+ report("_test_error") { raise "uh oh" }
83
+ expect_not_environment_metadata("_test_error")
84
+ end
85
+ expect(logs).to contains_log(
86
+ :error,
87
+ "Unable to report on environment metadata \"_test_error\":\n" \
88
+ "RuntimeError: uh oh"
89
+ )
90
+ end
91
+ end
92
+
93
+ context "when something unforseen errors" do
94
+ it "does not re-raise the error and writes it to the log" do
95
+ klass = Class.new do
96
+ def inspect
97
+ raise "inspect error"
98
+ end
99
+ end
100
+
101
+ logs =
102
+ capture_logs do
103
+ report(klass.new) { raise "value error" }
104
+ expect(Appsignal::Extension).to_not have_received(:set_environment_metadata)
105
+ end
106
+ expect(logs).to contains_log(
107
+ :error,
108
+ "Unable to report on environment metadata:\n" \
109
+ "RuntimeError: inspect error"
110
+ )
111
+ end
112
+ end
113
+ end
114
+
115
+ describe ".report_supported_gems" do
116
+ it "reports about all AppSignal supported gems in the bundle" do
117
+ logs = capture_logs { described_class.report_supported_gems }
118
+
119
+ expect(logs).to be_empty
120
+
121
+ bundle_gem_specs = ::Bundler.rubygems.all_specs
122
+ rack_spec = bundle_gem_specs.find { |s| s.name == "rack" }
123
+ rake_spec = bundle_gem_specs.find { |s| s.name == "rake" }
124
+ expect_environment_metadata("ruby_rack_version", rack_spec.version.to_s)
125
+ expect_environment_metadata("ruby_rake_version", rake_spec.version.to_s)
126
+ expect(rack_spec.version.to_s).to_not be_empty
127
+ expect(rake_spec.version.to_s).to_not be_empty
128
+ end
129
+
130
+ context "when something unforseen errors" do
131
+ it "does not re-raise the error and writes it to the log" do
132
+ expect(Bundler).to receive(:rubygems).and_raise(RuntimeError, "bundler error")
133
+
134
+ logs = capture_logs { described_class.report_supported_gems }
135
+ expect(logs).to contains_log(
136
+ :error,
137
+ "Unable to report supported gems:\nRuntimeError: bundler error"
138
+ )
139
+ end
140
+ end
141
+ end
142
+
143
+ describe ".report_enabled" do
144
+ it "reports a feature being enabled" do
145
+ logs = capture_logs { described_class.report_enabled("a_test") }
146
+
147
+ expect(logs).to be_empty
148
+ expect_environment_metadata("ruby_a_test_enabled", "true")
149
+ end
150
+
151
+ context "when something unforseen errors" do
152
+ it "does not re-raise the error and writes it to the log" do
153
+ klass = Class.new do
154
+ def to_s
155
+ raise "to_s error"
156
+ end
157
+ end
158
+
159
+ logs = capture_logs { described_class.report_enabled(klass.new) }
160
+ expect(logs).to contains_log(
161
+ :error,
162
+ "Unable to report integration enabled:\nRuntimeError: to_s error"
163
+ )
164
+ end
165
+ end
166
+ end
167
+ end