appsignal 0.12.beta.31 → 0.12.beta.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/Rakefile +1 -0
  4. data/benchmark.rake +20 -20
  5. data/ext/appsignal_extension.c +31 -23
  6. data/gemfiles/padrino.gemfile +7 -0
  7. data/lib/appsignal.rb +50 -27
  8. data/lib/appsignal/capistrano.rb +2 -1
  9. data/lib/appsignal/config.rb +94 -39
  10. data/lib/appsignal/event_formatter/active_record/sql_formatter.rb +12 -17
  11. data/lib/appsignal/integrations/padrino.rb +65 -0
  12. data/lib/appsignal/integrations/rails.rb +4 -2
  13. data/lib/appsignal/integrations/rake.rb +30 -0
  14. data/lib/appsignal/integrations/sidekiq.rb +2 -2
  15. data/lib/appsignal/integrations/sinatra.rb +0 -1
  16. data/lib/appsignal/js_exception_transaction.rb +4 -9
  17. data/lib/appsignal/params_sanitizer.rb +8 -5
  18. data/lib/appsignal/rack/rails_instrumentation.rb +41 -0
  19. data/lib/appsignal/rack/sinatra_instrumentation.rb +31 -24
  20. data/lib/appsignal/subscriber.rb +2 -9
  21. data/lib/appsignal/transaction.rb +86 -75
  22. data/lib/appsignal/transmitter.rb +30 -3
  23. data/lib/appsignal/version.rb +2 -2
  24. data/spec/lib/appsignal/cli_spec.rb +1 -1
  25. data/spec/lib/appsignal/config_spec.rb +38 -131
  26. data/spec/lib/appsignal/event_formatter/active_record/sql_formatter_spec.rb +27 -29
  27. data/spec/lib/appsignal/extension_spec.rb +11 -29
  28. data/spec/lib/appsignal/integrations/padrino_spec.rb +191 -0
  29. data/spec/lib/appsignal/integrations/rails_spec.rb +3 -4
  30. data/spec/lib/appsignal/integrations/rake_spec.rb +78 -0
  31. data/spec/lib/appsignal/integrations/resque_spec.rb +2 -2
  32. data/spec/lib/appsignal/integrations/sequel_spec.rb +2 -3
  33. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +22 -5
  34. data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -6
  35. data/spec/lib/appsignal/js_exception_transaction_spec.rb +4 -6
  36. data/spec/lib/appsignal/params_sanitizer_spec.rb +27 -11
  37. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +79 -0
  38. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +71 -71
  39. data/spec/lib/appsignal/subscriber_spec.rb +3 -37
  40. data/spec/lib/appsignal/transaction_spec.rb +290 -155
  41. data/spec/lib/appsignal/transmitter_spec.rb +10 -0
  42. data/spec/lib/appsignal_spec.rb +80 -47
  43. data/spec/spec_helper.rb +21 -2
  44. data/spec/support/helpers/env_helpers.rb +31 -0
  45. data/spec/support/helpers/notification_helpers.rb +1 -30
  46. data/spec/support/helpers/transaction_helpers.rb +7 -7
  47. data/spec/support/project_fixture/config/appsignal.yml +2 -0
  48. metadata +14 -8
  49. data/lib/appsignal/rack/instrumentation.rb +0 -32
  50. data/lib/appsignal/rack/listener.rb +0 -32
  51. data/spec/lib/appsignal/rack/instrumentation_spec.rb +0 -72
  52. data/spec/lib/appsignal/rack/listener_spec.rb +0 -104
@@ -60,13 +60,40 @@ module Appsignal
60
60
  end
61
61
 
62
62
  def http_client
63
- Net::HTTP.new(uri.host, uri.port).tap do |http|
63
+ client = if config[:http_proxy]
64
+ Net::HTTP.new(uri.host, uri.port, proxy_addr, proxy_port)
65
+ else
66
+ Net::HTTP.new(uri.host, uri.port)
67
+ end
68
+
69
+ client.tap do |http|
64
70
  if uri.scheme == 'https'
65
- http.use_ssl = true
71
+ http.use_ssl = true
72
+ http.ssl_version = :TLSv1
66
73
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
67
- http.ca_file = CA_FILE_PATH
74
+ http.ca_file = CA_FILE_PATH
68
75
  end
69
76
  end
70
77
  end
78
+
79
+ def proxy_uri
80
+ @proxy_uri ||= URI.parse(config[:http_proxy])
81
+ end
82
+
83
+ def proxy_addr
84
+ if config[:http_proxy]
85
+ proxy_uri.host
86
+ else
87
+ nil
88
+ end
89
+ end
90
+
91
+ def proxy_port
92
+ if config[:http_proxy]
93
+ proxy_uri.port
94
+ else
95
+ nil
96
+ end
97
+ end
71
98
  end
72
99
  end
@@ -1,4 +1,4 @@
1
1
  module Appsignal
2
- VERSION = '0.12.beta.31'
3
- AGENT_VERSION = '8cdd29b'
2
+ VERSION = '0.12.beta.32'
3
+ AGENT_VERSION = '246e4be'
4
4
  end
@@ -26,7 +26,7 @@ describe Appsignal::CLI do
26
26
  subject { cli.config }
27
27
 
28
28
  it { should be_instance_of(Appsignal::Config) }
29
- its(:loaded?) { should be_true }
29
+ its(:valid?) { should be_true }
30
30
  end
31
31
 
32
32
  it "should print the help with no arguments, -h and --help" do
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Appsignal::Config do
4
4
  subject { config }
5
5
 
6
- describe "when there is a config file" do
6
+ describe "with a config file" do
7
7
  let(:config) { project_fixture_config('production') }
8
8
 
9
9
  it "should not log an error" do
@@ -11,13 +11,13 @@ describe Appsignal::Config do
11
11
  subject
12
12
  end
13
13
 
14
- its(:loaded?) { should be_true }
14
+ its(:valid?) { should be_true }
15
15
  its(:active?) { should be_true }
16
16
 
17
17
  it "should merge with the default config and fill the config hash" do
18
18
  subject.config_hash.should == {
19
19
  :debug => false,
20
- :ignore_exceptions => [],
20
+ :ignore_errors => [],
21
21
  :ignore_actions => [],
22
22
  :instrument_net_http => true,
23
23
  :skip_session_data => false,
@@ -43,6 +43,8 @@ describe Appsignal::Config do
43
43
 
44
44
  describe "#write_to_environment" do
45
45
  before do
46
+ subject.config_hash[:http_proxy] = 'http://localhost'
47
+ subject.config_hash[:ignore_actions] = ['action1', 'action2']
46
48
  subject.write_to_environment
47
49
  end
48
50
 
@@ -57,6 +59,8 @@ describe Appsignal::Config do
57
59
  ENV['APPSIGNAL_APP_NAME'].should == 'TestApp'
58
60
  ENV['APPSIGNAL_ENVIRONMENT'].should == 'production'
59
61
  ENV['APPSIGNAL_AGENT_VERSION'].should == Appsignal::AGENT_VERSION
62
+ ENV['APPSIGNAL_HTTP_PROXY'].should == 'http://localhost'
63
+ ENV['APPSIGNAL_IGNORE_ACTIONS'].should == 'action1,action2'
60
64
  end
61
65
  end
62
66
 
@@ -66,14 +70,19 @@ describe Appsignal::Config do
66
70
  its(:active?) { should be_true }
67
71
  end
68
72
 
69
- context "and there's also an env var present" do
73
+ context "and there's config in the environment" do
70
74
  before do
71
75
  ENV['APPSIGNAL_PUSH_API_KEY'] = 'push_api_key'
76
+ ENV['APPSIGNAL_DEBUG'] = 'true'
72
77
  end
73
78
 
74
- it "should ignore the env var" do
79
+ it "should ignore env vars that are present in the config file" do
75
80
  subject[:push_api_key].should == 'abc'
76
81
  end
82
+
83
+ it "should use env vars that are not present in the config file" do
84
+ subject[:debug].should == true
85
+ end
77
86
  end
78
87
 
79
88
  context "and there is an initial config" do
@@ -85,12 +94,16 @@ describe Appsignal::Config do
85
94
  end
86
95
  end
87
96
 
88
- context "and there is an old-style api_key defined" do
97
+ context "and there is an old-style config" do
89
98
  let(:config) { project_fixture_config('old_api_key') }
90
99
 
91
100
  it "should fill the push_api_key with the old style key" do
92
101
  subject[:push_api_key].should == 'def'
93
102
  end
103
+
104
+ it "should fill ignore_errors with the old style ignore exceptions" do
105
+ subject[:ignore_errors].should == ['StandardError']
106
+ end
94
107
  end
95
108
  end
96
109
 
@@ -99,148 +112,42 @@ describe Appsignal::Config do
99
112
 
100
113
  it "should log an error" do
101
114
  Appsignal::Config.any_instance.should_receive(:carefully_log_error).with(
102
- "Not loading: config for 'nonsense' not found"
103
- )
115
+ "Not loading from config file: config for 'nonsense' not found"
116
+ ).once
117
+ Appsignal::Config.any_instance.should_receive(:carefully_log_error).with(
118
+ "Push api key not set after loading config"
119
+ ).once
104
120
  subject
105
121
  end
106
122
 
107
- its(:loaded?) { should be_false }
123
+ its(:valid?) { should be_false }
108
124
  its(:active?) { should be_false }
109
125
  end
110
126
 
111
127
  context "when there is no config file" do
112
- before do
113
- ENV.keys.select { |key| key.start_with?('APPSIGNAL_') }.each do |key|
114
- ENV[key] = nil
115
- end
116
- end
117
128
  let(:initial_config) { {} }
118
129
  let(:config) { Appsignal::Config.new('/nothing', 'production', initial_config) }
119
130
 
120
- it "should log an error" do
121
- Appsignal::Config.any_instance.should_receive(:carefully_log_error).with(
122
- "Not loading: No config file found at '/nothing/config/appsignal.yml' " \
123
- "and no APPSIGNAL_PUSH_API_KEY env var present"
124
- )
125
- subject
126
- end
127
-
128
- its(:loaded?) { should be_false }
131
+ its(:valid?) { should be_false }
129
132
  its(:active?) { should be_false }
130
133
 
131
- describe "#[]" do
132
- it "should return nil" do
133
- subject[:endpoint].should be_nil
134
- end
135
- end
136
-
137
- context "and an env var is present" do
134
+ context "with valid config in the environment" do
138
135
  before do
139
- ENV['APPSIGNAL_PUSH_API_KEY'] = 'push_api_key'
140
- end
141
-
142
- it "should not log an error" do
143
- Appsignal::Config.any_instance.should_not_receive(:carefully_log_error)
144
- subject
136
+ ENV['APPSIGNAL_PUSH_API_KEY'] = 'aaa-bbb-ccc'
137
+ ENV['APPSIGNAL_ACTIVE'] = 'true'
138
+ ENV['APPSIGNAL_APP_NAME'] = 'App name'
139
+ ENV['APPSIGNAL_DEBUG'] = 'true'
140
+ ENV['APPSIGNAL_IGNORE_ACTIONS'] = 'action1,action2'
145
141
  end
146
142
 
147
- its(:loaded?) { should be_true }
143
+ its(:valid?) { should be_true }
148
144
  its(:active?) { should be_true }
149
145
 
150
- it "should merge with the default config, fill the config hash and log about the missing name" do
151
- Appsignal.logger.should_receive(:debug).with(
152
- "There's no application name set in your config file or in the APPSIGNAL_APP_NAME env var. You should set one unless your app runs on Heroku."
153
- )
154
-
155
- subject.config_hash.should == {
156
- :debug => false,
157
- :push_api_key => 'push_api_key',
158
- :ignore_exceptions => [],
159
- :ignore_actions => [],
160
- :send_params => true,
161
- :instrument_net_http => true,
162
- :skip_session_data => false,
163
- :endpoint => 'https://push.appsignal.com',
164
- :active => true,
165
- :enable_frontend_error_catching => false,
166
- :frontend_error_catching_path => '/appsignal_error_catcher'
167
- }
168
- end
169
-
170
- context "and an initial config with a name is present" do
171
- let(:initial_config) { {:name => 'Initial Name'} }
172
-
173
- it "should merge with the config" do
174
- Appsignal.logger.should_not_receive(:debug)
175
- subject[:name].should == 'Initial Name'
176
- end
177
- end
178
-
179
- context "more config in environment" do
180
- context "APPSIGNAL_APP_NAME is set" do
181
- before do
182
- ENV['APPSIGNAL_APP_NAME'] = 'Name from env'
183
- end
184
-
185
- it "should set the name" do
186
- Appsignal.logger.should_not_receive(:debug)
187
- subject[:name].should == 'Name from env'
188
- end
189
- end
190
-
191
- context "APPSIGNAL_ACTIVE" do
192
- context "not present" do
193
- before do
194
- ENV.delete('APPSIGNAL_ACTIVE')
195
- end
196
-
197
- it "should still set active to true" do
198
- subject[:active].should be_true
199
- end
200
- end
201
-
202
- context "true" do
203
- before do
204
- ENV['APPSIGNAL_ACTIVE'] = 'true'
205
- end
206
-
207
- it "should set active to true" do
208
- subject[:active].should be_true
209
- end
210
- end
211
-
212
- context "false" do
213
- before do
214
- ENV['APPSIGNAL_ACTIVE'] = 'false'
215
- end
216
-
217
- it "should set active to false" do
218
- subject[:active].should be_false
219
- end
220
- end
221
- end
222
- end
223
-
224
- context "with only APPSIGNAL_API_KEY" do
225
- before do
226
- ENV.delete('APPSIGNAL_PUSH_API_KEY')
227
- ENV['APPSIGNAL_API_KEY'] = 'old_style_api_key'
228
- end
229
-
230
- it "should use the old style api key" do
231
- subject[:push_api_key].should == 'old_style_api_key'
232
- end
233
- end
234
-
235
- context "with both APPSIGNAL_PUSH_API_KEY and APPSIGNAL_API_KEY" do
236
- before do
237
- ENV['APPSIGNAL_API_KEY'] = 'old_style_api_key'
238
- end
239
-
240
- it "should use the new style push api key" do
241
- subject[:push_api_key].should == 'push_api_key'
242
- end
243
- end
146
+ its([:push_api_key]) { should == 'aaa-bbb-ccc' }
147
+ its([:active]) { should == true }
148
+ its([:name]) { should == 'App name' }
149
+ its([:debug]) { should == true }
150
+ its([:ignore_actions]) { should == ['action1', 'action2'] }
244
151
  end
245
152
  end
246
153
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- if rails_present?
3
+ if active_record_present?
4
4
  require 'active_record'
5
5
 
6
6
  describe Appsignal::EventFormatter::ActiveRecord::SqlFormatter do
@@ -57,14 +57,8 @@ if rails_present?
57
57
 
58
58
  it { should == ['Model load', "SELECT `table`.* FROM `table` WHERE `id` = ?"] }
59
59
 
60
- context "with an escaped single quote" do
61
- let(:sql) { "`id` = '\\'big\\' secret'" }
62
-
63
- it { should == ['Model load', "`id` = ?"] }
64
- end
65
-
66
- context "with an escaped double quote" do
67
- let(:sql) { "`id` = '\\\"big\\\" secret'" }
60
+ context "with escaped single quotes in the string" do
61
+ let(:sql) { "`id` = 'this is a \'big\' secret'" }
68
62
 
69
63
  it { should == ['Model load', "`id` = ?"] }
70
64
  end
@@ -75,34 +69,36 @@ if rails_present?
75
69
 
76
70
  it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` = ?'] }
77
71
 
78
- context "with an escaped single quote" do
79
- let(:sql) { '`id` = "\\\'big\\\' secret"' }
72
+ context "with escaped double quotes in the string" do
73
+ let(:sql) { '`id` = "this is a \"big\" secret"' }
80
74
 
81
75
  it { should == ['Model load', "`id` = ?"] }
82
76
  end
77
+ end
83
78
 
84
- context "with an escaped double quote" do
85
- let(:sql) { '`id` = "\\"big\\" secret"' }
79
+ context "numeric parameter" do
80
+ context "integer" do
81
+ let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` = 1' }
86
82
 
87
- it { should == ['Model load', "`id` = ?"] }
83
+ it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` = ?'] }
88
84
  end
89
- end
90
85
 
91
- context "numeric parameter" do
92
- let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` = 1' }
86
+ context "float" do
87
+ let(:sql) { 'SELECT `table`.* FROM `table` WHERE `value` = 10.0' }
93
88
 
94
- it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` = ?'] }
89
+ it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `value` = ?'] }
90
+ end
95
91
  end
96
92
 
97
- context "parameter array" do
93
+ context "in operator with params" do
98
94
  let(:sql) { 'SELECT `table`.* FROM `table` WHERE `id` IN (1, 2)' }
99
95
 
100
96
  it { should == ['Model load', 'SELECT `table`.* FROM `table` WHERE `id` IN (?)'] }
101
97
  end
102
98
  end
103
99
 
104
- context "with double quote style table names and no prepared statements" do
105
- let(:connection_config) { {:adapter => 'postgresql', :prepared_statements => false} }
100
+ context "with double quote style table names" do
101
+ let(:connection_config) { {:adapter => 'postgresql'} }
106
102
 
107
103
  context "single quoted data value" do
108
104
  let(:sql) { "SELECT \"table\".* FROM \"table\" WHERE \"id\" = 'secret'" }
@@ -110,22 +106,24 @@ if rails_present?
110
106
  it { should == ['Model load', "SELECT \"table\".* FROM \"table\" WHERE \"id\" = ?"] }
111
107
 
112
108
  context "with an escaped single quote" do
113
- let(:sql) { "\"id\" = '\\'big\\' secret'" }
109
+ let(:sql) { "\"id\" = 'this is a \'big\' secret'" }
114
110
 
115
111
  it { should == ['Model load', "\"id\" = ?"] }
116
112
  end
113
+ end
117
114
 
118
- context "with an escaped double quote" do
119
- let(:sql) { "\"id\" = '\\\"big\\\" secret'" }
115
+ context "numeric parameter" do
116
+ context "integer" do
117
+ let(:sql) { 'SELECT "table".* FROM "table" WHERE "id"=1' }
120
118
 
121
- it { should == ['Model load', "\"id\" = ?"] }
119
+ it { should == ['Model load', 'SELECT "table".* FROM "table" WHERE "id"=?'] }
122
120
  end
123
- end
124
121
 
125
- context "numeric parameter" do
126
- let(:sql) { 'SELECT "table".* FROM "table" WHERE "id"=1' }
122
+ context "float" do
123
+ let(:sql) { 'SELECT "table".* FROM "table" WHERE "value"=10.0' }
127
124
 
128
- it { should == ['Model load', 'SELECT "table".* FROM "table" WHERE "id"=?'] }
125
+ it { should == ['Model load', 'SELECT "table".* FROM "table" WHERE "value"=?'] }
126
+ end
129
127
  end
130
128
  end
131
129
 
@@ -18,7 +18,7 @@ describe Appsignal::Extension do
18
18
  end
19
19
 
20
20
  it "should have a start_transaction method" do
21
- subject.start_transaction('request_id')
21
+ subject.start_transaction('request_id', 'http_request')
22
22
  end
23
23
 
24
24
  it "should have a start_event method" do
@@ -26,45 +26,27 @@ describe Appsignal::Extension do
26
26
  end
27
27
 
28
28
  it "should have a finish_event method" do
29
- subject.finish_event(
30
- 1,
31
- 'name',
32
- 'title',
33
- 'body'
34
- )
29
+ subject.finish_event(1, 'name', 'title', 'body')
35
30
  end
36
31
 
37
32
  it "should have a set_transaction_error method" do
38
- subject.set_transaction_error(
39
- 1,
40
- 'name',
41
- 'message'
42
- )
33
+ subject.set_transaction_error(1, 'name', 'message')
43
34
  end
44
35
 
45
36
  it "should have a set_transaction_error_data method" do
46
- subject.set_transaction_error_data(
47
- 1,
48
- 'params',
49
- '{}'
50
- )
37
+ subject.set_transaction_error_data(1, 'params', '{}')
51
38
  end
52
39
 
53
- it "should have a set_transaction_base_data method" do
54
- subject.set_transaction_base_data(
55
- 1,
56
- 'kind',
57
- 'action',
58
- 100
59
- )
40
+ it "should have a set_transaction_action method" do
41
+ subject.set_transaction_action(1, 'value')
42
+ end
43
+
44
+ it "should have a set_transaction_queue_start method" do
45
+ subject.set_transaction_queue_start(1, 10)
60
46
  end
61
47
 
62
48
  it "should have a set_transaction_metadata method" do
63
- subject.set_transaction_metadata(
64
- 1,
65
- 'key',
66
- 'value'
67
- )
49
+ subject.set_transaction_metadata(1, 'key', 'value')
68
50
  end
69
51
 
70
52
  it "should have a finish_transaction method" do