appsignal 3.4.4-java → 3.4.6-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/CHANGELOG.md +26 -0
- data/lib/appsignal/config.rb +3 -0
- data/lib/appsignal/rack/sinatra_instrumentation.rb +3 -2
- data/lib/appsignal/transaction.rb +17 -5
- data/lib/appsignal/utils/hash_sanitizer.rb +21 -9
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +1 -0
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +163 -71
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +1 -0
- data/spec/lib/appsignal/transaction_spec.rb +38 -4
- data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +42 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af3d35d071f1564b0cbdaf41dbc8d28578aa4bef90ac880a3731b227fb067643
|
4
|
+
data.tar.gz: 69d319fa4870d64c3e54bb78f12c643934bb0a17c20145dcc373b52defcea554
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a977d7886759656795f443e7488420708c54e1086701f55a3d17aec8f22c1a50a54068b2a63b0e804433913f79aee7927e02bd97890cb055ef0abd7015ece32f
|
7
|
+
data.tar.gz: e23e971908c575908983bd7f16ed6321f559799af5e6442766208532a117722dc51d245b11d723a08a22e348b18cbec6f2911f52abe598df87be24cc2aea1743
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
# AppSignal for Ruby gem Changelog
|
2
2
|
|
3
|
+
## 3.4.6
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
|
7
|
+
- [85c155a0](https://github.com/appsignal/appsignal-ruby/commit/85c155a0a4b2b618c04db52c34ee7f0adba8f3c5) patch - When sanitizing an array or hash, replace recursively nested values with a placeholder string. This fixes a SystemStackError issue when sanitising arrays and hashes.
|
8
|
+
|
9
|
+
## 3.4.5
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- [e5e79d9a](https://github.com/appsignal/appsignal-ruby/commit/e5e79d9aa17006a6995e9ea18fabdc14a2356c82) patch - Add `filter_metadata` config option to filter metadata set on Transactions set by default. Metadata like `path`, (request) `method`, `request_id`, `hostname`, etc. This can be useful if there's PII or other sensitive data in any of the app's metadata.
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
|
17
|
+
- [5a4797c8](https://github.com/appsignal/appsignal-ruby/commit/5a4797c8560c2d1e60b4f1a750136c906505746c) patch - Fix Sinatra request custom request parameters method. If the Sinatra option `params_method` is set, a different method than `params` will be called on the request object to fetch the request parameters. This can be used to add custom filtering to parameters recorded by AppSignal.
|
18
|
+
- [9cdee8aa](https://github.com/appsignal/appsignal-ruby/commit/9cdee8aae3cb7b969583493440469ac0dfea764f) patch - Log error when the argument type of the breadcrumb metadata is invalid. This metadata argument should be a Hash, and other values are not supported. More information can be found in the [Ruby gem breadcrumb documentation](https://docs.appsignal.com/ruby/instrumentation/breadcrumbs.html).
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
Appsignal.add_breadcrumb(
|
22
|
+
"breadcrumb category",
|
23
|
+
"breadcrumb action",
|
24
|
+
"some message",
|
25
|
+
{ :metadata_key => "some value" } # This needs to be a Hash object
|
26
|
+
)
|
27
|
+
```
|
28
|
+
|
3
29
|
## 3.4.4
|
4
30
|
|
5
31
|
### Fixed
|
data/lib/appsignal/config.rb
CHANGED
@@ -24,6 +24,7 @@ module Appsignal
|
|
24
24
|
:enable_rails_error_reporter => true,
|
25
25
|
:endpoint => "https://push.appsignal.com",
|
26
26
|
:files_world_accessible => true,
|
27
|
+
:filter_metadata => [],
|
27
28
|
:filter_parameters => [],
|
28
29
|
:filter_session_data => [],
|
29
30
|
:ignore_actions => [],
|
@@ -77,6 +78,7 @@ module Appsignal
|
|
77
78
|
"APPSIGNAL_ENABLE_GVL_WAITING_THREADS" => :enable_gvl_waiting_threads,
|
78
79
|
"APPSIGNAL_ENABLE_RAILS_ERROR_REPORTER" => :enable_rails_error_reporter,
|
79
80
|
"APPSIGNAL_FILES_WORLD_ACCESSIBLE" => :files_world_accessible,
|
81
|
+
"APPSIGNAL_FILTER_METADATA" => :filter_metadata,
|
80
82
|
"APPSIGNAL_FILTER_PARAMETERS" => :filter_parameters,
|
81
83
|
"APPSIGNAL_FILTER_SESSION_DATA" => :filter_session_data,
|
82
84
|
"APPSIGNAL_HOSTNAME" => :hostname,
|
@@ -150,6 +152,7 @@ module Appsignal
|
|
150
152
|
# @api private
|
151
153
|
ENV_ARRAY_KEYS = %w[
|
152
154
|
APPSIGNAL_DNS_SERVERS
|
155
|
+
APPSIGNAL_FILTER_METADATA
|
153
156
|
APPSIGNAL_FILTER_PARAMETERS
|
154
157
|
APPSIGNAL_FILTER_SESSION_DATA
|
155
158
|
APPSIGNAL_IGNORE_ACTIONS
|
@@ -47,13 +47,14 @@ module Appsignal
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def call_with_appsignal_monitoring(env)
|
50
|
-
|
50
|
+
options = { :force => @options.include?(:force) && @options[:force] }
|
51
|
+
options.merge!(:params_method => @options[:params_method]) if @options[:params_method]
|
51
52
|
request = @options.fetch(:request_class, Sinatra::Request).new(env)
|
52
53
|
transaction = Appsignal::Transaction.create(
|
53
54
|
SecureRandom.uuid,
|
54
55
|
Appsignal::Transaction::HTTP_REQUEST,
|
55
56
|
request,
|
56
|
-
|
57
|
+
options
|
57
58
|
)
|
58
59
|
begin
|
59
60
|
Appsignal.instrument("process_action.sinatra") do
|
@@ -186,6 +186,12 @@ module Appsignal
|
|
186
186
|
# @see https://docs.appsignal.com/ruby/instrumentation/breadcrumbs.html
|
187
187
|
# Breadcrumb reference
|
188
188
|
def add_breadcrumb(category, action, message = "", metadata = {}, time = Time.now.utc)
|
189
|
+
unless metadata.is_a? Hash
|
190
|
+
Appsignal.logger.error "add_breadcrumb: Cannot add breadcrumb. " \
|
191
|
+
"The given metadata argument is not a Hash."
|
192
|
+
return
|
193
|
+
end
|
194
|
+
|
189
195
|
@breadcrumbs.push(
|
190
196
|
:time => time.to_i,
|
191
197
|
:category => category,
|
@@ -308,6 +314,7 @@ module Appsignal
|
|
308
314
|
|
309
315
|
def set_metadata(key, value)
|
310
316
|
return unless key && value
|
317
|
+
return if Appsignal.config[:filter_metadata].include?(key.to_s)
|
311
318
|
|
312
319
|
@ext.set_metadata(key, value)
|
313
320
|
end
|
@@ -337,7 +344,7 @@ module Appsignal
|
|
337
344
|
:params => sanitized_params,
|
338
345
|
:environment => sanitized_environment,
|
339
346
|
:session_data => sanitized_session_data,
|
340
|
-
:metadata =>
|
347
|
+
:metadata => sanitized_metadata,
|
341
348
|
:tags => sanitized_tags,
|
342
349
|
:breadcrumbs => breadcrumbs
|
343
350
|
}.each do |key, data|
|
@@ -522,12 +529,17 @@ module Appsignal
|
|
522
529
|
)
|
523
530
|
end
|
524
531
|
|
525
|
-
# Returns metadata from the
|
532
|
+
# Returns sanitized metadata set by {#set_metadata} and from the
|
533
|
+
# {#environment}.
|
526
534
|
#
|
527
|
-
# @return [nil] if no `:metadata` key is present in the {#environment}.
|
528
535
|
# @return [Hash<String, Object>]
|
529
|
-
def
|
530
|
-
environment[:metadata]
|
536
|
+
def sanitized_metadata
|
537
|
+
metadata = environment[:metadata]
|
538
|
+
return unless metadata
|
539
|
+
|
540
|
+
metadata
|
541
|
+
.transform_keys(&:to_s)
|
542
|
+
.except(*Appsignal.config[:filter_metadata])
|
531
543
|
end
|
532
544
|
|
533
545
|
# Returns the environment for a transaction.
|
@@ -5,20 +5,21 @@ module Appsignal
|
|
5
5
|
# @api private
|
6
6
|
class HashSanitizer
|
7
7
|
FILTERED = "[FILTERED]"
|
8
|
+
RECURSIVE = "[RECURSIVE VALUE]"
|
8
9
|
|
9
10
|
class << self
|
10
11
|
def sanitize(value, filter_keys = [])
|
11
|
-
sanitize_value(value, filter_keys)
|
12
|
+
sanitize_value(value, filter_keys, [])
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
15
16
|
|
16
|
-
def sanitize_value(value, filter_keys)
|
17
|
+
def sanitize_value(value, filter_keys, seen)
|
17
18
|
case value
|
18
19
|
when Hash
|
19
|
-
sanitize_hash(value, filter_keys)
|
20
|
+
sanitize_hash(value, filter_keys, seen)
|
20
21
|
when Array
|
21
|
-
sanitize_array(value, filter_keys)
|
22
|
+
sanitize_array(value, filter_keys, seen)
|
22
23
|
when TrueClass, FalseClass, NilClass, Integer, String, Symbol, Float
|
23
24
|
unmodified(value)
|
24
25
|
else
|
@@ -26,23 +27,34 @@ module Appsignal
|
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
def sanitize_hash(source, filter_keys)
|
30
|
+
def sanitize_hash(source, filter_keys, seen)
|
31
|
+
seen = seen.clone << source.object_id
|
32
|
+
|
30
33
|
{}.tap do |hash|
|
31
34
|
source.each_pair do |key, value|
|
32
35
|
hash[key] =
|
33
|
-
if
|
36
|
+
if seen.include?(value.object_id)
|
37
|
+
RECURSIVE
|
38
|
+
elsif filter_keys.include?(key.to_s)
|
34
39
|
FILTERED
|
35
40
|
else
|
36
|
-
sanitize_value(value, filter_keys)
|
41
|
+
sanitize_value(value, filter_keys, seen)
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
42
|
-
def sanitize_array(source, filter_keys)
|
47
|
+
def sanitize_array(source, filter_keys, seen)
|
48
|
+
seen = seen.clone << source.object_id
|
49
|
+
|
43
50
|
[].tap do |array|
|
44
51
|
source.each_with_index do |item, index|
|
45
|
-
array[index] =
|
52
|
+
array[index] =
|
53
|
+
if seen.include?(item.object_id)
|
54
|
+
RECURSIVE
|
55
|
+
else
|
56
|
+
sanitize_value(item, filter_keys, seen)
|
57
|
+
end
|
46
58
|
end
|
47
59
|
end
|
48
60
|
end
|
data/lib/appsignal/version.rb
CHANGED
@@ -165,6 +165,7 @@ describe Appsignal::Config do
|
|
165
165
|
:enable_rails_error_reporter => true,
|
166
166
|
:endpoint => "https://push.appsignal.com",
|
167
167
|
:files_world_accessible => true,
|
168
|
+
:filter_metadata => [],
|
168
169
|
:filter_parameters => [],
|
169
170
|
:filter_session_data => [],
|
170
171
|
:ignore_actions => [],
|
@@ -1,39 +1,49 @@
|
|
1
1
|
if DependencyHelper.sinatra_present?
|
2
2
|
require "appsignal/integrations/sinatra"
|
3
3
|
|
4
|
+
module SinatraRequestHelpers
|
5
|
+
def make_request(env)
|
6
|
+
middleware.call(env)
|
7
|
+
end
|
8
|
+
|
9
|
+
def make_request_with_error(env, error)
|
10
|
+
expect { middleware.call(env) }.to raise_error(error)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
describe Appsignal::Rack::SinatraInstrumentation do
|
15
|
+
include SinatraRequestHelpers
|
16
|
+
|
5
17
|
let(:settings) { double(:raise_errors => false) }
|
6
18
|
let(:app) { double(:call => true, :settings => settings) }
|
7
19
|
let(:env) { { "sinatra.route" => "GET /", :path => "/", :method => "GET" } }
|
8
20
|
let(:middleware) { Appsignal::Rack::SinatraInstrumentation.new(app) }
|
9
21
|
|
22
|
+
before(:context) { start_agent }
|
23
|
+
around do |example|
|
24
|
+
keep_transactions { example.run }
|
25
|
+
end
|
26
|
+
|
10
27
|
describe "#call" do
|
11
|
-
before
|
12
|
-
start_agent
|
13
|
-
allow(middleware).to receive(:raw_payload).and_return({})
|
14
|
-
allow(Appsignal).to receive(:active?).and_return(true)
|
15
|
-
end
|
28
|
+
before { allow(middleware).to receive(:raw_payload).and_return({}) }
|
16
29
|
|
17
|
-
it "
|
18
|
-
|
30
|
+
it "doesn't instrument requests" do
|
31
|
+
make_request(env)
|
32
|
+
expect(created_transactions.count).to eq(0)
|
19
33
|
end
|
20
|
-
|
21
|
-
after { middleware.call(env) }
|
22
34
|
end
|
23
35
|
|
24
36
|
describe ".settings" do
|
25
37
|
subject { middleware.settings }
|
26
38
|
|
27
|
-
it "
|
39
|
+
it "returns the app's settings" do
|
28
40
|
expect(subject).to eq(app.settings)
|
29
41
|
end
|
30
42
|
end
|
31
43
|
end
|
32
44
|
|
33
45
|
describe Appsignal::Rack::SinatraBaseInstrumentation do
|
34
|
-
|
35
|
-
start_agent
|
36
|
-
end
|
46
|
+
include SinatraRequestHelpers
|
37
47
|
|
38
48
|
let(:settings) { double(:raise_errors => false) }
|
39
49
|
let(:app) { double(:call => true, :settings => settings) }
|
@@ -41,11 +51,16 @@ if DependencyHelper.sinatra_present?
|
|
41
51
|
let(:options) { {} }
|
42
52
|
let(:middleware) { Appsignal::Rack::SinatraBaseInstrumentation.new(app, options) }
|
43
53
|
|
54
|
+
before(:context) { start_agent }
|
55
|
+
around do |example|
|
56
|
+
keep_transactions { example.run }
|
57
|
+
end
|
58
|
+
|
44
59
|
describe "#initialize" do
|
45
60
|
context "with no settings method in the Sinatra app" do
|
46
61
|
let(:app) { double(:call => true) }
|
47
62
|
|
48
|
-
it "
|
63
|
+
it "does not raise errors" do
|
49
64
|
expect(middleware.raise_errors_on).to be(false)
|
50
65
|
end
|
51
66
|
end
|
@@ -53,7 +68,7 @@ if DependencyHelper.sinatra_present?
|
|
53
68
|
context "with no raise_errors setting in the Sinatra app" do
|
54
69
|
let(:app) { double(:call => true, :settings => double) }
|
55
70
|
|
56
|
-
it "
|
71
|
+
it "does not raise errors" do
|
57
72
|
expect(middleware.raise_errors_on).to be(false)
|
58
73
|
end
|
59
74
|
end
|
@@ -61,7 +76,7 @@ if DependencyHelper.sinatra_present?
|
|
61
76
|
context "with raise_errors turned off in the Sinatra app" do
|
62
77
|
let(:app) { double(:call => true, :settings => double(:raise_errors => false)) }
|
63
78
|
|
64
|
-
it "
|
79
|
+
it "raises errors" do
|
65
80
|
expect(middleware.raise_errors_on).to be(false)
|
66
81
|
end
|
67
82
|
end
|
@@ -69,21 +84,17 @@ if DependencyHelper.sinatra_present?
|
|
69
84
|
context "with raise_errors turned on in the Sinatra app" do
|
70
85
|
let(:app) { double(:call => true, :settings => double(:raise_errors => true)) }
|
71
86
|
|
72
|
-
it "
|
87
|
+
it "raises errors" do
|
73
88
|
expect(middleware.raise_errors_on).to be(true)
|
74
89
|
end
|
75
90
|
end
|
76
91
|
end
|
77
92
|
|
78
93
|
describe "#call" do
|
79
|
-
before
|
80
|
-
allow(middleware).to receive(:raw_payload).and_return({})
|
81
|
-
end
|
94
|
+
before { allow(middleware).to receive(:raw_payload).and_return({}) }
|
82
95
|
|
83
96
|
context "when appsignal is active" do
|
84
|
-
|
85
|
-
|
86
|
-
it "should call with monitoring" do
|
97
|
+
it "instruments requests" do
|
87
98
|
expect(middleware).to receive(:call_with_appsignal_monitoring).with(env)
|
88
99
|
end
|
89
100
|
end
|
@@ -91,34 +102,36 @@ if DependencyHelper.sinatra_present?
|
|
91
102
|
context "when appsignal is not active" do
|
92
103
|
before { allow(Appsignal).to receive(:active?).and_return(false) }
|
93
104
|
|
94
|
-
it "
|
95
|
-
expect(
|
105
|
+
it "does not instrument requests" do
|
106
|
+
expect(created_transactions.count).to eq(0)
|
96
107
|
end
|
97
108
|
|
98
|
-
it "
|
109
|
+
it "calls the next middleware in the stack" do
|
99
110
|
expect(app).to receive(:call).with(env)
|
100
111
|
end
|
101
112
|
end
|
102
113
|
|
103
|
-
after {
|
114
|
+
after { make_request(env) }
|
104
115
|
end
|
105
116
|
|
106
|
-
describe "#call_with_appsignal_monitoring"
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
kind_of(Hash)
|
113
|
-
).and_return(double(:set_action_if_nil => nil, :set_http_or_background_queue_start => nil,
|
114
|
-
:set_metadata => nil))
|
115
|
-
end
|
117
|
+
describe "#call_with_appsignal_monitoring" do
|
118
|
+
context "without an error" do
|
119
|
+
it "creates a transaction" do
|
120
|
+
expect(app).to receive(:call).with(env)
|
121
|
+
|
122
|
+
make_request(env)
|
116
123
|
|
117
|
-
|
118
|
-
|
124
|
+
expect(created_transactions.count).to eq(1)
|
125
|
+
expect(last_transaction.to_h).to include(
|
126
|
+
"namespace" => Appsignal::Transaction::HTTP_REQUEST,
|
127
|
+
"action" => "GET /",
|
128
|
+
"error" => nil,
|
129
|
+
"metadata" => { "path" => "" }
|
130
|
+
)
|
131
|
+
end
|
119
132
|
end
|
120
133
|
|
121
|
-
context "with an error"
|
134
|
+
context "with an error" do
|
122
135
|
let(:error) { ExampleException }
|
123
136
|
let(:app) do
|
124
137
|
double.tap do |d|
|
@@ -128,23 +141,48 @@ if DependencyHelper.sinatra_present?
|
|
128
141
|
end
|
129
142
|
|
130
143
|
it "records the exception" do
|
131
|
-
|
144
|
+
make_request_with_error(env, error)
|
145
|
+
|
146
|
+
expect(created_transactions.count).to eq(1)
|
147
|
+
expect(last_transaction.to_h).to include(
|
148
|
+
"namespace" => Appsignal::Transaction::HTTP_REQUEST,
|
149
|
+
"action" => "GET /",
|
150
|
+
"error" => hash_including(
|
151
|
+
"name" => "ExampleException",
|
152
|
+
"message" => "ExampleException"
|
153
|
+
)
|
154
|
+
)
|
132
155
|
end
|
133
156
|
end
|
134
157
|
|
135
158
|
context "with an error in sinatra.error" do
|
136
|
-
let(:error) { ExampleException }
|
159
|
+
let(:error) { ExampleException.new }
|
137
160
|
let(:env) { { "sinatra.error" => error } }
|
138
161
|
|
139
|
-
|
140
|
-
|
162
|
+
context "when raise_errors is off" do
|
163
|
+
let(:settings) { double(:raise_errors => false) }
|
164
|
+
|
165
|
+
it "record the error" do
|
166
|
+
make_request(env)
|
167
|
+
|
168
|
+
expect(created_transactions.count).to eq(1)
|
169
|
+
expect(last_transaction.to_h).to include(
|
170
|
+
"error" => hash_including(
|
171
|
+
"name" => "ExampleException",
|
172
|
+
"message" => "ExampleException"
|
173
|
+
)
|
174
|
+
)
|
175
|
+
end
|
141
176
|
end
|
142
177
|
|
143
178
|
context "when raise_errors is on" do
|
144
179
|
let(:settings) { double(:raise_errors => true) }
|
145
180
|
|
146
181
|
it "does not record the error" do
|
147
|
-
|
182
|
+
make_request(env)
|
183
|
+
|
184
|
+
expect(created_transactions.count).to eq(1)
|
185
|
+
expect(last_transaction.to_h).to include("error" => nil)
|
148
186
|
end
|
149
187
|
end
|
150
188
|
|
@@ -152,22 +190,30 @@ if DependencyHelper.sinatra_present?
|
|
152
190
|
let(:env) { { "sinatra.error" => error, "sinatra.skip_appsignal_error" => true } }
|
153
191
|
|
154
192
|
it "does not record the error" do
|
155
|
-
|
193
|
+
make_request(env)
|
194
|
+
|
195
|
+
expect(created_transactions.count).to eq(1)
|
196
|
+
expect(last_transaction.to_h).to include("error" => nil)
|
156
197
|
end
|
157
198
|
end
|
158
199
|
end
|
159
200
|
|
160
201
|
describe "action name" do
|
161
|
-
it "
|
162
|
-
|
163
|
-
|
202
|
+
it "sets the action" do
|
203
|
+
make_request(env)
|
204
|
+
|
205
|
+
expect(created_transactions.count).to eq(1)
|
206
|
+
expect(last_transaction.to_h).to include("action" => "GET /")
|
164
207
|
end
|
165
208
|
|
166
209
|
context "without 'sinatra.route' env" do
|
167
210
|
let(:env) { { :path => "/", :method => "GET" } }
|
168
211
|
|
169
|
-
it "
|
170
|
-
|
212
|
+
it "doesn't set an action name" do
|
213
|
+
make_request(env)
|
214
|
+
|
215
|
+
expect(created_transactions.count).to eq(1)
|
216
|
+
expect(last_transaction.to_h).to include("action" => nil)
|
171
217
|
end
|
172
218
|
end
|
173
219
|
|
@@ -175,44 +221,90 @@ if DependencyHelper.sinatra_present?
|
|
175
221
|
before { env["SCRIPT_NAME"] = "/api" }
|
176
222
|
|
177
223
|
it "should call set_action with an application prefix path" do
|
178
|
-
|
179
|
-
|
224
|
+
make_request(env)
|
225
|
+
|
226
|
+
expect(created_transactions.count).to eq(1)
|
227
|
+
expect(last_transaction.to_h).to include("action" => "GET /api/")
|
180
228
|
end
|
181
229
|
|
182
230
|
context "without 'sinatra.route' env" do
|
183
231
|
let(:env) { { :path => "/", :method => "GET" } }
|
184
232
|
|
185
|
-
it "
|
186
|
-
|
187
|
-
|
233
|
+
it "doesn't set an action name" do
|
234
|
+
make_request(env)
|
235
|
+
|
236
|
+
expect(created_transactions.count).to eq(1)
|
237
|
+
expect(last_transaction.to_h).to include("action" => nil)
|
188
238
|
end
|
189
239
|
end
|
190
240
|
end
|
191
241
|
end
|
192
242
|
|
193
|
-
|
194
|
-
|
243
|
+
context "metadata" do
|
244
|
+
let(:env) { { "PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET" } }
|
245
|
+
|
246
|
+
it "sets metadata from the environment" do
|
247
|
+
make_request(env)
|
248
|
+
|
249
|
+
expect(created_transactions.count).to eq(1)
|
250
|
+
expect(last_transaction.to_h).to include(
|
251
|
+
"metadata" => {
|
252
|
+
"method" => "GET",
|
253
|
+
"path" => "/some/path"
|
254
|
+
},
|
255
|
+
"sample_data" => hash_including(
|
256
|
+
"environment" => hash_including(
|
257
|
+
"REQUEST_METHOD" => "GET",
|
258
|
+
"PATH_INFO" => "/some/path"
|
259
|
+
)
|
260
|
+
)
|
261
|
+
)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context "with queue start" do
|
266
|
+
let(:queue_start_time) { fixed_time * 1_000 }
|
267
|
+
let(:env) do
|
268
|
+
{ "HTTP_X_REQUEST_START" => "t=#{queue_start_time.to_i}" } # in milliseconds
|
269
|
+
end
|
270
|
+
|
271
|
+
it "sets the queue start" do
|
272
|
+
make_request(env)
|
273
|
+
expect(last_transaction.ext.queue_start).to eq(queue_start_time)
|
274
|
+
end
|
195
275
|
end
|
196
276
|
|
197
|
-
|
198
|
-
|
199
|
-
|
277
|
+
class FilteredRequest
|
278
|
+
def initialize(_args) # rubocop:disable Style/RedundantInitialize
|
279
|
+
end
|
280
|
+
|
281
|
+
def path
|
282
|
+
"/static/path"
|
283
|
+
end
|
284
|
+
|
285
|
+
def request_method
|
286
|
+
"GET"
|
287
|
+
end
|
288
|
+
|
289
|
+
def filtered_params
|
290
|
+
{ "abc" => "123" }
|
291
|
+
end
|
200
292
|
end
|
201
293
|
|
202
294
|
context "with overridden request class and params method" do
|
203
|
-
let(:options) { { :request_class =>
|
295
|
+
let(:options) { { :request_class => FilteredRequest, :params_method => :filtered_params } }
|
204
296
|
|
205
|
-
it "
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
297
|
+
it "uses the overridden request class and params method to fetch params" do
|
298
|
+
make_request(env)
|
299
|
+
|
300
|
+
expect(created_transactions.count).to eq(1)
|
301
|
+
expect(last_transaction.to_h).to include(
|
302
|
+
"sample_data" => hash_including(
|
303
|
+
"params" => { "abc" => "123" }
|
304
|
+
)
|
305
|
+
)
|
211
306
|
end
|
212
307
|
end
|
213
|
-
|
214
|
-
after(:error => false) { middleware.call(env) }
|
215
|
-
after(:error => true) { expect { middleware.call(env) }.to raise_error(error) }
|
216
308
|
end
|
217
309
|
end
|
218
310
|
end
|
@@ -432,6 +432,19 @@ describe Appsignal::Transaction do
|
|
432
432
|
expect(breadcrumb["metadata"]).to eq({})
|
433
433
|
end
|
434
434
|
end
|
435
|
+
|
436
|
+
context "with metadata argument that's not a Hash" do
|
437
|
+
it "does not add the breadcrumb and logs and error" do
|
438
|
+
transaction.add_breadcrumb("category", "action", "message", "invalid metadata")
|
439
|
+
transaction.sample_data
|
440
|
+
|
441
|
+
expect(transaction.to_h["sample_data"]["breadcrumbs"]).to be_empty
|
442
|
+
expect(log_contents(log)).to contains_log(
|
443
|
+
:error,
|
444
|
+
"add_breadcrumb: Cannot add breadcrumb. The given metadata argument is not a Hash."
|
445
|
+
)
|
446
|
+
end
|
447
|
+
end
|
435
448
|
end
|
436
449
|
|
437
450
|
describe "#set_action" do
|
@@ -623,6 +636,18 @@ describe Appsignal::Transaction do
|
|
623
636
|
expect(transaction.to_h["metadata"]).to eq("request_method" => "GET")
|
624
637
|
end
|
625
638
|
|
639
|
+
context "when filter_metadata includes metadata key" do
|
640
|
+
before { Appsignal.config[:filter_metadata] = ["filter_key"] }
|
641
|
+
after { Appsignal.config[:filter_metadata] = [] }
|
642
|
+
|
643
|
+
it "does not set the metadata on the transaction" do
|
644
|
+
transaction.set_metadata(:filter_key, "filtered value")
|
645
|
+
transaction.set_metadata("filter_key", "filtered value")
|
646
|
+
|
647
|
+
expect(transaction.to_h["metadata"].keys).to_not include("filter_key")
|
648
|
+
end
|
649
|
+
end
|
650
|
+
|
626
651
|
context "when the key is nil" do
|
627
652
|
it "does not update the metadata on the transaction" do
|
628
653
|
transaction.set_metadata(nil, "GET")
|
@@ -1275,8 +1300,8 @@ describe Appsignal::Transaction do
|
|
1275
1300
|
end
|
1276
1301
|
end
|
1277
1302
|
|
1278
|
-
describe "#
|
1279
|
-
subject { transaction.send(:
|
1303
|
+
describe "#sanitized_metadata" do
|
1304
|
+
subject { transaction.send(:sanitized_metadata) }
|
1280
1305
|
|
1281
1306
|
context "when request is nil" do
|
1282
1307
|
let(:request) { nil }
|
@@ -1291,9 +1316,18 @@ describe Appsignal::Transaction do
|
|
1291
1316
|
end
|
1292
1317
|
|
1293
1318
|
context "when env is present" do
|
1294
|
-
let(:env) { {
|
1319
|
+
let(:env) { { "key" => "value" } }
|
1320
|
+
|
1321
|
+
it { is_expected.to eq("key" => "value") }
|
1295
1322
|
|
1296
|
-
|
1323
|
+
context "with filter_metadata option set" do
|
1324
|
+
before { Appsignal.config[:filter_metadata] = ["key"] }
|
1325
|
+
after { Appsignal.config[:filter_metadata] = [] }
|
1326
|
+
|
1327
|
+
it "filters out keys listed in the filter_metadata option" do
|
1328
|
+
expect(subject.keys).to_not include("key")
|
1329
|
+
end
|
1330
|
+
end
|
1297
1331
|
end
|
1298
1332
|
end
|
1299
1333
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
describe Appsignal::Utils::HashSanitizer do
|
2
2
|
let(:file) { uploaded_file }
|
3
|
+
let(:some_array) { [1, 2, 3] }
|
4
|
+
let(:some_hash) { { :a => 1, :b => 2 } }
|
3
5
|
let(:params) do
|
4
6
|
{
|
5
7
|
:text => "string",
|
@@ -8,6 +10,10 @@ describe Appsignal::Utils::HashSanitizer do
|
|
8
10
|
:float => 0.0,
|
9
11
|
:bool_true => true,
|
10
12
|
:bool_false => false,
|
13
|
+
# Non-recursive appearances of the same array instance
|
14
|
+
:some_arrays => [some_array, some_array],
|
15
|
+
# Non-recursive appearances of the same hash instance
|
16
|
+
:some_hashes => { :a => some_hash, :b => some_hash },
|
11
17
|
:nil => nil,
|
12
18
|
:int => 1, # Fixnum
|
13
19
|
:int64 => 1 << 64, # Bignum
|
@@ -20,9 +26,20 @@ describe Appsignal::Utils::HashSanitizer do
|
|
20
26
|
{
|
21
27
|
:key => "value",
|
22
28
|
:file => file
|
23
|
-
}
|
24
|
-
|
25
|
-
|
29
|
+
}.tap do |hsh|
|
30
|
+
# Recursive hash-in-hash (should be [:nested_array][3][:recursive_hash])
|
31
|
+
hsh[:recursive_hash] = hsh
|
32
|
+
end
|
33
|
+
].tap do |ary|
|
34
|
+
# Recursive array-in-array (should be [:nested_array][4])
|
35
|
+
ary << ary
|
36
|
+
# Recursive array-in-hash (should be [:nested_array][3][:recursive_array])
|
37
|
+
ary[3][:recursive_array] = ary
|
38
|
+
end
|
39
|
+
}.tap do |hsh|
|
40
|
+
# Recursive hash-in-array (should be [:nested_array][5])
|
41
|
+
hsh[:nested_array] << hsh
|
42
|
+
end
|
26
43
|
}
|
27
44
|
end
|
28
45
|
|
@@ -43,6 +60,9 @@ describe Appsignal::Utils::HashSanitizer do
|
|
43
60
|
expect(subject[:nil]).to be_nil
|
44
61
|
expect(subject[:int]).to eq(1)
|
45
62
|
expect(subject[:int64]).to eq(1 << 64)
|
63
|
+
expect(subject[:some_arrays]).to eq([[1, 2, 3], [1, 2, 3]])
|
64
|
+
expect(subject[:some_hashes]).to eq({ :a => { :a => 1, :b => 2 },
|
65
|
+
:b => { :a => 1, :b => 2 } })
|
46
66
|
end
|
47
67
|
|
48
68
|
it "does not change the original params" do
|
@@ -72,7 +92,7 @@ describe Appsignal::Utils::HashSanitizer do
|
|
72
92
|
expect(subject[2]).to include "::UploadedFile"
|
73
93
|
end
|
74
94
|
|
75
|
-
describe "
|
95
|
+
describe "nested hash" do
|
76
96
|
subject { sanitized_params[:hash][:nested_array][3] }
|
77
97
|
|
78
98
|
it "returns a sanitized Hash" do
|
@@ -82,6 +102,24 @@ describe Appsignal::Utils::HashSanitizer do
|
|
82
102
|
expect(subject[:file]).to be_instance_of String
|
83
103
|
expect(subject[:file]).to include "::UploadedFile"
|
84
104
|
end
|
105
|
+
|
106
|
+
it "replaces a recursive array" do
|
107
|
+
expect(subject[:recursive_array]).to eq("[RECURSIVE VALUE]")
|
108
|
+
end
|
109
|
+
|
110
|
+
it "replaces a recursive hash" do
|
111
|
+
expect(subject[:recursive_hash]).to eq("[RECURSIVE VALUE]")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "nested array" do
|
116
|
+
it "replaces a recursive array" do
|
117
|
+
expect(sanitized_params[:hash][:nested_array][4]).to eq("[RECURSIVE VALUE]")
|
118
|
+
end
|
119
|
+
|
120
|
+
it "replaces a recursive hash" do
|
121
|
+
expect(sanitized_params[:hash][:nested_array][5]).to eq("[RECURSIVE VALUE]")
|
122
|
+
end
|
85
123
|
end
|
86
124
|
end
|
87
125
|
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.
|
4
|
+
version: 3.4.6
|
5
5
|
platform: java
|
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-
|
13
|
+
date: 2023-07-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -453,7 +453,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
453
453
|
- !ruby/object:Gem::Version
|
454
454
|
version: '0'
|
455
455
|
requirements: []
|
456
|
-
rubygems_version: 3.
|
456
|
+
rubygems_version: 3.3.7
|
457
457
|
signing_key:
|
458
458
|
specification_version: 4
|
459
459
|
summary: Logs performance and exception data from your app to appsignal.com
|