baseline_red_rpm 1.0.0

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/lib/baseline_red_rpm.rb +164 -0
  3. data/lib/baseline_red_rpm/backtrace.rb +117 -0
  4. data/lib/baseline_red_rpm/configuration.rb +63 -0
  5. data/lib/baseline_red_rpm/instrumentation.rb +23 -0
  6. data/lib/baseline_red_rpm/instruments/action_controller.rb +70 -0
  7. data/lib/baseline_red_rpm/instruments/action_view.rb +222 -0
  8. data/lib/baseline_red_rpm/instruments/active_model_serializer.rb +37 -0
  9. data/lib/baseline_red_rpm/instruments/active_record.rb +66 -0
  10. data/lib/baseline_red_rpm/instruments/active_record/adapters/mysql2.rb +55 -0
  11. data/lib/baseline_red_rpm/instruments/active_record/adapters/postgresql.rb +143 -0
  12. data/lib/baseline_red_rpm/instruments/active_record/adapters/sqlite3.rb +142 -0
  13. data/lib/baseline_red_rpm/instruments/activerecord_import.rb +57 -0
  14. data/lib/baseline_red_rpm/instruments/emque_consuming.rb +41 -0
  15. data/lib/baseline_red_rpm/instruments/faraday.rb +48 -0
  16. data/lib/baseline_red_rpm/instruments/grape.rb +63 -0
  17. data/lib/baseline_red_rpm/instruments/net_http.rb +43 -0
  18. data/lib/baseline_red_rpm/instruments/rack.rb +129 -0
  19. data/lib/baseline_red_rpm/instruments/redis.rb +75 -0
  20. data/lib/baseline_red_rpm/instruments/roda.rb +48 -0
  21. data/lib/baseline_red_rpm/instruments/sequel.rb +100 -0
  22. data/lib/baseline_red_rpm/instruments/sidekiq.rb +100 -0
  23. data/lib/baseline_red_rpm/instruments/sinatra.rb +82 -0
  24. data/lib/baseline_red_rpm/instruments/typhoeus.rb +74 -0
  25. data/lib/baseline_red_rpm/introspector.rb +53 -0
  26. data/lib/baseline_red_rpm/logger.rb +34 -0
  27. data/lib/baseline_red_rpm/rails.rb +15 -0
  28. data/lib/baseline_red_rpm/railtie.rb +19 -0
  29. data/lib/baseline_red_rpm/reporters/json_client.rb +69 -0
  30. data/lib/baseline_red_rpm/reporters/null_client.rb +16 -0
  31. data/lib/baseline_red_rpm/tracer.rb +75 -0
  32. data/lib/baseline_red_rpm/tracing/buffer.rb +27 -0
  33. data/lib/baseline_red_rpm/tracing/carrier.rb +25 -0
  34. data/lib/baseline_red_rpm/tracing/collector.rb +33 -0
  35. data/lib/baseline_red_rpm/tracing/endpoint.rb +21 -0
  36. data/lib/baseline_red_rpm/tracing/managed_span.rb +40 -0
  37. data/lib/baseline_red_rpm/tracing/managed_tracer.rb +36 -0
  38. data/lib/baseline_red_rpm/tracing/span.rb +72 -0
  39. data/lib/baseline_red_rpm/tracing/span_context.rb +43 -0
  40. data/lib/baseline_red_rpm/tracing/thread_span_stack.rb +34 -0
  41. data/lib/baseline_red_rpm/tracing/trace_id.rb +13 -0
  42. data/lib/baseline_red_rpm/tracing/tracer.rb +100 -0
  43. data/lib/baseline_red_rpm/utils.rb +45 -0
  44. data/lib/tasks/install.rake +6 -0
  45. metadata +212 -0
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module Redis
6
+ include BaselineRedRpm::Utils
7
+
8
+ def call_with_trace(*command, &block)
9
+ if ::BaselineRedRpm::Tracer.tracing?
10
+ span = ::BaselineRedRpm.tracer.start_span("redis", tags: {
11
+ "component" => "Redis",
12
+ "span.kind" => "client",
13
+ "peer.address" => self.host,
14
+ "peer.port" => self.port,
15
+ "db.type" => "redis",
16
+ "db.vendor" => "redis",
17
+ "db.instance" => self.db,
18
+ "db.statement" => format_redis_command(*command)
19
+ })
20
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :redis)
21
+ end
22
+
23
+ call_without_trace(*command, &block)
24
+ rescue Exception => e
25
+ if span
26
+ span.set_tag('error', true)
27
+ span.log_error(e)
28
+ end
29
+ raise
30
+ ensure
31
+ span.finish if span
32
+ end
33
+
34
+ def call_pipeline_with_trace(*pipeline)
35
+ if ::BaselineRedRpm::Tracer.tracing?
36
+ span = ::BaselineRedRpm.tracer.start_span("redis", tags: {
37
+ "component" => "Redis",
38
+ "span.kind" => "client",
39
+ "peer.address" => self.host,
40
+ "peer.port" => self.port,
41
+ "db.type" => "redis",
42
+ "db.vendor" => "redis",
43
+ "db.instance" => self.db,
44
+ "db.statement" => pipeline[0].commands.map { |c| format_redis_command(c) }.join("\n")
45
+ })
46
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :redis)
47
+ end
48
+
49
+ call_pipeline_without_trace(*pipeline)
50
+ rescue Exception => e
51
+ if span
52
+ span.set_tag('error', true)
53
+ span.log_error(e)
54
+ end
55
+ raise
56
+ ensure
57
+ span.finish if span
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ if ::BaselineRedRpm.config.instrumentation[:redis][:enabled] &&
64
+ defined?(::Redis)
65
+ ::BaselineRedRpm.logger.info "Initializing redis tracer."
66
+
67
+ ::Redis::Client.send(:include, ::BaselineRedRpm::Instruments::Redis)
68
+
69
+ ::Redis::Client.class_eval do
70
+ alias_method :call_without_trace, :call
71
+ alias_method :call, :call_with_trace
72
+ alias_method :call_pipeline_without_trace, :call_pipeline
73
+ alias_method :call_pipeline, :call_pipeline_with_trace
74
+ end
75
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module Roda
6
+ def call_with_trace(&block)
7
+ if BaselineRedRpm::Tracer.tracing?
8
+ req = ::Rack::Request.new(env)
9
+ request_method = req.request_method.to_s.upcase
10
+ path = req.path
11
+
12
+ parts = path.to_s.rpartition("/")
13
+ action = parts.last
14
+ controller = parts.first.sub(/\A\//, '').split("/").collect {|w| w.capitalize }.join("::")
15
+ operation = "#{controller}##{action}"
16
+
17
+ span = BaselineRedRpm.tracer.start_span(operation, tags: {
18
+ "component" => "Roda",
19
+ "http.url" => path,
20
+ "http.method" => request_method,
21
+ "params" => @_request.params
22
+ })
23
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :roda)
24
+ end
25
+
26
+ call_without_trace(&block)
27
+ rescue Exception => e
28
+ if span
29
+ span.set_tag('error', true)
30
+ span.log_error(e)
31
+ end
32
+ raise
33
+ ensure
34
+ span.finish if span
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ if defined?(::Roda) && ::BaselineRedRpm.config.instrumentation[:roda][:enabled]
41
+ ::BaselineRedRpm.logger.info "Initializing roda tracer."
42
+
43
+ ::Roda::RodaPlugins::Base::InstanceMethods.send(:include, BaselineRedRpm::Instruments::Roda)
44
+ ::Roda::RodaPlugins::Base::InstanceMethods.class_eval do
45
+ alias_method :call_without_trace, :call
46
+ alias_method :call, :call_with_trace
47
+ end
48
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module Sequel
6
+ def sanitize_sql(sql)
7
+ regexp = Regexp.new('(\'[\s\S][^\']*\'|\d*\.\d+|\d+|NULL)', Regexp::IGNORECASE)
8
+ sql.to_s.gsub(regexp, '?')
9
+ end
10
+
11
+ def parse_opts(sql, opts)
12
+ if ::Sequel::VERSION < '3.41.0' && !(self.class.to_s =~ /Dataset$/)
13
+ db_opts = @opts
14
+ elsif @pool
15
+ db_opts = @pool.db.opts
16
+ else
17
+ db_opts = @db.opts
18
+ end
19
+
20
+ if ::Sequel::VERSION > '4.36.0' && !sql.is_a?(String)
21
+ # In 4.37.0, sql was converted to a prepared statement object
22
+ sql = sql.prepared_sql unless sql.is_a?(Symbol)
23
+ end
24
+
25
+ {
26
+ "db.type" => opts[:type],
27
+ "db.statement" => sanitize_sql(sql),
28
+ "db.instance" => db_opts[:database],
29
+ "db.user" => db_opts[:user],
30
+ "db.vendor" => db_opts[:adapter],
31
+ "peer.address" => db_opts[:host],
32
+ "peer.port" => db_opts[:port]
33
+ }
34
+ end
35
+ end
36
+
37
+ module SequelDatabase
38
+ include ::BaselineRedRpm::Instruments::Sequel
39
+
40
+ def run_with_trace(sql, options = ::Sequel::OPTS)
41
+ if ::BaselineRedRpm::Tracer.tracing?
42
+ span = ::BaselineRedRpm.tracer.start_span("sequel", tags: parse_opts(sql, options))
43
+ span.set_tag "component", "Sequel"
44
+ span.set_tag "span.kind", "client"
45
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :sequel)
46
+ end
47
+
48
+ run_without_trace(sql, options)
49
+ rescue Exception => e
50
+ if span
51
+ span.set_tag('error', true)
52
+ span.log_error(e)
53
+ end
54
+ raise
55
+ ensure
56
+ span.finish if span
57
+ end
58
+ end
59
+
60
+ module SequelDataset
61
+ include ::BaselineRedRpm::Instruments::Sequel
62
+
63
+ def execute_with_trace(sql, options = ::Sequel::OPTS, &block)
64
+ if ::BaselineRedRpm::Tracer.tracing?
65
+ span = ::BaselineRedRpm.tracer.start_span("sequel", tags: parse_opts(sql, options))
66
+ span.set_tag "component", "Sequel"
67
+ span.set_tag "span.kind", "client"
68
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :sequel)
69
+ end
70
+
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)
76
+ end
77
+ raise
78
+ ensure
79
+ span.finish if span
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ if ::BaselineRedRpm.config.instrumentation[:sequel][:enabled] && defined?(::Sequel)
86
+ ::BaselineRedRpm.logger.info "Initializing sequel tracer."
87
+
88
+ ::Sequel::Database.send(:include, BaselineRedRpm::Instruments::SequelDatabase)
89
+ ::Sequel::Dataset.send(:include, BaselineRedRpm::Instruments::SequelDataset)
90
+
91
+ ::Sequel::Database.class_eval do
92
+ alias_method :run_without_trace, :run
93
+ alias_method :run, :run_with_trace
94
+ end
95
+
96
+ ::Sequel::Dataset.class_eval do
97
+ alias_method :execute_without_trace, :execute
98
+ alias_method :execute, :execute_with_trace
99
+ end
100
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ class SidekiqServer
5
+ def call(*args)
6
+ worker, msg, queue = args
7
+
8
+ parent_span_context = extract(msg)
9
+ BaselineRedRpm::Tracer.sample!(parent_span_context)
10
+
11
+ if BaselineRedRpm::Tracer.tracing?
12
+ operation = "Sidekiq_#{queue}##{msg["wrapped"]}"
13
+ span = BaselineRedRpm.tracer.start_span(operation, :child_of => parent_span_context, tags: {
14
+ "component" => "Sidekiq",
15
+ "span.kind" => "server",
16
+ "http.url" => "/sidekiq/#{queue}/#{msg['wrapped']}",
17
+ "peer.address" => Socket.gethostname,
18
+ "bg.queue" => queue,
19
+ "bg.job_name" => worker.class.to_s
20
+ })
21
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :sidekiq)
22
+ end
23
+
24
+ yield
25
+ rescue Exception => e
26
+ if span
27
+ span.set_tag('error', true)
28
+ span.log_error(e)
29
+ end
30
+ raise
31
+ ensure
32
+ span.finish if span
33
+ BaselineRedRpm::Tracer.sample_off!
34
+ end
35
+
36
+ private
37
+
38
+ def extract(job)
39
+ carrier = job[BaselineRedRpm::TRACE_CONTEXT_KEY]
40
+ return unless carrier
41
+ BaselineRedRpm::tracer.extract(OpenTracing::FORMAT_TEXT_MAP, carrier)
42
+ end
43
+ end
44
+
45
+ class SidekiqClient
46
+ def call(*args)
47
+ worker, msg, queue = args
48
+
49
+ if ::BaselineRedRpm::Tracer.tracing?
50
+ operation = "Sidekiq_#{queue}##{msg["wrapped"]}"
51
+ span = BaselineRedRpm.tracer.start_span(operation, tags: {
52
+ "component" => "Sidekiq",
53
+ "span.kind" => "client",
54
+ "http.url" => "/sidekiq/#{queue}/#{msg['wrapped']}",
55
+ "peer.address" => Socket.gethostname,
56
+ "bg.queue" => queue,
57
+ "bg.job_name" => worker.class.to_s
58
+ })
59
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :sidekiq)
60
+
61
+ inject(span, msg)
62
+ end
63
+
64
+ yield
65
+ rescue Exception => e
66
+ if span
67
+ span.set_tag('error', true)
68
+ span.log_error(e)
69
+ end
70
+ raise
71
+ ensure
72
+ span.finish if span
73
+ end
74
+
75
+ private
76
+
77
+ def inject(span, job)
78
+ carrier = {}
79
+ BaselineRedRpm.tracer.inject(span.context, OpenTracing::FORMAT_TEXT_MAP, carrier)
80
+ job[BaselineRedRpm::TRACE_CONTEXT_KEY] = carrier
81
+ end
82
+ end
83
+ end
84
+
85
+ if ::BaselineRedRpm.config.instrumentation[:sidekiq][:enabled] &&
86
+ defined?(::Sidekiq)
87
+ BaselineRedRpm.logger.info "Initializing sidekiq tracer."
88
+
89
+ ::Sidekiq.configure_server do |config|
90
+ config.server_middleware do |chain|
91
+ chain.add ::BaselineRedRpm::SidekiqServer
92
+ end
93
+ end
94
+
95
+ ::Sidekiq.configure_client do |config|
96
+ config.client_middleware do |chain|
97
+ chain.add ::BaselineRedRpm::SidekiqClient
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module Sinatra
6
+ module Base
7
+ def dispatch_with_trace
8
+ if ::BaselineRedRpm::Tracer.tracing?
9
+ operation = "#{self.class}##{env["PATH_INFO"]}"
10
+ span = ::BaselineRedRpm.tracer.start_span(operation, tags: {
11
+ component: "Sinatra"
12
+ })
13
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :sinatra)
14
+ end
15
+
16
+ dispatch_without_trace
17
+ rescue Exception => e
18
+ if span
19
+ span.set_tag('error', true)
20
+ span.log_error(e)
21
+ end
22
+ raise
23
+ ensure
24
+ span.finish if span
25
+ end
26
+
27
+ def handle_exception_with_trace(boom)
28
+ handle_exception_without_trace(boom)
29
+ end
30
+ end
31
+
32
+ module Templates
33
+ def render_with_trace(engine, data, options = {}, locals = {}, &block)
34
+ if ::BaselineRedRpm::Tracer.tracing?
35
+ name = data
36
+
37
+ span = ::BaselineRedRpm.tracer.start_span("render", tags: {
38
+ "component" => "Sinatra",
39
+ "view.engine" => engine,
40
+ "view.name" => name,
41
+ "view.line_number" => __LINE__,
42
+ "view.template" => __FILE__
43
+ })
44
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :sinatra)
45
+ end
46
+
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)
52
+ end
53
+ raise
54
+ ensure
55
+ span.finish if span
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ if ::BaselineRedRpm.config.instrumentation[:sinatra][:enabled] &&
63
+ defined?(::Sinatra)
64
+ ::BaselineRedRpm.logger.info "Initializing sinatra tracer."
65
+
66
+ ::Sinatra::Base.use BaselineRedRpm::Instruments::Rack
67
+
68
+ unless defined?(::Padrino)
69
+ ::Sinatra::Base.send(:include, ::BaselineRedRpm::Instruments::Sinatra::Base)
70
+ ::Sinatra::Base.class_eval do
71
+ alias_method :dispatch_without_trace, :dispatch!
72
+ alias_method :dispatch!, :dispatch_with_trace
73
+ alias_method :handle_exception_without_trace, :handle_exception!
74
+ alias_method :handle_exception!, :handle_exception_with_trace
75
+ end
76
+
77
+ ::Sinatra::Templates.send(:include, ::BaselineRedRpm::Instruments::Sinatra::Templates)
78
+ ::Sinatra::Base.class_eval do
79
+ alias_method :render_without_trace, :render
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module TyphoeusRequest
6
+ def run_with_trace
7
+ if ::BaselineRedRpm::Tracer.tracing?
8
+ span = ::BaselineRedRpm.tracer.start_span("typhoeus", tags: {
9
+ "component" => "Typhoeus"
10
+ })
11
+ BaselineRedRpm.tracer.inject(span.context, OpenTracing::FORMAT_RACK, options[:headers])
12
+
13
+ response = run_without_trace
14
+ span.exit
15
+ uri = URI(response.effective_url)
16
+
17
+ span.set_tag "http.status_code", response.code
18
+ span.set_tag "http.url", uri.to_s
19
+ span.set_tag "http.method", options[:method]
20
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :typhoeus)
21
+ else
22
+ response = run_without_trace
23
+ end
24
+ response
25
+ rescue Exception => e
26
+ if span
27
+ span.set_tag('error', true)
28
+ span.log_error(e)
29
+ end
30
+ raise
31
+ ensure
32
+ span.finish if span
33
+ end
34
+ end
35
+
36
+ module TyphoeusHydra
37
+ def run_with_trace
38
+ span = ::BaselineRedRpm.tracer.start_span("typhoeus", tags: {
39
+ "component" => "Typhoeus",
40
+ "method" => "hydra",
41
+ "http.queued_requests" => queued_requests.count,
42
+ "http.max_concurrency" => max_concurrency
43
+ })
44
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :typhoeus)
45
+
46
+ run_without_trace
47
+ rescue Exception => e
48
+ if span
49
+ span.set_tag('error', true)
50
+ span.log_error(e)
51
+ end
52
+ raise
53
+ ensure
54
+ span.finish if span
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ if ::BaselineRedRpm.config.instrumentation[:typhoeus][:enabled] && defined?(::Typhoeus)
61
+ ::BaselineRedRpm.logger.info "Initializing typhoeus tracer."
62
+
63
+ ::Typhoeus::Request::Operations.send(:include, BaselineRedRpm::Instruments::TyphoeusRequest)
64
+ ::Typhoeus::Request::Operations.class_eval do
65
+ alias_method :run_without_trace, :run
66
+ alias_method :run, :run_with_trace
67
+ end
68
+
69
+ ::Typhoeus::Hydra.send(:include, BaselineRedRpm::Instruments::TyphoeusHydra)
70
+ ::Typhoeus::Hydra.class_eval do
71
+ alias_method :run_without_trace, :run
72
+ alias_method :run, :run_with_trace
73
+ end
74
+ end