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,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Tracing
5
+ class Span
6
+ attr_accessor :operation_name
7
+
8
+ attr_reader :context, :start_time, :end_time, :tags, :log_entries
9
+ def initialize(context, operation_name, collector, opts = {})
10
+ @context = context
11
+ @operation_name = operation_name
12
+ @collector = collector
13
+ @start_time = opts[:start_time] || BaselineRedRpm.now
14
+ @end_time = nil
15
+ @tags = opts[:tags] || {}
16
+ @log_entries = []
17
+ end
18
+
19
+ def set_tag(key, value)
20
+ @tags = @tags.merge(key => value)
21
+ end
22
+
23
+ def add_tags(tags)
24
+ tags.each_pair do |key, value|
25
+ set_tag(key, value)
26
+ end
27
+ end
28
+
29
+ def set_baggage_item(key, value)
30
+ @context.set_baggage_item(key, value)
31
+ end
32
+
33
+ def get_baggage_item(key)
34
+ @context.get_baggage_item(key)
35
+ end
36
+
37
+ # Original definition for ruby 2+ was this:
38
+ # def log(opts = { :event => nil, :timestamp => BaselineRedRpm.now }, **fields)
39
+ # but this doesn't work in 1.9.
40
+ def log(opts = {}, *_, fields)
41
+ entry = {
42
+ "event" => opts[:event] || nil,
43
+ "timestamp" => opts[:timestamp] || BaselineRedRpm.now,
44
+ }
45
+
46
+ entry["fields"] = fields
47
+ @log_entries << entry
48
+
49
+ nil
50
+ end
51
+
52
+ def log_error(exception, opts = {})
53
+ log(
54
+ event: "error",
55
+ timestamp: opts[:timestamp] || BaselineRedRpm.now,
56
+ message: exception.message,
57
+ error_class: exception.class.to_s,
58
+ backtrace: BaselineRedRpm::Backtrace.clean(exception.backtrace),
59
+ source: BaselineRedRpm::Backtrace.source_extract(backtrace: exception.backtrace)
60
+ )
61
+ end
62
+
63
+ def exit(opts = {})
64
+ @end_time = opts[:end_time] || BaselineRedRpm.now
65
+ end
66
+
67
+ def finish(opts = {})
68
+ @collector.send_span(self, @end_time || opts[:end_time] || BaselineRedRpm.now)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Tracing
5
+ class SpanContext
6
+ def self.create_parent_context
7
+ trace_id = TraceId.generate
8
+ new(trace_id: trace_id, span_id: trace_id, sampled: true)
9
+ end
10
+
11
+ def self.create_from_parent_context(span_context)
12
+ new(
13
+ span_id: TraceId.generate,
14
+ parent_id: span_context.span_id,
15
+ trace_id: span_context.trace_id,
16
+ sampled: span_context.sampled?
17
+ )
18
+ end
19
+
20
+ attr_reader :span_id, :parent_id, :trace_id, :baggage
21
+
22
+ def initialize(opts = {})
23
+ @span_id = opts[:span_id] || nil
24
+ @parent_id = opts[:parent_id] || nil
25
+ @trace_id = opts[:trace_id] || nil
26
+ @sampled = opts[:sampled] || nil
27
+ @baggage = opts[:baggage] || {}
28
+ end
29
+
30
+ def set_baggage_item(key, value)
31
+ baggage[key] = value
32
+ end
33
+
34
+ def get_baggage_item(key)
35
+ baggage[key]
36
+ end
37
+
38
+ def sampled?
39
+ @sampled
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Tracing
5
+ class ThreadSpanStack
6
+ def set_active_span(span)
7
+ active_span = ManagedSpan.new(span, method(:pop))
8
+ push(active_span)
9
+ active_span
10
+ end
11
+
12
+ def active_span
13
+ local_stack.last
14
+ end
15
+
16
+ def clear
17
+ local_stack.clear
18
+ end
19
+
20
+ private
21
+ def push(span)
22
+ local_stack << span
23
+ end
24
+
25
+ def pop
26
+ local_stack.pop
27
+ end
28
+
29
+ def local_stack
30
+ Thread.current[:__active_span__] ||= []
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Tracing
5
+ module TraceId
6
+ TRACE_ID_UPPER_BOUND = 2 ** 64
7
+
8
+ def self.generate
9
+ rand(TRACE_ID_UPPER_BOUND).to_s(16)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Tracing
5
+ class Tracer
6
+ attr_reader :thread_span_stack, :collector
7
+
8
+ def self.build(opts = {})
9
+ opts[:collector] ||= nil
10
+ opts[:sender] ||= nil
11
+ opts[:service_name] ||= nil
12
+
13
+ opts[:sender].start
14
+
15
+ new(opts[:collector], opts[:sender])
16
+ end
17
+
18
+ def initialize(collector, sender)
19
+ @collector = collector
20
+ @sender = sender
21
+ end
22
+
23
+ def stop
24
+ @sender.stop
25
+ end
26
+
27
+ def start_span(operation_name, opts = {}, *)
28
+ child_of = opts[:child_of] || nil
29
+ opts[:start_time] ||= BaselineRedRpm.now
30
+ opts[:tags] ||= {}
31
+
32
+ context =
33
+ if child_of
34
+ parent_context = child_of.respond_to?(:context) ? child_of.context : child_of
35
+ SpanContext.create_from_parent_context(parent_context)
36
+ else
37
+ SpanContext.create_parent_context
38
+ end
39
+
40
+ span = Span.new(context, operation_name, @collector, {
41
+ start_time: opts[:start_time],
42
+ tags: opts[:tags]
43
+ })
44
+ end
45
+
46
+ def inject(span_context, format, carrier)
47
+ case format
48
+ when OpenTracing::FORMAT_TEXT_MAP
49
+ carrier['trace-id'] = span_context.trace_id
50
+ carrier['parent-id'] = span_context.parent_id
51
+ carrier['span-id'] = span_context.span_id
52
+ carrier['sampled'] = span_context.sampled? ? '1' : '0'
53
+ when OpenTracing::FORMAT_RACK
54
+ carrier['X-BaselineRed-TraceId'] = span_context.trace_id
55
+ carrier['X-BaselineRed-ParentSpanId'] = span_context.parent_id
56
+ carrier['X-BaselineRed-SpanId'] = span_context.span_id
57
+ carrier['X-BaselineRed-Sampled'] = span_context.sampled? ? '1' : '0'
58
+ else
59
+ STDERR.puts "BaselineRedRpm::Tracer with format #{format} is not supported yet"
60
+ end
61
+ end
62
+
63
+ def extract(format, carrier)
64
+ case format
65
+ when OpenTracing::FORMAT_TEXT_MAP
66
+ trace_id = carrier['trace-id']
67
+ parent_id = carrier['parent-id']
68
+ span_id = carrier['span-id']
69
+ sampled = carrier['sampled'] == '1'
70
+
71
+ create_span_context(trace_id, span_id, parent_id, sampled)
72
+ when OpenTracing::FORMAT_RACK
73
+ trace_id = carrier['HTTP_X_BaselineRed_TRACEID']
74
+ parent_id = carrier['HTTP_X_BaselineRed_PARENTSPANID']
75
+ span_id = carrier['HTTP_X_BaselineRed_SPANID']
76
+ sampled = carrier['HTTP_X_BaselineRed_SAMPLED'] == '1'
77
+
78
+ create_span_context(trace_id, span_id, parent_id, sampled)
79
+ else
80
+ STDERR.puts "BaselineRedRpm::Tracer with format #{format} is not supported yet"
81
+ nil
82
+ end
83
+ end
84
+
85
+ private
86
+ def create_span_context(trace_id, span_id, parent_id, sampled)
87
+ if trace_id && span_id
88
+ SpanContext.new(
89
+ trace_id: trace_id,
90
+ parent_id: parent_id,
91
+ span_id: span_id,
92
+ sampled: sampled
93
+ )
94
+ else
95
+ nil
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BaselineRedRpm
4
+ module Utils
5
+ REGEXP ||= Regexp.new('(\'[\s\S][^\']*\'|\d*\.\d+|\d+|NULL)')
6
+
7
+ def sanitize_sql(sql, adapter)
8
+ sql.gsub(REGEXP, '?')
9
+ end
10
+
11
+ def connection_config
12
+ @connection_config ||= if ::ActiveRecord::VERSION::MAJOR == 2 || (::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR < 1)
13
+ ActiveRecord::Base.connection.instance_variable_get(:@config)
14
+ else
15
+ ::ActiveRecord::Base.connection_config
16
+ end
17
+ end
18
+
19
+ def format_redis(command)
20
+ command.is_a?(Symbol) ? command.to_s.upcase : command.to_s
21
+ rescue StandardError => e
22
+ "?"
23
+ end
24
+
25
+ def format_redis_command(command)
26
+ command.map { |x| format_redis(x) }.join(' ')
27
+ end
28
+
29
+ def self.log_source_and_backtrace(span, instrument)
30
+ config = ::BaselineRedRpm.config.instrumentation[instrument] || {}
31
+ if kind = config[:backtrace]
32
+ backtrace = BaselineRedRpm::Backtrace.backtrace(kind: kind)
33
+ if backtrace.length > 0
34
+ span.log(event: "backtrace", stack: backtrace)
35
+ end
36
+ end
37
+ if config[:source]
38
+ source = BaselineRedRpm::Backtrace.source_extract
39
+ if source.length > 0
40
+ span.log(event: "source", stack: source)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,6 @@
1
+ namespace :baseline_red do
2
+ desc "Install baseline_red_ruby_agent.yml file"
3
+ task :install do
4
+ load File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "install.rb"))
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,212 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: baseline_red_rpm
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jim Jones
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-11-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: msgpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: opentracing
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: appraisal
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: wwtd
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Ruby Agent for the Baseline Red, APM.
140
+ email: jim@baseline.red
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - lib/baseline_red_rpm.rb
146
+ - lib/baseline_red_rpm/backtrace.rb
147
+ - lib/baseline_red_rpm/configuration.rb
148
+ - lib/baseline_red_rpm/instrumentation.rb
149
+ - lib/baseline_red_rpm/instruments/action_controller.rb
150
+ - lib/baseline_red_rpm/instruments/action_view.rb
151
+ - lib/baseline_red_rpm/instruments/active_model_serializer.rb
152
+ - lib/baseline_red_rpm/instruments/active_record.rb
153
+ - lib/baseline_red_rpm/instruments/active_record/adapters/mysql2.rb
154
+ - lib/baseline_red_rpm/instruments/active_record/adapters/postgresql.rb
155
+ - lib/baseline_red_rpm/instruments/active_record/adapters/sqlite3.rb
156
+ - lib/baseline_red_rpm/instruments/activerecord_import.rb
157
+ - lib/baseline_red_rpm/instruments/emque_consuming.rb
158
+ - lib/baseline_red_rpm/instruments/faraday.rb
159
+ - lib/baseline_red_rpm/instruments/grape.rb
160
+ - lib/baseline_red_rpm/instruments/net_http.rb
161
+ - lib/baseline_red_rpm/instruments/rack.rb
162
+ - lib/baseline_red_rpm/instruments/redis.rb
163
+ - lib/baseline_red_rpm/instruments/roda.rb
164
+ - lib/baseline_red_rpm/instruments/sequel.rb
165
+ - lib/baseline_red_rpm/instruments/sidekiq.rb
166
+ - lib/baseline_red_rpm/instruments/sinatra.rb
167
+ - lib/baseline_red_rpm/instruments/typhoeus.rb
168
+ - lib/baseline_red_rpm/introspector.rb
169
+ - lib/baseline_red_rpm/logger.rb
170
+ - lib/baseline_red_rpm/rails.rb
171
+ - lib/baseline_red_rpm/railtie.rb
172
+ - lib/baseline_red_rpm/reporters/json_client.rb
173
+ - lib/baseline_red_rpm/reporters/null_client.rb
174
+ - lib/baseline_red_rpm/tracer.rb
175
+ - lib/baseline_red_rpm/tracing/buffer.rb
176
+ - lib/baseline_red_rpm/tracing/carrier.rb
177
+ - lib/baseline_red_rpm/tracing/collector.rb
178
+ - lib/baseline_red_rpm/tracing/endpoint.rb
179
+ - lib/baseline_red_rpm/tracing/managed_span.rb
180
+ - lib/baseline_red_rpm/tracing/managed_tracer.rb
181
+ - lib/baseline_red_rpm/tracing/span.rb
182
+ - lib/baseline_red_rpm/tracing/span_context.rb
183
+ - lib/baseline_red_rpm/tracing/thread_span_stack.rb
184
+ - lib/baseline_red_rpm/tracing/trace_id.rb
185
+ - lib/baseline_red_rpm/tracing/tracer.rb
186
+ - lib/baseline_red_rpm/utils.rb
187
+ - lib/tasks/install.rake
188
+ homepage: https://baseline.red
189
+ licenses:
190
+ - MIT
191
+ metadata: {}
192
+ post_install_message:
193
+ rdoc_options: []
194
+ require_paths:
195
+ - lib
196
+ required_ruby_version: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ required_rubygems_version: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ requirements: []
207
+ rubyforge_project:
208
+ rubygems_version: 2.6.13
209
+ signing_key:
210
+ specification_version: 4
211
+ summary: Baseline Red Ruby Agent
212
+ test_files: []