appsignal 1.4.0.beta.1 → 2.0.0.beta.1
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 +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
|