Class: NewRelic::Agent::ThreadProfile
- Inherits:
-
Object
- Object
- NewRelic::Agent::ThreadProfile
- Defined in:
- lib/new_relic/agent/thread_profiler.rb
Defined Under Namespace
Classes: Node
Constant Summary collapse
- THREAD_PROFILER_NODES =
20_000
Instance Attribute Summary collapse
-
#interval ⇒ Object
readonly
Returns the value of attribute interval.
-
#poll_count ⇒ Object
readonly
Returns the value of attribute poll_count.
-
#profile_agent_code ⇒ Object
readonly
Returns the value of attribute profile_agent_code.
-
#profile_id ⇒ Object
readonly
Returns the value of attribute profile_id.
-
#sample_count ⇒ Object
readonly
Returns the value of attribute sample_count.
-
#start_time ⇒ Object
readonly
Returns the value of attribute start_time.
-
#stop_time ⇒ Object
readonly
Returns the value of attribute stop_time.
-
#traces ⇒ Object
readonly
Returns the value of attribute traces.
Class Method Summary collapse
Instance Method Summary collapse
- #aggregate(trace, trees = , parent = nil) ⇒ Object
- #finished? ⇒ Boolean
-
#initialize(profile_id, duration, interval, profile_agent_code) ⇒ ThreadProfile
constructor
A new instance of ThreadProfile.
- #log ⇒ Object
- #mark_done ⇒ Object
- #mark_for_pruning(nodes, count_to_keep) ⇒ Object
- #now_in_millis ⇒ Object
- #prune!(count_to_keep) ⇒ Object
- #run ⇒ Object
- #stop ⇒ Object
- #to_compressed_array ⇒ Object
Constructor Details
#initialize(profile_id, duration, interval, profile_agent_code) ⇒ ThreadProfile
Returns a new instance of ThreadProfile.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 102 def initialize(profile_id, duration, interval, profile_agent_code) @profile_id = profile_id @profile_agent_code = profile_agent_code @worker_loop = NewRelic::Agent::WorkerLoop.new(:duration => duration) @interval = interval @finished = false @traces = { :agent => [], :background => [], :other => [], :request => [] } @flattened_nodes = [] @poll_count = 0 @sample_count = 0 end |
Instance Attribute Details
#interval ⇒ Object (readonly)
Returns the value of attribute interval.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def interval @interval end |
#poll_count ⇒ Object (readonly)
Returns the value of attribute poll_count.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def poll_count @poll_count end |
#profile_agent_code ⇒ Object (readonly)
Returns the value of attribute profile_agent_code.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def profile_agent_code @profile_agent_code end |
#profile_id ⇒ Object (readonly)
Returns the value of attribute profile_id.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def profile_id @profile_id end |
#sample_count ⇒ Object (readonly)
Returns the value of attribute sample_count.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def sample_count @sample_count end |
#start_time ⇒ Object (readonly)
Returns the value of attribute start_time.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def start_time @start_time end |
#stop_time ⇒ Object (readonly)
Returns the value of attribute stop_time.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def stop_time @stop_time end |
#traces ⇒ Object (readonly)
Returns the value of attribute traces.
96 97 98 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 96 def traces @traces end |
Class Method Details
.compress(json) ⇒ Object
226 227 228 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 226 def self.compress(json) compressed = Base64.encode64(Zlib::Deflate.deflate(json, Zlib::DEFAULT_COMPRESSION)) end |
.flattened_nodes(nodes) ⇒ Object
222 223 224 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 222 def self.flattened_nodes(nodes) nodes.map { |n| [n, flattened_nodes(n.children)] }.flatten end |
.parse_backtrace(trace) ⇒ Object
230 231 232 233 234 235 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 230 def self.parse_backtrace(trace) trace.map do |line| line =~ /(.*)\:(\d+)\:in `(.*)'/ { :method => $3, :line_no => $2.to_i, :file => $1 } end end |
Instance Method Details
#aggregate(trace, trees = , parent = nil) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 152 def aggregate(trace, trees=@traces[:request], parent=nil) return nil if trace.nil? || trace.empty? node = Node.new(trace.last) existing = trees.find {|n| n == node} if existing.nil? existing = node @flattened_nodes << node end if parent parent.add_child(node) else trees << node unless trees.include? node end existing.runnable_count += 1 aggregate(trace[0..-2], existing.children, existing) existing end |
#finished? ⇒ Boolean
208 209 210 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 208 def finished? @finished end |
#log ⇒ Object
290 291 292 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 290 def log NewRelic::Agent.logger end |
#mark_done ⇒ Object
212 213 214 215 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 212 def mark_done @finished = true @stop_time = now_in_millis end |
#mark_for_pruning(nodes, count_to_keep) ⇒ Object
217 218 219 220 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 217 def mark_for_pruning(nodes, count_to_keep) to_prune = nodes[count_to_keep..-1] || [] to_prune.each { |n| n.to_prune = true } end |
#now_in_millis ⇒ Object
204 205 206 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 204 def now_in_millis Time.now.to_f * 1_000 end |
#prune!(count_to_keep) ⇒ Object
174 175 176 177 178 179 180 181 182 183 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 174 def prune!(count_to_keep) @flattened_nodes.sort!(&:order_for_pruning) NewRelic::Agent.instance.stats_engine. record_supportability_metrics_count(@flattened_nodes.size, "ThreadProfiler/NodeCount") mark_for_pruning(@flattened_nodes, count_to_keep) traces.each { |_, nodes| Node.prune!(nodes) } end |
#run ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 122 def run Thread.new('Thread Profiler') do @start_time = now_in_millis @worker_loop.run(@interval) do NewRelic::Agent.instance.stats_engine. record_supportability_metrics_timed("ThreadProfiler/PollingTime") do @poll_count += 1 Thread.list.each do |t| @sample_count += 1 bucket = Thread.bucket_thread(t, @profile_agent_code) backtrace = Thread.scrub_backtrace(t, @profile_agent_code) aggregate(backtrace, @traces[bucket]) unless bucket == :ignore end end end mark_done log.debug("Finished thread profile. Will send with next harvest.") end end |
#stop ⇒ Object
146 147 148 149 150 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 146 def stop @worker_loop.stop mark_done log.debug("Stopping thread profile.") end |
#to_compressed_array ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/new_relic/agent/thread_profiler.rb', line 187 def to_compressed_array prune!(THREAD_PROFILER_NODES) traces = { "OTHER" => @traces[:other].map{|t| t.to_array }, "REQUEST" => @traces[:request].map{|t| t.to_array }, "AGENT" => @traces[:agent].map{|t| t.to_array }, "BACKGROUND" => @traces[:background].map{|t| t.to_array } } [[@profile_id, @start_time.to_f, @stop_time.to_f, @poll_count, ThreadProfile.compress(JSON.dump(traces)), @sample_count, 0]] end |