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
@@ -21,11 +21,13 @@ module AppPerfRpm
21
21
  end
22
22
 
23
23
  {
24
- "name" => opts[:type],
25
- "query" => sanitize_sql(sql),
26
- "database" => db_opts[:database],
27
- "host" => db_opts[:host],
28
- "adapter" => db_opts[:adapter]
24
+ "db.type" => opts[:type],
25
+ "db.statement" => sanitize_sql(sql),
26
+ "db.instance" => db_opts[:database],
27
+ "db.user" => db_opts[:user],
28
+ "db.vendor" => db_opts[:adapter],
29
+ "peer.address" => db_opts[:host],
30
+ "peer.port" => db_opts[:port]
29
31
  }
30
32
  end
31
33
  end
@@ -35,19 +37,22 @@ module AppPerfRpm
35
37
 
36
38
  def run_with_trace(sql, options = ::Sequel::OPTS)
37
39
  if ::AppPerfRpm::Tracer.tracing?
38
- begin
39
- ::AppPerfRpm::Tracer.trace("sequel") do |span|
40
- span.options = parse_opts(sql, options)
40
+ span = ::AppPerfRpm.tracer.start_span("sequel", tags: parse_opts(sql, options))
41
+ span.set_tag "component", "Sequel"
42
+ span.set_tag "span.kind", "client"
43
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
44
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
45
+ end
41
46
 
42
- run_without_trace(sql, options)
43
- end
44
- rescue => e
45
- ::AppPerfRpm.logger.error e.inspect
46
- raise
47
- end
48
- else
49
- run_without_trace(sql, options)
47
+ run_without_trace(sql, options)
48
+ rescue Exception => e
49
+ if span
50
+ span.set_tag('error', true)
51
+ span.log_error(e)
50
52
  end
53
+ raise
54
+ ensure
55
+ span.finish if span
51
56
  end
52
57
  end
53
58
 
@@ -56,25 +61,28 @@ module AppPerfRpm
56
61
 
57
62
  def execute_with_trace(sql, options = ::Sequel::OPTS, &block)
58
63
  if ::AppPerfRpm::Tracer.tracing?
59
- begin
60
- ::AppPerfRpm::Tracer.trace("sequel", opts) do |span|
61
- span.options = parse_opts(sql, options)
64
+ span = ::AppPerfRpm.tracer.start_span("sequel", tags: parse_opts(sql, options))
65
+ span.set_tag "component", "Sequel"
66
+ span.set_tag "span.kind", "client"
67
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
68
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
69
+ end
62
70
 
63
- execute_without_trace(sql, options, &block)
64
- end
65
- rescue => e
66
- ::AppPerfRpm.logger.error e.inspect
67
- raise
68
- end
69
- else
70
- execute_without_trace(sql, options, &block)
71
+ execute_without_trace(sql, options, &block)
72
+ rescue Exception => e
73
+ if span
74
+ span.set_tag('error', true)
75
+ span.log_error(e)
71
76
  end
77
+ raise
78
+ ensure
79
+ span.finish if span
72
80
  end
73
81
  end
74
82
  end
75
83
  end
76
84
 
77
- if ::AppPerfRpm.configuration.instrumentation[:sequel][:enabled] && defined?(::Sequel)
85
+ if ::AppPerfRpm.config.instrumentation[:sequel][:enabled] && defined?(::Sequel)
78
86
  ::AppPerfRpm.logger.info "Initializing sequel tracer."
79
87
 
80
88
  ::Sequel::Database.send(:include, AppPerfRpm::Instruments::SequelDatabase)
@@ -3,41 +3,85 @@ module AppPerfRpm
3
3
  def call(*args)
4
4
  worker, msg, queue = args
5
5
 
6
- result = AppPerfRpm::Tracer.start_trace("sidekiq-worker") do |span|
7
- span.type = "job"
8
- span.controller = "Sidekiq_#{queue}"
9
- span.action = msg["wrapped"]
10
- span.url = "/sidekiq/#{queue}/#{msg['wrapped']}"
11
- span.domain = Socket.gethostname
12
- span.options = {
13
- "job_name" => worker.class.to_s,
14
- "queue" => queue
15
- }
16
-
17
- yield
6
+ parent_span_context = extract(msg)
7
+ AppPerfRpm::Tracer.sample!(parent_span_context)
8
+
9
+ if AppPerfRpm::Tracer.tracing?
10
+ operation = "Sidekiq_#{queue}##{msg["wrapped"]}"
11
+ span = AppPerfRpm.tracer.start_span(operation, :child_of => parent_span_context, tags: {
12
+ "component" => "Sidekiq",
13
+ "span.kind" => "server",
14
+ "http.url" => "/sidekiq/#{queue}/#{msg['wrapped']}",
15
+ "peer.address" => Socket.gethostname,
16
+ "bg.queue" => queue,
17
+ "bg.job_name" => worker.class.to_s
18
+ })
19
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
20
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
21
+ end
22
+
23
+ yield
24
+ rescue Exception => e
25
+ if span
26
+ span.set_tag('error', true)
27
+ span.log_error(e)
18
28
  end
29
+ raise
30
+ ensure
31
+ span.finish if span
32
+ end
33
+
34
+ private
19
35
 
20
- result
36
+ def extract(job)
37
+ carrier = job[AppPerfRpm::TRACE_CONTEXT_KEY]
38
+ return unless carrier
39
+ AppPerfRpm::tracer.extract(OpenTracing::FORMAT_TEXT_MAP, carrier)
21
40
  end
22
41
  end
23
42
 
24
43
  class SidekiqClient
25
44
  def call(*args)
45
+ worker, msg, queue = args
46
+
26
47
  if ::AppPerfRpm::Tracer.tracing?
27
- worker, msg, queue = args
48
+ operation = "Sidekiq_#{queue}##{msg["wrapped"]}"
49
+ span = AppPerfRpm.tracer.start_span(operation, tags: {
50
+ "component" => "Sidekiq",
51
+ "span.kind" => "client",
52
+ "http.url" => "/sidekiq/#{queue}/#{msg['wrapped']}",
53
+ "peer.address" => Socket.gethostname,
54
+ "bg.queue" => queue,
55
+ "bg.job_name" => worker.class.to_s
56
+ })
57
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
58
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
59
+
60
+ inject(span, msg)
61
+ end
28
62
 
29
- result = AppPerfRpm::Tracer.trace("sidekiq-client") do |span|
30
- yield
31
- end
32
- else
33
- result = yield
63
+ yield
64
+ rescue Exception => e
65
+ if span
66
+ span.set_tag('error', true)
67
+ span.log_error(e)
34
68
  end
35
- result
69
+ raise
70
+ ensure
71
+ span.finish if span
72
+ end
73
+
74
+ private
75
+
76
+ def inject(span, job)
77
+ carrier = {}
78
+ AppPerfRpm.tracer.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, carrier)
79
+ job[AppPerfRpm::TRACE_CONTEXT_KEY] = carrier
36
80
  end
37
81
  end
38
82
  end
39
83
 
40
- if ::AppPerfRpm.configuration.instrumentation[:sidekiq][:enabled] &&
84
+ if ::AppPerfRpm.config.instrumentation[:sidekiq][:enabled] &&
41
85
  defined?(::Sidekiq)
42
86
  AppPerfRpm.logger.info "Initializing sidekiq tracer."
43
87
 
@@ -4,15 +4,23 @@ module AppPerfRpm
4
4
  module Base
5
5
  def dispatch_with_trace
6
6
  if ::AppPerfRpm::Tracer.tracing?
7
- ::AppPerfRpm::Tracer.trace("sinatra") do |span|
8
- span.controller = self.class.to_s
9
- span.action = env["PATH_INFO"]
7
+ operation = "#{self.class}##{env["PATH_INFO"]}"
8
+ span = ::AppPerfRpm.tracer.start_span(operation, tags: {
9
+ component: "Sinatra"
10
+ })
11
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
12
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
13
+ end
10
14
 
11
- dispatch_without_trace
12
- end
13
- else
14
- dispatch_without_trace
15
+ dispatch_without_trace
16
+ rescue Exception => e
17
+ if span
18
+ span.set_tag('error', true)
19
+ span.log_error(e)
15
20
  end
21
+ raise
22
+ ensure
23
+ span.finish if span
16
24
  end
17
25
 
18
26
  def handle_exception_with_trace(boom)
@@ -25,27 +33,33 @@ module AppPerfRpm
25
33
  if ::AppPerfRpm::Tracer.tracing?
26
34
  name = data
27
35
 
28
- ::AppPerfRpm::Tracer.trace("sinatra") do |span|
29
- span.options = {
30
- "engine" => engine,
31
- "name" => name,
32
- "type" => "render",
33
- "file" => __FILE__,
34
- "line_number" => __LINE__
35
- }
36
+ span = ::AppPerfRpm.tracer.start_span("render", tags: {
37
+ "component" => "Sinatra",
38
+ "view.engine" => engine,
39
+ "view.name" => name,
40
+ "view.line_number" => __LINE__,
41
+ "view.template" => __FILE__
42
+ })
43
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
44
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
45
+ end
36
46
 
37
- render_without_trace(engine, data, options, locals, &block)
38
- end
39
- else
40
- render_without_trace(engine, data, options, locals, &block)
47
+ render_without_trace(engine, data, options, locals, &block)
48
+ rescue Exception => e
49
+ if span
50
+ span.set_tag('error', true)
51
+ span.log_error(e)
41
52
  end
53
+ raise
54
+ ensure
55
+ span.finish if span
42
56
  end
43
57
  end
44
58
  end
45
59
  end
46
60
  end
47
61
 
48
- if ::AppPerfRpm.configuration.instrumentation[:sinatra][:enabled] &&
62
+ if ::AppPerfRpm.config.instrumentation[:sinatra][:enabled] &&
49
63
  defined?(::Sinatra)
50
64
  ::AppPerfRpm.logger.info "Initializing sinatra tracer."
51
65
 
@@ -2,43 +2,62 @@ module AppPerfRpm
2
2
  module Instruments
3
3
  module TyphoeusRequest
4
4
  def run_with_trace
5
- if ::AppPerfRpm.tracing?
6
- span = ::AppPerfRpm::Tracer.start_span("typhoeus")
7
- response = run_without_trace
8
- span.finish
5
+ if ::AppPerfRpm::Tracer.tracing?
6
+ span = ::AppPerfRpm.tracer.start_span("typhoeus", tags: {
7
+ "component" => "Typhoeus"
8
+ })
9
+ AppPerfRpm.tracer.inject(span.context, OpenTracing::FORMAT_RACK, options[:headers])
9
10
 
11
+ response = run_without_trace
12
+ span.exit
10
13
  uri = URI(response.effective_url)
11
14
 
12
- span.options = {
13
- "http_status" => response.code,
14
- "remote_url" => uri.to_s,
15
- "http_method" => options[:method]
16
- }
17
- span.submit(opts)
18
-
19
- response
15
+ span.set_tag "http.status_code", response.code
16
+ span.set_tag "http.url", uri.to_s
17
+ span.set_tag "http.method", options[:method]
18
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
19
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
20
20
  else
21
- run_without_trace
21
+ response = run_without_trace
22
+ end
23
+ response
24
+ rescue Exception => e
25
+ if span
26
+ span.set_tag('error', true)
27
+ span.log_error(e)
22
28
  end
29
+ raise
30
+ ensure
31
+ span.finish if span
23
32
  end
24
33
  end
25
34
 
26
35
  module TyphoeusHydra
27
36
  def run_with_trace
28
- ::AppPerfRpm::Tracer.trace("typhoeus") do |span|
29
- span.options = {
30
- "method" => :hydra,
31
- "queued_requests" => queued_requests.count,
32
- "max_concurrency" => max_concurrency
33
- }
34
- run_without_trace
37
+ span = ::AppPerfRpm.tracer.start_span("typhoeus", tags: {
38
+ "component" => "Typhoeus",
39
+ "method" => "hydra",
40
+ "http.queued_requests" => queued_requests.count,
41
+ "http.max_concurrency" => max_concurrency
42
+ })
43
+ span.log(event: "backtrace", stack: ::AppPerfRpm::Backtrace.backtrace)
44
+ span.log(event: "source", stack: ::AppPerfRpm::Backtrace.source_extract)
45
+
46
+ run_without_trace
47
+ rescue Exception => e
48
+ if span
49
+ span.set_tag('error', true)
50
+ span.log_error(e)
35
51
  end
52
+ raise
53
+ ensure
54
+ span.finish if span
36
55
  end
37
56
  end
38
57
  end
39
58
  end
40
59
 
41
- if ::AppPerfRpm.configuration.instrumentation[:typhoeus][:enabled] && defined?(::Typhoeus)
60
+ if ::AppPerfRpm.config.instrumentation[:typhoeus][:enabled] && defined?(::Typhoeus)
42
61
  ::AppPerfRpm.logger.info "Initializing typhoeus tracer."
43
62
 
44
63
  ::Typhoeus::Request::Operations.send(:include, AppPerfRpm::Instruments::TyphoeusRequest)
@@ -5,7 +5,8 @@ if defined?(::Rails)
5
5
  Rails.configuration.after_initialize do
6
6
  unless AppPerfRpm.disable_agent?
7
7
  AppPerfRpm.load
8
- Rails.configuration.middleware.use AppPerfRpm::Middleware
8
+ AppPerfRpm.logger.info "Initializing rack middleware tracer."
9
+ Rails.configuration.middleware.insert 0, AppPerfRpm::Instruments::Rack
9
10
  end
10
11
  end
11
12
  end
@@ -1,15 +1,15 @@
1
1
  module AppPerfRpm
2
2
  class Railtie < ::Rails::Railtie
3
- # TODO: Why this isn't working with the initializer?
4
3
  initializer "app_perf.initialize" do |app|
5
4
  unless AppPerfRpm.disable_agent?
6
5
  require 'app_perf_rpm/instruments/rack'
7
- app.middleware.use AppPerfRpm::Middleware
6
+ AppPerfRpm.logger.info "Initializing rack middleware tracer."
7
+ app.middleware.insert 0, AppPerfRpm::Instruments::Rack
8
8
  end
9
9
 
10
10
  config.after_initialize do
11
- AppPerfRpm.configuration.app_root = Rails.root
12
- AppPerfRpm.configuration.reload
11
+ AppPerfRpm.config.app_root = Rails.root
12
+ AppPerfRpm.config.reload
13
13
  AppPerfRpm.load
14
14
  end
15
15
  end
@@ -0,0 +1,69 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'base64'
5
+
6
+ module AppPerfRpm
7
+ module Reporters
8
+ class JsonClient
9
+ def initialize(url:, collector:, flush_interval:)
10
+ @collector = collector
11
+ @flush_interval = flush_interval
12
+ @spans_uri = URI.parse(url)
13
+ end
14
+
15
+ def start
16
+ @thread = Thread.new do
17
+ loop do
18
+ emit_batch(@collector.retrieve)
19
+ sleep @flush_interval
20
+ end
21
+ end
22
+ end
23
+
24
+ def stop
25
+ @thread.terminate if @thread
26
+ emit_batch(@collector.retrieve)
27
+ end
28
+
29
+ private
30
+
31
+ def compress_body(data)
32
+ body = Oj.dump({
33
+ "name" => AppPerfRpm.config.application_name,
34
+ "host" => AppPerfRpm.host,
35
+ "data" => data
36
+ })
37
+
38
+ compressed_body = Zlib::Deflate.deflate(body, Zlib::DEFAULT_COMPRESSION)
39
+ Base64.encode64(compressed_body)
40
+ end
41
+
42
+ def emit_batch(spans)
43
+ return if spans.empty?
44
+
45
+ sock = Net::HTTP.new(@spans_uri.host, @spans_uri.port)
46
+ sock.use_ssl = ::AppPerfRpm.config.ssl
47
+
48
+ request = Net::HTTP::Post.new(@spans_uri.request_uri, {
49
+ 'Content-Type' => 'application/json',
50
+ "Accept-Encoding" => "gzip",
51
+ "User-Agent" => "gzip"
52
+ })
53
+ request.body = compress_body(spans)
54
+ request.content_type = "application/octet-stream"
55
+
56
+ response = sock.start do |http|
57
+ http.read_timeout = 30
58
+ http.request(request)
59
+ end
60
+
61
+ if response.code != 202
62
+ STDERR.puts(response.body)
63
+ end
64
+ rescue => e
65
+ STDERR.puts("Error emitting spans batch: #{e.message}\n#{e.backtrace.join("\n")}")
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,14 @@
1
+ module AppPerfRpm
2
+ module Reporters
3
+ class NullClient
4
+ def initialize
5
+ end
6
+
7
+ def start
8
+ end
9
+
10
+ def stop
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,69 +1,37 @@
1
+ require 'opentracing'
2
+
1
3
  module AppPerfRpm
2
4
  class Tracer
3
5
  class << self
4
- def trace_id
5
- Thread.current[:trace_id]
6
+ # This method should be called by any components that are
7
+ # capable of starting the tracing process.
8
+ # ie. rack, sidekiq worker, etc
9
+ def sample!(incoming_trace = nil)
10
+ # Since we keep track of the active span, meaning we have entered into
11
+ # tracing at some point, and we no longer have an active span,
12
+ # reset tracing.
13
+ Thread.current[:sample] = false if !AppPerfRpm.tracer.active_span
14
+
15
+ # Now determine if we want to trace, either by an incoming
16
+ # trace or meeting the sample rate.
17
+ Thread.current[:sample] = !!incoming_trace || should_sample?
18
+ Thread.current[:sample]
6
19
  end
7
20
 
8
- def trace_id=(t)
9
- Thread.current[:trace_id] = t
21
+ def sampled?
22
+ !!Thread.current[:sample]
10
23
  end
11
24
 
12
25
  def tracing?
13
- Thread.current[:trace_id]
14
- end
15
-
16
- def in_trace?
17
- !Thread.current[:trace_id].nil?
18
- end
19
-
20
- def start_span(layer, opts = {})
21
- Instance.new(layer, opts)
26
+ AppPerfRpm.tracing? && sampled?
22
27
  end
23
28
 
24
29
  def random_percentage
25
30
  rand * 100
26
31
  end
27
32
 
28
- def should_trace?
29
- random_percentage < ::AppPerfRpm.configuration.sample_rate.to_i
30
- end
31
-
32
- def start_trace(layer, opts = {})
33
- start = Time.now.to_f
34
-
35
- trace_id = opts.delete("trace_id")
36
- if trace_id || should_trace?
37
- self.trace_id = trace_id || generate_trace_id
38
- result = trace(layer, opts) do |span|
39
- yield(span)
40
- end
41
- self.trace_id = nil
42
- else
43
- span = Span.new
44
- result = yield(span)
45
- end
46
-
47
- return result, (Time.now.to_f - start) * 1000
48
- end
49
-
50
- def trace(layer, opts = {})
51
- result = nil
52
-
53
- if tracing?
54
- span = Span.new
55
- span.layer = layer
56
- span.trace_id = self.trace_id
57
- span.started_at = Time.now.to_f
58
- result = yield(span)
59
- span.ended_at = Time.now.to_f
60
- span.options.merge!(opts)
61
- ::AppPerfRpm.store(span)
62
- else
63
- result = yield
64
- end
65
-
66
- result
33
+ def should_sample?
34
+ random_percentage <= ::AppPerfRpm.config.sample_rate.to_i
67
35
  end
68
36
 
69
37
  def profile(layer, opts = {})
@@ -98,43 +66,6 @@ module AppPerfRpm
98
66
  return [], yield
99
67
  end
100
68
  end
101
-
102
- def log_event(event, opts = {})
103
- ::AppPerfRpm.store([event, generate_trace_id, Time.now.to_f, opts])
104
- end
105
-
106
- def generate_trace_id
107
- Digest::SHA1.hexdigest([Time.now, rand].join)
108
- end
109
-
110
- class Instance
111
- attr_accessor :layer, :opts, :start, :duration
112
-
113
- def initialize(layer, opts = {})
114
- @span = Span.new
115
- @span.layer = layer
116
- @span.options = opts
117
- @span.started_at = Time.now.to_f
118
- end
119
-
120
- def finish(opts = {})
121
- @span.options.merge!(opts)
122
- @span.ended_at = Time.now.to_f
123
- end
124
-
125
- def submit(opts = {})
126
- if ::AppPerfRpm::Tracer.tracing?
127
- @span.options.merge!(opts)
128
- ::AppPerfRpm.store(@span)
129
- end
130
- end
131
-
132
- private
133
-
134
- def trace_id
135
- ::AppPerfRpm::Tracer.trace_id
136
- end
137
- end
138
69
  end
139
70
  end
140
71
  end
@@ -0,0 +1,25 @@
1
+ module AppPerfRpm
2
+ module Tracing
3
+ class Buffer
4
+ def initialize
5
+ @buffer = []
6
+ @mutex = Mutex.new
7
+ end
8
+
9
+ def <<(element)
10
+ @mutex.synchronize do
11
+ @buffer << element
12
+ true
13
+ end
14
+ end
15
+
16
+ def retrieve
17
+ @mutex.synchronize do
18
+ elements = @buffer.dup
19
+ @buffer.clear
20
+ elements
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ module AppPerfRpm
2
+ module Tracing
3
+ class Carrier
4
+ def initialize
5
+ @data = {}
6
+ end
7
+
8
+ def [](key)
9
+ @data[key]
10
+ end
11
+
12
+ def []=(key, value)
13
+ @data[key] = value
14
+ end
15
+
16
+ def each(&block)
17
+ @data.each do |datum|
18
+ yield(datum)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end