app_perf_rpm 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/app_perf_rpm/backtrace.rb +7 -7
- data/lib/app_perf_rpm/configuration.rb +6 -4
- data/lib/app_perf_rpm/instruments/action_controller.rb +33 -16
- data/lib/app_perf_rpm/instruments/action_view.rb +93 -65
- data/lib/app_perf_rpm/instruments/active_record/adapters/mysql2.rb +24 -15
- data/lib/app_perf_rpm/instruments/active_record/adapters/postgresql.rb +95 -52
- data/lib/app_perf_rpm/instruments/active_record/adapters/sqlite3.rb +95 -54
- data/lib/app_perf_rpm/instruments/active_record.rb +1 -1
- data/lib/app_perf_rpm/instruments/activerecord_import.rb +22 -13
- data/lib/app_perf_rpm/instruments/emque_consuming.rb +16 -7
- data/lib/app_perf_rpm/instruments/faraday.rb +26 -16
- data/lib/app_perf_rpm/instruments/net_http.rb +16 -10
- data/lib/app_perf_rpm/instruments/rack.rb +75 -25
- data/lib/app_perf_rpm/instruments/redis.rb +49 -13
- data/lib/app_perf_rpm/instruments/sequel.rb +36 -28
- data/lib/app_perf_rpm/instruments/sidekiq.rb +65 -21
- data/lib/app_perf_rpm/instruments/sinatra.rb +34 -20
- data/lib/app_perf_rpm/instruments/typhoeus.rb +40 -21
- data/lib/app_perf_rpm/rails.rb +2 -1
- data/lib/app_perf_rpm/railtie.rb +4 -4
- data/lib/app_perf_rpm/reporters/json_client.rb +69 -0
- data/lib/app_perf_rpm/reporters/null_client.rb +14 -0
- data/lib/app_perf_rpm/tracer.rb +20 -89
- data/lib/app_perf_rpm/tracing/buffer.rb +25 -0
- data/lib/app_perf_rpm/tracing/carrier.rb +23 -0
- data/lib/app_perf_rpm/tracing/collector.rb +31 -0
- data/lib/app_perf_rpm/tracing/endpoint.rb +19 -0
- data/lib/app_perf_rpm/tracing/managed_span.rb +36 -0
- data/lib/app_perf_rpm/tracing/managed_tracer.rb +32 -0
- data/lib/app_perf_rpm/tracing/span.rb +67 -0
- data/lib/app_perf_rpm/tracing/span_context.rb +41 -0
- data/lib/app_perf_rpm/tracing/thread_span_stack.rb +32 -0
- data/lib/app_perf_rpm/tracing/trace_id.rb +11 -0
- data/lib/app_perf_rpm/tracing/tracer.rb +91 -0
- data/lib/app_perf_rpm/utils.rb +18 -0
- data/lib/app_perf_rpm.rb +59 -26
- metadata +90 -12
- data/lib/app_perf_rpm/aggregator.rb +0 -77
- data/lib/app_perf_rpm/dispatcher.rb +0 -85
- data/lib/app_perf_rpm/middleware.rb +0 -30
- data/lib/app_perf_rpm/span.rb +0 -103
- data/lib/app_perf_rpm/worker.rb +0 -46
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
|
3
|
-
module AppPerfRpm
|
4
|
-
class Aggregator
|
5
|
-
def initialize
|
6
|
-
end
|
7
|
-
|
8
|
-
def aggregate(traces)
|
9
|
-
metrics = []
|
10
|
-
traces = arrange_traces(traces)
|
11
|
-
spans = traces_to_spans(traces)
|
12
|
-
spans_by_time(spans).each_pair do |time, spans|
|
13
|
-
group_spans(spans).each_pair do |(type, layer, domain, url, controller, action), grouped_spans|
|
14
|
-
opts = {}
|
15
|
-
opts["type"] = type if type
|
16
|
-
opts["layer"] = layer if layer
|
17
|
-
opts["domain"] = domain if domain
|
18
|
-
opts["url"] = url if url
|
19
|
-
opts["controller"] = controller if controller
|
20
|
-
opts["action"] = action if action
|
21
|
-
metrics << build_metric("trace.web.request.duration", time, grouped_spans, opts)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
return metrics
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def build_metric(metric_name, time, spans, opts)
|
31
|
-
num_spans = spans.uniq(&:trace_id).size
|
32
|
-
durations = spans.inject(0.0) {|s, x| s + x.exclusive_duration }.to_f
|
33
|
-
hits = spans.size
|
34
|
-
|
35
|
-
tags = {
|
36
|
-
"traces" => num_spans,
|
37
|
-
"hits" => hits
|
38
|
-
}.merge(opts)
|
39
|
-
|
40
|
-
["metric", time.to_f, metric_name, durations, tags]
|
41
|
-
end
|
42
|
-
|
43
|
-
def arrange_traces(traces)
|
44
|
-
traces
|
45
|
-
.group_by(&:trace_id)
|
46
|
-
.map {|span| Span.arrange(span.last.dup) }
|
47
|
-
end
|
48
|
-
|
49
|
-
def traces_to_spans(traces)
|
50
|
-
traces
|
51
|
-
.map {|trace| trace.to_spans}
|
52
|
-
.flatten
|
53
|
-
end
|
54
|
-
|
55
|
-
def spans_by_time(spans)
|
56
|
-
spans.group_by {|span|
|
57
|
-
AppPerfRpm.floor_time(Time.at(span.started_at), dispatch_interval)
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
def group_spans(spans)
|
62
|
-
spans
|
63
|
-
.group_by {|span| [
|
64
|
-
span.type,
|
65
|
-
span.layer,
|
66
|
-
span.domain,
|
67
|
-
span.url,
|
68
|
-
span.controller,
|
69
|
-
span.action
|
70
|
-
]}
|
71
|
-
end
|
72
|
-
|
73
|
-
def dispatch_interval
|
74
|
-
30
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
module AppPerfRpm
|
4
|
-
class Dispatcher
|
5
|
-
def initialize
|
6
|
-
@start_time = Time.now
|
7
|
-
@queue = Queue.new
|
8
|
-
@aggregator = Aggregator.new
|
9
|
-
end
|
10
|
-
|
11
|
-
def add_event(event)
|
12
|
-
@queue << event
|
13
|
-
end
|
14
|
-
|
15
|
-
def configuration
|
16
|
-
::AppPerfRpm.configuration
|
17
|
-
end
|
18
|
-
|
19
|
-
def ready?
|
20
|
-
Time.now > @start_time + configuration.dispatch_interval.to_f &&
|
21
|
-
@queue.size.to_i > 0
|
22
|
-
end
|
23
|
-
|
24
|
-
def reset
|
25
|
-
@queue.clear
|
26
|
-
@start_time = Time.now
|
27
|
-
end
|
28
|
-
|
29
|
-
def dispatch
|
30
|
-
begin
|
31
|
-
spans = drain(@queue)
|
32
|
-
metrics = []#@aggregator.aggregate(spans)
|
33
|
-
|
34
|
-
dispatch_events(spans.map(&:to_a) + metrics)
|
35
|
-
rescue => ex
|
36
|
-
::AppPerfRpm.logger.error "#{ex.inspect}"
|
37
|
-
::AppPerfRpm.logger.error "#{ex.backtrace.inspect}"
|
38
|
-
ensure
|
39
|
-
reset
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def dispatch_events(data)
|
46
|
-
if data && data.length > 0
|
47
|
-
uri = URI(url)
|
48
|
-
|
49
|
-
sock = Net::HTTP.new(uri.host, uri.port)
|
50
|
-
sock.use_ssl = configuration.ssl
|
51
|
-
|
52
|
-
req = Net::HTTP::Post.new(uri.path, { "Content-Type" => "application/json", "Accept-Encoding" => "gzip", "User-Agent" => "gzip" })
|
53
|
-
req.body = compress_body(data)
|
54
|
-
req.content_type = "application/octet-stream"
|
55
|
-
|
56
|
-
res = sock.start do |http|
|
57
|
-
http.read_timeout = 30
|
58
|
-
http.request(req)
|
59
|
-
end
|
60
|
-
data.clear
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def compress_body(data)
|
65
|
-
body = Oj.dump({
|
66
|
-
"name" => configuration.application_name,
|
67
|
-
"host" => AppPerfRpm.host,
|
68
|
-
"data" => data
|
69
|
-
})
|
70
|
-
|
71
|
-
compressed_body = Zlib::Deflate.deflate(body, Zlib::DEFAULT_COMPRESSION)
|
72
|
-
Base64.encode64(compressed_body)
|
73
|
-
end
|
74
|
-
|
75
|
-
def drain(queue)
|
76
|
-
Array.new(queue.size) { queue.pop }
|
77
|
-
end
|
78
|
-
|
79
|
-
def url
|
80
|
-
host = configuration.host
|
81
|
-
license_key = configuration.license_key
|
82
|
-
@url ||= "#{host}/api/listener/2/#{license_key}"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module AppPerfRpm
|
2
|
-
class Middleware
|
3
|
-
attr_reader :app
|
4
|
-
|
5
|
-
def initialize(app)
|
6
|
-
@app = app
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(env)
|
10
|
-
begin
|
11
|
-
@status, @headers, @response = @app.call(env)
|
12
|
-
rescue Exception => e
|
13
|
-
handle_exception(env, e)
|
14
|
-
end
|
15
|
-
[@status, @headers, @response]
|
16
|
-
end
|
17
|
-
|
18
|
-
def handle_exception(env, exception)
|
19
|
-
::AppPerfRpm::Tracer.log_event("error",
|
20
|
-
"path" => env["PATH_INFO"],
|
21
|
-
"method" => env["REQUEST_METHOD"],
|
22
|
-
"message" => exception.message,
|
23
|
-
"error_class" => exception.class.to_s,
|
24
|
-
"backtrace" => ::AppPerfRpm::Backtrace.clean(exception.backtrace),
|
25
|
-
"source" => ::AppPerfRpm::Backtrace.source_extract(exception.backtrace)
|
26
|
-
)
|
27
|
-
raise exception
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/app_perf_rpm/span.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
module AppPerfRpm
|
2
|
-
class Span
|
3
|
-
attr_accessor :layer,
|
4
|
-
:controller,
|
5
|
-
:action,
|
6
|
-
:url,
|
7
|
-
:domain,
|
8
|
-
:type,
|
9
|
-
:backtrace,
|
10
|
-
:source,
|
11
|
-
:trace_id,
|
12
|
-
:started_at,
|
13
|
-
:ended_at,
|
14
|
-
:children,
|
15
|
-
:options
|
16
|
-
|
17
|
-
def self.arrange(spans)
|
18
|
-
spans.sort! { |a, b| (a.ended_at <=> b.ended_at) }
|
19
|
-
|
20
|
-
null_span = Span.new
|
21
|
-
controller = (spans.find {|s| s.controller } || null_span).controller
|
22
|
-
action = (spans.find {|s| s.action } || null_span).action
|
23
|
-
domain = (spans.find {|s| s.domain } || null_span).domain
|
24
|
-
url = (spans.find {|s| s.url } || null_span).url
|
25
|
-
|
26
|
-
while span = spans.shift
|
27
|
-
span.controller ||= controller
|
28
|
-
span.action ||= action
|
29
|
-
span.domain ||= domain
|
30
|
-
span.url ||= url
|
31
|
-
|
32
|
-
if parent = spans.find { |n| n.parent_of?(span) }
|
33
|
-
parent.children << span
|
34
|
-
elsif spans.empty?
|
35
|
-
root = span
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
root
|
40
|
-
end
|
41
|
-
|
42
|
-
def initialize
|
43
|
-
self.children = []
|
44
|
-
self.type = "web"
|
45
|
-
self.options = {}
|
46
|
-
end
|
47
|
-
|
48
|
-
def duration
|
49
|
-
@duration ||= (ended_at - started_at) * 1000.0
|
50
|
-
end
|
51
|
-
|
52
|
-
def exclusive_duration
|
53
|
-
@exclusive_duration ||= duration - children.inject(0.0) { |sum, child| sum + child.duration }
|
54
|
-
end
|
55
|
-
|
56
|
-
def parent_of?(span)
|
57
|
-
start = (started_at - span.started_at) * 1000.0
|
58
|
-
start <= 0 && (start + duration >= span.duration)
|
59
|
-
end
|
60
|
-
|
61
|
-
def child_of?(span)
|
62
|
-
span.parent_of?(self)
|
63
|
-
end
|
64
|
-
|
65
|
-
def to_spans
|
66
|
-
span = self.dup
|
67
|
-
span.exclusive_duration
|
68
|
-
span.children = []
|
69
|
-
|
70
|
-
if children.size > 0
|
71
|
-
return [span] + children.map(&:to_spans)
|
72
|
-
else
|
73
|
-
return [span]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def base_options
|
78
|
-
opts = {}
|
79
|
-
opts["domain"] = domain
|
80
|
-
opts["controller"] = controller
|
81
|
-
opts["action"] = action
|
82
|
-
opts["url"] = url
|
83
|
-
opts["type"] = type
|
84
|
-
#opts["backtrace"] = ::AppPerfRpm::Backtrace.backtrace
|
85
|
-
opts["source"] = ::AppPerfRpm::Backtrace.source_extract
|
86
|
-
opts.delete_if { |k, v| v.nil? }
|
87
|
-
end
|
88
|
-
|
89
|
-
def to_s
|
90
|
-
"#{layer}:#{trace_id}:#{started_at}:#{exclusive_duration}"
|
91
|
-
end
|
92
|
-
|
93
|
-
def to_a
|
94
|
-
[
|
95
|
-
layer,
|
96
|
-
trace_id,
|
97
|
-
started_at,
|
98
|
-
duration,
|
99
|
-
base_options.merge(options)
|
100
|
-
]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/lib/app_perf_rpm/worker.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module AppPerfRpm
|
2
|
-
class Worker
|
3
|
-
def initialize
|
4
|
-
AppPerfRpm.logger.info "Starting worker."
|
5
|
-
@dispatcher = Dispatcher.new
|
6
|
-
end
|
7
|
-
|
8
|
-
def save(event)
|
9
|
-
start
|
10
|
-
return if event.nil?
|
11
|
-
@dispatcher.add_event(event)
|
12
|
-
end
|
13
|
-
|
14
|
-
def start
|
15
|
-
return if worker_running?
|
16
|
-
::AppPerfRpm.mutex.synchronize do
|
17
|
-
return if worker_running?
|
18
|
-
start_dispatcher
|
19
|
-
::AppPerfRpm.logger.info "Worker is running."
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def worker_running?
|
24
|
-
@worker_thread && @worker_thread.alive?
|
25
|
-
end
|
26
|
-
|
27
|
-
def start_dispatcher
|
28
|
-
@worker_thread = Thread.new do
|
29
|
-
::AppPerfRpm.configuration.reload
|
30
|
-
@dispatcher.reset
|
31
|
-
|
32
|
-
loop do
|
33
|
-
start = Time.now
|
34
|
-
if @dispatcher.ready?
|
35
|
-
@dispatcher.dispatch
|
36
|
-
@dispatcher.reset
|
37
|
-
end
|
38
|
-
sleep_for = (start + 15 - Time.now)
|
39
|
-
sleep_for = 1 if sleep_for < 1
|
40
|
-
sleep sleep_for
|
41
|
-
end
|
42
|
-
end
|
43
|
-
@worker_thread.abort_on_exception = true
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|