appsignal 0.6.7 → 0.7.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.gitignore +3 -2
- data/.travis.yml +11 -11
- data/CHANGELOG.md +6 -0
- data/README.md +26 -0
- data/Rakefile +32 -3
- data/appsignal.gemspec +25 -16
- data/gemfiles/no_dependencies.gemfile +3 -0
- data/gemfiles/{3.0.gemfile → rails-3.0.gemfile} +2 -1
- data/gemfiles/{3.1.gemfile → rails-3.1.gemfile} +2 -1
- data/gemfiles/{3.2.gemfile → rails-3.2.gemfile} +2 -1
- data/gemfiles/{4.0.gemfile → rails-4.0.gemfile} +2 -1
- data/gemfiles/sinatra.gemfile +5 -0
- data/lib/appsignal.rb +30 -25
- data/lib/appsignal/agent.rb +37 -17
- data/lib/appsignal/aggregator.rb +2 -4
- data/lib/appsignal/aggregator/middleware.rb +4 -0
- data/lib/appsignal/aggregator/middleware/action_view_sanitizer.rb +23 -0
- data/lib/appsignal/aggregator/middleware/active_record_sanitizer.rb +64 -0
- data/lib/appsignal/aggregator/middleware/chain.rb +101 -0
- data/lib/appsignal/aggregator/middleware/delete_blanks.rb +16 -0
- data/lib/appsignal/aggregator/post_processor.rb +21 -18
- data/lib/appsignal/auth_check.rb +7 -21
- data/lib/appsignal/capistrano.rb +1 -36
- data/lib/appsignal/cli.rb +30 -46
- data/lib/appsignal/config.rb +46 -61
- data/lib/appsignal/integrations/capistrano.rb +44 -0
- data/lib/appsignal/{careful_logger.rb → integrations/capistrano/careful_logger.rb} +2 -0
- data/lib/appsignal/integrations/passenger.rb +6 -6
- data/lib/appsignal/integrations/rails.rb +33 -0
- data/lib/appsignal/integrations/sinatra.rb +20 -0
- data/lib/appsignal/marker.rb +9 -10
- data/lib/appsignal/rack/instrumentation.rb +28 -0
- data/lib/appsignal/rack/listener.rb +33 -0
- data/lib/appsignal/transaction.rb +18 -12
- data/lib/appsignal/transaction/formatter.rb +96 -0
- data/lib/appsignal/transaction/params_sanitizer.rb +80 -78
- data/lib/appsignal/transmitter.rb +10 -9
- data/lib/appsignal/version.rb +1 -1
- data/lib/generators/appsignal/appsignal_generator.rb +20 -21
- data/lib/generators/appsignal/templates/appsignal.yml +15 -21
- data/spec/{appsignal → lib/appsignal}/agent_spec.rb +69 -1
- data/spec/lib/appsignal/aggregator/middleware/action_view_sanitizer_spec.rb +32 -0
- data/spec/lib/appsignal/aggregator/middleware/active_record_sanitizer_spec.rb +215 -0
- data/spec/{appsignal → lib/appsignal/aggregator}/middleware/chain_spec.rb +5 -5
- data/spec/{appsignal → lib/appsignal/aggregator}/middleware/delete_blanks_spec.rb +2 -2
- data/spec/{appsignal → lib/appsignal}/aggregator/post_processor_spec.rb +15 -6
- data/spec/{appsignal → lib/appsignal}/aggregator_spec.rb +4 -1
- data/spec/{appsignal → lib/appsignal}/auth_check_spec.rb +8 -23
- data/spec/{appsignal → lib/appsignal}/cli_spec.rb +65 -66
- data/spec/lib/appsignal/config_spec.rb +132 -0
- data/spec/lib/appsignal/integrations/capistrano_spec.rb +123 -0
- data/spec/{appsignal → lib/appsignal}/integrations/passenger_spec.rb +0 -1
- data/spec/lib/appsignal/integrations/rails_spec.rb +38 -0
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +43 -0
- data/spec/{appsignal → lib/appsignal}/marker_spec.rb +20 -23
- data/spec/lib/appsignal/rack/instrumentation_spec.rb +49 -0
- data/spec/{appsignal → lib/appsignal/rack}/listener_spec.rb +39 -6
- data/spec/{appsignal/transaction/transaction_formatter_spec.rb → lib/appsignal/transaction/formatter_spec.rb} +29 -6
- data/spec/{appsignal → lib/appsignal}/transaction/params_sanitizer_spec.rb +13 -12
- data/spec/{appsignal → lib/appsignal}/transaction_spec.rb +52 -7
- data/spec/{appsignal → lib/appsignal}/transmitter_spec.rb +27 -20
- data/spec/lib/appsignal_spec.rb +230 -0
- data/spec/lib/generators/appsignal/appsignal_generator_spec.rb +166 -0
- data/spec/lib/tmp/config/appsignal.yml +2 -0
- data/spec/spec_helper.rb +29 -20
- data/spec/support/delegate_matcher.rb +0 -1
- data/spec/support/fixtures/generated_config.yml +20 -0
- data/{log/.gitkeep → spec/support/fixtures/uploaded_file.txt} +0 -0
- data/spec/support/helpers/config_helpers.rb +24 -0
- data/spec/support/helpers/notification_helpers.rb +0 -2
- data/spec/support/helpers/transaction_helpers.rb +17 -2
- data/spec/support/project_fixture/config/appsignal.yml +18 -0
- data/spec/support/project_fixture/log/.gitkeep +0 -0
- data/spec/support/rails/my_app.rb +6 -0
- metadata +99 -83
- data/config/appsignal.yml +0 -10
- data/lib/appsignal/listener.rb +0 -21
- data/lib/appsignal/middleware.rb +0 -3
- data/lib/appsignal/middleware/action_view_sanitizer.rb +0 -21
- data/lib/appsignal/middleware/active_record_sanitizer.rb +0 -62
- data/lib/appsignal/middleware/chain.rb +0 -99
- data/lib/appsignal/middleware/delete_blanks.rb +0 -12
- data/lib/appsignal/railtie.rb +0 -37
- data/lib/appsignal/to_appsignal_hash.rb +0 -21
- data/lib/appsignal/transaction/transaction_formatter.rb +0 -67
- data/spec/appsignal/capistrano_spec.rb +0 -81
- data/spec/appsignal/config_spec.rb +0 -177
- data/spec/appsignal/inactive_railtie_spec.rb +0 -32
- data/spec/appsignal/middleware/action_view_sanitizer_spec.rb +0 -27
- data/spec/appsignal/middleware/active_record_sanitizer_spec.rb +0 -212
- data/spec/appsignal/railtie_spec.rb +0 -74
- data/spec/appsignal/to_appsignal_hash_spec.rb +0 -29
- data/spec/appsignal_spec.rb +0 -195
- data/spec/generators/appsignal/appsignal_generator_spec.rb +0 -181
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Appsignal
|
4
|
+
class Transaction
|
5
|
+
class Formatter < SimpleDelegator
|
6
|
+
def initialize(transaction)
|
7
|
+
super(transaction)
|
8
|
+
end
|
9
|
+
|
10
|
+
def hash
|
11
|
+
@hash ||= default_hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
merge_process_action_event_with_log_entry! if process_action_event
|
16
|
+
add_http_queue_duration_to_hash!
|
17
|
+
if exception?
|
18
|
+
add_exception_to_hash!
|
19
|
+
add_tags_to_hash!
|
20
|
+
end
|
21
|
+
add_events_to_hash! if slow_request?
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def default_hash
|
28
|
+
{
|
29
|
+
:request_id => request_id,
|
30
|
+
:log_entry => {
|
31
|
+
:path => fullpath,
|
32
|
+
:kind => 'http_request',
|
33
|
+
:time => time,
|
34
|
+
:environment => sanitized_environment,
|
35
|
+
:session_data => sanitized_session_data
|
36
|
+
},
|
37
|
+
:failed => exception?
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def merge_process_action_event_with_log_entry!
|
42
|
+
hash[:log_entry].merge!(event_to_hash(process_action_event))
|
43
|
+
hash[:log_entry].tap do |o|
|
44
|
+
o.merge!(o.delete(:payload))
|
45
|
+
o.delete(:action)
|
46
|
+
o.delete(:controller)
|
47
|
+
o.delete(:name)
|
48
|
+
o[:action] = action
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_http_queue_duration_to_hash!
|
53
|
+
start = http_queue_start
|
54
|
+
if start
|
55
|
+
hash[:log_entry][:queue_duration] = hash[:log_entry][:time] - start
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_tags_to_hash!
|
60
|
+
hash[:log_entry][:tags] = tags
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_exception_to_hash!
|
64
|
+
hash[:exception] = {
|
65
|
+
:exception => exception.class.name,
|
66
|
+
:message => exception.message,
|
67
|
+
:backtrace => clean_backtrace(exception)
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def clean_backtrace(exception)
|
72
|
+
if defined?(::Rails)
|
73
|
+
::Rails.backtrace_cleaner.clean(exception.backtrace, nil)
|
74
|
+
else
|
75
|
+
exception.backtrace
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_events_to_hash!
|
80
|
+
hash[:events] = events.map do |event|
|
81
|
+
event_to_hash(event)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def event_to_hash(event)
|
86
|
+
{
|
87
|
+
:name => event.name,
|
88
|
+
:duration => event.duration,
|
89
|
+
:time => event.time.to_f,
|
90
|
+
:end => event.end.to_f,
|
91
|
+
:payload => event.payload
|
92
|
+
}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -1,113 +1,115 @@
|
|
1
1
|
module Appsignal
|
2
|
-
class
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def sanitize!(params)
|
9
|
-
ParamsSanitizerDestructive.sanitize_value(params)
|
10
|
-
end
|
2
|
+
class Transaction
|
3
|
+
class ParamsSanitizer
|
4
|
+
class << self
|
5
|
+
def sanitize(params)
|
6
|
+
ParamsSanitizerCopy.sanitize_value(params)
|
7
|
+
end
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
def sanitize!(params)
|
10
|
+
ParamsSanitizerDestructive.sanitize_value(params)
|
11
|
+
end
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
def scrub(params)
|
14
|
+
ParamsSanitizerCopyScrub.sanitize_value(params)
|
15
|
+
end
|
19
16
|
|
20
|
-
|
17
|
+
def scrub!(params)
|
18
|
+
ParamsSanitizerDestructiveScrub.sanitize_value(params)
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
21
|
+
protected
|
22
|
+
|
23
|
+
def sanitize_value(value)
|
24
|
+
case value
|
25
|
+
when Hash
|
26
|
+
sanitize_hash(value)
|
27
|
+
when Array
|
28
|
+
sanitize_array(value)
|
29
|
+
when Fixnum, String, Symbol
|
30
|
+
unmodified(value)
|
31
|
+
else
|
32
|
+
inspected(value)
|
33
|
+
end
|
32
34
|
end
|
33
|
-
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
def sanitize_hash_with_target(source_hash, target_hash)
|
37
|
+
source_hash.each_pair do |key, value|
|
38
|
+
target_hash[key] = sanitize_value(value)
|
39
|
+
end
|
40
|
+
target_hash
|
38
41
|
end
|
39
|
-
target_hash
|
40
|
-
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
def sanitize_array_with_target(source_array, target_array)
|
44
|
+
source_array.each_with_index do |item, index|
|
45
|
+
target_array[index] = sanitize_value(item)
|
46
|
+
end
|
47
|
+
target_array
|
45
48
|
end
|
46
|
-
target_array
|
47
|
-
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
50
|
+
def unmodified(value)
|
51
|
+
value
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
-
|
54
|
+
def inspected(value)
|
55
|
+
value.inspect
|
56
|
+
end
|
55
57
|
end
|
56
58
|
end
|
57
|
-
end
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
60
|
+
class ParamsSanitizerCopy < ParamsSanitizer
|
61
|
+
class << self
|
62
|
+
protected
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
def sanitize_hash(hash)
|
65
|
+
sanitize_hash_with_target(hash, {})
|
66
|
+
end
|
66
67
|
|
67
|
-
|
68
|
-
|
68
|
+
def sanitize_array(array)
|
69
|
+
sanitize_array_with_target(array, [])
|
70
|
+
end
|
69
71
|
end
|
70
72
|
end
|
71
|
-
end
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
74
|
+
class ParamsSanitizerDestructive < ParamsSanitizer
|
75
|
+
class << self
|
76
|
+
protected
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
|
78
|
+
def sanitize_hash(hash)
|
79
|
+
sanitize_hash_with_target(hash, hash)
|
80
|
+
end
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
def sanitize_array(array)
|
83
|
+
sanitize_array_with_target(array, array)
|
84
|
+
end
|
83
85
|
end
|
84
86
|
end
|
85
|
-
end
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
class ParamsSanitizerCopyScrub < ParamsSanitizerCopy
|
89
|
+
class << self
|
90
|
+
protected
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
92
|
+
def unmodified(value)
|
93
|
+
'?'
|
94
|
+
end
|
94
95
|
|
95
|
-
|
96
|
-
|
96
|
+
def inspected(value)
|
97
|
+
'?'
|
98
|
+
end
|
97
99
|
end
|
98
100
|
end
|
99
|
-
end
|
100
101
|
|
101
|
-
|
102
|
-
|
103
|
-
|
102
|
+
class ParamsSanitizerDestructiveScrub < ParamsSanitizerDestructive
|
103
|
+
class << self
|
104
|
+
protected
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
106
|
+
def unmodified(value)
|
107
|
+
'?'
|
108
|
+
end
|
108
109
|
|
109
|
-
|
110
|
-
|
110
|
+
def inspected(value)
|
111
|
+
'?'
|
112
|
+
end
|
111
113
|
end
|
112
114
|
end
|
113
115
|
end
|
@@ -7,21 +7,21 @@ module Appsignal
|
|
7
7
|
class Transmitter
|
8
8
|
CONTENT_TYPE = 'application/json; charset=UTF-8'.freeze
|
9
9
|
CONTENT_ENCODING = 'gzip'.freeze
|
10
|
-
CA_FILE_PATH = File.
|
11
|
-
expand_path(File.join(__FILE__, '../../../resources/cacert.pem'))
|
10
|
+
CA_FILE_PATH = File.expand_path(File.join(__FILE__, '../../../resources/cacert.pem'))
|
12
11
|
|
13
|
-
attr_reader :
|
12
|
+
attr_reader :config, :action
|
14
13
|
|
15
|
-
def initialize(
|
16
|
-
@endpoint = endpoint
|
14
|
+
def initialize(action, config=Appsignal.config)
|
17
15
|
@action = action
|
18
|
-
@
|
16
|
+
@config = config
|
19
17
|
end
|
20
18
|
|
21
19
|
def uri
|
22
|
-
@uri ||= URI("#{
|
23
|
-
uri.query = Rack::Utils.build_query({
|
24
|
-
:api_key =>
|
20
|
+
@uri ||= URI("#{config[:endpoint]}/#{action}").tap do |uri|
|
21
|
+
uri.query = ::Rack::Utils.build_query({
|
22
|
+
:api_key => config[:push_api_key],
|
23
|
+
:name => config[:name],
|
24
|
+
:environment => config.env,
|
25
25
|
:hostname => Socket.gethostname,
|
26
26
|
:gem_version => Appsignal::VERSION
|
27
27
|
})
|
@@ -29,6 +29,7 @@ module Appsignal
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def transmit(payload)
|
32
|
+
Appsignal.logger.debug "Transmitting payload to #{uri}"
|
32
33
|
http_client.request(http_post(payload)).code
|
33
34
|
end
|
34
35
|
|
data/lib/appsignal/version.rb
CHANGED
@@ -1,33 +1,27 @@
|
|
1
1
|
require 'appsignal'
|
2
2
|
|
3
3
|
class AppsignalGenerator < Rails::Generators::Base
|
4
|
-
EXCLUDED_ENVIRONMENTS = [
|
4
|
+
EXCLUDED_ENVIRONMENTS = ['test'].freeze
|
5
5
|
|
6
6
|
source_root File.expand_path('../templates', __FILE__)
|
7
|
-
argument :
|
8
|
-
|
9
|
-
desc "Install the config file for AppSignal with your PUSH_KEY."
|
7
|
+
argument :push_api_key, :type => :string
|
8
|
+
desc 'Generate a config file for AppSignal'
|
10
9
|
|
11
10
|
def copy_config_file
|
12
11
|
template_file = 'appsignal.yml'
|
13
|
-
|
14
|
-
if File.exists?(
|
15
|
-
say_status(:error,
|
16
|
-
say_status(:error, "Add the following to config/appsignal.yml:\n\n", :red)
|
17
|
-
say_status(:error, "#{environment}:", :red)
|
18
|
-
say_status(:error, " api_key: #{push_key}\n\n", :red)
|
19
|
-
say_status(:info, "Then run:\n\n", :red)
|
20
|
-
say_status(:info, " appsignal api_check", :red)
|
12
|
+
destination_file = File.join('config', template_file)
|
13
|
+
if File.exists?(destination_file)
|
14
|
+
say_status(:error, 'Looks like you already have a config file', :red)
|
21
15
|
else
|
22
|
-
template
|
23
|
-
|
24
|
-
|
16
|
+
template(template_file, destination_file)
|
17
|
+
add_appsignal_require_for_capistrano
|
18
|
+
check_push_api_key
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
28
22
|
protected
|
29
23
|
|
30
|
-
def
|
24
|
+
def add_appsignal_require_for_capistrano
|
31
25
|
deploy_file = File.expand_path(File.join('config', 'deploy.rb'))
|
32
26
|
cap_file = File.expand_path('Capfile')
|
33
27
|
if [deploy_file, cap_file].all? { |file| File.exists?(file) }
|
@@ -43,8 +37,15 @@ class AppsignalGenerator < Rails::Generators::Base
|
|
43
37
|
end
|
44
38
|
end
|
45
39
|
|
46
|
-
def
|
47
|
-
|
40
|
+
def config
|
41
|
+
Appsignal::Config.new(
|
42
|
+
Rails.root,
|
43
|
+
'development'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def check_push_api_key
|
48
|
+
auth_check = ::Appsignal::AuthCheck.new(config, Appsignal.logger)
|
48
49
|
status, result = auth_check.perform_with_result
|
49
50
|
if status == '200'
|
50
51
|
say_status :success, result
|
@@ -55,11 +56,9 @@ class AppsignalGenerator < Rails::Generators::Base
|
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
|
-
alias :selected_environment :environment
|
59
|
-
|
60
59
|
def environments
|
61
60
|
@environments ||= Dir.glob(
|
62
61
|
File.join(%w(. config environments *.rb))
|
63
|
-
).map { |o| File.basename(o, ".rb") } - EXCLUDED_ENVIRONMENTS
|
62
|
+
).map { |o| File.basename(o, ".rb") }.sort - EXCLUDED_ENVIRONMENTS
|
64
63
|
end
|
65
64
|
end
|
@@ -1,25 +1,19 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# AppSignal. (required)
|
9
|
-
#
|
10
|
-
# It is possible to use ERB.
|
11
|
-
# api_key: "<%%= ENV['APPSIGNAL_API_KEY'] %>"
|
12
|
-
api_key: "<%= push_key %>"
|
1
|
+
default: &defaults
|
2
|
+
# Your push api key, it is possible to set this dynamically using ERB:
|
3
|
+
# push_api_key: "<%%= ENV['APPSIGNAL_PUSH_API_KEY'] %>"
|
4
|
+
push_api_key: "<%= push_api_key %>"
|
5
|
+
|
6
|
+
# Your app's name
|
7
|
+
name: "<%= Rails.application.class.parent_name %>"
|
13
8
|
|
14
|
-
# The cuttoff point above which a request is considered slow
|
9
|
+
# The cuttoff point in ms above which a request is considered slow, default is 200
|
15
10
|
# slow_request_threshold: 200
|
16
11
|
|
17
|
-
|
12
|
+
# Configuration per environment, leave out an environment or set active
|
13
|
+
# to false to not push metrics for that environment.
|
14
|
+
<% environments.each do |environment| -%>
|
15
|
+
<%= environment %>:
|
16
|
+
<<: *defaults
|
18
17
|
active: true
|
19
|
-
|
20
|
-
|
21
|
-
# environment to obtain an api key.
|
22
|
-
# api_key: <<%= environment.upcase %>-API-KEY>
|
23
|
-
active: false
|
24
|
-
<%- end -%>
|
25
|
-
<%- end -%>
|
18
|
+
<%= "\n" unless environment == environments.last -%>
|
19
|
+
<% end -%>
|