baseline_red_rpm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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