appsignal 2.5.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.
Files changed (211) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.rspec +4 -0
  4. data/.rubocop.yml +66 -0
  5. data/.rubocop_todo.yml +124 -0
  6. data/.travis.yml +72 -0
  7. data/.yardopts +8 -0
  8. data/CHANGELOG.md +639 -0
  9. data/Gemfile +3 -0
  10. data/LICENSE +20 -0
  11. data/README.md +264 -0
  12. data/Rakefile +214 -0
  13. data/appsignal.gemspec +42 -0
  14. data/benchmark.rake +77 -0
  15. data/bin/appsignal +13 -0
  16. data/ext/Rakefile +27 -0
  17. data/ext/agent.yml +64 -0
  18. data/ext/appsignal_extension.c +692 -0
  19. data/ext/base.rb +79 -0
  20. data/ext/extconf.rb +35 -0
  21. data/gemfiles/capistrano2.gemfile +7 -0
  22. data/gemfiles/capistrano3.gemfile +7 -0
  23. data/gemfiles/grape.gemfile +7 -0
  24. data/gemfiles/no_dependencies.gemfile +5 -0
  25. data/gemfiles/padrino.gemfile +7 -0
  26. data/gemfiles/que.gemfile +5 -0
  27. data/gemfiles/rails-3.2.gemfile +6 -0
  28. data/gemfiles/rails-4.0.gemfile +6 -0
  29. data/gemfiles/rails-4.1.gemfile +6 -0
  30. data/gemfiles/rails-4.2.gemfile +10 -0
  31. data/gemfiles/rails-5.0.gemfile +5 -0
  32. data/gemfiles/rails-5.1.gemfile +5 -0
  33. data/gemfiles/resque.gemfile +12 -0
  34. data/gemfiles/sequel-435.gemfile +11 -0
  35. data/gemfiles/sequel.gemfile +11 -0
  36. data/gemfiles/sinatra.gemfile +6 -0
  37. data/gemfiles/webmachine.gemfile +5 -0
  38. data/lib/appsignal.rb +804 -0
  39. data/lib/appsignal/auth_check.rb +65 -0
  40. data/lib/appsignal/capistrano.rb +10 -0
  41. data/lib/appsignal/cli.rb +108 -0
  42. data/lib/appsignal/cli/demo.rb +63 -0
  43. data/lib/appsignal/cli/diagnose.rb +500 -0
  44. data/lib/appsignal/cli/helpers.rb +72 -0
  45. data/lib/appsignal/cli/install.rb +277 -0
  46. data/lib/appsignal/cli/notify_of_deploy.rb +113 -0
  47. data/lib/appsignal/config.rb +287 -0
  48. data/lib/appsignal/demo.rb +107 -0
  49. data/lib/appsignal/event_formatter.rb +74 -0
  50. data/lib/appsignal/event_formatter/action_view/render_formatter.rb +24 -0
  51. data/lib/appsignal/event_formatter/active_record/instantiation_formatter.rb +14 -0
  52. data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +14 -0
  53. data/lib/appsignal/event_formatter/elastic_search/search_formatter.rb +32 -0
  54. data/lib/appsignal/event_formatter/faraday/request_formatter.rb +19 -0
  55. data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +89 -0
  56. data/lib/appsignal/event_formatter/moped/query_formatter.rb +80 -0
  57. data/lib/appsignal/extension.rb +63 -0
  58. data/lib/appsignal/extension/jruby.rb +460 -0
  59. data/lib/appsignal/garbage_collection_profiler.rb +48 -0
  60. data/lib/appsignal/hooks.rb +105 -0
  61. data/lib/appsignal/hooks/action_cable.rb +113 -0
  62. data/lib/appsignal/hooks/active_support_notifications.rb +52 -0
  63. data/lib/appsignal/hooks/celluloid.rb +30 -0
  64. data/lib/appsignal/hooks/data_mapper.rb +18 -0
  65. data/lib/appsignal/hooks/delayed_job.rb +19 -0
  66. data/lib/appsignal/hooks/mongo_ruby_driver.rb +21 -0
  67. data/lib/appsignal/hooks/net_http.rb +29 -0
  68. data/lib/appsignal/hooks/passenger.rb +22 -0
  69. data/lib/appsignal/hooks/puma.rb +35 -0
  70. data/lib/appsignal/hooks/que.rb +21 -0
  71. data/lib/appsignal/hooks/rake.rb +39 -0
  72. data/lib/appsignal/hooks/redis.rb +30 -0
  73. data/lib/appsignal/hooks/sequel.rb +60 -0
  74. data/lib/appsignal/hooks/shoryuken.rb +43 -0
  75. data/lib/appsignal/hooks/sidekiq.rb +144 -0
  76. data/lib/appsignal/hooks/unicorn.rb +40 -0
  77. data/lib/appsignal/hooks/webmachine.rb +23 -0
  78. data/lib/appsignal/integrations/capistrano/appsignal.cap +39 -0
  79. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +52 -0
  80. data/lib/appsignal/integrations/data_mapper.rb +33 -0
  81. data/lib/appsignal/integrations/delayed_job_plugin.rb +54 -0
  82. data/lib/appsignal/integrations/grape.rb +53 -0
  83. data/lib/appsignal/integrations/mongo_ruby_driver.rb +55 -0
  84. data/lib/appsignal/integrations/object.rb +35 -0
  85. data/lib/appsignal/integrations/padrino.rb +84 -0
  86. data/lib/appsignal/integrations/que.rb +43 -0
  87. data/lib/appsignal/integrations/railtie.rb +41 -0
  88. data/lib/appsignal/integrations/rake.rb +2 -0
  89. data/lib/appsignal/integrations/resque.rb +20 -0
  90. data/lib/appsignal/integrations/resque_active_job.rb +30 -0
  91. data/lib/appsignal/integrations/sinatra.rb +17 -0
  92. data/lib/appsignal/integrations/webmachine.rb +38 -0
  93. data/lib/appsignal/js_exception_transaction.rb +54 -0
  94. data/lib/appsignal/marker.rb +63 -0
  95. data/lib/appsignal/minutely.rb +42 -0
  96. data/lib/appsignal/rack/generic_instrumentation.rb +49 -0
  97. data/lib/appsignal/rack/js_exception_catcher.rb +70 -0
  98. data/lib/appsignal/rack/rails_instrumentation.rb +51 -0
  99. data/lib/appsignal/rack/sinatra_instrumentation.rb +99 -0
  100. data/lib/appsignal/rack/streaming_listener.rb +73 -0
  101. data/lib/appsignal/system.rb +81 -0
  102. data/lib/appsignal/transaction.rb +498 -0
  103. data/lib/appsignal/transmitter.rb +107 -0
  104. data/lib/appsignal/utils.rb +127 -0
  105. data/lib/appsignal/utils/params_sanitizer.rb +59 -0
  106. data/lib/appsignal/utils/query_params_sanitizer.rb +55 -0
  107. data/lib/appsignal/version.rb +3 -0
  108. data/lib/sequel/extensions/appsignal_integration.rb +3 -0
  109. data/resources/appsignal.yml.erb +39 -0
  110. data/resources/cacert.pem +3866 -0
  111. data/spec/.rubocop.yml +7 -0
  112. data/spec/lib/appsignal/auth_check_spec.rb +80 -0
  113. data/spec/lib/appsignal/capistrano2_spec.rb +224 -0
  114. data/spec/lib/appsignal/capistrano3_spec.rb +237 -0
  115. data/spec/lib/appsignal/cli/demo_spec.rb +67 -0
  116. data/spec/lib/appsignal/cli/diagnose_spec.rb +988 -0
  117. data/spec/lib/appsignal/cli/helpers_spec.rb +171 -0
  118. data/spec/lib/appsignal/cli/install_spec.rb +632 -0
  119. data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +168 -0
  120. data/spec/lib/appsignal/cli_spec.rb +56 -0
  121. data/spec/lib/appsignal/config_spec.rb +637 -0
  122. data/spec/lib/appsignal/demo_spec.rb +87 -0
  123. data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +44 -0
  124. data/spec/lib/appsignal/event_formatter/active_record/instantiation_formatter_spec.rb +21 -0
  125. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +21 -0
  126. data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +52 -0
  127. data/spec/lib/appsignal/event_formatter/faraday/request_formatter_spec.rb +21 -0
  128. data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +113 -0
  129. data/spec/lib/appsignal/event_formatter/moped/query_formatter_spec.rb +112 -0
  130. data/spec/lib/appsignal/event_formatter_spec.rb +100 -0
  131. data/spec/lib/appsignal/extension/jruby_spec.rb +43 -0
  132. data/spec/lib/appsignal/extension_spec.rb +137 -0
  133. data/spec/lib/appsignal/garbage_collection_profiler_spec.rb +66 -0
  134. data/spec/lib/appsignal/hooks/action_cable_spec.rb +370 -0
  135. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +92 -0
  136. data/spec/lib/appsignal/hooks/celluloid_spec.rb +35 -0
  137. data/spec/lib/appsignal/hooks/data_mapper_spec.rb +39 -0
  138. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +358 -0
  139. data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +44 -0
  140. data/spec/lib/appsignal/hooks/net_http_spec.rb +53 -0
  141. data/spec/lib/appsignal/hooks/passenger_spec.rb +30 -0
  142. data/spec/lib/appsignal/hooks/puma_spec.rb +80 -0
  143. data/spec/lib/appsignal/hooks/que_spec.rb +19 -0
  144. data/spec/lib/appsignal/hooks/rake_spec.rb +73 -0
  145. data/spec/lib/appsignal/hooks/redis_spec.rb +55 -0
  146. data/spec/lib/appsignal/hooks/sequel_spec.rb +46 -0
  147. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +192 -0
  148. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +419 -0
  149. data/spec/lib/appsignal/hooks/unicorn_spec.rb +52 -0
  150. data/spec/lib/appsignal/hooks/webmachine_spec.rb +35 -0
  151. data/spec/lib/appsignal/hooks_spec.rb +195 -0
  152. data/spec/lib/appsignal/integrations/data_mapper_spec.rb +65 -0
  153. data/spec/lib/appsignal/integrations/grape_spec.rb +225 -0
  154. data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +127 -0
  155. data/spec/lib/appsignal/integrations/object_spec.rb +249 -0
  156. data/spec/lib/appsignal/integrations/padrino_spec.rb +323 -0
  157. data/spec/lib/appsignal/integrations/que_spec.rb +174 -0
  158. data/spec/lib/appsignal/integrations/railtie_spec.rb +129 -0
  159. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +83 -0
  160. data/spec/lib/appsignal/integrations/resque_spec.rb +92 -0
  161. data/spec/lib/appsignal/integrations/sinatra_spec.rb +73 -0
  162. data/spec/lib/appsignal/integrations/webmachine_spec.rb +69 -0
  163. data/spec/lib/appsignal/js_exception_transaction_spec.rb +128 -0
  164. data/spec/lib/appsignal/marker_spec.rb +51 -0
  165. data/spec/lib/appsignal/minutely_spec.rb +50 -0
  166. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +90 -0
  167. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +147 -0
  168. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +117 -0
  169. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +213 -0
  170. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +161 -0
  171. data/spec/lib/appsignal/system_spec.rb +131 -0
  172. data/spec/lib/appsignal/transaction_spec.rb +1146 -0
  173. data/spec/lib/appsignal/transmitter_spec.rb +152 -0
  174. data/spec/lib/appsignal/utils/params_sanitizer_spec.rb +136 -0
  175. data/spec/lib/appsignal/utils/query_params_sanitizer_spec.rb +192 -0
  176. data/spec/lib/appsignal/utils_spec.rb +150 -0
  177. data/spec/lib/appsignal_spec.rb +1049 -0
  178. data/spec/spec_helper.rb +116 -0
  179. data/spec/support/fixtures/containers/cgroups/docker +14 -0
  180. data/spec/support/fixtures/containers/cgroups/docker_systemd +8 -0
  181. data/spec/support/fixtures/containers/cgroups/lxc +10 -0
  182. data/spec/support/fixtures/containers/cgroups/no_permission +0 -0
  183. data/spec/support/fixtures/containers/cgroups/none +1 -0
  184. data/spec/support/fixtures/generated_config.yml +24 -0
  185. data/spec/support/fixtures/uploaded_file.txt +0 -0
  186. data/spec/support/helpers/api_request_helper.rb +19 -0
  187. data/spec/support/helpers/cli_helpers.rb +26 -0
  188. data/spec/support/helpers/config_helpers.rb +21 -0
  189. data/spec/support/helpers/dependency_helper.rb +73 -0
  190. data/spec/support/helpers/directory_helper.rb +27 -0
  191. data/spec/support/helpers/env_helpers.rb +33 -0
  192. data/spec/support/helpers/example_exception.rb +13 -0
  193. data/spec/support/helpers/example_standard_error.rb +13 -0
  194. data/spec/support/helpers/log_helpers.rb +22 -0
  195. data/spec/support/helpers/std_streams_helper.rb +66 -0
  196. data/spec/support/helpers/system_helpers.rb +8 -0
  197. data/spec/support/helpers/time_helpers.rb +11 -0
  198. data/spec/support/helpers/transaction_helpers.rb +37 -0
  199. data/spec/support/matchers/contains_log.rb +7 -0
  200. data/spec/support/mocks/fake_gc_profiler.rb +19 -0
  201. data/spec/support/mocks/mock_extension.rb +6 -0
  202. data/spec/support/project_fixture/config/application.rb +0 -0
  203. data/spec/support/project_fixture/config/appsignal.yml +32 -0
  204. data/spec/support/project_fixture/config/environments/development.rb +0 -0
  205. data/spec/support/project_fixture/config/environments/production.rb +0 -0
  206. data/spec/support/project_fixture/config/environments/test.rb +0 -0
  207. data/spec/support/project_fixture/log/.gitkeep +0 -0
  208. data/spec/support/rails/my_app.rb +6 -0
  209. data/spec/support/shared_examples/instrument.rb +43 -0
  210. data/spec/support/stubs/delayed_job.rb +0 -0
  211. metadata +483 -0
@@ -0,0 +1,152 @@
1
+ describe Appsignal::Transmitter do
2
+ let(:config) { project_fixture_config }
3
+ let(:base_uri) { "action" }
4
+ let(:log) { StringIO.new }
5
+ let(:instance) { Appsignal::Transmitter.new(base_uri, config) }
6
+ before do
7
+ config.config_hash[:hostname] = "app1.local"
8
+ config.logger = Logger.new(log)
9
+ end
10
+
11
+ describe "#uri" do
12
+ let(:uri) { instance.uri }
13
+
14
+ it "returns a URI object with configuration data" do
15
+ expect(uri.to_s).to start_with(config[:endpoint])
16
+ expect(uri.path).to eq("/1/action")
17
+ expect(CGI.parse(uri.query)).to eq(
18
+ "api_key" => ["abc"],
19
+ "hostname" => ["app1.local"],
20
+ "name" => ["TestApp"],
21
+ "environment" => ["production"],
22
+ "gem_version" => [Appsignal::VERSION]
23
+ )
24
+ end
25
+
26
+ context "when base_uri argument is a full URI" do
27
+ let(:base_uri) { "http://foo.bar/path" }
28
+
29
+ it "uses the full URI" do
30
+ expect(uri.to_s).to start_with("#{base_uri}?")
31
+ end
32
+ end
33
+
34
+ context "when base_uri argument is only a path" do
35
+ it "uses the config[:endpoint] base" do
36
+ expect(uri.to_s).to start_with("#{config[:endpoint]}/1/#{base_uri}?")
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#transmit" do
42
+ before do
43
+ stub_request(:post, "https://push.appsignal.com/1/action").with(
44
+ :query => {
45
+ :api_key => "abc",
46
+ :environment => "production",
47
+ :gem_version => Appsignal::VERSION,
48
+ :hostname => config[:hostname],
49
+ :name => "TestApp"
50
+ },
51
+ :body => "{\"the\":\"payload\"}",
52
+ :headers => {
53
+ "Content-Type" => "application/json; charset=UTF-8"
54
+ }
55
+ ).to_return(:status => 200)
56
+ end
57
+ let(:response) { instance.transmit(:the => :payload) }
58
+
59
+ it "returns Net::HTTP response" do
60
+ expect(response).to be_kind_of(Net::HTTPResponse)
61
+ expect(response.code).to eq "200"
62
+ end
63
+
64
+ context "with ca_file_path config option set" do
65
+ context "when file does not exist" do
66
+ before do
67
+ config.config_hash[:ca_file_path] = File.join(resources_dir, "cacert.pem")
68
+ end
69
+
70
+ it "ignores the config and logs a warning" do
71
+ expect(response).to be_kind_of(Net::HTTPResponse)
72
+ expect(response.code).to eq "200"
73
+ expect(log.string).to_not include "Ignoring non-existing or unreadable " \
74
+ "`ca_file_path`: #{config[:ca_file_path]}"
75
+ end
76
+ end
77
+
78
+ context "when not existing file" do
79
+ before do
80
+ config.config_hash[:ca_file_path] = File.join(tmp_dir, "ca_file_that_does_not_exist")
81
+ end
82
+
83
+ it "ignores the config and logs a warning" do
84
+ expect(response).to be_kind_of(Net::HTTPResponse)
85
+ expect(response.code).to eq "200"
86
+ expect(log.string).to include "Ignoring non-existing or unreadable " \
87
+ "`ca_file_path`: #{config[:ca_file_path]}"
88
+ end
89
+ end
90
+
91
+ context "when not readable file" do
92
+ let(:file) { File.join(tmp_dir, "ca_file") }
93
+ before do
94
+ config.config_hash[:ca_file_path] = file
95
+ File.open(file, "w") { |f| f.chmod 0o000 }
96
+ end
97
+
98
+ it "ignores the config and logs a warning" do
99
+ expect(response).to be_kind_of(Net::HTTPResponse)
100
+ expect(response.code).to eq "200"
101
+ expect(log.string).to include "Ignoring non-existing or unreadable " \
102
+ "`ca_file_path`: #{config[:ca_file_path]}"
103
+ end
104
+
105
+ after { File.delete file }
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#http_post" do
111
+ subject { instance.send(:http_post, "the" => "payload") }
112
+
113
+ it "sets the path" do
114
+ expect(subject.path).to eq instance.uri.request_uri
115
+ end
116
+
117
+ it "sets the correct headers" do
118
+ expect(subject["Content-Type"]).to eq "application/json; charset=UTF-8"
119
+ end
120
+ end
121
+
122
+ describe "#http_client" do
123
+ subject { instance.send(:http_client) }
124
+
125
+ context "with a http uri" do
126
+ let(:config) { project_fixture_config("test") }
127
+
128
+ it { expect(subject).to be_instance_of(Net::HTTP) }
129
+ it { expect(subject.proxy?).to be_falsy }
130
+ it { expect(subject.use_ssl?).to be_falsy }
131
+ end
132
+
133
+ context "with a https uri" do
134
+ let(:config) { project_fixture_config("production") }
135
+
136
+ it { expect(subject).to be_instance_of(Net::HTTP) }
137
+ it { expect(subject.proxy?).to be_falsy }
138
+ it { expect(subject.use_ssl?).to be_truthy }
139
+ it { expect(subject.verify_mode).to eq OpenSSL::SSL::VERIFY_PEER }
140
+ it { expect(subject.ca_file).to eq config[:ca_file_path] }
141
+ end
142
+
143
+ context "with a proxy" do
144
+ let(:config) { project_fixture_config("production", :http_proxy => "http://localhost:8080") }
145
+
146
+ it { expect(subject).to be_instance_of(Net::HTTP) }
147
+ it { expect(subject.proxy?).to be_truthy }
148
+ it { expect(subject.proxy_address).to eq "localhost" }
149
+ it { expect(subject.proxy_port).to eq 8080 }
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,136 @@
1
+ describe Appsignal::Utils::ParamsSanitizer do
2
+ let(:file) { uploaded_file }
3
+ let(:params) do
4
+ {
5
+ :text => "string",
6
+ "string" => "string key value",
7
+ :file => file,
8
+ :float => 0.0,
9
+ :bool_true => true,
10
+ :bool_false => false,
11
+ :nil => nil,
12
+ :int => 1, # Fixnum
13
+ :int64 => 1 << 64, # Bignum
14
+ :hash => {
15
+ :nested_text => "string",
16
+ :nested_array => [
17
+ "something",
18
+ "else",
19
+ file,
20
+ {
21
+ :key => "value",
22
+ :file => file
23
+ }
24
+ ]
25
+ }
26
+ }
27
+ end
28
+
29
+ describe ".sanitize" do
30
+ let(:sanitized_params) { described_class.sanitize(params) }
31
+ subject { sanitized_params }
32
+
33
+ it { is_expected.to be_instance_of Hash }
34
+ it { expect(subject[:text]).to eq("string") }
35
+ it { expect(subject["string"]).to eq("string key value") }
36
+ it do
37
+ expect(subject[:file]).to be_instance_of String
38
+ expect(subject[:file]).to include "::UploadedFile"
39
+ end
40
+ it { expect(subject[:float]).to eq(0.0) }
41
+ it { expect(subject[:bool_true]).to be(true) }
42
+ it { expect(subject[:bool_false]).to be(false) }
43
+ it { expect(subject[:nil]).to be_nil }
44
+ it { expect(subject[:int]).to eq(1) }
45
+ it { expect(subject[:int64]).to eq(1 << 64) }
46
+
47
+ it "does not change the original params" do
48
+ subject
49
+ expect(params[:file]).to eq(file)
50
+ expect(params[:hash][:nested_array][2]).to eq(file)
51
+ end
52
+
53
+ describe ":hash" do
54
+ subject { sanitized_params[:hash] }
55
+
56
+ it { is_expected.to be_instance_of Hash }
57
+ it { expect(subject[:nested_text]).to eq("string") }
58
+
59
+ describe ":nested_array" do
60
+ subject { sanitized_params[:hash][:nested_array] }
61
+
62
+ it { is_expected.to be_instance_of Array }
63
+ it { expect(subject[0]).to eq("something") }
64
+ it { expect(subject[1]).to eq("else") }
65
+ it do
66
+ expect(subject[2]).to be_instance_of String
67
+ expect(subject[2]).to include "::UploadedFile"
68
+ end
69
+
70
+ describe ":nested_hash" do
71
+ subject { sanitized_params[:hash][:nested_array][3] }
72
+
73
+ it { is_expected.to be_instance_of Hash }
74
+ it { expect(subject[:key]).to eq("value") }
75
+ it do
76
+ expect(subject[:file]).to be_instance_of String
77
+ expect(subject[:file]).to include "::UploadedFile"
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ context "with :filter_parameters option" do
84
+ let(:sanitized_params) do
85
+ described_class.sanitize(params, :filter_parameters => %w[text hash])
86
+ end
87
+ subject { sanitized_params }
88
+
89
+ it { expect(subject[:text]).to eq(described_class::FILTERED) }
90
+ it { expect(subject[:hash]).to eq(described_class::FILTERED) }
91
+ it do
92
+ expect(subject[:file]).to be_instance_of String
93
+ expect(subject[:file]).to include "::UploadedFile"
94
+ end
95
+ it { expect(subject[:float]).to eq(0.0) }
96
+ it { expect(subject[:bool_true]).to be(true) }
97
+ it { expect(subject[:bool_false]).to be(false) }
98
+ it { expect(subject[:nil]).to be_nil }
99
+ it { expect(subject[:int]).to eq(1) }
100
+
101
+ context "with strings as key filter values" do
102
+ let(:sanitized_params) do
103
+ described_class.sanitize(params, :filter_parameters => %w[string])
104
+ end
105
+
106
+ it "sanitizes values" do
107
+ expect(subject["string"]).to eq("[FILTERED]")
108
+ end
109
+ end
110
+
111
+ describe ":hash" do
112
+ let(:sanitized_params) do
113
+ described_class.sanitize(params, :filter_parameters => %w[nested_text])
114
+ end
115
+ subject { sanitized_params[:hash] }
116
+
117
+ it "sanitizes values in nested hashes" do
118
+ expect(subject[:nested_text]).to eq("[FILTERED]")
119
+ end
120
+
121
+ describe ":nested_array" do
122
+ describe ":nested_hash" do
123
+ let(:sanitized_params) do
124
+ described_class.sanitize(params, :filter_parameters => %w[key])
125
+ end
126
+ subject { sanitized_params[:hash][:nested_array][3] }
127
+
128
+ it "sanitizes values in deeply nested hashes and arrays" do
129
+ expect(subject[:key]).to eq("[FILTERED]")
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,192 @@
1
+ describe Appsignal::Utils::QueryParamsSanitizer do
2
+ describe ".sanitize" do
3
+ context "when only_top_level = true" do
4
+ subject { described_class.sanitize(value, true) }
5
+
6
+ context "when value is a hash" do
7
+ let(:value) { { "foo" => "bar" } }
8
+
9
+ it "should only return the first level of the object" do
10
+ expect(subject).to eq("foo" => "?")
11
+ end
12
+
13
+ it "should not modify source value" do
14
+ subject
15
+ expect(value).to eq("foo" => "bar")
16
+ end
17
+ end
18
+
19
+ context "when value is a nested hash" do
20
+ let(:value) { { "foo" => { "bar" => "baz" } } }
21
+
22
+ it "should only return the first level of the object" do
23
+ expect(subject).to eq("foo" => "?")
24
+ end
25
+
26
+ it "should not modify source value" do
27
+ subject
28
+ expect(value).to eq("foo" => { "bar" => "baz" })
29
+ end
30
+ end
31
+
32
+ context "when value is an array of hashes" do
33
+ let(:value) { ["foo" => "bar"] }
34
+
35
+ it "should sanitize all hash values with a questionmark" do
36
+ expect(subject).to eq("foo" => "?")
37
+ end
38
+
39
+ it "should not modify source value" do
40
+ subject
41
+ expect(value).to eq(["foo" => "bar"])
42
+ end
43
+ end
44
+
45
+ context "when value is an array" do
46
+ let(:value) { %w[foo bar] }
47
+
48
+ it "should only return the first level of the object" do
49
+ expect(subject).to eq("?")
50
+ end
51
+
52
+ it "should not modify source value" do
53
+ subject
54
+ expect(value).to eq(%w[foo bar])
55
+ end
56
+ end
57
+
58
+ context "when value is a mixed array" do
59
+ let(:value) { [nil, "foo", "bar"] }
60
+
61
+ it "should sanitize all hash values with a single questionmark" do
62
+ expect(subject).to eq("?")
63
+ end
64
+ end
65
+
66
+ context "when value is a string" do
67
+ let(:value) { "foo" }
68
+
69
+ it "should sanitize all hash values with a questionmark" do
70
+ expect(subject).to eq("?")
71
+ end
72
+ end
73
+ end
74
+
75
+ context "when only_top_level = false" do
76
+ subject { described_class.sanitize(value, false) }
77
+
78
+ context "when value is a hash" do
79
+ let(:value) { { "foo" => "bar" } }
80
+
81
+ it "should sanitize all hash values with a questionmark" do
82
+ expect(subject).to eq("foo" => "?")
83
+ end
84
+
85
+ it "should not modify source value" do
86
+ subject
87
+ expect(value).to eq("foo" => "bar")
88
+ end
89
+ end
90
+
91
+ context "when value is a nested hash" do
92
+ let(:value) { { "foo" => { "bar" => "baz" } } }
93
+
94
+ it "should replaces values" do
95
+ expect(subject).to eq("foo" => { "bar" => "?" })
96
+ end
97
+
98
+ it "should not modify source value" do
99
+ subject
100
+ expect(value).to eq("foo" => { "bar" => "baz" })
101
+ end
102
+ end
103
+
104
+ context "when value is an array of hashes" do
105
+ let(:value) { ["foo" => "bar"] }
106
+
107
+ it "should sanitize all hash values with a questionmark" do
108
+ expect(subject).to eq(["foo" => "?"])
109
+ end
110
+
111
+ it "should not modify source value" do
112
+ subject
113
+ expect(value).to eq(["foo" => "bar"])
114
+ end
115
+ end
116
+
117
+ context "when value is an array" do
118
+ let(:value) { %w[foo bar] }
119
+
120
+ it "should sanitize all hash values with a single questionmark" do
121
+ expect(subject).to eq(["?"])
122
+ end
123
+ end
124
+
125
+ context "when value is a mixed array" do
126
+ let(:value) { [nil, "foo", "bar"] }
127
+
128
+ it "should sanitize all hash values with a single questionmark" do
129
+ expect(subject).to eq(["?"])
130
+ end
131
+ end
132
+
133
+ context "when value is a string" do
134
+ let(:value) { "bar" }
135
+
136
+ it "should sanitize all hash values with a questionmark" do
137
+ expect(subject).to eq("?")
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ describe "key_sanitizer option" do
144
+ context "without key_sanitizer" do
145
+ subject { described_class.sanitize(value) }
146
+
147
+ context "when dots are in the key" do
148
+ let(:value) { { "foo.bar" => "bar" } }
149
+
150
+ it "should not sanitize the key" do
151
+ expect(subject).to eql("foo.bar" => "?")
152
+ end
153
+ end
154
+
155
+ context "when key is a symbol" do
156
+ let(:value) { { :ismaster => "bar" } }
157
+
158
+ it "should sanitize the key" do
159
+ expect(subject).to eql(:ismaster => "?")
160
+ end
161
+ end
162
+ end
163
+
164
+ context "with mongodb key_sanitizer" do
165
+ subject { described_class.sanitize(value, false, :mongodb) }
166
+
167
+ context "when no dots are in the key" do
168
+ let(:value) { { "foo" => "bar" } }
169
+
170
+ it "should not sanitize the key" do
171
+ expect(subject).to eql("foo" => "?")
172
+ end
173
+ end
174
+
175
+ context "when dots are in the key" do
176
+ let(:value) { { "foo.bar" => "bar" } }
177
+
178
+ it "should sanitize the key" do
179
+ expect(subject).to eql("foo.?" => "?")
180
+ end
181
+ end
182
+
183
+ context "when key is a symbol" do
184
+ let(:value) { { :ismaster => "bar" } }
185
+
186
+ it "should sanitize the key" do
187
+ expect(subject).to eql("ismaster" => "?")
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end