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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/app_perf_rpm/backtrace.rb +7 -7
  3. data/lib/app_perf_rpm/configuration.rb +6 -4
  4. data/lib/app_perf_rpm/instruments/action_controller.rb +33 -16
  5. data/lib/app_perf_rpm/instruments/action_view.rb +93 -65
  6. data/lib/app_perf_rpm/instruments/active_record/adapters/mysql2.rb +24 -15
  7. data/lib/app_perf_rpm/instruments/active_record/adapters/postgresql.rb +95 -52
  8. data/lib/app_perf_rpm/instruments/active_record/adapters/sqlite3.rb +95 -54
  9. data/lib/app_perf_rpm/instruments/active_record.rb +1 -1
  10. data/lib/app_perf_rpm/instruments/activerecord_import.rb +22 -13
  11. data/lib/app_perf_rpm/instruments/emque_consuming.rb +16 -7
  12. data/lib/app_perf_rpm/instruments/faraday.rb +26 -16
  13. data/lib/app_perf_rpm/instruments/net_http.rb +16 -10
  14. data/lib/app_perf_rpm/instruments/rack.rb +75 -25
  15. data/lib/app_perf_rpm/instruments/redis.rb +49 -13
  16. data/lib/app_perf_rpm/instruments/sequel.rb +36 -28
  17. data/lib/app_perf_rpm/instruments/sidekiq.rb +65 -21
  18. data/lib/app_perf_rpm/instruments/sinatra.rb +34 -20
  19. data/lib/app_perf_rpm/instruments/typhoeus.rb +40 -21
  20. data/lib/app_perf_rpm/rails.rb +2 -1
  21. data/lib/app_perf_rpm/railtie.rb +4 -4
  22. data/lib/app_perf_rpm/reporters/json_client.rb +69 -0
  23. data/lib/app_perf_rpm/reporters/null_client.rb +14 -0
  24. data/lib/app_perf_rpm/tracer.rb +20 -89
  25. data/lib/app_perf_rpm/tracing/buffer.rb +25 -0
  26. data/lib/app_perf_rpm/tracing/carrier.rb +23 -0
  27. data/lib/app_perf_rpm/tracing/collector.rb +31 -0
  28. data/lib/app_perf_rpm/tracing/endpoint.rb +19 -0
  29. data/lib/app_perf_rpm/tracing/managed_span.rb +36 -0
  30. data/lib/app_perf_rpm/tracing/managed_tracer.rb +32 -0
  31. data/lib/app_perf_rpm/tracing/span.rb +67 -0
  32. data/lib/app_perf_rpm/tracing/span_context.rb +41 -0
  33. data/lib/app_perf_rpm/tracing/thread_span_stack.rb +32 -0
  34. data/lib/app_perf_rpm/tracing/trace_id.rb +11 -0
  35. data/lib/app_perf_rpm/tracing/tracer.rb +91 -0
  36. data/lib/app_perf_rpm/utils.rb +18 -0
  37. data/lib/app_perf_rpm.rb +59 -26
  38. metadata +90 -12
  39. data/lib/app_perf_rpm/aggregator.rb +0 -77
  40. data/lib/app_perf_rpm/dispatcher.rb +0 -85
  41. data/lib/app_perf_rpm/middleware.rb +0 -30
  42. data/lib/app_perf_rpm/span.rb +0 -103
  43. 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
@@ -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
@@ -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