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,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module ActiveRecord
6
+ module Adapters
7
+ module Sqlite3
8
+ include BaselineRedRpm::Utils
9
+
10
+ IGNORE_STATEMENTS = {
11
+ "SCHEMA" => true,
12
+ "EXPLAIN" => true,
13
+ "CACHE" => true
14
+ }
15
+
16
+ def ignore_trace?(name)
17
+ IGNORE_STATEMENTS[name.to_s] ||
18
+ (name && name.to_sym == :skip_logging) ||
19
+ name == 'ActiveRecord::SchemaMigration Load'
20
+ end
21
+
22
+ def exec_query_with_trace(sql, name = nil, *args)
23
+ if ::BaselineRedRpm::Tracer.tracing?
24
+ unless ignore_trace?(name)
25
+ adapter = connection_config.fetch(:adapter)
26
+ sanitized_sql = sanitize_sql(sql, adapter)
27
+
28
+ span = BaselineRedRpm.tracer.start_span(name || 'SQL', tags: {
29
+ "component" => "ActiveRecord",
30
+ "span.kind" => "client",
31
+ "db.statement" => sanitized_sql,
32
+ "db.user" => connection_config.fetch(:username, 'unknown'),
33
+ "db.instance" => connection_config.fetch(:database),
34
+ "db.vendor" => adapter,
35
+ "db.type" => "sql"
36
+ })
37
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :active_record)
38
+ end
39
+ end
40
+
41
+ exec_query_without_trace(sql, name, *args)
42
+ rescue Exception => e
43
+ if span
44
+ span.set_tag('error', true)
45
+ span.log_error(e)
46
+ end
47
+ raise
48
+ ensure
49
+ span.finish if span
50
+ end
51
+
52
+ def exec_delete_with_trace(sql, name = nil, *args)
53
+ if ::BaselineRedRpm::Tracer.tracing?
54
+ unless ignore_trace?(name)
55
+ adapter = connection_config.fetch(:adapter)
56
+ sanitized_sql = sanitize_sql(sql, adapter)
57
+
58
+ span = BaselineRedRpm.tracer.start_span(name || 'SQL', tags: {
59
+ "component" => "ActiveRecord",
60
+ "span.kind" => "client",
61
+ "db.statement" => sanitized_sql,
62
+ "db.user" => connection_config.fetch(:username, 'unknown'),
63
+ "db.instance" => connection_config.fetch(:database),
64
+ "db.vendor" => adapter,
65
+ "db.type" => "sql"
66
+ })
67
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :active_record)
68
+ end
69
+ end
70
+
71
+ exec_delete_without_trace(sql, name, *args)
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
+
82
+ def exec_insert_with_trace(sql, name = nil, *args)
83
+ if ::BaselineRedRpm::Tracer.tracing?
84
+ unless ignore_trace?(name)
85
+ adapter = connection_config.fetch(:adapter)
86
+ sanitized_sql = sanitize_sql(sql, adapter)
87
+
88
+ span = BaselineRedRpm.tracer.start_span(name || 'SQL', tags: {
89
+ "component" => "ActiveRecord",
90
+ "span.kind" => "client",
91
+ "db.statement" => sanitized_sql,
92
+ "db.user" => connection_config.fetch(:username, 'unknown'),
93
+ "db.instance" => connection_config.fetch(:database),
94
+ "db.vendor" => adapter,
95
+ "db.type" => "sql"
96
+ })
97
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :active_record)
98
+ end
99
+ end
100
+
101
+ exec_insert_without_trace(sql, name, binds, *args)
102
+ rescue Exception => e
103
+ if span
104
+ span.set_tag('error', true)
105
+ span.log_error(e)
106
+ end
107
+ raise
108
+ ensure
109
+ span.finish if span
110
+ end
111
+
112
+ def begin_db_transaction_with_trace
113
+ if ::BaselineRedRpm::Tracer.tracing?
114
+ adapter = connection_config.fetch(:adapter)
115
+
116
+ span = BaselineRedRpm.tracer.start_span(name || 'SQL', tags: {
117
+ "component" => "ActiveRecord",
118
+ "span.kind" => "client",
119
+ "db.statement" => "BEGIN",
120
+ "db.user" => connection_config.fetch(:username, 'unknown'),
121
+ "db.instance" => connection_config.fetch(:database),
122
+ "db.vendor" => adapter,
123
+ "db.type" => "sql"
124
+ })
125
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :active_record)
126
+ end
127
+
128
+ begin_db_transaction_without_trace
129
+ rescue Exception => e
130
+ if span
131
+ span.set_tag('error', true)
132
+ span.log_error(e)
133
+ end
134
+ raise
135
+ ensure
136
+ span.finish if span
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module ActiveRecordImport
6
+ include BaselineRedRpm::Utils
7
+
8
+ def insert_many_with_trace( sql, values, *args )
9
+ if ::BaselineRedRpm::Tracer.tracing?
10
+ sql_copy = sql.dup
11
+ base_sql, post_sql = if sql_copy.dup.is_a?( String )
12
+ [sql_copy, '']
13
+ elsif sql.is_a?( Array )
14
+ [sql_copy.shift, sql_copy.join( ' ' )]
15
+ end
16
+
17
+ adapter = connection_config.fetch(:adapter)
18
+ sanitized_sql = sanitize_sql(base_sql + values.join( ',' ) + post_sql, adapter)
19
+
20
+ span = BaselineRedRpm.tracer.start_span(self.class.name || 'sql.query', tags: {
21
+ "component" => "ActiveRecordImport",
22
+ "span.kind" => "client",
23
+ "db.statement" => sanitized_sql,
24
+ "db.user" => connection_config.fetch(:username, 'unknown'),
25
+ "db.instance" => connection_config.fetch(:database),
26
+ "db.vendor" => adapter,
27
+ "db.type" => "sql"
28
+ })
29
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :active_record_import)
30
+ end
31
+
32
+ insert_many_without_trace(sql, values, *args)
33
+ rescue Exception => e
34
+ if span
35
+ span.set_tag('error', true)
36
+ span.log_error(e)
37
+ end
38
+ raise
39
+ ensure
40
+ span.finish if span
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+
47
+ if ::BaselineRedRpm.config.instrumentation[:active_record_import][:enabled] &&
48
+ defined?(ActiveRecord::Import::PostgreSQLAdapter)
49
+ BaselineRedRpm.logger.info "Initializing activerecord-import tracer."
50
+
51
+ ActiveRecord::Import::PostgreSQLAdapter.send(:include, BaselineRedRpm::Instruments::ActiveRecordImport)
52
+
53
+ ActiveRecord::Import::PostgreSQLAdapter.class_eval do
54
+ alias_method :insert_many_without_trace, :insert_many
55
+ alias_method :insert_many, :insert_many_with_trace
56
+ end
57
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module EmqueConsuming
6
+ module Router
7
+ def route_with_trace(topic, type, message)
8
+ action = type.to_s.split(".").last
9
+
10
+ span = ::BaselineRedRpm.tracer.start_span("#{topic}##{action}", tags: {
11
+ "component" => "EmqueConsuming",
12
+ "http.url" => "/#{topic}/#{action}",
13
+ "peer.address" => Socket.gethostname
14
+ })
15
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :emque_consuming)
16
+
17
+ route_without_trace(topic, type, message)
18
+ rescue Exception => e
19
+ if span
20
+ span.set_tag('error', true)
21
+ span.log_error(e)
22
+ end
23
+ raise
24
+ ensure
25
+ span.finish if span
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ if ::BaselineRedRpm.config.instrumentation[:emque_consuming][:enabled] && defined?(Emque::Consuming)
33
+ BaselineRedRpm.logger.info "Initializing emque-consuming tracer."
34
+
35
+ Emque::Consuming::Router.send(:include, BaselineRedRpm::Instruments::EmqueConsuming::Router)
36
+
37
+ Emque::Consuming::Router.class_eval do
38
+ alias_method :route_without_trace, :route
39
+ alias_method :route, :route_with_trace
40
+ end
41
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module FaradayConnection
6
+ def run_request_with_trace(method, url, body, headers, &block)
7
+ if ::BaselineRedRpm::Tracer.tracing?
8
+ span = ::BaselineRedRpm.tracer.start_span("faraday", tags: {
9
+ "component" => "Faraday",
10
+ "span.kind" => "client"
11
+ })
12
+ BaselineRedRpm.tracer.inject(span.context, OpenTracing::FORMAT_RACK, @headers)
13
+ result = run_request_without_trace(method, url, body, headers, &block)
14
+ span.set_tag "middleware", @builder.handlers
15
+ span.set_tag "peer.hostname", @url_prefix.host
16
+ span.set_tag "peer.port", @url_prefix.port
17
+ span.set_tag "http.protocol", @url_prefix.scheme
18
+ span.set_tag "http.url", url
19
+ span.set_tag "http.method", method
20
+ span.set_tag "http.status_code", result.status
21
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :faraday)
22
+ span.finish
23
+ else
24
+ result = run_request_without_trace(method, url, body, headers, &block)
25
+ end
26
+ result
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 ::BaselineRedRpm.config.instrumentation[:faraday][:enabled] && defined?(::Faraday)
41
+ ::BaselineRedRpm.logger.info "Initializing faraday tracer."
42
+
43
+ ::Faraday::Connection.send(:include, BaselineRedRpm::Instruments::FaradayConnection)
44
+ ::Faraday::Connection.class_eval do
45
+ alias_method :run_request_without_trace, :run_request
46
+ alias_method :run_request, :run_request_with_trace
47
+ end
48
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module GrapeMiddleware
6
+
7
+ def call_with_trace(env)
8
+ req = ::Rack::Request.new(env)
9
+
10
+ if BaselineRedRpm::Tracer.tracing?
11
+ request_method = req.request_method.to_s.upcase
12
+ path = req.path
13
+ endpoint = env["api.endpoint"]
14
+
15
+ if endpoint && endpoint.options
16
+ options = endpoint.options
17
+ request_method = options[:method].first.to_s.upcase
18
+ klass = options[:for]
19
+ namespace = endpoint.namespace
20
+ namespace = "" if namespace == "/"
21
+
22
+ path = options[:path].first.to_s
23
+ path = "/#{path}" if path[0] != "/"
24
+ path = "#{namespace}#{path}"
25
+ end
26
+
27
+ action = path.to_s.split("/").last
28
+ operation = "#{klass}##{action}"
29
+
30
+ span = BaselineRedRpm.tracer.start_span(operation, tags: {
31
+ "component" => "Grape",
32
+ "span.kind" => "client",
33
+ "class.name" => @app.class.name,
34
+ "http.path" => path,
35
+ "http.method" => request_method
36
+ })
37
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :rack)
38
+ end
39
+
40
+ begin
41
+ call_without_trace(env)
42
+ rescue Exception => e
43
+ if span
44
+ span.set_tag('error', true)
45
+ span.log_error(e)
46
+ end
47
+ raise
48
+ ensure
49
+ span.finish if span
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ if ::BaselineRedRpm.config.instrumentation[:grape][:enabled] && defined?(::Grape)
57
+ ::BaselineRedRpm.logger.info "Initializing grape tracer."
58
+ ::Grape::Middleware::Base.send(:include, BaselineRedRpm::Instruments::GrapeMiddleware)
59
+ ::Grape::Middleware::Base.class_eval do
60
+ alias_method :call_without_trace, :call
61
+ alias_method :call, :call_with_trace
62
+ end
63
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ if ::BaselineRedRpm.config.instrumentation[:net_http][:enabled] && defined?(Net::HTTP)
4
+ ::BaselineRedRpm.logger.info "Initializing net-http tracer."
5
+
6
+ Net::HTTP.class_eval do
7
+ def request_with_trace(*args, &block)
8
+ if ::BaselineRedRpm::Tracer.tracing?
9
+ span = ::BaselineRedRpm.tracer.start_span("net-http", tags: {
10
+ "component" => "NetHttp",
11
+ "span.kind" => "client"
12
+ })
13
+
14
+ if args.length && args[0]
15
+ req = args[0]
16
+ BaselineRedRpm.tracer.inject(span.context, OpenTracing::FORMAT_RACK, req)
17
+ span.set_tag "http.protocol", (use_ssl? ? "https" : "http")
18
+ span.set_tag "http.url", req.path
19
+ span.set_tag "http.method", req.method
20
+ span.set_tag "peer.hostname", addr_port
21
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :net_http)
22
+ end
23
+
24
+ response = request_without_trace(*args, &block)
25
+
26
+ span.exit
27
+ span.set_tag "http.status_code", response.code
28
+
29
+ if (response.code.to_i >= 300 || response.code.to_i <= 308) && response.header["Location"]
30
+ span.set_tag "http.redirect", response.header["Location"]
31
+ end
32
+
33
+ span.finish
34
+ else
35
+ response = request_without_trace(*args, &block)
36
+ end
37
+ response
38
+ end
39
+
40
+ alias request_without_trace request
41
+ alias request request_with_trace
42
+ end
43
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Instruments
5
+ module RackModule
6
+ def call(env)
7
+ req = ::Rack::Request.new(env)
8
+
9
+ #if ::BaselineRedRpm::Tracer.in_trace? &&
10
+ # ::BaselineRedRpm.config.instrumentation[:rack][:trace_middleware]
11
+ # BaselineRedRpm::Tracer.trace("rack-middleware") do |span|
12
+ # span.set_tag "type", "web"
13
+ # span.set_tag "domain", req.host
14
+ # span.set_tag "url", req.path
15
+ # span.set_tag "class", @app.class.name
16
+ #
17
+ # status, headers, body = @app.call env
18
+ # end
19
+ #else
20
+ span = BaselineRedRpm.tracer.start_span("rack")
21
+ span.set_tag "type", "web"
22
+ span.set_tag "domain", req.host
23
+ span.set_tag "url", req.path
24
+ span.set_tag "class", @app.class.name
25
+ span.set_tag "backtrace", ::BaselineRedRpm::Backtrace.backtrace
26
+ span.set_tag "source", ::BaselineRedRpm::Backtrace.source_extract
27
+
28
+ @app.call(env)
29
+ rescue Exception => e
30
+ if span
31
+ span.set_tag('error', true)
32
+ span.log_error(e)
33
+ end
34
+ raise
35
+ ensure
36
+ span.finish if span
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ if ::BaselineRedRpm.config.instrumentation[:rack][:enabled]
43
+ ::BaselineRedRpm.logger.info "Initializing rack tracer."
44
+
45
+ if ::BaselineRedRpm.config.instrumentation[:rack][:trace_middleware]
46
+ ::BaselineRedRpm.logger.info "Initializing rack-middleware tracer."
47
+ end
48
+
49
+ module BaselineRedRpm
50
+ module Instruments
51
+ class Rack
52
+ attr_reader :app
53
+
54
+ #include BaselineRedRpm::Instruments::RackModule
55
+
56
+ def initialize(app)
57
+ @app = app
58
+ end
59
+
60
+ def call(env)
61
+ req = ::Rack::Request.new(env)
62
+
63
+ unless ignore_path?(req.path)
64
+ extracted_ctx = BaselineRedRpm.tracer.extract(OpenTracing::FORMAT_RACK, env)
65
+ BaselineRedRpm::Tracer.sample!(extracted_ctx, !!req.params["app-perf-sample"])
66
+
67
+ if BaselineRedRpm::Tracer.tracing?
68
+ span = BaselineRedRpm.tracer.start_span(@app.class.name, :child_of => extracted_ctx, tags: {
69
+ "component" => "Rack",
70
+ "span.kind" => "client"
71
+ })
72
+ BaselineRedRpm::Utils.log_source_and_backtrace(span, :rack)
73
+ end
74
+ end
75
+
76
+ status, headers, response = @app.call(env)
77
+
78
+ if span
79
+ span.set_tag "peer.address", req.host
80
+ span.set_tag "peer.port", req.port
81
+ span.set_tag "http.method", req.request_method
82
+ span.set_tag "http.url", req.path
83
+ span.set_tag "http.status_code", status
84
+ end
85
+
86
+ [status, headers, response]
87
+ rescue Exception => e
88
+ if span
89
+ span.set_tag('error', true)
90
+ span.log_error(e)
91
+ end
92
+ raise
93
+ ensure
94
+ span.finish if span
95
+ BaselineRedRpm::Tracer.sample_off!
96
+ end
97
+
98
+ def ignore_path?(path)
99
+ path.to_s =~ BaselineRedRpm.config.ignore_paths
100
+ end
101
+ end
102
+ end
103
+ end
104
+ =begin
105
+ module ActionDispatch
106
+ class MiddlewareStack
107
+ class BaselineRedRack
108
+ include BaselineRedRpm::Instruments::RackModule
109
+
110
+ def initialize(app)
111
+ @app = app
112
+ end
113
+ end
114
+
115
+ class Middleware
116
+ def build(app)
117
+ BaselineRedRack.new(klass.new(app, *args, &block))
118
+ end
119
+ end
120
+
121
+ def build(app = nil, &block)
122
+ app ||= block
123
+ raise "BaselineRedRack#build requires an app" unless app
124
+ middlewares.reverse.inject(BaselineRedRack.new(app)) {|a, e| e.build(a)}
125
+ end
126
+ end
127
+ end
128
+ =end
129
+ end