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.
Files changed (95) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +3 -2
  3. data/.travis.yml +11 -11
  4. data/CHANGELOG.md +6 -0
  5. data/README.md +26 -0
  6. data/Rakefile +32 -3
  7. data/appsignal.gemspec +25 -16
  8. data/gemfiles/no_dependencies.gemfile +3 -0
  9. data/gemfiles/{3.0.gemfile → rails-3.0.gemfile} +2 -1
  10. data/gemfiles/{3.1.gemfile → rails-3.1.gemfile} +2 -1
  11. data/gemfiles/{3.2.gemfile → rails-3.2.gemfile} +2 -1
  12. data/gemfiles/{4.0.gemfile → rails-4.0.gemfile} +2 -1
  13. data/gemfiles/sinatra.gemfile +5 -0
  14. data/lib/appsignal.rb +30 -25
  15. data/lib/appsignal/agent.rb +37 -17
  16. data/lib/appsignal/aggregator.rb +2 -4
  17. data/lib/appsignal/aggregator/middleware.rb +4 -0
  18. data/lib/appsignal/aggregator/middleware/action_view_sanitizer.rb +23 -0
  19. data/lib/appsignal/aggregator/middleware/active_record_sanitizer.rb +64 -0
  20. data/lib/appsignal/aggregator/middleware/chain.rb +101 -0
  21. data/lib/appsignal/aggregator/middleware/delete_blanks.rb +16 -0
  22. data/lib/appsignal/aggregator/post_processor.rb +21 -18
  23. data/lib/appsignal/auth_check.rb +7 -21
  24. data/lib/appsignal/capistrano.rb +1 -36
  25. data/lib/appsignal/cli.rb +30 -46
  26. data/lib/appsignal/config.rb +46 -61
  27. data/lib/appsignal/integrations/capistrano.rb +44 -0
  28. data/lib/appsignal/{careful_logger.rb → integrations/capistrano/careful_logger.rb} +2 -0
  29. data/lib/appsignal/integrations/passenger.rb +6 -6
  30. data/lib/appsignal/integrations/rails.rb +33 -0
  31. data/lib/appsignal/integrations/sinatra.rb +20 -0
  32. data/lib/appsignal/marker.rb +9 -10
  33. data/lib/appsignal/rack/instrumentation.rb +28 -0
  34. data/lib/appsignal/rack/listener.rb +33 -0
  35. data/lib/appsignal/transaction.rb +18 -12
  36. data/lib/appsignal/transaction/formatter.rb +96 -0
  37. data/lib/appsignal/transaction/params_sanitizer.rb +80 -78
  38. data/lib/appsignal/transmitter.rb +10 -9
  39. data/lib/appsignal/version.rb +1 -1
  40. data/lib/generators/appsignal/appsignal_generator.rb +20 -21
  41. data/lib/generators/appsignal/templates/appsignal.yml +15 -21
  42. data/spec/{appsignal → lib/appsignal}/agent_spec.rb +69 -1
  43. data/spec/lib/appsignal/aggregator/middleware/action_view_sanitizer_spec.rb +32 -0
  44. data/spec/lib/appsignal/aggregator/middleware/active_record_sanitizer_spec.rb +215 -0
  45. data/spec/{appsignal → lib/appsignal/aggregator}/middleware/chain_spec.rb +5 -5
  46. data/spec/{appsignal → lib/appsignal/aggregator}/middleware/delete_blanks_spec.rb +2 -2
  47. data/spec/{appsignal → lib/appsignal}/aggregator/post_processor_spec.rb +15 -6
  48. data/spec/{appsignal → lib/appsignal}/aggregator_spec.rb +4 -1
  49. data/spec/{appsignal → lib/appsignal}/auth_check_spec.rb +8 -23
  50. data/spec/{appsignal → lib/appsignal}/cli_spec.rb +65 -66
  51. data/spec/lib/appsignal/config_spec.rb +132 -0
  52. data/spec/lib/appsignal/integrations/capistrano_spec.rb +123 -0
  53. data/spec/{appsignal → lib/appsignal}/integrations/passenger_spec.rb +0 -1
  54. data/spec/lib/appsignal/integrations/rails_spec.rb +38 -0
  55. data/spec/lib/appsignal/integrations/sinatra_spec.rb +43 -0
  56. data/spec/{appsignal → lib/appsignal}/marker_spec.rb +20 -23
  57. data/spec/lib/appsignal/rack/instrumentation_spec.rb +49 -0
  58. data/spec/{appsignal → lib/appsignal/rack}/listener_spec.rb +39 -6
  59. data/spec/{appsignal/transaction/transaction_formatter_spec.rb → lib/appsignal/transaction/formatter_spec.rb} +29 -6
  60. data/spec/{appsignal → lib/appsignal}/transaction/params_sanitizer_spec.rb +13 -12
  61. data/spec/{appsignal → lib/appsignal}/transaction_spec.rb +52 -7
  62. data/spec/{appsignal → lib/appsignal}/transmitter_spec.rb +27 -20
  63. data/spec/lib/appsignal_spec.rb +230 -0
  64. data/spec/lib/generators/appsignal/appsignal_generator_spec.rb +166 -0
  65. data/spec/lib/tmp/config/appsignal.yml +2 -0
  66. data/spec/spec_helper.rb +29 -20
  67. data/spec/support/delegate_matcher.rb +0 -1
  68. data/spec/support/fixtures/generated_config.yml +20 -0
  69. data/{log/.gitkeep → spec/support/fixtures/uploaded_file.txt} +0 -0
  70. data/spec/support/helpers/config_helpers.rb +24 -0
  71. data/spec/support/helpers/notification_helpers.rb +0 -2
  72. data/spec/support/helpers/transaction_helpers.rb +17 -2
  73. data/spec/support/project_fixture/config/appsignal.yml +18 -0
  74. data/spec/support/project_fixture/log/.gitkeep +0 -0
  75. data/spec/support/rails/my_app.rb +6 -0
  76. metadata +99 -83
  77. data/config/appsignal.yml +0 -10
  78. data/lib/appsignal/listener.rb +0 -21
  79. data/lib/appsignal/middleware.rb +0 -3
  80. data/lib/appsignal/middleware/action_view_sanitizer.rb +0 -21
  81. data/lib/appsignal/middleware/active_record_sanitizer.rb +0 -62
  82. data/lib/appsignal/middleware/chain.rb +0 -99
  83. data/lib/appsignal/middleware/delete_blanks.rb +0 -12
  84. data/lib/appsignal/railtie.rb +0 -37
  85. data/lib/appsignal/to_appsignal_hash.rb +0 -21
  86. data/lib/appsignal/transaction/transaction_formatter.rb +0 -67
  87. data/spec/appsignal/capistrano_spec.rb +0 -81
  88. data/spec/appsignal/config_spec.rb +0 -177
  89. data/spec/appsignal/inactive_railtie_spec.rb +0 -32
  90. data/spec/appsignal/middleware/action_view_sanitizer_spec.rb +0 -27
  91. data/spec/appsignal/middleware/active_record_sanitizer_spec.rb +0 -212
  92. data/spec/appsignal/railtie_spec.rb +0 -74
  93. data/spec/appsignal/to_appsignal_hash_spec.rb +0 -29
  94. data/spec/appsignal_spec.rb +0 -195
  95. 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 ParamsSanitizer
3
- class << self
4
- def sanitize(params)
5
- ParamsSanitizerCopy.sanitize_value(params)
6
- end
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
- def scrub(params)
13
- ParamsSanitizerCopyScrub.sanitize_value(params)
14
- end
9
+ def sanitize!(params)
10
+ ParamsSanitizerDestructive.sanitize_value(params)
11
+ end
15
12
 
16
- def scrub!(params)
17
- ParamsSanitizerDestructiveScrub.sanitize_value(params)
18
- end
13
+ def scrub(params)
14
+ ParamsSanitizerCopyScrub.sanitize_value(params)
15
+ end
19
16
 
20
- protected
17
+ def scrub!(params)
18
+ ParamsSanitizerDestructiveScrub.sanitize_value(params)
19
+ end
21
20
 
22
- def sanitize_value(value)
23
- case value
24
- when Hash
25
- sanitize_hash(value)
26
- when Array
27
- sanitize_array(value)
28
- when Fixnum, String, Symbol
29
- unmodified(value)
30
- else
31
- inspected(value)
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
- def sanitize_hash_with_target(source_hash, target_hash)
36
- source_hash.each_pair do |key, value|
37
- target_hash[key] = sanitize_value(value)
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
- def sanitize_array_with_target(source_array, target_array)
43
- source_array.each_with_index do |item, index|
44
- target_array[index] = sanitize_value(item)
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
- def unmodified(value)
50
- value
51
- end
50
+ def unmodified(value)
51
+ value
52
+ end
52
53
 
53
- def inspected(value)
54
- value.inspect
54
+ def inspected(value)
55
+ value.inspect
56
+ end
55
57
  end
56
58
  end
57
- end
58
59
 
59
- class ParamsSanitizerCopy < ParamsSanitizer
60
- class << self
61
- protected
60
+ class ParamsSanitizerCopy < ParamsSanitizer
61
+ class << self
62
+ protected
62
63
 
63
- def sanitize_hash(hash)
64
- sanitize_hash_with_target(hash, {})
65
- end
64
+ def sanitize_hash(hash)
65
+ sanitize_hash_with_target(hash, {})
66
+ end
66
67
 
67
- def sanitize_array(array)
68
- sanitize_array_with_target(array, [])
68
+ def sanitize_array(array)
69
+ sanitize_array_with_target(array, [])
70
+ end
69
71
  end
70
72
  end
71
- end
72
73
 
73
- class ParamsSanitizerDestructive < ParamsSanitizer
74
- class << self
75
- protected
74
+ class ParamsSanitizerDestructive < ParamsSanitizer
75
+ class << self
76
+ protected
76
77
 
77
- def sanitize_hash(hash)
78
- sanitize_hash_with_target(hash, hash)
79
- end
78
+ def sanitize_hash(hash)
79
+ sanitize_hash_with_target(hash, hash)
80
+ end
80
81
 
81
- def sanitize_array(array)
82
- sanitize_array_with_target(array, array)
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
- class ParamsSanitizerCopyScrub < ParamsSanitizerCopy
88
- class << self
89
- protected
88
+ class ParamsSanitizerCopyScrub < ParamsSanitizerCopy
89
+ class << self
90
+ protected
90
91
 
91
- def unmodified(value)
92
- '?'
93
- end
92
+ def unmodified(value)
93
+ '?'
94
+ end
94
95
 
95
- def inspected(value)
96
- '?'
96
+ def inspected(value)
97
+ '?'
98
+ end
97
99
  end
98
100
  end
99
- end
100
101
 
101
- class ParamsSanitizerDestructiveScrub < ParamsSanitizerDestructive
102
- class << self
103
- protected
102
+ class ParamsSanitizerDestructiveScrub < ParamsSanitizerDestructive
103
+ class << self
104
+ protected
104
105
 
105
- def unmodified(value)
106
- '?'
107
- end
106
+ def unmodified(value)
107
+ '?'
108
+ end
108
109
 
109
- def inspected(value)
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 :endpoint, :action, :api_key
12
+ attr_reader :config, :action
14
13
 
15
- def initialize(endpoint, action, api_key, logger=nil)
16
- @endpoint = endpoint
14
+ def initialize(action, config=Appsignal.config)
17
15
  @action = action
18
- @api_key = api_key
16
+ @config = config
19
17
  end
20
18
 
21
19
  def uri
22
- @uri ||= URI("#{@endpoint}/#{@action}").tap do |uri|
23
- uri.query = Rack::Utils.build_query({
24
- :api_key => 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
 
@@ -1,3 +1,3 @@
1
1
  module Appsignal
2
- VERSION = '0.6.7'
2
+ VERSION = '0.7.0.alpha.1'
3
3
  end
@@ -1,33 +1,27 @@
1
1
  require 'appsignal'
2
2
 
3
3
  class AppsignalGenerator < Rails::Generators::Base
4
- EXCLUDED_ENVIRONMENTS = [:test].freeze
4
+ EXCLUDED_ENVIRONMENTS = ['test'].freeze
5
5
 
6
6
  source_root File.expand_path('../templates', __FILE__)
7
- argument :environment, :type => :string
8
- argument :push_key, :type => :string
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
- appsignal_file = File.join('config', template_file)
14
- if File.exists?(appsignal_file)
15
- say_status(:error, "Looks like you already have a config file.", :red)
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 template_file, appsignal_file
23
- capyistrano_install
24
- check_key
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 capyistrano_install
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 check_key
47
- auth_check = ::Appsignal::AuthCheck.new(environment)
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
- # Unlisted environments will not be visible on the AppSignal site,
3
- # Active environments count towards the account plan limit.
4
- <%- environments.each do |environment| -%>
5
- <%= environment %>:
6
- <%- if selected_environment == environment -%>
7
- # The API key used by the AppSignal gem to push this specific environment to
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. (default: 200)
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
- # Change whether this environment should be monitored. (default: false)
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
- <%- else -%>
20
- # Go to https://appsignal.com if you want to monitor your <%= environment %>
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 -%>