baseline_red_rpm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/baseline_red_rpm.rb +164 -0
- data/lib/baseline_red_rpm/backtrace.rb +117 -0
- data/lib/baseline_red_rpm/configuration.rb +63 -0
- data/lib/baseline_red_rpm/instrumentation.rb +23 -0
- data/lib/baseline_red_rpm/instruments/action_controller.rb +70 -0
- data/lib/baseline_red_rpm/instruments/action_view.rb +222 -0
- data/lib/baseline_red_rpm/instruments/active_model_serializer.rb +37 -0
- data/lib/baseline_red_rpm/instruments/active_record.rb +66 -0
- data/lib/baseline_red_rpm/instruments/active_record/adapters/mysql2.rb +55 -0
- data/lib/baseline_red_rpm/instruments/active_record/adapters/postgresql.rb +143 -0
- data/lib/baseline_red_rpm/instruments/active_record/adapters/sqlite3.rb +142 -0
- data/lib/baseline_red_rpm/instruments/activerecord_import.rb +57 -0
- data/lib/baseline_red_rpm/instruments/emque_consuming.rb +41 -0
- data/lib/baseline_red_rpm/instruments/faraday.rb +48 -0
- data/lib/baseline_red_rpm/instruments/grape.rb +63 -0
- data/lib/baseline_red_rpm/instruments/net_http.rb +43 -0
- data/lib/baseline_red_rpm/instruments/rack.rb +129 -0
- data/lib/baseline_red_rpm/instruments/redis.rb +75 -0
- data/lib/baseline_red_rpm/instruments/roda.rb +48 -0
- data/lib/baseline_red_rpm/instruments/sequel.rb +100 -0
- data/lib/baseline_red_rpm/instruments/sidekiq.rb +100 -0
- data/lib/baseline_red_rpm/instruments/sinatra.rb +82 -0
- data/lib/baseline_red_rpm/instruments/typhoeus.rb +74 -0
- data/lib/baseline_red_rpm/introspector.rb +53 -0
- data/lib/baseline_red_rpm/logger.rb +34 -0
- data/lib/baseline_red_rpm/rails.rb +15 -0
- data/lib/baseline_red_rpm/railtie.rb +19 -0
- data/lib/baseline_red_rpm/reporters/json_client.rb +69 -0
- data/lib/baseline_red_rpm/reporters/null_client.rb +16 -0
- data/lib/baseline_red_rpm/tracer.rb +75 -0
- data/lib/baseline_red_rpm/tracing/buffer.rb +27 -0
- data/lib/baseline_red_rpm/tracing/carrier.rb +25 -0
- data/lib/baseline_red_rpm/tracing/collector.rb +33 -0
- data/lib/baseline_red_rpm/tracing/endpoint.rb +21 -0
- data/lib/baseline_red_rpm/tracing/managed_span.rb +40 -0
- data/lib/baseline_red_rpm/tracing/managed_tracer.rb +36 -0
- data/lib/baseline_red_rpm/tracing/span.rb +72 -0
- data/lib/baseline_red_rpm/tracing/span_context.rb +43 -0
- data/lib/baseline_red_rpm/tracing/thread_span_stack.rb +34 -0
- data/lib/baseline_red_rpm/tracing/trace_id.rb +13 -0
- data/lib/baseline_red_rpm/tracing/tracer.rb +100 -0
- data/lib/baseline_red_rpm/utils.rb +45 -0
- data/lib/tasks/install.rake +6 -0
- metadata +212 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2f48e985c64b6fe5ef0768cd698bdff34087adaf
|
4
|
+
data.tar.gz: 616121b88979893ded3bdc189d275621aee00f34
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 472252bfc20315849876f30e1c9cff7a7916f53ffa0ffa300812344215168733ba4044d02127870ae0730f0568ef2a69f5eae0baa1c290c46ee71777ac1c9fc5
|
7
|
+
data.tar.gz: f1460dd9d695924e8ffcc177ba4ac96962dac1f73f2ea77e5a5378a551d7947be8bb6672c22053e80fbb0c5d921868a732ed29580c48fcc14128a57843a7fdf1
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BaselineRedRpm
|
4
|
+
require "opentracing"
|
5
|
+
require 'msgpack'
|
6
|
+
|
7
|
+
require 'baseline_red_rpm/logger'
|
8
|
+
require 'baseline_red_rpm/configuration'
|
9
|
+
require 'baseline_red_rpm/backtrace'
|
10
|
+
|
11
|
+
require 'baseline_red_rpm/reporters/json_client'
|
12
|
+
require 'baseline_red_rpm/reporters/null_client'
|
13
|
+
|
14
|
+
require 'baseline_red_rpm/tracing/buffer'
|
15
|
+
require 'baseline_red_rpm/tracing/carrier'
|
16
|
+
require 'baseline_red_rpm/tracing/collector'
|
17
|
+
require 'baseline_red_rpm/tracing/endpoint'
|
18
|
+
require 'baseline_red_rpm/tracing/trace_id'
|
19
|
+
require 'baseline_red_rpm/tracing/span_context'
|
20
|
+
require 'baseline_red_rpm/tracing/span'
|
21
|
+
require 'baseline_red_rpm/tracing/managed_span'
|
22
|
+
require 'baseline_red_rpm/tracing/tracer'
|
23
|
+
require 'baseline_red_rpm/tracing/managed_tracer'
|
24
|
+
require 'baseline_red_rpm/tracing/thread_span_stack'
|
25
|
+
|
26
|
+
require 'baseline_red_rpm/tracer'
|
27
|
+
require 'baseline_red_rpm/utils'
|
28
|
+
require 'baseline_red_rpm/instrumentation'
|
29
|
+
require 'baseline_red_rpm/rails'
|
30
|
+
require 'baseline_red_rpm/introspector'
|
31
|
+
|
32
|
+
TRACE_CONTEXT_KEY = 'BaselineRed-Trace-Context'
|
33
|
+
|
34
|
+
class << self
|
35
|
+
|
36
|
+
attr_writer :config
|
37
|
+
|
38
|
+
def config
|
39
|
+
@config ||= Configuration.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def configure
|
43
|
+
yield(config)
|
44
|
+
end
|
45
|
+
|
46
|
+
def load
|
47
|
+
#Oj.mimic_JSON
|
48
|
+
unless disable_agent?
|
49
|
+
BaselineRedRpm::Instrumentation.load
|
50
|
+
BaselineRedRpm.tracing_on
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def mutex
|
55
|
+
@mutex ||= Mutex.new
|
56
|
+
end
|
57
|
+
|
58
|
+
def endpoint
|
59
|
+
@endpoint ||= BaselineRedRpm::Tracing::Endpoint.local_endpoint(config.application_name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def collector
|
63
|
+
@collector ||= BaselineRedRpm::Tracing::Collector.new(endpoint)
|
64
|
+
end
|
65
|
+
|
66
|
+
def url
|
67
|
+
@url ||= "#{config.host}/api/listener/3/#{config.license_key}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def sender
|
71
|
+
@sender ||= BaselineRedRpm::Reporters::JsonClient.new(
|
72
|
+
url: url,
|
73
|
+
collector: collector,
|
74
|
+
flush_interval: config.flush_interval
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def tracer
|
79
|
+
@tracer ||= BaselineRedRpm::Tracing::ManagedTracer.new(
|
80
|
+
BaselineRedRpm::Tracing::Tracer.build(
|
81
|
+
:service_name => config.application_name,
|
82
|
+
:sender => sender,
|
83
|
+
:collector => collector
|
84
|
+
),
|
85
|
+
BaselineRedRpm::Tracing::ThreadSpanStack.new
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
def tracing_on
|
90
|
+
if @without_tracing_enabled
|
91
|
+
BaselineRedRpm.logger.debug "Not turning tracing on due to without tracing mode."
|
92
|
+
return
|
93
|
+
end
|
94
|
+
mutex.synchronize do
|
95
|
+
BaselineRedRpm.logger.debug "Enabling tracing."
|
96
|
+
@tracing = true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def tracing_off
|
101
|
+
mutex.synchronize do
|
102
|
+
BaselineRedRpm.logger.debug "Disabling tracing."
|
103
|
+
@tracing = false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def tracing?
|
108
|
+
!!@tracing
|
109
|
+
end
|
110
|
+
|
111
|
+
def without_tracing
|
112
|
+
@previously_tracing = BaselineRedRpm.tracing?
|
113
|
+
@without_tracing_enabled = true
|
114
|
+
BaselineRedRpm.tracing_off
|
115
|
+
yield if block_given?
|
116
|
+
@without_tracing_enabled = false
|
117
|
+
ensure
|
118
|
+
BaselineRedRpm.tracing_on if @previously_tracing
|
119
|
+
end
|
120
|
+
|
121
|
+
def host
|
122
|
+
@host ||= Socket.gethostname
|
123
|
+
end
|
124
|
+
|
125
|
+
def round_time(t, sec = 1)
|
126
|
+
t = Time.parse(t.to_s)
|
127
|
+
|
128
|
+
down = t - (t.to_i % sec)
|
129
|
+
up = down + sec
|
130
|
+
|
131
|
+
difference_down = t - down
|
132
|
+
difference_up = up - t
|
133
|
+
|
134
|
+
if (difference_down < difference_up)
|
135
|
+
return down
|
136
|
+
else
|
137
|
+
return up
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def floor_time(t, sec = 1)
|
142
|
+
Time.at((t.to_f / sec).floor * sec)
|
143
|
+
end
|
144
|
+
|
145
|
+
def disable_agent?
|
146
|
+
if config.agent_disabled
|
147
|
+
true
|
148
|
+
elsif Introspector.agentable?
|
149
|
+
false
|
150
|
+
else
|
151
|
+
true
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def now
|
156
|
+
if defined?(Process::CLOCK_REALTIME)
|
157
|
+
Process.clock_gettime(Process::CLOCK_REALTIME)
|
158
|
+
else
|
159
|
+
Time.now
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BaselineRedRpm
|
4
|
+
class Backtrace
|
5
|
+
class << self
|
6
|
+
def backtrace(opts = {})
|
7
|
+
kind = opts[:kind]
|
8
|
+
|
9
|
+
if kind
|
10
|
+
bt = Kernel.caller
|
11
|
+
bt = clean(bt)
|
12
|
+
bt = filter(bt, kind)
|
13
|
+
trim_backtrace(bt)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def clean(backtrace)
|
18
|
+
Array(backtrace)
|
19
|
+
.map {|b| clean_line(b) }
|
20
|
+
.select {|b| b !~ %r{lib/baseline_red_rpm} }
|
21
|
+
end
|
22
|
+
|
23
|
+
def filter(backtrace, kind)
|
24
|
+
case kind
|
25
|
+
when :all
|
26
|
+
backtrace
|
27
|
+
when :app
|
28
|
+
backtrace.select {|b| b =~ /\[APP_PATH\]/ }
|
29
|
+
when :gem
|
30
|
+
backtrace.select {|b| b =~ /\[GEM_PATH\]/ }
|
31
|
+
else
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#def source_extract(_backtrace = Kernel.caller(2))
|
37
|
+
# if(trace = _backtrace.first)
|
38
|
+
# file, line_number = extract_file_and_line_number(trace)
|
39
|
+
|
40
|
+
# {
|
41
|
+
# code: source_fragment(file, line_number),
|
42
|
+
# line_number: line_number
|
43
|
+
# }
|
44
|
+
# else
|
45
|
+
# nil
|
46
|
+
# end
|
47
|
+
#end
|
48
|
+
|
49
|
+
def source_extract(opts = {})
|
50
|
+
backtrace = opts[:backtrace] || Kernel.caller(0)
|
51
|
+
|
52
|
+
Array(backtrace).select {|bt| bt[/^#{::BaselineRedRpm.config.app_root.to_s}\//] }.map do |trace|
|
53
|
+
file, line_number = extract_file_and_line_number(trace)
|
54
|
+
source_to_hash(file, line_number)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def source_to_hash(file, line_number)
|
59
|
+
{
|
60
|
+
"file" => clean_line(file),
|
61
|
+
"code" => source_fragment(file, line_number),
|
62
|
+
"line_number" => line_number
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def clean_line(line)
|
67
|
+
line
|
68
|
+
.sub(/#{::BaselineRedRpm.config.app_root.to_s}\//, "[APP_PATH]/")
|
69
|
+
.sub(gems_regexp, '\2 (\3) [GEM_PATH]/\4')
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def gems_regexp
|
75
|
+
gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
|
76
|
+
if gems_paths
|
77
|
+
%r{(#{gems_paths.join('|')})/gems/([^/]+)-([\w.]+)/(.*)}
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def source_fragment(path, line)
|
84
|
+
return unless BaselineRedRpm.config.app_root
|
85
|
+
full_path = BaselineRedRpm.config.app_root.join(path)
|
86
|
+
if File.exist?(full_path)
|
87
|
+
File.open(full_path, "r") do |file|
|
88
|
+
start = [line - 3, 0].max
|
89
|
+
lines = file.each_line.drop(start).take(6)
|
90
|
+
Hash[*(start + 1..(lines.count + start)).zip(lines).flatten]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def extract_file_and_line_number(trace)
|
96
|
+
file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
|
97
|
+
[file, line.to_i]
|
98
|
+
end
|
99
|
+
|
100
|
+
def trim_backtrace(_backtrace, opts = {})
|
101
|
+
kind = opts[:kind]
|
102
|
+
|
103
|
+
return _backtrace unless _backtrace.is_a?(Array)
|
104
|
+
|
105
|
+
length = _backtrace.size
|
106
|
+
if length > 80
|
107
|
+
trimmed = _backtrace[0, 80]
|
108
|
+
trimmed += ['...[snip]...']
|
109
|
+
trimmed += _backtrace[length - 20, 20]
|
110
|
+
else
|
111
|
+
trimmed = _backtrace
|
112
|
+
end
|
113
|
+
trimmed
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module BaselineRedRpm
|
6
|
+
class Configuration
|
7
|
+
attr_accessor :app_root,
|
8
|
+
:host,
|
9
|
+
:port,
|
10
|
+
:license_key,
|
11
|
+
:ssl,
|
12
|
+
:sample_rate,
|
13
|
+
:sample_threshold,
|
14
|
+
:flush_interval,
|
15
|
+
:application_name,
|
16
|
+
:instrumentation,
|
17
|
+
:agent_disabled,
|
18
|
+
:ignore_paths
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
reload
|
22
|
+
end
|
23
|
+
|
24
|
+
def reload
|
25
|
+
::BaselineRedRpm.mutex.synchronize do
|
26
|
+
self.app_root = app_root ? Pathname.new(app_root.to_s) : nil
|
27
|
+
self.host ||= default_if_blank(ENV["BASELINE_RED_HOST"], "http://localhost:5000")
|
28
|
+
self.ssl ||= default_if_blank(ENV["BASELINE_RED_SSL"], false)
|
29
|
+
self.license_key ||= default_if_blank(ENV["BASELINE_RED_LICENSE_KEY"], nil)
|
30
|
+
self.application_name ||= "Default"
|
31
|
+
self.sample_rate ||= 10 # Percentage of request to sample
|
32
|
+
self.sample_threshold ||= 0 # Minimum amount of duration to sample
|
33
|
+
self.flush_interval ||= 60 # In seconds
|
34
|
+
self.agent_disabled ||= default_if_blank(ENV["BASELINE_RED_AGENT_DISABLED"], false)
|
35
|
+
self.ignore_paths ||= /\/assets/
|
36
|
+
self.instrumentation = {
|
37
|
+
:rack => { :enabled => true, :backtrace => :app, :source => true, :trace_middleware => false },
|
38
|
+
:roda => { :enabled => true, :backtrace => :app, :source => true },
|
39
|
+
:grape => { :enabled => true, :backtrace => :app, :source => true },
|
40
|
+
:active_record => { :enabled => true, :backtrace => :app, :source => true },
|
41
|
+
:active_record_import => { :enabled => true, :backtrace => :app, :source => true },
|
42
|
+
:active_model_serializer => { :enabled => true, :backtrace => :app, :source => true },
|
43
|
+
:action_view => { :enabled => true, :backtrace => :app, :source => true },
|
44
|
+
:action_controller => { :enabled => true, :backtrace => :app, :source => true },
|
45
|
+
:emque_consuming => { :enabled => true, :backtrace => :app, :source => true },
|
46
|
+
:redis => { :enabled => true, :backtrace => :app, :source => true },
|
47
|
+
:sequel => { :enabled => true, :backtrace => :app, :source => true },
|
48
|
+
:sidekiq => { :enabled => true, :backtrace => :app, :source => true },
|
49
|
+
:sinatra => { :enabled => true, :backtrace => :app, :source => true },
|
50
|
+
:net_http => { :enabled => true, :backtrace => :app, :source => true },
|
51
|
+
:typhoeus => { :enabled => true, :backtrace => :app, :source => true },
|
52
|
+
:faraday => { :enabled => true, :backtrace => :app, :source => true }
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def default_if_blank(value, default)
|
60
|
+
value.nil? || value.blank? ? default : value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BaselineRedRpm
|
4
|
+
class Instrumentation
|
5
|
+
class << self
|
6
|
+
def load
|
7
|
+
pattern = File.join(File.dirname(__FILE__), 'instruments', '**', '*.rb')
|
8
|
+
Dir.glob(pattern) do |f|
|
9
|
+
begin
|
10
|
+
require f
|
11
|
+
rescue => e
|
12
|
+
BaselineRedRpm.logger.error "Error loading instrumentation file '#{f}' : #{e}"
|
13
|
+
BaselineRedRpm.logger.error "#{e.backtrace[0..10]}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
if defined? Rails::Railtie
|
18
|
+
require "baseline_red_rpm/railtie"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BaselineRedRpm
|
4
|
+
module Instruments
|
5
|
+
module ActionController
|
6
|
+
def process_action_with_trace(method_name, *args)
|
7
|
+
if ::BaselineRedRpm::Tracer.tracing?
|
8
|
+
operation = "#{self.class.name}##{self.action_name}"
|
9
|
+
span = BaselineRedRpm.tracer.start_span(operation, tags: {
|
10
|
+
"component" => "ActionController",
|
11
|
+
"span.kind" => "client"
|
12
|
+
})
|
13
|
+
BaselineRedRpm::Utils.log_source_and_backtrace(span, :action_controller)
|
14
|
+
end
|
15
|
+
|
16
|
+
process_action_without_trace(method_name, *args)
|
17
|
+
rescue Exception => e
|
18
|
+
puts e.message.inspect
|
19
|
+
puts e.backtrace.join("\n")
|
20
|
+
if span
|
21
|
+
span.set_tag('error', true)
|
22
|
+
span.log_error(e)
|
23
|
+
end
|
24
|
+
raise
|
25
|
+
ensure
|
26
|
+
span.finish if span
|
27
|
+
end
|
28
|
+
|
29
|
+
def perform_action_with_trace(*arguments)
|
30
|
+
if ::BaselineRedRpm::Tracer.tracing?
|
31
|
+
operation = "#{@_request.path_parameters['controller']}##{@_request.path_parameters['action']}"
|
32
|
+
span = BaselineRedRpm.tracer.start_span(operation, tags: {
|
33
|
+
"component" => "ActionController",
|
34
|
+
"span.kind" => "client"
|
35
|
+
})
|
36
|
+
BaselineRedRpm::Utils.log_source_and_backtrace(span, :action_controller)
|
37
|
+
end
|
38
|
+
perform_action_without_trace(*arguments)
|
39
|
+
rescue Exception => e
|
40
|
+
if span
|
41
|
+
span.set_tag('error', true)
|
42
|
+
span.log_error(e)
|
43
|
+
end
|
44
|
+
raise
|
45
|
+
ensure
|
46
|
+
span.finish if span
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if ::BaselineRedRpm.config.instrumentation[:action_controller][:enabled] &&
|
53
|
+
defined?(::ActionController)
|
54
|
+
BaselineRedRpm.logger.info "Initializing actioncontroller tracer."
|
55
|
+
|
56
|
+
::ActionController::Base.send(
|
57
|
+
:include,
|
58
|
+
BaselineRedRpm::Instruments::ActionController
|
59
|
+
)
|
60
|
+
|
61
|
+
::ActionController::Base.class_eval do
|
62
|
+
if ::Rails::VERSION::MAJOR > 2
|
63
|
+
alias_method :process_action_without_trace, :process_action
|
64
|
+
alias_method :process_action, :process_action_with_trace
|
65
|
+
else
|
66
|
+
alias_method :perform_action_without_trace, :perform_action
|
67
|
+
alias_method :perform_action, :perform_action_with_trace
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|