app_perf_rpm 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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