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.
- checksums.yaml +4 -4
- data/.semaphore/semaphore.yml +1 -1
- data/CHANGELOG.md +3 -12
- data/README.md +4 -4
- data/appsignal.gemspec +1 -1
- data/build_matrix.yml +2 -2
- data/ext/agent.yml +19 -19
- data/ext/appsignal_extension.c +10 -1
- data/lib/appsignal.rb +21 -1
- data/lib/appsignal/capistrano.rb +2 -0
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +8 -38
- data/lib/appsignal/environment.rb +126 -0
- data/lib/appsignal/extension/jruby.rb +10 -0
- data/lib/appsignal/hooks/net_http.rb +2 -0
- data/lib/appsignal/hooks/redis.rb +2 -0
- data/lib/appsignal/hooks/sequel.rb +2 -0
- data/lib/appsignal/integrations/object.rb +4 -0
- data/lib/appsignal/integrations/resque_active_job.rb +2 -0
- data/lib/appsignal/rack/js_exception_catcher.rb +2 -5
- data/lib/appsignal/transaction.rb +22 -7
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
- data/spec/lib/appsignal/capistrano3_spec.rb +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +0 -42
- data/spec/lib/appsignal/config_spec.rb +5 -24
- data/spec/lib/appsignal/environment_spec.rb +167 -0
- data/spec/lib/appsignal/marker_spec.rb +1 -1
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +4 -9
- data/spec/lib/appsignal/transaction_spec.rb +30 -13
- data/spec/lib/appsignal_spec.rb +22 -0
- data/spec/support/helpers/config_helpers.rb +2 -3
- data/spec/support/helpers/env_helpers.rb +1 -1
- data/spec/support/helpers/environment_metdata_helper.rb +16 -0
- metadata +10 -5
@@ -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
|
@@ -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
|
33
|
-
"
|
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
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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.
|
data/lib/appsignal/version.rb
CHANGED
@@ -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, "
|
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, "
|
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
|
-
:
|
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["
|
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
|