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,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