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
@@ -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
|