appsignal 1.4.0.beta.1 → 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -17
- data/README.md +6 -5
- data/ext/agent.yml +11 -11
- data/lib/appsignal.rb +20 -19
- data/lib/appsignal/cli.rb +5 -7
- data/lib/appsignal/cli/diagnose.rb +133 -41
- data/lib/appsignal/cli/notify_of_deploy.rb +26 -11
- data/lib/appsignal/config.rb +9 -5
- data/lib/appsignal/integrations/grape.rb +23 -16
- data/lib/appsignal/js_exception_transaction.rb +3 -3
- data/lib/appsignal/marker.rb +4 -3
- data/lib/appsignal/rack/js_exception_catcher.rb +11 -4
- data/lib/appsignal/utils.rb +0 -12
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/capistrano2_spec.rb +7 -7
- data/spec/lib/appsignal/capistrano3_spec.rb +7 -7
- data/spec/lib/appsignal/cli/diagnose_spec.rb +329 -22
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +144 -96
- data/spec/lib/appsignal/cli_spec.rb +1 -18
- data/spec/lib/appsignal/config_spec.rb +27 -2
- data/spec/lib/appsignal/hooks/rake_spec.rb +35 -52
- data/spec/lib/appsignal/integrations/grape_spec.rb +172 -63
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +76 -36
- data/spec/lib/appsignal/marker_spec.rb +5 -5
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +49 -9
- data/spec/lib/appsignal_spec.rb +18 -7
- data/spec/support/helpers/cli_helpers.rb +17 -0
- data/spec/support/helpers/env_helpers.rb +2 -1
- metadata +5 -6
- data/lib/appsignal/params_sanitizer.rb +0 -13
- data/lib/tasks/diag.rake +0 -79
@@ -1,122 +1,170 @@
|
|
1
|
-
require
|
1
|
+
require "appsignal/cli"
|
2
2
|
|
3
3
|
describe Appsignal::CLI::NotifyOfDeploy do
|
4
|
+
include CLIHelpers
|
5
|
+
|
4
6
|
let(:out_stream) { StringIO.new }
|
5
|
-
let(:
|
6
|
-
let(:config) { Appsignal::Config.new(project_fixture_path, {}) }
|
7
|
-
let(:marker_data) { {:revision => 'aaaaa', :user => 'thijs', :environment => 'production'} }
|
8
|
-
before do
|
9
|
-
config.stub(:active? => true)
|
10
|
-
end
|
7
|
+
let(:output) { out_stream.string }
|
11
8
|
around do |example|
|
12
9
|
capture_stdout(out_stream) { example.run }
|
13
10
|
end
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
define :include_deploy_notification do
|
13
|
+
match do |log|
|
14
|
+
log.include?("Notifying AppSignal of deploy with: ") &&
|
15
|
+
log.include?("AppSignal has been notified of this deploy!")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
define :include_deploy_notification_with do |options|
|
19
|
+
match do |log|
|
20
|
+
return false unless options
|
21
|
+
values = "revision: #{options[:revision]}, user: #{options[:user]}"
|
22
|
+
log.include?("Notifying AppSignal of deploy with: #{values}") &&
|
23
|
+
log.include?("AppSignal has been notified of this deploy!")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
define :include_config_error do
|
27
|
+
match do |log|
|
28
|
+
log.include? "Error: No valid config found."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
define :include_missing_options do |options|
|
32
|
+
match do |log|
|
33
|
+
log.include? "Error: Missing options: #{options.join(", ")}"
|
25
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def run
|
38
|
+
run_cli("notify_of_deploy", options)
|
39
|
+
end
|
26
40
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
kind_of(Appsignal::Config)
|
35
|
-
).and_return(marker)
|
36
|
-
marker.should_receive(:transmit)
|
37
|
-
|
38
|
-
cli.run(marker_data, config)
|
41
|
+
context "without config" do
|
42
|
+
let(:config) { Appsignal::Config.new(tmp_dir, "production") }
|
43
|
+
let(:options) { {} }
|
44
|
+
around do |example|
|
45
|
+
Dir.chdir tmp_dir do
|
46
|
+
example.run
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
|
-
it "
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
marker = double
|
46
|
-
Appsignal::Marker.should_receive(:new).with(
|
47
|
-
{
|
48
|
-
:revision => 'aaaaa',
|
49
|
-
:user => 'thijs'
|
50
|
-
},
|
51
|
-
kind_of(Appsignal::Config)
|
52
|
-
).and_return(marker)
|
53
|
-
marker.should_receive(:transmit)
|
54
|
-
|
55
|
-
cli.run(marker_data, config)
|
50
|
+
it "prints a config error" do
|
51
|
+
expect { run }.to raise_error(SystemExit)
|
52
|
+
expect(output).to include_config_error
|
53
|
+
expect(output).to_not include_deploy_notification
|
56
54
|
end
|
57
55
|
end
|
58
56
|
|
59
|
-
|
60
|
-
let(:
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
:
|
65
|
-
|
66
|
-
|
67
|
-
:option_2 => 2,
|
68
|
-
:option_3 => 3
|
69
|
-
},
|
70
|
-
required_options
|
71
|
-
)
|
72
|
-
out_stream.string.should be_empty
|
57
|
+
context "with config" do
|
58
|
+
let(:config) { project_fixture_config }
|
59
|
+
before do
|
60
|
+
config[:name] = options[:name] if options[:name]
|
61
|
+
stub_api_request config, "markers", {
|
62
|
+
:revision => options[:revision],
|
63
|
+
:user => options[:user]
|
64
|
+
}
|
73
65
|
end
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
:validate_required_options,
|
79
|
-
{
|
80
|
-
:option_1 => 1,
|
81
|
-
:option_2 => 2
|
82
|
-
},
|
83
|
-
required_options
|
84
|
-
)
|
85
|
-
}.should raise_error(SystemExit)
|
86
|
-
out_stream.string.should include('Missing options: option_3')
|
66
|
+
around do |example|
|
67
|
+
Dir.chdir project_fixture_path do
|
68
|
+
example.run
|
69
|
+
end
|
87
70
|
end
|
88
71
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
)
|
99
|
-
|
100
|
-
|
72
|
+
context "without environment" do
|
73
|
+
let(:options) { {:environment => "", :revision => "foo", :user => "thijs"} }
|
74
|
+
before do
|
75
|
+
# Makes the config "active"
|
76
|
+
ENV["APPSIGNAL_PUSH_API_KEY"] = "foo"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "requires environment option" do
|
80
|
+
expect { run }.to raise_error(SystemExit)
|
81
|
+
expect(output).to include_missing_options(%w(environment))
|
82
|
+
expect(output).to_not include_deploy_notification
|
83
|
+
end
|
101
84
|
end
|
102
|
-
end
|
103
85
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
86
|
+
context "without known environment" do
|
87
|
+
let(:options) { {:environment => "foo"} }
|
88
|
+
|
89
|
+
it "prints a config error" do
|
90
|
+
expect { run }.to raise_error(SystemExit)
|
91
|
+
expect(output).to include_config_error
|
92
|
+
expect(output).to_not include_missing_options([])
|
93
|
+
expect(output).to_not include_deploy_notification
|
109
94
|
end
|
110
95
|
end
|
111
96
|
|
112
|
-
context "
|
113
|
-
|
97
|
+
context "with known environment" do
|
98
|
+
context "without required options" do
|
99
|
+
let(:options) { {:environment => "production"} }
|
100
|
+
|
101
|
+
it "prints a missing required options error" do
|
102
|
+
expect { run }.to raise_error(SystemExit)
|
103
|
+
expect(output).to_not include_config_error
|
104
|
+
expect(output).to include_missing_options(%w(revision user))
|
105
|
+
expect(output).to_not include_deploy_notification
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with empty required option" do
|
109
|
+
let(:options) { {:environment => "production", :revision => "foo", :user => ""} }
|
110
|
+
|
111
|
+
it "prints a missing required option error" do
|
112
|
+
expect { run }.to raise_error(SystemExit)
|
113
|
+
expect(output).to_not include_config_error
|
114
|
+
expect(output).to include_missing_options(%w(user))
|
115
|
+
expect(output).to_not include_deploy_notification
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "with required options" do
|
121
|
+
let(:options) { {:environment => "production", :revision => "aaaaa", :user => "thijs"} }
|
122
|
+
|
123
|
+
it "notifies of a deploy" do
|
124
|
+
run
|
125
|
+
expect(output).to_not include_config_error
|
126
|
+
expect(output).to_not include_missing_options([])
|
127
|
+
expect(output).to include_deploy_notification_with(options)
|
128
|
+
end
|
129
|
+
|
130
|
+
context "with no app name configured" do
|
131
|
+
before { ENV["APPSIGNAL_APP_NAME"] = "" }
|
132
|
+
|
133
|
+
context "without name option" do
|
134
|
+
let(:options) { {:environment => "production", :revision => "aaaaa", :user => "thijs"} }
|
135
|
+
|
136
|
+
it "requires name option" do
|
137
|
+
expect { run }.to raise_error(SystemExit)
|
138
|
+
expect(output).to_not include_config_error
|
139
|
+
expect(output).to include_missing_options(%w(name))
|
140
|
+
expect(output).to_not include_deploy_notification
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with name option" do
|
145
|
+
let(:options) { {:environment => "production", :revision => "aaaaa", :user => "thijs", :name => "foo"} }
|
146
|
+
|
147
|
+
it "notifies of a deploy with a custom name" do
|
148
|
+
run
|
149
|
+
expect(output).to_not include_config_error
|
150
|
+
expect(output).to_not include_missing_options([])
|
151
|
+
expect(output).to include_deploy_notification_with(options)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "with name option" do
|
157
|
+
let(:options) do
|
158
|
+
{:environment => "production", :revision => "aaaaa", :user => "thijs", :name => "foo"}
|
159
|
+
end
|
114
160
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
161
|
+
it "notifies of a deploy with a custom name" do
|
162
|
+
run
|
163
|
+
expect(output).to_not include_config_error
|
164
|
+
expect(output).to_not include_missing_options([])
|
165
|
+
expect(output).to include_deploy_notification_with(options)
|
166
|
+
end
|
167
|
+
end
|
120
168
|
end
|
121
169
|
end
|
122
170
|
end
|
@@ -35,7 +35,7 @@ describe Appsignal::CLI do
|
|
35
35
|
cli.run([arg])
|
36
36
|
}.should raise_error(SystemExit)
|
37
37
|
|
38
|
-
out_stream.string.should include '
|
38
|
+
out_stream.string.should include 'AppSignal'
|
39
39
|
out_stream.string.should include '.'
|
40
40
|
end
|
41
41
|
end
|
@@ -72,21 +72,4 @@ describe Appsignal::CLI do
|
|
72
72
|
])
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
76
|
-
describe "notify_of_deploy" do
|
77
|
-
it "should call Appsignal::Install.install" do
|
78
|
-
Appsignal::CLI::NotifyOfDeploy.should_receive(:run).with(
|
79
|
-
{:revision=>"aaaaa", :user=>"thijs", :environment=>"production"},
|
80
|
-
instance_of(Appsignal::Config)
|
81
|
-
)
|
82
|
-
|
83
|
-
cli.run([
|
84
|
-
'notify_of_deploy',
|
85
|
-
'--name=project-production',
|
86
|
-
'--revision=aaaaa',
|
87
|
-
'--user=thijs',
|
88
|
-
'--environment=production'
|
89
|
-
])
|
90
|
-
end
|
91
|
-
end
|
92
75
|
end
|
@@ -29,6 +29,26 @@ describe Appsignal::Config do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
describe ":log" do
|
34
|
+
subject { config[:log] }
|
35
|
+
|
36
|
+
context "when running on Heroku" do
|
37
|
+
around { |example| recognize_as_heroku { example.run } }
|
38
|
+
|
39
|
+
it "is set to stdout" do
|
40
|
+
expect(subject).to eq("stdout")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when not running on Heroku" do
|
45
|
+
around { |example| recognize_as_container(:none) { example.run } }
|
46
|
+
|
47
|
+
it "is set to file" do
|
48
|
+
expect(subject).to eq("file")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
32
52
|
end
|
33
53
|
|
34
54
|
describe "initial config" do
|
@@ -46,6 +66,7 @@ describe Appsignal::Config do
|
|
46
66
|
it "merges with the default config" do
|
47
67
|
expect(config.config_hash).to eq(
|
48
68
|
:debug => false,
|
69
|
+
:log => 'file',
|
49
70
|
:ignore_errors => [],
|
50
71
|
:ignore_actions => [],
|
51
72
|
:filter_parameters => [],
|
@@ -319,7 +340,7 @@ describe Appsignal::Config do
|
|
319
340
|
expect(ENV['APPSIGNAL_APP_NAME']).to eq 'TestApp'
|
320
341
|
expect(ENV['APPSIGNAL_ENVIRONMENT']).to eq 'production'
|
321
342
|
expect(ENV['APPSIGNAL_AGENT_VERSION']).to eq Appsignal::Extension.agent_version
|
322
|
-
expect(ENV['APPSIGNAL_LANGUAGE_INTEGRATION_VERSION']).to eq Appsignal::VERSION
|
343
|
+
expect(ENV['APPSIGNAL_LANGUAGE_INTEGRATION_VERSION']).to eq "ruby-#{Appsignal::VERSION}"
|
323
344
|
expect(ENV['APPSIGNAL_HTTP_PROXY']).to eq 'http://localhost'
|
324
345
|
expect(ENV['APPSIGNAL_IGNORE_ACTIONS']).to eq 'action1,action2'
|
325
346
|
expect(ENV['APPSIGNAL_FILTER_PARAMETERS']).to eq 'password,confirm_password'
|
@@ -349,7 +370,11 @@ describe Appsignal::Config do
|
|
349
370
|
let(:stdout) { StringIO.new }
|
350
371
|
let(:config) { project_fixture_config('production', :log_path => log_path) }
|
351
372
|
subject { config.log_file_path }
|
352
|
-
around
|
373
|
+
around do |example|
|
374
|
+
recognize_as_container(:none) do
|
375
|
+
capture_stdout(stdout) { example.run }
|
376
|
+
end
|
377
|
+
end
|
353
378
|
|
354
379
|
context "when path is writable" do
|
355
380
|
let(:log_path) { File.join(tmp_dir, 'writable-path') }
|
@@ -1,72 +1,55 @@
|
|
1
1
|
require 'rake'
|
2
2
|
|
3
3
|
describe Appsignal::Hooks::RakeHook do
|
4
|
-
let(:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
:execute_without_appsignal => true
|
10
|
-
)
|
11
|
-
end
|
12
|
-
before :all do
|
13
|
-
Appsignal::Hooks::RakeHook.new.install
|
4
|
+
let(:task) { Rake::Task.new('task:name', Rake::Application.new) }
|
5
|
+
before(:all) do
|
6
|
+
Appsignal.config = project_fixture_config
|
7
|
+
expect(Appsignal.active?).to be_true
|
8
|
+
Appsignal::Hooks.load_hooks
|
14
9
|
end
|
15
10
|
|
16
11
|
describe "#execute" do
|
17
|
-
context "
|
18
|
-
|
19
|
-
|
20
|
-
before do
|
21
|
-
transaction.stub(:set_action)
|
22
|
-
transaction.stub(:set_error)
|
23
|
-
transaction.stub(:complete)
|
24
|
-
SecureRandom.stub(:uuid => '123')
|
25
|
-
Appsignal::Transaction.stub(:create => transaction)
|
26
|
-
Appsignal.stub(:active? => true)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should call the original task" do
|
30
|
-
expect( task ).to receive(:execute_without_appsignal).with('foo')
|
12
|
+
context "without error" do
|
13
|
+
it "creates no transaction" do
|
14
|
+
expect(Appsignal::Transaction).to_not receive(:create)
|
31
15
|
end
|
32
16
|
|
33
|
-
it "
|
34
|
-
expect(
|
17
|
+
it "calls the original task" do
|
18
|
+
expect(task).to receive(:execute_without_appsignal).with('foo')
|
35
19
|
end
|
36
20
|
|
37
|
-
|
38
|
-
|
21
|
+
after { task.execute('foo') }
|
22
|
+
end
|
39
23
|
|
40
|
-
|
41
|
-
|
42
|
-
|
24
|
+
context "with error" do
|
25
|
+
let(:error) { VerySpecificError.new }
|
26
|
+
let(:transaction) { background_job_transaction }
|
27
|
+
before do
|
28
|
+
task.enhance { raise error }
|
43
29
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
30
|
+
expect(Appsignal::Transaction).to receive(:create).with(
|
31
|
+
kind_of(String),
|
32
|
+
Appsignal::Transaction::BACKGROUND_JOB,
|
33
|
+
kind_of(Appsignal::Transaction::GenericRequest)
|
34
|
+
).and_return(transaction)
|
35
|
+
end
|
51
36
|
|
52
|
-
|
53
|
-
|
54
|
-
|
37
|
+
it "sets the action" do
|
38
|
+
expect(transaction).to receive(:set_action).with('task:name')
|
39
|
+
end
|
55
40
|
|
56
|
-
|
57
|
-
|
58
|
-
|
41
|
+
it "sets the error" do
|
42
|
+
expect(transaction).to receive(:set_error).with(error)
|
43
|
+
end
|
59
44
|
|
60
|
-
|
61
|
-
|
62
|
-
|
45
|
+
it "completes the transaction and stops" do
|
46
|
+
expect(transaction).to receive(:complete).ordered
|
47
|
+
expect(Appsignal).to receive(:stop).with('rake').ordered
|
48
|
+
end
|
63
49
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
50
|
+
after do
|
51
|
+
expect { task.execute('foo') }.to raise_error VerySpecificError
|
67
52
|
end
|
68
53
|
end
|
69
|
-
|
70
|
-
after { task.execute('foo') rescue VerySpecificError }
|
71
54
|
end
|
72
55
|
end
|