scout_apm 0.1.18.stackprof4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7040acd30e2e30aceb89d48e43c699e007d87ea5
4
- data.tar.gz: 76222f981eb632a50948c4f765ad387c671bbf80
3
+ metadata.gz: 359e7ebbd4d2be52175b519c7eed26801f332cf6
4
+ data.tar.gz: d54ba2ef21fc61b38e54136637bd97391ba0c26b
5
5
  SHA512:
6
- metadata.gz: 811ca92ad91009f8e3577caa8641a7b8c6e189bf2460b871f24c1d98d9e5a8b75376194391729aa42d47e3a47e9bf138dfcb34f0cd316f346281b870fd50e902
7
- data.tar.gz: 5b0e5825e3d97e4ba7ce950792890bc5318be6e5fb23d60e6ad4c8bbeac6f1599a14d2f8ecf721c44cc56f046b711b090e322f8f87133dadf912220eeef7f613
6
+ metadata.gz: d5c7c714ffa299176340a4b6d1c62f248106840565245c1ecef1696e103218f3c91dcd2e31d3f0164bf97d125f36f6312c4f4db1c3875dc6c4a2a9b3d12c3420
7
+ data.tar.gz: 45cabecb512ef84af5ab618d227a787d92f64e62874352c770d70a8b8ccf23facf992b30a0ce7ded385b291bf44f11858a5cf3b5f5544d63766fa34fb504ab7b
data/CHANGELOG.markdown CHANGED
@@ -1,6 +1,10 @@
1
+ # 0.9.0
2
+
3
+ * Come out of alpha, and release a beta version.
4
+
1
5
  # 0.1.16
2
6
 
3
- * Beta support for Sinatra monitoring.
7
+ * Initial support for Sinatra monitoring.
4
8
 
5
9
  # 0.1.15
6
10
 
data/lib/scout_apm.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  module ScoutApm
2
2
  end
3
3
 
4
- #####################################
5
- # Ruby StdLibrary Requires
6
- #####################################
7
4
  require 'cgi'
8
5
  require 'logger'
9
6
  require 'net/http'
@@ -13,18 +10,6 @@ require 'socket'
13
10
  require 'yaml'
14
11
  require 'thread'
15
12
 
16
- #####################################
17
- # Gem Requires
18
- #####################################
19
- begin
20
- require 'stackprof'
21
- rescue LoadError
22
- require 'scout_apm/utils/fake_stack_prof'
23
- end
24
-
25
- #####################################
26
- # Internal Requires
27
- #####################################
28
13
  require 'scout_apm/version'
29
14
 
30
15
  require 'scout_apm/server_integrations/passenger'
@@ -40,9 +25,6 @@ require 'scout_apm/framework_integrations/rails_3_or_4'
40
25
  require 'scout_apm/framework_integrations/sinatra'
41
26
  require 'scout_apm/framework_integrations/ruby'
42
27
 
43
- require 'scout_apm/deploy_integrations/capistrano_3'
44
- #require 'scout_apm/deploy_integrations/capistrano_2'
45
-
46
28
  require 'scout_apm/instruments/net_http'
47
29
  require 'scout_apm/instruments/moped'
48
30
  require 'scout_apm/instruments/mongoid'
@@ -59,7 +41,6 @@ require 'scout_apm/utils/sql_sanitizer'
59
41
  require 'scout_apm/utils/null_logger'
60
42
  require 'scout_apm/utils/installed_gems'
61
43
  require 'scout_apm/utils/time'
62
-
63
44
  require 'scout_apm/config'
64
45
  require 'scout_apm/environment'
65
46
  require 'scout_apm/agent'
@@ -75,14 +56,12 @@ require 'scout_apm/stack_item'
75
56
  require 'scout_apm/store'
76
57
  require 'scout_apm/tracer'
77
58
  require 'scout_apm/context'
78
- require 'scout_apm/stackprof_tree_collapser'
79
59
  require 'scout_apm/slow_transaction'
80
60
  require 'scout_apm/capacity'
81
61
 
82
62
  require 'scout_apm/serializers/payload_serializer'
83
63
  require 'scout_apm/serializers/directive_serializer'
84
64
  require 'scout_apm/serializers/app_server_load_serializer'
85
- require 'scout_apm/serializers/deploy_serializer'
86
65
 
87
66
  if defined?(Rails) and Rails.respond_to?(:version) and Rails.version >= '3'
88
67
  module ScoutApm
@@ -78,11 +78,6 @@ module ScoutApm
78
78
  init_logger
79
79
  logger.info "Attempting to start Scout Agent [#{ScoutApm::VERSION}] on [#{environment.hostname}]"
80
80
 
81
- if environment.deploy_integration
82
- logger.info "Starting monitoring for [#{environment.deploy_integration.name}]]."
83
- return environment.deploy_integration.install
84
- end
85
-
86
81
  return false unless preconditions_met?
87
82
 
88
83
  @started = true
@@ -202,9 +197,5 @@ module ScoutApm
202
197
  @installed_instruments << instance
203
198
  instance.install
204
199
  end
205
-
206
- def deploy_integration
207
- environment.deploy_integration
208
- end
209
200
  end
210
201
  end
@@ -21,7 +21,6 @@ module ScoutApm
21
21
  DEFAULTS = {
22
22
  'host' => 'https://apm.scoutapp.com',
23
23
  'log_level' => 'info',
24
- 'stackprof_interval' => 20000 # microseconds, 1000 = 1 millisecond, so 20k == 20 milliseconds
25
24
  }.freeze
26
25
 
27
26
  def initialize(config_path = nil)
@@ -36,10 +35,11 @@ module ScoutApm
36
35
  # all, and only read off the ENV var this is useful to break a loop during
37
36
  # boot, where we needed an option to set the application root.
38
37
  def value(key, env_only=false)
39
- value = ENV['SCOUT_'+key.upcase]
40
- if !value && !env_only
41
- value = setting(key)
42
- end
38
+ value = if env_only
39
+ ENV['SCOUT_'+key.upcase]
40
+ else
41
+ ENV['SCOUT_'+key.upcase] || settings[key]
42
+ end
43
43
 
44
44
  value.to_s.strip.length.zero? ? nil : value
45
45
  end
@@ -54,12 +54,8 @@ module ScoutApm
54
54
  File.expand_path(config_path)
55
55
  end
56
56
 
57
- def setting(key)
58
- settings[key] || settings(true)[key]
59
- end
60
-
61
- def settings(try_reload=false)
62
- (@settings.nil? || try_reload) ? @settings = load_file : @settings
57
+ def settings
58
+ @settings ||= load_file
63
59
  end
64
60
 
65
61
  def config_environment
@@ -24,13 +24,8 @@ module ScoutApm
24
24
  ScoutApm::FrameworkIntegrations::Ruby.new, # Fallback if none match
25
25
  ]
26
26
 
27
- DEPLOY_INTEGRATIONS = [
28
- ScoutApm::DeployIntegrations::Capistrano3.new(Logger.new(STDOUT)),
29
- # ScoutApm::DeployIntegrations::Capistrano2.new(Logger.new(STDOUT)),
30
- ]
31
-
32
27
  def env
33
- @env ||= deploy_integration? ? deploy_integration.env : framework_integration.env
28
+ @env ||= framework_integration.env
34
29
  end
35
30
 
36
31
  def framework
@@ -63,7 +58,6 @@ module ScoutApm
63
58
  end
64
59
 
65
60
  def root
66
- return deploy_integration.root if deploy_integration
67
61
  framework_root
68
62
  end
69
63
 
@@ -71,6 +65,7 @@ module ScoutApm
71
65
  if override_root = Agent.instance.config.value("application_root", true)
72
66
  return override_root
73
67
  end
68
+
74
69
  if framework == :rails
75
70
  RAILS_ROOT.to_s
76
71
  elsif framework == :rails3_or_4
@@ -111,14 +106,6 @@ module ScoutApm
111
106
  app_server_integration.forking?
112
107
  end
113
108
 
114
- def deploy_integration
115
- @deploy_integration ||= DEPLOY_INTEGRATIONS.detect{ |integration| integration.present? }
116
- end
117
-
118
- def deploy_integration?
119
- !@deploy_integration.nil?
120
- end
121
-
122
109
  ### ruby checks
123
110
 
124
111
  def rubinius?
@@ -27,25 +27,12 @@ module ScoutApm
27
27
 
28
28
  if defined?(::ActionView) && defined?(::ActionView::PartialRenderer)
29
29
  ScoutApm::Agent.instance.logger.debug "Instrumenting ActionView::PartialRenderer"
30
- ::ActionView::PartialRenderer.class_eval do
30
+ ActionView::PartialRenderer.class_eval do
31
31
  include ScoutApm::Tracer
32
- instrument_method :render_partial,
33
- :metric_name => 'View/#{@template.virtual_path rescue "Unknown Partial"}/Rendering',
34
- :scope => true
35
-
36
- instrument_method :collection_with_template,
37
- :metric_name => 'View/#{@template.virtual_path rescue "Unknown Collection"}/Rendering',
38
- :scope => true
39
- end
40
-
41
- ScoutApm::Agent.instance.logger.debug "Instrumenting ActionView::TemplateRenderer"
42
- ::ActionView::TemplateRenderer.class_eval do
43
- include ScoutApm::Tracer
44
- instrument_method :render_template,
45
- :metric_name => 'View/#{args[0].virtual_path rescue "Unknown"}/Rendering',
46
- :scope => true
32
+ instrument_method :render_partial, :metric_name => 'View/#{@template.virtual_path}/Rendering', :scope => true
47
33
  end
48
34
  end
35
+
49
36
  end
50
37
  end
51
38
 
@@ -55,18 +42,13 @@ module ScoutApm
55
42
  scout_controller_action = "Controller/#{controller_path}/#{action_name}"
56
43
 
57
44
  self.class.scout_apm_trace(scout_controller_action, :uri => request.fullpath, :ip => request.remote_ip) do
58
- Thread::current[:scout_apm_prof] = nil
59
- StackProf.start(mode: :wall, interval: ScoutApm::Agent.instance.config.value("stackprof_interval"))
60
-
61
45
  begin
62
46
  super
63
47
  rescue Exception
64
- ScoutApm::Agent.instance.store.track!("Errors/Request", 1, :scope => nil)
48
+ ScoutApm::Agent.instance.store.track!("Errors/Request",1, :scope => nil)
65
49
  raise
66
50
  ensure
67
51
  Thread::current[:scout_apm_scope_name] = nil
68
- StackProf.stop
69
- Thread::current[:scout_apm_prof] = StackProf.results
70
52
  end
71
53
  end
72
54
  end
@@ -74,3 +56,9 @@ module ScoutApm
74
56
  end
75
57
  end
76
58
 
59
+
60
+ # Rails 3/4
61
+ module ScoutApm
62
+ module Instruments
63
+ end
64
+ end
@@ -16,8 +16,8 @@ module ScoutApm
16
16
  end
17
17
 
18
18
  # TODO: Parse & return a real response object, not the HTTP Response object
19
- def report(payload, headers = {})
20
- post(uri, payload, headers)
19
+ def report(payload)
20
+ post(uri, payload)
21
21
  end
22
22
 
23
23
  def uri
@@ -26,26 +26,9 @@ module ScoutApm
26
26
  URI.parse("#{config.value('host')}/apps/checkin.scout?key=#{config.value('key')}&name=#{CGI.escape(Environment.instance.application_name)}")
27
27
  when :app_server_load
28
28
  URI.parse("#{config.value('host')}/apps/app_server_load.scout?key=#{config.value('key')}&name=#{CGI.escape(Environment.instance.application_name)}")
29
- when :deploy_hook
30
- URI.parse("#{config.value('host')}/apps/deploy.scout?key=#{config.value('key')}&name=#{CGI.escape(config.value('name'))}")
31
29
  end.tap{|u| logger.debug("Posting to #{u.to_s}")}
32
30
  end
33
31
 
34
- def can_report?
35
- case type
36
- when :deploy_hook
37
- %w(host key name).each do |k|
38
- if config.value(k).nil?
39
- logger.warn "/#{type} FAILED: missing required config value for #{k}"
40
- return false
41
- end
42
- end
43
- return true
44
- else
45
- return true
46
- end
47
- end
48
-
49
32
  private
50
33
 
51
34
  def post(uri, body, headers = Hash.new)
@@ -69,8 +52,6 @@ module ScoutApm
69
52
  logger.debug "/#{type} OK"
70
53
  when Net::HTTPBadRequest
71
54
  logger.warn "/#{type} FAILED: The Account Key [#{config.value('key')}] is invalid."
72
- when Net::HTTPUnprocessableEntity
73
- logger.warn "/#{type} FAILED: #{response.body}"
74
55
  else
75
56
  logger.debug "/#{type} FAILED: #{response.inspect}"
76
57
  end
@@ -1,49 +1,36 @@
1
- module ScoutApm
2
- class SlowTransaction
3
- BACKTRACE_THRESHOLD = 0.5 # the minimum threshold to record the backtrace for a metric.
4
- BACKTRACE_LIMIT = 5 # Max length of callers to display
5
- MAX_SIZE = 100 # Limits the size of the metric hash to prevent a metric explosion.
1
+ class ScoutApm::SlowTransaction
2
+ BACKTRACE_THRESHOLD = 0.5 # the minimum threshold to record the backtrace for a metric.
3
+ BACKTRACE_LIMIT = 5 # Max length of callers to display
4
+ MAX_SIZE = 100 # Limits the size of the metric hash to prevent a metric explosion.
5
+ attr_reader :metric_name, :total_call_time, :metrics, :meta, :uri, :context, :time, :prof, :raw_prof
6
6
 
7
- attr_reader :metric_name
8
- attr_reader :total_call_time
9
- attr_reader :metrics
10
- attr_reader :meta
11
- attr_reader :uri
12
- attr_reader :context
13
- attr_reader :time
14
- attr_reader :prof
15
- attr_reader :raw_prof
16
-
17
- # Given a call stack, generates a filtered backtrace that:
18
- # * Limits to the app/models, app/controllers, or app/views directories
19
- # * Limits to 5 total callers
20
- # * Makes the app folder the top-level folder used in trace info
21
- def self.backtrace_parser(backtrace)
22
- stack = []
23
- backtrace.each do |c|
24
- if m=c.match(/(\/app\/(controllers|models|views)\/.+)/)
25
- stack << m[1]
26
- break if stack.size == BACKTRACE_LIMIT
27
- end
7
+ # Given a call stack, generates a filtered backtrace that:
8
+ # * Limits to the app/models, app/controllers, or app/views directories
9
+ # * Limits to 5 total callers
10
+ # * Makes the app folder the top-level folder used in trace info
11
+ def self.backtrace_parser(backtrace)
12
+ stack = []
13
+ backtrace.each do |c|
14
+ if m=c.match(/(\/app\/(controllers|models|views)\/.+)/)
15
+ stack << m[1]
16
+ break if stack.size == BACKTRACE_LIMIT
28
17
  end
29
- stack
30
18
  end
19
+ stack
20
+ end
31
21
 
32
- def initialize(uri, metric_name, total_call_time, metrics, context, time, raw_stackprof)
33
- @uri = uri
34
- @metric_name = metric_name
35
- @total_call_time = total_call_time
36
- @metrics = metrics
37
- @context = context
38
- @time = time
39
- @prof = ScoutApm::StackprofTreeCollapser.new(raw_stackprof).call
40
- @raw_prof = raw_stackprof # Send whole data up to server
41
- end
22
+ def initialize(uri,metric_name,total_call_time,metrics,context,time)
23
+ @uri = uri
24
+ @metric_name = metric_name
25
+ @total_call_time = total_call_time
26
+ @metrics = metrics
27
+ @context = context
28
+ @time = time
29
+ end
42
30
 
43
- # Used to remove metrics when the payload will be too large.
44
- def clear_metrics!
45
- @metrics = nil
46
- self
47
- end
31
+ # Used to remove metrics when the payload will be too large.
32
+ def clear_metrics!
33
+ @metrics = nil
34
+ self
48
35
  end
49
36
  end
@@ -72,7 +72,7 @@ module ScoutApm
72
72
  end
73
73
 
74
74
  duration = Time.now - item.start_time
75
- if last = stack.last
75
+ if last=stack.last
76
76
  last.children_time += duration
77
77
  end
78
78
 
@@ -90,8 +90,8 @@ module ScoutApm
90
90
 
91
91
  # Uses controllers as the entry point for a transaction. Otherwise, stats are ignored.
92
92
  if stack_empty and meta.metric_name.match(/\AController\//)
93
- aggs = aggregate_calls(transaction_hash.dup,meta)
94
- store_slow(options[:uri], transaction_hash.dup.merge(aggs), meta, stat)
93
+ aggs=aggregate_calls(transaction_hash.dup,meta)
94
+ store_slow(options[:uri],transaction_hash.dup.merge(aggs),meta,stat)
95
95
  # deep duplicate
96
96
  duplicate = aggs.dup
97
97
  duplicate.each_pair do |k,v|
@@ -139,20 +139,12 @@ module ScoutApm
139
139
  aggregates
140
140
  end
141
141
 
142
- SLOW_TRANSACTION_THRESHOLD = 2
143
-
144
142
  # Stores slow transactions. This will be sent to the server.
145
- def store_slow(uri, transaction_hash, parent_meta, parent_stat, options = {})
143
+ def store_slow(uri,transaction_hash,parent_meta,parent_stat,options = {})
146
144
  @slow_transaction_lock.synchronize do
147
- if parent_stat.total_call_time >= SLOW_TRANSACTION_THRESHOLD
148
- slow_transaction = ScoutApm::SlowTransaction.new(uri,
149
- parent_meta.metric_name,
150
- parent_stat.total_call_time,
151
- transaction_hash.dup,
152
- ScoutApm::Context.current,
153
- Thread::current[:scout_apm_trace_time],
154
- Thread::current[:scout_apm_prof])
155
- @slow_transactions.push(slow_transaction)
145
+ # tree map of all slow transactions
146
+ if parent_stat.total_call_time >= 2
147
+ @slow_transactions.push(ScoutApm::SlowTransaction.new(uri,parent_meta.metric_name,parent_stat.total_call_time,transaction_hash.dup,ScoutApm::Context.current,Thread::current[:scout_apm_trace_time]))
156
148
  ScoutApm::Agent.instance.logger.debug "Slow transaction sample added. [URI: #{uri}] [Context: #{ScoutApm::Context.current.to_hash}] Array Size: #{@slow_transactions.size}"
157
149
  end
158
150
  end
@@ -54,16 +54,13 @@ module ScoutApm
54
54
  elsif Thread::current[:scout_ignore_children]
55
55
  return yield
56
56
  end
57
-
58
57
  if options.delete(:scope)
59
58
  Thread::current[:scout_apm_sub_scope] = metric_name
60
59
  end
61
-
62
60
  if options[:ignore_children]
63
61
  Thread::current[:scout_ignore_children] = true
64
62
  end
65
63
  stack_item = ScoutApm::Agent.instance.store.record(metric_name)
66
-
67
64
  begin
68
65
  yield
69
66
  ensure
@@ -71,21 +68,15 @@ module ScoutApm
71
68
  if options[:ignore_children]
72
69
  Thread::current[:scout_ignore_children] = nil
73
70
  end
74
-
75
71
  ScoutApm::Agent.instance.store.stop_recording(stack_item,options)
76
72
  end
77
73
  end
78
74
 
79
- def instrument_method(method, options = {})
75
+ def instrument_method(method,options = {})
80
76
  ScoutApm::Agent.instance.logger.info "Instrumenting #{method}"
81
77
  metric_name = options[:metric_name] || default_metric_name(method)
82
78
  return if !instrumentable?(method) or instrumented?(method,metric_name)
83
-
84
- class_eval(instrumented_method_string(
85
- method,
86
- {:metric_name => metric_name, :scope => options[:scope] }),
87
- __FILE__, __LINE__
88
- )
79
+ class_eval instrumented_method_string(method, {:metric_name => metric_name, :scope => options[:scope]}), __FILE__, __LINE__
89
80
 
90
81
  alias_method _uninstrumented_method_name(method, metric_name), method
91
82
  alias_method method, _instrumented_method_name(method, metric_name)
@@ -95,15 +86,12 @@ module ScoutApm
95
86
 
96
87
  def instrumented_method_string(method, options)
97
88
  klass = (self === Module) ? "self" : "self.class"
98
- method_str = "def #{_instrumented_method_name(method, options[:metric_name])}(*args, &block)
89
+ "def #{_instrumented_method_name(method, options[:metric_name])}(*args, &block)
99
90
  result = #{klass}.instrument(\"#{options[:metric_name]}\",{:scope => #{options[:scope] || false}}) do
100
91
  #{_uninstrumented_method_name(method, options[:metric_name])}(*args, &block)
101
92
  end
102
93
  result
103
94
  end"
104
-
105
- ScoutApm::Agent.instance.logger.debug "Instrumented Method:\n#{method_str}"
106
- method_str
107
95
  end
108
96
 
109
97
  # The method must exist to be instrumented.
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "0.1.18.stackprof4"
2
+ VERSION = "0.9.0"
3
3
  end
4
4
 
data/scout_apm.gemspec CHANGED
@@ -18,8 +18,6 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib","data"]
20
20
 
21
- s.add_dependency 'stackprof'
22
-
23
21
  s.add_development_dependency "minitest"
24
22
  s.add_development_dependency "pry"
25
23
  s.add_development_dependency "m"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scout_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.18.stackprof4
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Haynes
@@ -9,22 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-09-28 00:00:00.000000000 Z
12
+ date: 2015-09-29 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: stackprof
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: minitest
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -89,10 +75,6 @@ files:
89
75
  - lib/scout_apm/capacity.rb
90
76
  - lib/scout_apm/config.rb
91
77
  - lib/scout_apm/context.rb
92
- - lib/scout_apm/deploy_integrations/capistrano_2.cap
93
- - lib/scout_apm/deploy_integrations/capistrano_2.rb
94
- - lib/scout_apm/deploy_integrations/capistrano_3.cap
95
- - lib/scout_apm/deploy_integrations/capistrano_3.rb
96
78
  - lib/scout_apm/environment.rb
97
79
  - lib/scout_apm/framework_integrations/rails_2.rb
98
80
  - lib/scout_apm/framework_integrations/rails_3_or_4.rb
@@ -113,7 +95,6 @@ files:
113
95
  - lib/scout_apm/metric_stats.rb
114
96
  - lib/scout_apm/reporter.rb
115
97
  - lib/scout_apm/serializers/app_server_load_serializer.rb
116
- - lib/scout_apm/serializers/deploy_serializer.rb
117
98
  - lib/scout_apm/serializers/directive_serializer.rb
118
99
  - lib/scout_apm/serializers/payload_serializer.rb
119
100
  - lib/scout_apm/server_integrations/null.rb
@@ -125,10 +106,8 @@ files:
125
106
  - lib/scout_apm/server_integrations/webrick.rb
126
107
  - lib/scout_apm/slow_transaction.rb
127
108
  - lib/scout_apm/stack_item.rb
128
- - lib/scout_apm/stackprof_tree_collapser.rb
129
109
  - lib/scout_apm/store.rb
130
110
  - lib/scout_apm/tracer.rb
131
- - lib/scout_apm/utils/fake_stack_prof.rb
132
111
  - lib/scout_apm/utils/installed_gems.rb
133
112
  - lib/scout_apm/utils/null_logger.rb
134
113
  - lib/scout_apm/utils/sql_sanitizer.rb
@@ -158,9 +137,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
137
  version: '0'
159
138
  required_rubygems_version: !ruby/object:Gem::Requirement
160
139
  requirements:
161
- - - ">"
140
+ - - ">="
162
141
  - !ruby/object:Gem::Version
163
- version: 1.3.1
142
+ version: '0'
164
143
  requirements: []
165
144
  rubyforge_project: scout_apm
166
145
  rubygems_version: 2.2.2
@@ -1,12 +0,0 @@
1
- namespace :scout_apm do
2
- namespace :deploy do
3
- task :starting do
4
- # Warn if missing scout apm deploy creds?
5
- end
6
- task :finished do
7
- ScoutApm::Agent.instance.deploy_integration.report
8
- end
9
- end
10
- end
11
-
12
- after 'deploy:finished', 'scout_apm:deploy:finished'
@@ -1,83 +0,0 @@
1
- require 'scout_apm'
2
-
3
- module ScoutApm
4
- module DeployIntegrations
5
- class Capistrano2
6
- attr_reader :logger
7
-
8
- def initialize(logger)
9
- @logger = logger
10
- @cap = defined?(Capistrano::Configuration) ? ObjectSpace.each_object(Capistrano::Configuration).map.first : nil rescue nil
11
- end
12
-
13
- def name
14
- :capistrano_2
15
- end
16
-
17
- def version
18
- present? ? Capistrano::VERSION : nil
19
- end
20
-
21
- def present?
22
- if !@cap.nil? && @cap.is_a?(Capistrano::Configuration)
23
- require 'capistrano/version'
24
- defined?(Capistrano::VERSION) && Gem::Dependency.new('', '~> 2.0').match?('', Capistrano::VERSION.to_s)
25
- else
26
- return false
27
- end
28
- return true
29
- rescue
30
- return false
31
- end
32
-
33
- def install
34
- logger.debug "Initializing Capistrano2 Deploy Integration."
35
- @cap.load File.expand_path("../capistrano_2.cap", __FILE__)
36
- end
37
-
38
- def root
39
- '.'
40
- end
41
-
42
- def env
43
- @cap.fetch(:stage)
44
- end
45
-
46
- def found?
47
- true
48
- end
49
-
50
- def report
51
- if reporter.can_report?
52
- data = deploy_data
53
- logger.debug "Sending deploy hook data: #{data}"
54
- payload = ScoutApm::Serializers::DeploySerializer.serialize(data)
55
- reporter.report(payload, ScoutApm::Serializers::DeploySerializer::HTTP_HEADERS)
56
- else
57
- logger.warn "Unable to post deploy hook data"
58
- end
59
- end
60
-
61
- def reporter
62
- @reporter ||= ScoutApm::Reporter.new(:deploy_hook, ScoutApm::Agent.instance.config, @logger)
63
- end
64
-
65
- def deploy_data
66
- {:revision => current_revision, :branch => branch, :deployed_by => deployed_by}
67
- end
68
-
69
- def branch
70
- @cap.fetch(:branch)
71
- end
72
-
73
- def current_revision
74
- @cap.fetch(:current_revision) || `git rev-list --max-count=1 --abbrev-commit --abbrev=12 #{branch}`.chomp
75
- end
76
-
77
- def deployed_by
78
- ScoutApm::Agent.instance.config.value('deployed_by')
79
- end
80
-
81
- end
82
- end
83
- end
@@ -1,12 +0,0 @@
1
- namespace :scout_apm do
2
- namespace :deploy do
3
- task :starting do
4
- # Warn if missing scout apm deploy creds?
5
- end
6
- task :finished do
7
- ScoutApm::Agent.instance.deploy_integration.report
8
- end
9
- end
10
- end
11
-
12
- after 'deploy:finished', 'scout_apm:deploy:finished'
@@ -1,82 +0,0 @@
1
- require 'scout_apm'
2
-
3
- module ScoutApm
4
- module DeployIntegrations
5
- class Capistrano3
6
- attr_reader :logger
7
-
8
- def initialize(logger)
9
- @logger = logger
10
- @cap = Rake.application rescue nil
11
- end
12
-
13
- def name
14
- :capistrano_3
15
- end
16
-
17
- def version
18
- present? ? Capistrano::VERSION : nil
19
- end
20
-
21
- def present?
22
- if !@cap.nil? && @cap.is_a?(Capistrano::Application)
23
- require 'capistrano/version'
24
- defined?(Capistrano::VERSION) && Gem::Dependency.new('', '~> 3.0').match?('', Capistrano::VERSION.to_s)
25
- else
26
- return false
27
- end
28
- rescue
29
- return false
30
- end
31
-
32
- def install
33
- logger.debug "Initializing Capistrano3 Deploy Integration."
34
- load File.expand_path("../capistrano_3.cap", __FILE__)
35
- end
36
-
37
- def root
38
- '.'
39
- end
40
-
41
- def env
42
- @cap.fetch(:stage).to_s
43
- end
44
-
45
- def found?
46
- true
47
- end
48
-
49
- def report
50
- if reporter.can_report?
51
- data = deploy_data
52
- logger.debug "Sending deploy hook data: #{data}"
53
- payload = ScoutApm::Serializers::DeploySerializer.serialize(data)
54
- reporter.report(payload, ScoutApm::Serializers::DeploySerializer::HTTP_HEADERS)
55
- else
56
- logger.warn "Unable to post deploy hook data"
57
- end
58
- end
59
-
60
- def reporter
61
- @reporter ||= ScoutApm::Reporter.new(:deploy_hook, ScoutApm::Agent.instance.config, @logger)
62
- end
63
-
64
- def deploy_data
65
- {:revision => current_revision, :branch => branch, :deployed_by => deployed_by}
66
- end
67
-
68
- def branch
69
- @cap.fetch(:branch)
70
- end
71
-
72
- def current_revision
73
- @cap.fetch(:current_revision) || `git rev-list --max-count=1 --abbrev-commit --abbrev=12 #{branch}`.chomp
74
- end
75
-
76
- def deployed_by
77
- ScoutApm::Agent.instance.config.value('deployed_by')
78
- end
79
-
80
- end
81
- end
82
- end
@@ -1,16 +0,0 @@
1
- # Serialize & deserialize deploy data up to the APM server
2
- module ScoutApm
3
- module Serializers
4
- class DeploySerializer
5
- HTTP_HEADERS = {'Content-Type' => 'application/x-www-form-urlencoded'}
6
-
7
- def self.serialize(data)
8
- URI.encode_www_form(data)
9
- end
10
-
11
- def self.deserialize(data)
12
- Marshal.load(data)
13
- end
14
- end
15
- end
16
- end
@@ -1,218 +0,0 @@
1
- # require 'json'; p = JSON::parse(File.read("/Users/cschneid/example_stackprof.out")); p=p.with_indifferent_access; ScoutApm::StackprofTreeCollapser.new(p).call
2
- # require 'json'; p = JSON::parse(File.read("/Users/cschneid/profile_appscontroller.json")); p=p.with_indifferent_access; ScoutApm::StackprofTreeCollapser.new(p).call
3
- # require 'json'; p = JSON::parse(File.read("/Users/cschneid/profile_elasticsearch.json")); p=p.with_indifferent_access; ScoutApm::StackprofTreeCollapser.new(p).call
4
-
5
- # in_app_nodes.map{|n| [n.samples_for_self_and_descendants, n.name, n.file, n.line]}.sort_by {|x| x[0] }
6
- # in_app_nodes.map{|n| [n.total_samples, n.name] }.sort_by {|x| x[0] }
7
-
8
-
9
-
10
- module ScoutApm
11
- class StackprofTreeCollapser
12
- attr_reader :raw_stackprof
13
- attr_reader :nodes # the current set of nodes under consideration
14
-
15
- def initialize(raw_stackprof)
16
- @raw_stackprof = raw_stackprof
17
- ScoutApm::Agent.instance.logger.info("StackProf - Samples: #{raw_stackprof[:samples]}, GC: #{raw_stackprof[:gc_samples]}, missed: #{raw_stackprof[:missed_samples]}, Interval: #{raw_stackprof[:interval]}")
18
- end
19
-
20
- def call
21
- build_tree
22
- connect_children
23
- total_samples_of_app_nodes
24
- end
25
-
26
- private
27
-
28
- def build_tree
29
- @nodes = raw_stackprof[:frames].map do |(frame_id, frame_data)|
30
- TreeNode.new(frame_id, # frame_id
31
- frame_data[:name], # name
32
- frame_data[:file], # file
33
- frame_data[:line], # line
34
- frame_data[:samples], # samples
35
- frame_data[:total_samples], # total_samples
36
- (frame_data[:edges] || {}), # children_edges [ { id => weight } ]
37
- [], # children [ treenode, ... ]
38
- [] # parents [ [treenode, int (weight) ], [...] ]
39
- )
40
- end
41
- end
42
-
43
- def connect_children
44
- nodes.each do |node|
45
- children = nodes.find_all { |n| node.children_edges.keys.include? n.frame_id }
46
-
47
- node.children_edges.each do |(frame_id, weight)|
48
- child = children.detect{ |c| c.frame_id == frame_id }
49
- child.parents << [node, weight]
50
- end
51
-
52
- node.children = children
53
- end
54
- end
55
-
56
- def in_app_nodes
57
- nodes.select {|n| n.app? }
58
- end
59
-
60
- def total_samples_of_app_nodes
61
- in_app_nodes.reject{|n| n.calls_only_app_nodes? && !n.has_samples? }.
62
- map{|n| { samples: n.total_samples,
63
- name: n.name,
64
- file: n.file,
65
- line: n.line
66
- }
67
- }
68
- end
69
-
70
- # @results will be [{name, samples, file, line}]
71
- # def calculate_results
72
- # @results = in_app_nodes.map do |node|
73
- # desc = node.all_descendants
74
- # total_samples = desc.map(&:samples).sum
75
- # { desc_count: desc.length, name: node.name, file: node.file, line: node.line, samples: total_samples }
76
- # end
77
- # end
78
-
79
- # def collapse_tree
80
- # while true
81
- # number_changed = collapse_tree_one_level
82
- # break if number_changed == 0
83
- # end
84
- # end
85
- #
86
- # # For each leaf node, sees if it is internal to the monitored app. If not,
87
- # # collapse that node to its parents, weighted by the edge counts
88
- # # If that node was internal to the monitored app, leave it.
89
- # # Returns 0 if nothing changed, a positive integer if things did change,
90
- # # indicating how many leaves were collapsed
91
- # def collapse_tree_one_level
92
- # number_changed = 0
93
- #
94
- # puts "===========ITERATION==========="
95
- # leaves.each do |leaf_node|
96
- # next if leaf_node.app?
97
- # puts "Collapsing - #{leaf_node.name}"
98
- # # app parent: #{leaf_node.self_or_parents_in_app?.map {|x| x.name}}"
99
- # number_changed += 1
100
- # leaf_node.collapse_to_parent!
101
- # @nodes = @nodes.reject { |n| n == leaf_node }
102
- # end
103
- #
104
- # number_changed
105
- # end
106
- #
107
- # # Returns the final result, an array of hashes
108
- # def generate_output
109
- # leaves.map{|x| { name: x.name, samples: x.samples, file: x.file, line: x.line } }
110
- # end
111
- #
112
- # # A leaf node has no children.
113
- # def leaves
114
- # nodes.find_all { |n| n.children.empty? }
115
- # end
116
- #
117
-
118
- ###########################################
119
- # TreeNode class represents a single node.
120
- ###########################################
121
- TreeNode = Struct.new(:frame_id, :name, :file, :line, :samples, :total_samples,
122
- :children_edges, :children, :parents) do
123
- def app?
124
- @is_app ||= file =~ /^#{ScoutApm::Environment.instance.root}/
125
- end
126
-
127
- # My samples, and the weighted samples of all of my children
128
- #def samples_for_self_and_descendants(seen=Set.new)
129
- # viable_children = children.reject(&:app?)
130
- # @samples_for_self_and_descendants ||= samples + viable_children.map{ |c_node|
131
- # if seen.include? self
132
- # puts "I've already seen #{self.name}, bailing"
133
- # return samples # we've already been included, we're looping
134
- # else
135
- # seen << self
136
- # c_node.samples_for_parent(self, seen.dup).tap { |val| puts "Child gave me #{val}" }
137
- # end
138
- # }.sum
139
- #end
140
-
141
- # For this parent of mine, how many of my samples do they get.
142
- # is combo of "how many samples do I have, and what's the relative weight of this parent"
143
- #def samples_for_parent(p_node, seen=Set.new)
144
- # samples_for_self_and_descendants(seen) * relative_weight_of_parent(p_node)
145
- #end
146
-
147
- #def relative_weight_of_parent(p_node)
148
- # total = parents.map{|(_, weight)| weight}.sum
149
- # p_node_weight = parents.detect(0) {|(this_parent, _)| this_parent == p_node }[1]
150
- # p_node_weight.to_f / total.to_f
151
- #end
152
-
153
- # Allocate this node's samples to its parents, in relation to the rate at
154
- # which each parent called this method. Then clear the child from each of the parents
155
- #def collapse_to_parent!
156
- # total_weight = parents.map{ |(_, weight)| weight }.inject(0){ |sum, weight| sum + weight }
157
- # parents.each do |(p_node, weight)|
158
- # relative_weight = weight.to_f / total_weight.to_f
159
- # p_node.samples += (samples * relative_weight)
160
- # end
161
-
162
- # parents.each {|(p_node, _)| p_node.delete_child!(self) }
163
- #end
164
-
165
- #def delete_child!(node)
166
- # self.children = self.children.reject {|c| c == node }
167
- #end
168
-
169
- # Force object_id to be the equality mechanism, rather than struct's
170
- # default which delegates to == on each value. That is wrong because
171
- # we want to be able to dup a node in the tree construction process and
172
- # not have those compare equal to each other.
173
- def ==(other)
174
- object_id == other.object_id
175
- end
176
-
177
- def inspect
178
- "#{frame_id}: #{name} - ##{samples}\n" +
179
- " Parents: #{parents.map{ |(p, w)| "#{p.name}: #{w}"}.join("\n ") }\n" +
180
- " Children: #{children_edges.inspect} \n"
181
- end
182
-
183
- #def all_descendants(max_depth=100)
184
- # descendants = [self]
185
- # unchecked_edge = self.children.reject(&:app?)
186
- # stop = false
187
-
188
- # puts "----------------------------------------"
189
-
190
- # while max_depth > 0 && !stop
191
- # before_count = descendants.length
192
-
193
- # descendants = (descendants + unchecked_edge).uniq
194
- # unchecked_edge = unchecked_edge.map(&:children).flatten.uniq.reject(&:app?)
195
- # puts "UncheckedEdge Children: #{unchecked_edge.length}"
196
-
197
- # after_count = descendants.length
198
- # stop = true if before_count == after_count
199
- # max_depth = max_depth - 1
200
- # end
201
-
202
- # puts "#{name} - Found #{descendants.length} children after #{100 - max_depth} iterations"
203
-
204
- # puts "----------------------------------------"
205
-
206
- # descendants
207
- #end
208
-
209
- def calls_only_app_nodes?
210
- children.all?(&:app?)
211
- end
212
-
213
- def has_samples?
214
- samples > 0
215
- end
216
- end
217
- end
218
- end
@@ -1,36 +0,0 @@
1
- # A fake implementation of stackprof, for systems that don't support it.
2
- class StackProf
3
- def self.start(*args)
4
- @running = true
5
- end
6
-
7
- def self.stop(*args)
8
- @running = false
9
- end
10
-
11
- def running?
12
- !!@running
13
- end
14
-
15
- def run(*args)
16
- start
17
- yield
18
- stop
19
- results
20
- end
21
-
22
- def sample(*args)
23
- end
24
-
25
- def results(*args)
26
- {
27
- :version => 0.0,
28
- :mode => :wall,
29
- :interval => 1000,
30
- :samples => 0,
31
- :gc_samples => 0,
32
- :missed_samples => 0,
33
- :frames => {},
34
- }
35
- end
36
- end