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
@@ -2,9 +2,15 @@ module Appsignal
|
|
2
2
|
class CLI
|
3
3
|
class NotifyOfDeploy
|
4
4
|
class << self
|
5
|
-
def run(options
|
5
|
+
def run(options)
|
6
|
+
config = config_for(options[:environment])
|
7
|
+
config[:name] = options[:name] if options[:name]
|
8
|
+
|
6
9
|
validate_active_config(config)
|
7
|
-
|
10
|
+
required_config = [:revision, :user]
|
11
|
+
required_config << :environment if config.env.empty?
|
12
|
+
required_config << :name if !config[:name] || config[:name].empty?
|
13
|
+
validate_required_options(options, required_config)
|
8
14
|
|
9
15
|
Appsignal::Marker.new(
|
10
16
|
{
|
@@ -15,24 +21,33 @@ module Appsignal
|
|
15
21
|
).transmit
|
16
22
|
end
|
17
23
|
|
18
|
-
|
24
|
+
private
|
19
25
|
|
20
26
|
def validate_required_options(options, required_options)
|
21
27
|
missing = required_options.select do |required_option|
|
22
28
|
val = options[required_option]
|
23
29
|
val.nil? || (val.respond_to?(:empty?) && val.empty?)
|
24
30
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
31
|
+
return unless missing.any?
|
32
|
+
|
33
|
+
puts "Error: Missing options: #{missing.join(', ')}"
|
34
|
+
exit 1
|
29
35
|
end
|
30
36
|
|
31
37
|
def validate_active_config(config)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
38
|
+
return if config.active?
|
39
|
+
|
40
|
+
puts "Error: No valid config found."
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
def config_for(environment)
|
45
|
+
Appsignal::Config.new(
|
46
|
+
Dir.pwd,
|
47
|
+
environment,
|
48
|
+
{},
|
49
|
+
Logger.new(StringIO.new)
|
50
|
+
)
|
36
51
|
end
|
37
52
|
end
|
38
53
|
end
|
data/lib/appsignal/config.rb
CHANGED
@@ -8,6 +8,7 @@ module Appsignal
|
|
8
8
|
SYSTEM_TMP_DIR = '/tmp'
|
9
9
|
DEFAULT_CONFIG = {
|
10
10
|
:debug => false,
|
11
|
+
:log => 'file',
|
11
12
|
:ignore_errors => [],
|
12
13
|
:ignore_actions => [],
|
13
14
|
:filter_parameters => [],
|
@@ -35,6 +36,7 @@ module Appsignal
|
|
35
36
|
'APPSIGNAL_PUSH_API_ENDPOINT' => :endpoint,
|
36
37
|
'APPSIGNAL_FRONTEND_ERROR_CATCHING_PATH' => :frontend_error_catching_path,
|
37
38
|
'APPSIGNAL_DEBUG' => :debug,
|
39
|
+
'APPSIGNAL_LOG' => :log,
|
38
40
|
'APPSIGNAL_LOG_PATH' => :log_path,
|
39
41
|
'APPSIGNAL_INSTRUMENT_NET_HTTP' => :instrument_net_http,
|
40
42
|
'APPSIGNAL_INSTRUMENT_REDIS' => :instrument_redis,
|
@@ -96,7 +98,7 @@ module Appsignal
|
|
96
98
|
if File.writable? SYSTEM_TMP_DIR
|
97
99
|
$stdout.puts "appsignal: Unable to log to '#{path}'. Logging to "\
|
98
100
|
"'#{SYSTEM_TMP_DIR}' instead. Please check the "\
|
99
|
-
"permissions for the application's log directory."
|
101
|
+
"permissions for the application's (log) directory."
|
100
102
|
File.join(SYSTEM_TMP_DIR, 'appsignal.log')
|
101
103
|
else
|
102
104
|
$stdout.puts "appsignal: Unable to log to '#{path}' or the "\
|
@@ -119,7 +121,7 @@ module Appsignal
|
|
119
121
|
ENV['APPSIGNAL_AGENT_PATH'] = File.expand_path('../../../ext', __FILE__).to_s
|
120
122
|
ENV['APPSIGNAL_ENVIRONMENT'] = env
|
121
123
|
ENV['APPSIGNAL_AGENT_VERSION'] = Appsignal::Extension.agent_version
|
122
|
-
ENV['APPSIGNAL_LANGUAGE_INTEGRATION_VERSION'] = Appsignal::VERSION
|
124
|
+
ENV['APPSIGNAL_LANGUAGE_INTEGRATION_VERSION'] = "ruby-#{Appsignal::VERSION}"
|
123
125
|
ENV['APPSIGNAL_DEBUG_LOGGING'] = config_hash[:debug].to_s
|
124
126
|
ENV['APPSIGNAL_LOG_FILE_PATH'] = log_file_path.to_s if log_file_path
|
125
127
|
ENV['APPSIGNAL_PUSH_API_ENDPOINT'] = config_hash[:endpoint]
|
@@ -146,7 +148,8 @@ module Appsignal
|
|
146
148
|
end
|
147
149
|
|
148
150
|
def detect_from_system
|
149
|
-
|
151
|
+
config_hash[:running_in_container] = true if Appsignal::System.container?
|
152
|
+
config_hash[:log] = 'stdout' if Appsignal::System.heroku?
|
150
153
|
end
|
151
154
|
|
152
155
|
def load_from_disk
|
@@ -184,8 +187,9 @@ module Appsignal
|
|
184
187
|
|
185
188
|
# Configuration with string type
|
186
189
|
%w(APPSIGNAL_PUSH_API_KEY APPSIGNAL_APP_NAME APPSIGNAL_PUSH_API_ENDPOINT
|
187
|
-
APPSIGNAL_FRONTEND_ERROR_CATCHING_PATH APPSIGNAL_HTTP_PROXY
|
188
|
-
|
190
|
+
APPSIGNAL_FRONTEND_ERROR_CATCHING_PATH APPSIGNAL_HTTP_PROXY
|
191
|
+
APPSIGNAL_LOG APPSIGNAL_LOG_PATH APPSIGNAL_WORKING_DIR_PATH
|
192
|
+
APPSIGNAL_HOSTNAME APPSIGNAL_CA_FILE_PATH).each do |var|
|
189
193
|
if env_var = ENV[var]
|
190
194
|
config[ENV_TO_KEY_MAPPING[var]] = env_var
|
191
195
|
end
|
@@ -1,41 +1,48 @@
|
|
1
1
|
module Appsignal
|
2
2
|
module Grape
|
3
3
|
class Middleware < ::Grape::Middleware::Base
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
4
|
def call(env)
|
9
5
|
if Appsignal.active?
|
10
6
|
call_with_appsignal_monitoring(env)
|
11
7
|
else
|
12
|
-
|
8
|
+
app.call(env)
|
13
9
|
end
|
14
10
|
end
|
15
11
|
|
16
12
|
def call_with_appsignal_monitoring(env)
|
17
|
-
request
|
18
|
-
transaction
|
13
|
+
request = ::Rack::Request.new(env)
|
14
|
+
transaction = Appsignal::Transaction.create(
|
19
15
|
SecureRandom.uuid,
|
20
16
|
Appsignal::Transaction::HTTP_REQUEST,
|
21
17
|
request
|
22
18
|
)
|
23
19
|
begin
|
24
|
-
|
20
|
+
app.call(env)
|
25
21
|
rescue => error
|
26
22
|
transaction.set_error(error)
|
27
23
|
raise error
|
28
24
|
ensure
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
request_method = request.request_method
|
26
|
+
path = request.path # Path without namespaces
|
27
|
+
endpoint = env["api.endpoint"]
|
28
|
+
|
29
|
+
if endpoint && endpoint.options
|
30
|
+
options = endpoint.options
|
31
|
+
request_method = options[:method].first
|
32
|
+
klass = options[:for]
|
33
|
+
namespace = endpoint.namespace
|
34
|
+
namespace = "" if namespace == "/"
|
35
|
+
|
36
|
+
path = options[:path].first.to_s
|
37
|
+
path = "/#{path}" if path[0] != "/"
|
38
|
+
path = "#{namespace}#{path}"
|
39
|
+
|
40
|
+
transaction.set_action("#{request_method}::#{klass}##{path}")
|
35
41
|
end
|
42
|
+
|
36
43
|
transaction.set_http_or_background_queue_start
|
37
|
-
transaction.set_metadata(
|
38
|
-
transaction.set_metadata(
|
44
|
+
transaction.set_metadata("path", path)
|
45
|
+
transaction.set_metadata("method", request_method)
|
39
46
|
Appsignal::Transaction.complete_current!
|
40
47
|
end
|
41
48
|
end
|
@@ -14,7 +14,7 @@ module Appsignal
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def set_action
|
17
|
-
@ext.set_action(@data['action'])
|
17
|
+
@ext.set_action(@data['action']) if @data['action']
|
18
18
|
end
|
19
19
|
|
20
20
|
def set_metadata
|
@@ -26,8 +26,8 @@ module Appsignal
|
|
26
26
|
def set_error
|
27
27
|
@ext.set_error(
|
28
28
|
@data['name'],
|
29
|
-
@data['message'],
|
30
|
-
Appsignal::Utils.data_generate(@data['backtrace'])
|
29
|
+
@data['message'] || '',
|
30
|
+
Appsignal::Utils.data_generate(@data['backtrace'] || [])
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
data/lib/appsignal/marker.rb
CHANGED
@@ -10,16 +10,17 @@ module Appsignal
|
|
10
10
|
|
11
11
|
def transmit
|
12
12
|
transmitter = Transmitter.new(ACTION, config)
|
13
|
-
puts "Notifying
|
13
|
+
puts "Notifying AppSignal of deploy with: "\
|
14
14
|
"revision: #{marker_data[:revision]}, user: #{marker_data[:user]}"
|
15
|
+
|
15
16
|
result = transmitter.transmit(marker_data)
|
16
17
|
if result == '200'
|
17
|
-
puts '
|
18
|
+
puts 'AppSignal has been notified of this deploy!'
|
18
19
|
else
|
19
20
|
raise "#{result} at #{transmitter.uri}"
|
20
21
|
end
|
21
22
|
rescue => e
|
22
|
-
puts "Something went wrong while trying to notify
|
23
|
+
puts "Something went wrong while trying to notify AppSignal: #{e}"
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
@@ -8,11 +8,18 @@ module Appsignal
|
|
8
8
|
|
9
9
|
def call(env)
|
10
10
|
if env['PATH_INFO'] == Appsignal.config[:frontend_error_catching_path]
|
11
|
-
body
|
12
|
-
transaction = JSExceptionTransaction.new(body)
|
13
|
-
transaction.complete!
|
11
|
+
body = JSON.parse(env['rack.input'].read)
|
14
12
|
|
15
|
-
|
13
|
+
if body['name'].is_a?(String) && body['name'].length > 0
|
14
|
+
transaction = JSExceptionTransaction.new(body)
|
15
|
+
transaction.complete!
|
16
|
+
code = 200
|
17
|
+
else
|
18
|
+
Appsignal.logger.debug "JSExceptionCatcher: Could not send exception, 'name' is empty."
|
19
|
+
code = 422
|
20
|
+
end
|
21
|
+
|
22
|
+
return [code, {}, []]
|
16
23
|
else
|
17
24
|
@app.call(env)
|
18
25
|
end
|
data/lib/appsignal/utils.rb
CHANGED
@@ -3,17 +3,6 @@ require 'appsignal/utils/query_params_sanitizer'
|
|
3
3
|
|
4
4
|
module Appsignal
|
5
5
|
module Utils
|
6
|
-
module ClassMethods
|
7
|
-
extend Gem::Deprecate
|
8
|
-
|
9
|
-
def sanitize(params, only_top_level = false, key_sanitizer = nil)
|
10
|
-
QueryParamsSanitizer.sanitize(params, only_top_level, key_sanitizer)
|
11
|
-
end
|
12
|
-
|
13
|
-
deprecate :sanitize, "AppSignal::Utils::QueryParamsSanitizer.sanitize", 2016, 9
|
14
|
-
end
|
15
|
-
extend ClassMethods
|
16
|
-
|
17
6
|
def self.data_generate(body)
|
18
7
|
Data.generate(body)
|
19
8
|
end
|
@@ -126,5 +115,4 @@ module Appsignal
|
|
126
115
|
end
|
127
116
|
end
|
128
117
|
end
|
129
|
-
|
130
118
|
end
|
data/lib/appsignal/version.rb
CHANGED
@@ -134,8 +134,8 @@ if DependencyHelper.capistrano2_present?
|
|
134
134
|
capistrano_config.find_and_execute_task('appsignal:deploy')
|
135
135
|
|
136
136
|
expect(out_stream.string).to include \
|
137
|
-
'Notifying
|
138
|
-
'
|
137
|
+
'Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman',
|
138
|
+
'AppSignal has been notified of this deploy!'
|
139
139
|
end
|
140
140
|
|
141
141
|
context "with overridden revision" do
|
@@ -147,8 +147,8 @@ if DependencyHelper.capistrano2_present?
|
|
147
147
|
|
148
148
|
it "transmits the overriden revision" do
|
149
149
|
expect(out_stream.string).to include \
|
150
|
-
'Notifying
|
151
|
-
'
|
150
|
+
'Notifying AppSignal of deploy with: revision: abc123, user: batman',
|
151
|
+
'AppSignal has been notified of this deploy!'
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -161,9 +161,9 @@ if DependencyHelper.capistrano2_present?
|
|
161
161
|
it "does not transmit marker" do
|
162
162
|
output = out_stream.string
|
163
163
|
expect(output).to include \
|
164
|
-
'Notifying
|
165
|
-
'Something went wrong while trying to notify
|
166
|
-
expect(output).to_not include '
|
164
|
+
'Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman',
|
165
|
+
'Something went wrong while trying to notify AppSignal:'
|
166
|
+
expect(output).to_not include 'AppSignal has been notified of this deploy!'
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
@@ -135,8 +135,8 @@ if DependencyHelper.capistrano3_present?
|
|
135
135
|
invoke('appsignal:deploy')
|
136
136
|
|
137
137
|
expect(out_stream.string).to include \
|
138
|
-
'Notifying
|
139
|
-
'
|
138
|
+
'Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman',
|
139
|
+
'AppSignal has been notified of this deploy!'
|
140
140
|
end
|
141
141
|
|
142
142
|
context "with overridden revision" do
|
@@ -148,8 +148,8 @@ if DependencyHelper.capistrano3_present?
|
|
148
148
|
|
149
149
|
it "transmits the overriden revision" do
|
150
150
|
expect(out_stream.string).to include \
|
151
|
-
'Notifying
|
152
|
-
'
|
151
|
+
'Notifying AppSignal of deploy with: revision: abc123, user: batman',
|
152
|
+
'AppSignal has been notified of this deploy!'
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
@@ -162,9 +162,9 @@ if DependencyHelper.capistrano3_present?
|
|
162
162
|
it "does not transmit marker" do
|
163
163
|
output = out_stream.string
|
164
164
|
expect(output).to include \
|
165
|
-
'Notifying
|
166
|
-
'Something went wrong while trying to notify
|
167
|
-
expect(output).to_not include '
|
165
|
+
'Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman',
|
166
|
+
'Something went wrong while trying to notify AppSignal:'
|
167
|
+
expect(output).to_not include 'AppSignal has been notified of this deploy!'
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
@@ -1,29 +1,336 @@
|
|
1
|
-
require
|
1
|
+
require "appsignal/cli"
|
2
2
|
|
3
3
|
describe Appsignal::CLI::Diagnose do
|
4
|
-
let(:out_stream) { StringIO.new }
|
5
|
-
let(:config) { project_fixture_config }
|
6
|
-
let(:cli) { described_class }
|
7
|
-
around do |example|
|
8
|
-
capture_stdout(out_stream) { example.run }
|
9
|
-
end
|
10
|
-
|
11
4
|
describe ".run" do
|
5
|
+
let(:out_stream) { StringIO.new }
|
6
|
+
let(:config) { project_fixture_config }
|
7
|
+
let(:cli) { described_class }
|
8
|
+
let(:output) { out_stream.string }
|
12
9
|
before do
|
13
|
-
|
14
|
-
stub_api_request config,
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
10
|
+
ENV["APPSIGNAL_APP_ENV"] = "production"
|
11
|
+
stub_api_request config, "auth"
|
12
|
+
end
|
13
|
+
after { Appsignal.config = nil }
|
14
|
+
around { |example| capture_stdout(out_stream) { example.run } }
|
15
|
+
|
16
|
+
def run
|
17
|
+
run_within_dir project_fixture_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_within_dir(chdir)
|
21
|
+
Dir.chdir chdir do
|
22
|
+
cli.run
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "outputs header and support text" do
|
27
|
+
run
|
28
|
+
expect(output).to include \
|
29
|
+
"AppSignal diagnose",
|
30
|
+
"http://docs.appsignal.com/",
|
31
|
+
"support@appsignal.com"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "outputs version numbers" do
|
35
|
+
run
|
36
|
+
gem_path = Bundler::CLI::Common.select_spec("appsignal").full_gem_path.strip
|
37
|
+
expect(output).to include \
|
38
|
+
"Gem version: #{Appsignal::VERSION}",
|
39
|
+
"Agent version: #{Appsignal::Extension.agent_version}",
|
40
|
+
"Gem install path: #{gem_path}"
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "host information" do
|
44
|
+
it "outputs host information" do
|
45
|
+
run
|
46
|
+
expect(output).to include \
|
47
|
+
"Host information",
|
48
|
+
"Architecture: #{RbConfig::CONFIG["host_cpu"]}",
|
49
|
+
"Operating System: #{RbConfig::CONFIG["host_os"]}",
|
50
|
+
"Ruby version: #{RbConfig::CONFIG["RUBY_VERSION_NAME"]}"
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "Heroku detection" do
|
54
|
+
context "when not on Heroku" do
|
55
|
+
before { recognize_as_container(:none) { run } }
|
56
|
+
|
57
|
+
it "does not output Heroku detection" do
|
58
|
+
expect(output).to_not include("Heroku:")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when on Heroku" do
|
63
|
+
before { recognize_as_heroku { run } }
|
64
|
+
|
65
|
+
it "outputs Heroku detection" do
|
66
|
+
expect(output).to include("Heroku: true")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "container detection" do
|
72
|
+
context "when not in container" do
|
73
|
+
before { recognize_as_container(:none) { run } }
|
74
|
+
|
75
|
+
it "does not output container detection" do
|
76
|
+
expect(output).to_not include("Container id:")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when in container" do
|
81
|
+
before { recognize_as_container(:docker) { run } }
|
82
|
+
|
83
|
+
it "outputs container information" do
|
84
|
+
expect(output).to include \
|
85
|
+
"Container id: 0c703b75cdeaad7c933aa68b4678cc5c37a12d5ef5d7cb52c9cefe684d98e575"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "configuration" do
|
92
|
+
context "without extension" do
|
93
|
+
before do
|
94
|
+
# When the extension isn't loaded the Appsignal.start operation exits
|
95
|
+
# early and doesn't load the configuration.
|
96
|
+
# Happens when the extension wasn't installed properly.
|
97
|
+
Appsignal.extension_loaded = false
|
98
|
+
run
|
99
|
+
end
|
100
|
+
after { Appsignal.extension_loaded = true }
|
101
|
+
|
102
|
+
it "outputs an error" do
|
103
|
+
expect(output).to include \
|
104
|
+
"Error: No config found!\nCould not start AppSignal."
|
105
|
+
end
|
106
|
+
|
107
|
+
it "outputs as much as it can" do
|
108
|
+
expect(output).to include \
|
109
|
+
"AppSignal agent\n Gem version: #{Appsignal::VERSION}",
|
110
|
+
"Host information\n Architecture: ",
|
111
|
+
%(Extension install log\n Path: "),
|
112
|
+
%(Makefile install log\n Path: ")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "without environment" do
|
117
|
+
let(:config) { project_fixture_config("") }
|
118
|
+
before do
|
119
|
+
ENV["APPSIGNAL_APP_ENV"] = ""
|
120
|
+
recognize_as_container(:none) { run }
|
121
|
+
end
|
122
|
+
|
123
|
+
it "outputs a warning that no config is loaded" do
|
124
|
+
expect(output).to_not include "Error"
|
125
|
+
expect(output).to include \
|
126
|
+
"Environment: \n Warning: No environment set, no config loaded!",
|
127
|
+
" APPSIGNAL_APP_ENV=production appsignal diagnose"
|
128
|
+
end
|
129
|
+
|
130
|
+
it "outputs config defaults" do
|
131
|
+
expect(output).to include("Configuration")
|
132
|
+
Appsignal::Config::DEFAULT_CONFIG.each do |key, value|
|
133
|
+
expect(output).to include("#{key}: #{value}")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "with configured environment" do
|
139
|
+
before { run }
|
140
|
+
|
141
|
+
it "outputs environment" do
|
142
|
+
expect(output).to include("Environment: production")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "outputs configuration" do
|
146
|
+
expect(output).to include("Configuration")
|
147
|
+
expect(output).to_not include "Error"
|
148
|
+
Appsignal.config.config_hash.each do |key, value|
|
149
|
+
expect(output).to include("#{key}: #{value}")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "with unconfigured environment" do
|
155
|
+
let(:config) { project_fixture_config("foobar") }
|
156
|
+
before do
|
157
|
+
ENV["APPSIGNAL_APP_ENV"] = "foobar"
|
158
|
+
recognize_as_container(:none) { run }
|
159
|
+
end
|
160
|
+
|
161
|
+
it "outputs environment" do
|
162
|
+
expect(output).to include("Environment: foobar")
|
163
|
+
end
|
164
|
+
|
165
|
+
it "outputs config defaults" do
|
166
|
+
expect(output).to include("Configuration")
|
167
|
+
expect(output).to_not include "Error"
|
168
|
+
Appsignal::Config::DEFAULT_CONFIG.each do |key, value|
|
169
|
+
expect(output).to include("#{key}: #{value}")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "API key validation" do
|
176
|
+
context "with valid key" do
|
177
|
+
before do
|
178
|
+
stub_api_request(config, "auth").to_return(:status => 200)
|
179
|
+
run
|
180
|
+
end
|
181
|
+
|
182
|
+
it "outputs valid" do
|
183
|
+
expect(output).to include("Validating API key: Valid")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "with invalid key" do
|
188
|
+
before do
|
189
|
+
stub_api_request(config, "auth").to_return(:status => 401)
|
190
|
+
run
|
191
|
+
end
|
192
|
+
|
193
|
+
it "outputs invalid" do
|
194
|
+
expect(output).to include("Validating API key: Invalid")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "with invalid key" do
|
199
|
+
before do
|
200
|
+
stub_api_request(config, "auth").to_return(:status => 500)
|
201
|
+
run
|
202
|
+
end
|
203
|
+
|
204
|
+
it "outputs failure with status code" do
|
205
|
+
expect(output).to include("Validating API key: Failed with status 500")
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "paths" do
|
211
|
+
before { FileUtils.mkdir_p(root_path) }
|
212
|
+
|
213
|
+
context "when a directory is writable" do
|
214
|
+
let(:root_path) { File.join(tmp_dir, "writable_path") }
|
215
|
+
let(:log_file) { File.join(root_path, "appsignal.log") }
|
216
|
+
let(:config) { Appsignal::Config.new(root_path, "production") }
|
217
|
+
|
218
|
+
context "without log file" do
|
219
|
+
before { run_within_dir root_path }
|
220
|
+
|
221
|
+
it "outputs writable" do
|
222
|
+
expect(output).to include \
|
223
|
+
"Required paths",
|
224
|
+
%(root_path: "#{root_path}" - Writable),
|
225
|
+
%(log_file_path: "#{log_file}" - Does not exist)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "with log file" do
|
230
|
+
context "when writable" do
|
231
|
+
before do
|
232
|
+
FileUtils.touch(log_file)
|
233
|
+
run_within_dir root_path
|
234
|
+
end
|
235
|
+
|
236
|
+
it "lists log file as writable" do
|
237
|
+
expect(output).to include \
|
238
|
+
%(root_path: "#{root_path}" - Writable),
|
239
|
+
%(log_file_path: "#{File.join(root_path, "appsignal.log")}" - Writable)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context "when not writable" do
|
244
|
+
before do
|
245
|
+
FileUtils.touch(log_file)
|
246
|
+
FileUtils.chmod(0444, log_file)
|
247
|
+
run_within_dir root_path
|
248
|
+
end
|
249
|
+
|
250
|
+
it "lists log file as not writable" do
|
251
|
+
expect(output).to include \
|
252
|
+
%(root_path: "#{root_path}" - Writable),
|
253
|
+
%(log_file_path: "#{File.join(root_path, "appsignal.log")}" - Not writable)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "when a directory is not writable" do
|
260
|
+
let(:root_path) { File.join(tmp_dir, "not_writable_path") }
|
261
|
+
let(:config) { Appsignal::Config.new(root_path, "production") }
|
262
|
+
before do
|
263
|
+
FileUtils.chmod(0555, root_path)
|
264
|
+
run_within_dir root_path
|
265
|
+
end
|
266
|
+
|
267
|
+
it "outputs not writable" do
|
268
|
+
expect(output).to include \
|
269
|
+
"Required paths",
|
270
|
+
%(root_path: "#{root_path}" - Not writable),
|
271
|
+
%(log_file_path: "" - Not writable)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
after { FileUtils.rm_rf(root_path) }
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "logs" do
|
279
|
+
shared_examples "ext log file" do |log_file|
|
280
|
+
let(:ext_path) { File.join(gem_path, "ext") }
|
281
|
+
let(:log_path) { File.join(ext_path, log_file) }
|
282
|
+
before do
|
283
|
+
allow(cli).to receive(:gem_path).and_return(gem_path)
|
284
|
+
end
|
285
|
+
|
286
|
+
context "when file exists" do
|
287
|
+
let(:gem_path) { File.join(tmp_dir, "gem") }
|
288
|
+
before do
|
289
|
+
FileUtils.mkdir_p ext_path
|
290
|
+
File.open log_path, "a" do |f|
|
291
|
+
f.write "log line 1"
|
292
|
+
f.write "log line 2"
|
293
|
+
end
|
294
|
+
run
|
295
|
+
end
|
296
|
+
|
297
|
+
it "outputs install.log" do
|
298
|
+
expect(output).to include \
|
299
|
+
%(Path: "#{log_path}"),
|
300
|
+
"log line 1",
|
301
|
+
"log line 2"
|
302
|
+
end
|
303
|
+
|
304
|
+
after { FileUtils.rm_rf(gem_path) }
|
305
|
+
end
|
306
|
+
|
307
|
+
context "when file does not exist" do
|
308
|
+
let(:gem_path) { File.join(tmp_dir, "non_existent_path") }
|
309
|
+
before { run }
|
310
|
+
|
311
|
+
it "outputs install.log" do
|
312
|
+
expect(output).to include %(Path: "#{log_path}"\n File not found.)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "install.log" do
|
318
|
+
it_behaves_like "ext log file", "install.log"
|
319
|
+
|
320
|
+
it "outputs header" do
|
321
|
+
run
|
322
|
+
expect(output).to include("Extension install log")
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
describe "mkmf.log" do
|
327
|
+
it_behaves_like "ext log file", "mkmf.log"
|
328
|
+
|
329
|
+
it "outputs header" do
|
330
|
+
run
|
331
|
+
expect(output).to include("Extension install log")
|
332
|
+
end
|
333
|
+
end
|
27
334
|
end
|
28
335
|
end
|
29
336
|
end
|