fair-ddtrace 0.8.2.a
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.
- checksums.yaml +7 -0
- data/.env +11 -0
- data/.gitignore +59 -0
- data/.rubocop.yml +61 -0
- data/.yardopts +5 -0
- data/Appraisals +136 -0
- data/Gemfile +3 -0
- data/LICENSE +24 -0
- data/README.md +156 -0
- data/Rakefile +176 -0
- data/circle.yml +61 -0
- data/ddtrace.gemspec +44 -0
- data/docker-compose.yml +42 -0
- data/docs/GettingStarted.md +735 -0
- data/gemfiles/contrib.gemfile +16 -0
- data/gemfiles/contrib_old.gemfile +15 -0
- data/gemfiles/rails30_postgres.gemfile +10 -0
- data/gemfiles/rails30_postgres_sidekiq.gemfile +11 -0
- data/gemfiles/rails32_mysql2.gemfile +11 -0
- data/gemfiles/rails32_postgres.gemfile +10 -0
- data/gemfiles/rails32_postgres_redis.gemfile +11 -0
- data/gemfiles/rails32_postgres_sidekiq.gemfile +11 -0
- data/gemfiles/rails4_mysql2.gemfile +9 -0
- data/gemfiles/rails4_postgres.gemfile +9 -0
- data/gemfiles/rails4_postgres_redis.gemfile +10 -0
- data/gemfiles/rails4_postgres_sidekiq.gemfile +11 -0
- data/gemfiles/rails5_mysql2.gemfile +8 -0
- data/gemfiles/rails5_postgres.gemfile +8 -0
- data/gemfiles/rails5_postgres_redis.gemfile +9 -0
- data/gemfiles/rails5_postgres_sidekiq.gemfile +10 -0
- data/lib/ddtrace.rb +73 -0
- data/lib/ddtrace/buffer.rb +52 -0
- data/lib/ddtrace/context.rb +145 -0
- data/lib/ddtrace/contrib/active_record/patcher.rb +94 -0
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +108 -0
- data/lib/ddtrace/contrib/elasticsearch/quantize.rb +22 -0
- data/lib/ddtrace/contrib/grape/endpoint.rb +164 -0
- data/lib/ddtrace/contrib/grape/patcher.rb +73 -0
- data/lib/ddtrace/contrib/http/patcher.rb +156 -0
- data/lib/ddtrace/contrib/rack/middlewares.rb +150 -0
- data/lib/ddtrace/contrib/rails/action_controller.rb +81 -0
- data/lib/ddtrace/contrib/rails/action_view.rb +110 -0
- data/lib/ddtrace/contrib/rails/active_record.rb +56 -0
- data/lib/ddtrace/contrib/rails/active_support.rb +113 -0
- data/lib/ddtrace/contrib/rails/core_extensions.rb +137 -0
- data/lib/ddtrace/contrib/rails/framework.rb +171 -0
- data/lib/ddtrace/contrib/rails/middlewares.rb +32 -0
- data/lib/ddtrace/contrib/rails/utils.rb +43 -0
- data/lib/ddtrace/contrib/redis/patcher.rb +118 -0
- data/lib/ddtrace/contrib/redis/quantize.rb +30 -0
- data/lib/ddtrace/contrib/redis/tags.rb +19 -0
- data/lib/ddtrace/contrib/sidekiq/tracer.rb +103 -0
- data/lib/ddtrace/contrib/sinatra/tracer.rb +169 -0
- data/lib/ddtrace/distributed.rb +38 -0
- data/lib/ddtrace/encoding.rb +65 -0
- data/lib/ddtrace/error.rb +37 -0
- data/lib/ddtrace/ext/app_types.rb +10 -0
- data/lib/ddtrace/ext/cache.rb +7 -0
- data/lib/ddtrace/ext/distributed.rb +10 -0
- data/lib/ddtrace/ext/errors.rb +10 -0
- data/lib/ddtrace/ext/http.rb +11 -0
- data/lib/ddtrace/ext/net.rb +8 -0
- data/lib/ddtrace/ext/redis.rb +11 -0
- data/lib/ddtrace/ext/sql.rb +8 -0
- data/lib/ddtrace/logger.rb +39 -0
- data/lib/ddtrace/monkey.rb +84 -0
- data/lib/ddtrace/pin.rb +63 -0
- data/lib/ddtrace/provider.rb +21 -0
- data/lib/ddtrace/sampler.rb +49 -0
- data/lib/ddtrace/span.rb +222 -0
- data/lib/ddtrace/tracer.rb +310 -0
- data/lib/ddtrace/transport.rb +162 -0
- data/lib/ddtrace/utils.rb +16 -0
- data/lib/ddtrace/version.rb +9 -0
- data/lib/ddtrace/workers.rb +108 -0
- data/lib/ddtrace/writer.rb +118 -0
- metadata +208 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'ddtrace/ext/sql'
|
|
2
|
+
|
|
3
|
+
require 'ddtrace/contrib/rails/utils'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Contrib
|
|
7
|
+
module Rails
|
|
8
|
+
# Code used to create and handle 'mysql.query', 'postgres.query', ... spans.
|
|
9
|
+
module ActiveRecord
|
|
10
|
+
def self.instrument
|
|
11
|
+
# ActiveRecord is instrumented only if it's available
|
|
12
|
+
return unless defined?(::ActiveRecord)
|
|
13
|
+
|
|
14
|
+
# subscribe when the active record query has been processed
|
|
15
|
+
::ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
|
|
16
|
+
sql(*args)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.sql(_name, start, finish, _id, payload)
|
|
21
|
+
tracer = ::Rails.configuration.datadog_trace.fetch(:tracer)
|
|
22
|
+
database_service = ::Rails.configuration.datadog_trace.fetch(:default_database_service)
|
|
23
|
+
adapter_name = ::ActiveRecord::Base.connection_config[:adapter]
|
|
24
|
+
adapter_name = Datadog::Contrib::Rails::Utils.normalize_vendor(adapter_name)
|
|
25
|
+
span_type = Datadog::Ext::SQL::TYPE
|
|
26
|
+
|
|
27
|
+
span = tracer.trace(
|
|
28
|
+
"#{adapter_name}.query",
|
|
29
|
+
resource: payload.fetch(:sql),
|
|
30
|
+
service: database_service,
|
|
31
|
+
span_type: span_type
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# find out if the SQL query has been cached in this request. This meta is really
|
|
35
|
+
# helpful to users because some spans may have 0ns of duration because the query
|
|
36
|
+
# is simply cached from memory, so the notification is fired with start == finish.
|
|
37
|
+
# TODO[manu]: this feature has been merged into master but has not yet released.
|
|
38
|
+
# We're supporting this action as a best effort, but we should add a test after
|
|
39
|
+
# a new version of Rails is out.
|
|
40
|
+
cached = payload[:cached]
|
|
41
|
+
|
|
42
|
+
# the span should have the query ONLY in the Resource attribute,
|
|
43
|
+
# so that the ``sql.query`` tag will be set in the agent with an
|
|
44
|
+
# obfuscated version
|
|
45
|
+
span.span_type = Datadog::Ext::SQL::TYPE
|
|
46
|
+
span.set_tag('rails.db.vendor', adapter_name)
|
|
47
|
+
span.set_tag('rails.db.cached', cached) if cached
|
|
48
|
+
span.start_time = start
|
|
49
|
+
span.finish(finish)
|
|
50
|
+
rescue StandardError => e
|
|
51
|
+
Datadog::Tracer.log.error(e.message)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require 'ddtrace/ext/cache'
|
|
3
|
+
|
|
4
|
+
module Datadog
|
|
5
|
+
module Contrib
|
|
6
|
+
module Rails
|
|
7
|
+
# Code used to create and handle 'rails.cache' spans.
|
|
8
|
+
module ActiveSupport
|
|
9
|
+
def self.instrument
|
|
10
|
+
# patch Rails core components
|
|
11
|
+
Datadog::RailsCachePatcher.patch_cache_store()
|
|
12
|
+
|
|
13
|
+
# subscribe when a cache read starts being processed
|
|
14
|
+
::ActiveSupport::Notifications.subscribe('start_cache_read.active_support') do |*args|
|
|
15
|
+
start_trace_cache('GET', *args)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# subscribe when a cache fetch starts being processed
|
|
19
|
+
::ActiveSupport::Notifications.subscribe('start_cache_fetch.active_support') do |*args|
|
|
20
|
+
start_trace_cache('GET', *args)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# subscribe when a cache write starts being processed
|
|
24
|
+
::ActiveSupport::Notifications.subscribe('start_cache_write.active_support') do |*args|
|
|
25
|
+
start_trace_cache('SET', *args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# subscribe when a cache delete starts being processed
|
|
29
|
+
::ActiveSupport::Notifications.subscribe('start_cache_delete.active_support') do |*args|
|
|
30
|
+
start_trace_cache('DELETE', *args)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# subscribe when a cache read has been processed
|
|
34
|
+
::ActiveSupport::Notifications.subscribe('cache_read.active_support') do |*args|
|
|
35
|
+
trace_cache('GET', *args)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# subscribe when a cache write has been processed
|
|
39
|
+
::ActiveSupport::Notifications.subscribe('cache_write.active_support') do |*args|
|
|
40
|
+
trace_cache('SET', *args)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# subscribe when a cache delete has been processed
|
|
44
|
+
::ActiveSupport::Notifications.subscribe('cache_delete.active_support') do |*args|
|
|
45
|
+
trace_cache('DELETE', *args)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.create_span(tracer)
|
|
50
|
+
service = ::Rails.configuration.datadog_trace.fetch(:default_cache_service)
|
|
51
|
+
type = Datadog::Ext::CACHE::TYPE
|
|
52
|
+
tracer.trace('rails.cache', service: service, span_type: type)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.get_key(resource)
|
|
56
|
+
'datadog_activesupport_' + resource
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.start_trace_cache(resource, *_args)
|
|
60
|
+
key = get_key(resource)
|
|
61
|
+
# This is mostly to trap the case of fetch/read. In some cases the framework
|
|
62
|
+
# will call fetch but fetch won't call read. In some cases read can be called
|
|
63
|
+
# alone. And in some cases they are nested. In all cases we want to have one
|
|
64
|
+
# and only one span.
|
|
65
|
+
return if Thread.current[key]
|
|
66
|
+
create_span(::Rails.configuration.datadog_trace.fetch(:tracer))
|
|
67
|
+
Thread.current[key] = true
|
|
68
|
+
rescue StandardError => e
|
|
69
|
+
Datadog::Tracer.log.error(e.message)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.trace_cache(resource, _name, start, finish, _id, payload)
|
|
73
|
+
tracer = ::Rails.configuration.datadog_trace.fetch(:tracer)
|
|
74
|
+
key = get_key(resource)
|
|
75
|
+
if Thread.current[key]
|
|
76
|
+
# span was created by start_trace_cache, plan to re-use this one
|
|
77
|
+
Thread.current[key] = false
|
|
78
|
+
else
|
|
79
|
+
# Create a span now, as start_trace_cache was not called.
|
|
80
|
+
#
|
|
81
|
+
# This could typically happen if, for some reason the monkey-patching
|
|
82
|
+
# of the cache class did not work as expected. Doing this, we might
|
|
83
|
+
# loose some interesting parentship between some spans, because this
|
|
84
|
+
# span is created too late, and children won't "find" their parent.
|
|
85
|
+
# But, it's better than no span at all, and it case there is no child
|
|
86
|
+
# at all, it will work just as expected. In practice, it's required to
|
|
87
|
+
# have standard file cache work together with redis cache.
|
|
88
|
+
create_span(tracer)
|
|
89
|
+
end
|
|
90
|
+
span = tracer.active_span()
|
|
91
|
+
return unless span
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
# finish the tracing and update the execution time
|
|
95
|
+
span.resource = resource
|
|
96
|
+
# discard parameters from the cache_store configuration
|
|
97
|
+
store, = *Array.wrap(::Rails.configuration.cache_store).flatten
|
|
98
|
+
span.set_tag('rails.cache.backend', store)
|
|
99
|
+
span.set_tag('rails.cache.key', payload.fetch(:key))
|
|
100
|
+
span.set_error(payload[:exception]) if payload[:exception]
|
|
101
|
+
ensure
|
|
102
|
+
span.start_time = start
|
|
103
|
+
span.finish(finish)
|
|
104
|
+
end
|
|
105
|
+
rescue StandardError => e
|
|
106
|
+
Datadog::Tracer.log.error(e.message)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private_class_method :create_span, :get_key, :start_trace_cache, :trace_cache
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Datadog
|
|
2
|
+
# RailsRendererPatcher contains function to patch Rails rendering libraries.
|
|
3
|
+
module RailsRendererPatcher
|
|
4
|
+
module_function
|
|
5
|
+
|
|
6
|
+
def patch_renderer
|
|
7
|
+
patch_renderer_render_template
|
|
8
|
+
patch_renderer_render_partial
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def patch_renderer_render_template
|
|
12
|
+
if defined?(::ActionView::Renderer)
|
|
13
|
+
::ActionView::Renderer.class_eval do
|
|
14
|
+
alias_method :render_template_without_datadog, :render_template
|
|
15
|
+
def render_template(*args, &block)
|
|
16
|
+
ActiveSupport::Notifications.instrument('start_render_template.action_view')
|
|
17
|
+
render_template_without_datadog(*args, &block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
else # Rails < 3.1
|
|
21
|
+
::ActionView::Template.class_eval do
|
|
22
|
+
alias_method :render_template_without_datadog, :render
|
|
23
|
+
def render(*args, &block)
|
|
24
|
+
ActiveSupport::Notifications.instrument('start_render_template.action_view')
|
|
25
|
+
render_template_without_datadog(*args, &block)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def patch_renderer_render_partial
|
|
32
|
+
if defined?(::ActionView::PartialRenderer)
|
|
33
|
+
::ActionView::PartialRenderer.class_eval do
|
|
34
|
+
alias_method :render_partial_without_datadog, :render_partial
|
|
35
|
+
def render_partial(*args, &block)
|
|
36
|
+
ActiveSupport::Notifications.instrument('start_render_partial.action_view')
|
|
37
|
+
render_partial_without_datadog(*args, &block)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
else # Rails < 3.1
|
|
41
|
+
::ActionView::Partials::PartialRenderer.class_eval do
|
|
42
|
+
alias_method :render_partial_without_datadog, :render
|
|
43
|
+
def render(*args, &block)
|
|
44
|
+
ActiveSupport::Notifications.instrument('start_render_partial.action_view')
|
|
45
|
+
render_partial_without_datadog(*args, &block)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# RailsCachePatcher contains function to patch Rails caching libraries.
|
|
53
|
+
module RailsCachePatcher
|
|
54
|
+
module_function
|
|
55
|
+
|
|
56
|
+
def patch_cache_store
|
|
57
|
+
patch_cache_store_read
|
|
58
|
+
patch_cache_store_fetch
|
|
59
|
+
patch_cache_store_write
|
|
60
|
+
patch_cache_store_delete
|
|
61
|
+
patch_cache_store_instrument
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def cache_store_class(k)
|
|
65
|
+
# When Redis is used, we can't only patch Cache::Store as it is
|
|
66
|
+
# Cache::RedisStore, a sub-class of it that is used, in practice.
|
|
67
|
+
# We need to do a per-method monkey patching as some of them might
|
|
68
|
+
# be redefined, and some of them not. The latest version of redis-activesupport
|
|
69
|
+
# redefines write but leaves untouched read and delete:
|
|
70
|
+
# https://github.com/redis-store/redis-activesupport/blob/master/lib/active_support/cache/redis_store.rb
|
|
71
|
+
c = if defined?(::ActiveSupport::Cache::RedisStore) &&
|
|
72
|
+
::ActiveSupport::Cache::RedisStore.instance_methods(false).include?(k)
|
|
73
|
+
::ActiveSupport::Cache::RedisStore
|
|
74
|
+
else
|
|
75
|
+
::ActiveSupport::Cache::Store
|
|
76
|
+
end
|
|
77
|
+
c
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def patch_cache_store_read
|
|
81
|
+
cache_store_class(:read).class_eval do
|
|
82
|
+
alias_method :read_without_datadog, :read
|
|
83
|
+
def read(*args, &block)
|
|
84
|
+
ActiveSupport::Notifications.instrument('start_cache_read.active_support')
|
|
85
|
+
read_without_datadog(*args, &block)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def patch_cache_store_fetch
|
|
91
|
+
cache_store_class(:fetch).class_eval do
|
|
92
|
+
alias_method :fetch_without_datadog, :fetch
|
|
93
|
+
def fetch(*args, &block)
|
|
94
|
+
ActiveSupport::Notifications.instrument('start_cache_fetch.active_support')
|
|
95
|
+
fetch_without_datadog(*args, &block)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def patch_cache_store_write
|
|
101
|
+
cache_store_class(:write).class_eval do
|
|
102
|
+
alias_method :write_without_datadog, :write
|
|
103
|
+
def write(*args, &block)
|
|
104
|
+
ActiveSupport::Notifications.instrument('start_cache_write.active_support')
|
|
105
|
+
write_without_datadog(*args, &block)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def patch_cache_store_delete
|
|
111
|
+
cache_store_class(:delete).class_eval do
|
|
112
|
+
alias_method :delete_without_datadog, :delete
|
|
113
|
+
def delete(*args, &block)
|
|
114
|
+
ActiveSupport::Notifications.instrument('start_cache_delete.active_support')
|
|
115
|
+
delete_without_datadog(*args, &block)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def patch_cache_store_instrument
|
|
121
|
+
# by default, Rails 3 doesn't instrument the cache system so we should turn it on
|
|
122
|
+
# using the ActiveSupport::Cache::Store.instrument= function. Unfortunately, early
|
|
123
|
+
# versions of Rails use a Thread.current store that is not compatible with some
|
|
124
|
+
# application servers like Passenger.
|
|
125
|
+
# More details: https://github.com/rails/rails/blob/v3.2.22.5/activesupport/lib/active_support/cache.rb#L175-L177
|
|
126
|
+
return unless ::Rails::VERSION::MAJOR.to_i == 3
|
|
127
|
+
::ActiveSupport::Cache::Store.singleton_class.class_eval do
|
|
128
|
+
# Add the instrument function that Rails 3.x uses
|
|
129
|
+
# to know if the underlying cache should be instrumented or not. By default,
|
|
130
|
+
# we force that instrumentation if the Rails application is auto instrumented.
|
|
131
|
+
def instrument
|
|
132
|
+
true
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require 'ddtrace/pin'
|
|
2
|
+
require 'ddtrace/ext/app_types'
|
|
3
|
+
|
|
4
|
+
require 'ddtrace/contrib/grape/endpoint'
|
|
5
|
+
require 'ddtrace/contrib/rack/middlewares'
|
|
6
|
+
|
|
7
|
+
require 'ddtrace/contrib/rails/core_extensions'
|
|
8
|
+
require 'ddtrace/contrib/rails/action_controller'
|
|
9
|
+
require 'ddtrace/contrib/rails/action_view'
|
|
10
|
+
require 'ddtrace/contrib/rails/active_record'
|
|
11
|
+
require 'ddtrace/contrib/rails/active_support'
|
|
12
|
+
require 'ddtrace/contrib/rails/utils'
|
|
13
|
+
|
|
14
|
+
# Rails < 3.1
|
|
15
|
+
if defined?(::ActiveRecord) && !defined?(::ActiveRecord::Base.connection_config)
|
|
16
|
+
ActiveRecord::Base.class_eval do
|
|
17
|
+
class << self
|
|
18
|
+
def connection_config
|
|
19
|
+
connection_pool.spec.config
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module Datadog
|
|
26
|
+
module Contrib
|
|
27
|
+
# Instrument Rails.
|
|
28
|
+
module Rails
|
|
29
|
+
# Rails framework code, used to essentially:
|
|
30
|
+
# - handle configuration entries which are specific to Datadog tracing
|
|
31
|
+
# - instrument parts of the framework when needed
|
|
32
|
+
module Framework
|
|
33
|
+
# default configurations for the Rails integration; by default
|
|
34
|
+
# the Datadog.tracer is enabled, while the Rails auto instrumentation
|
|
35
|
+
# is kept disabled.
|
|
36
|
+
DEFAULT_CONFIG = {
|
|
37
|
+
enabled: true,
|
|
38
|
+
auto_instrument: false,
|
|
39
|
+
auto_instrument_redis: false,
|
|
40
|
+
auto_instrument_grape: false,
|
|
41
|
+
default_service: 'rails-app',
|
|
42
|
+
default_controller_service: 'rails-controller',
|
|
43
|
+
default_cache_service: 'rails-cache',
|
|
44
|
+
default_grape_service: 'grape',
|
|
45
|
+
template_base_path: 'views/',
|
|
46
|
+
tracer: Datadog.tracer,
|
|
47
|
+
debug: false,
|
|
48
|
+
trace_agent_hostname: Datadog::Writer::HOSTNAME,
|
|
49
|
+
trace_agent_port: Datadog::Writer::PORT,
|
|
50
|
+
env: nil,
|
|
51
|
+
tags: {}
|
|
52
|
+
}.freeze
|
|
53
|
+
|
|
54
|
+
# configure Datadog settings
|
|
55
|
+
# rubocop:disable Metrics/MethodLength
|
|
56
|
+
def self.configure(config)
|
|
57
|
+
# tracer defaults
|
|
58
|
+
# merge default configurations with users settings
|
|
59
|
+
user_config = config[:config].datadog_trace rescue {}
|
|
60
|
+
datadog_config = DEFAULT_CONFIG.merge(user_config)
|
|
61
|
+
datadog_config[:tracer].enabled = datadog_config[:enabled]
|
|
62
|
+
|
|
63
|
+
# set debug logging
|
|
64
|
+
Datadog::Tracer.debug_logging = datadog_config[:debug]
|
|
65
|
+
|
|
66
|
+
# set the address of the trace agent
|
|
67
|
+
datadog_config[:tracer].configure(
|
|
68
|
+
hostname: datadog_config[:trace_agent_hostname],
|
|
69
|
+
port: datadog_config[:trace_agent_port]
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# set default tracer tags
|
|
73
|
+
datadog_config[:tracer].set_tags(datadog_config[:tags])
|
|
74
|
+
|
|
75
|
+
datadog_config[:tracer].set_tags('env' => datadog_config[:env]) if datadog_config[:env]
|
|
76
|
+
|
|
77
|
+
# set default service details
|
|
78
|
+
datadog_config[:tracer].set_service_info(
|
|
79
|
+
datadog_config[:default_service],
|
|
80
|
+
'rack',
|
|
81
|
+
Datadog::Ext::AppTypes::WEB
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
datadog_config[:tracer].set_service_info(
|
|
85
|
+
datadog_config[:default_controller_service],
|
|
86
|
+
'rails',
|
|
87
|
+
Datadog::Ext::AppTypes::WEB
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
datadog_config[:tracer].set_service_info(
|
|
91
|
+
datadog_config[:default_cache_service],
|
|
92
|
+
'rails',
|
|
93
|
+
Datadog::Ext::AppTypes::CACHE
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# By default, default service would be guessed from the script
|
|
97
|
+
# being executed, but here we know better, get it from Rails config.
|
|
98
|
+
datadog_config[:tracer].default_service = datadog_config[:default_service]
|
|
99
|
+
|
|
100
|
+
if defined?(::ActiveRecord)
|
|
101
|
+
begin
|
|
102
|
+
# set default database service details and store it in the configuration
|
|
103
|
+
conn_cfg = ::ActiveRecord::Base.connection_config()
|
|
104
|
+
adapter_name = Datadog::Contrib::Rails::Utils.normalize_vendor(conn_cfg[:adapter])
|
|
105
|
+
database_service = datadog_config.fetch(:default_database_service, adapter_name)
|
|
106
|
+
datadog_config[:default_database_service] = database_service
|
|
107
|
+
datadog_config[:tracer].set_service_info(
|
|
108
|
+
database_service,
|
|
109
|
+
adapter_name,
|
|
110
|
+
Datadog::Ext::AppTypes::DB
|
|
111
|
+
)
|
|
112
|
+
rescue StandardError => e
|
|
113
|
+
Datadog::Tracer.log.warn("Unable to get database config (#{e}), skipping ActiveRecord instrumentation")
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# update global configurations
|
|
118
|
+
::Rails.configuration.datadog_trace = datadog_config
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def self.auto_instrument_redis
|
|
122
|
+
return unless ::Rails.configuration.datadog_trace[:auto_instrument_redis]
|
|
123
|
+
Datadog::Tracer.log.debug('Enabling auto-instrumentation for Redis client')
|
|
124
|
+
|
|
125
|
+
# patch the Redis library and reload the CacheStore if it was using Redis
|
|
126
|
+
Datadog::Monkey.patch_module(:redis)
|
|
127
|
+
|
|
128
|
+
# reload the cache store if it's available and it's using Redis
|
|
129
|
+
return unless defined?(::ActiveSupport::Cache::RedisStore) &&
|
|
130
|
+
defined?(::Rails.cache) &&
|
|
131
|
+
::Rails.cache.is_a?(::ActiveSupport::Cache::RedisStore)
|
|
132
|
+
Datadog::Tracer.log.debug('Enabling auto-instrumentation for redis-rails connector')
|
|
133
|
+
|
|
134
|
+
# backward compatibility: Rails 3.x doesn't have `cache=` method
|
|
135
|
+
cache_store = ::Rails.configuration.cache_store
|
|
136
|
+
cache_instance = ::ActiveSupport::Cache.lookup_store(cache_store)
|
|
137
|
+
if ::Rails::VERSION::MAJOR.to_i == 3
|
|
138
|
+
silence_warnings { Object.const_set 'RAILS_CACHE', cache_instance }
|
|
139
|
+
elsif ::Rails::VERSION::MAJOR.to_i > 3
|
|
140
|
+
::Rails.cache = cache_instance
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.auto_instrument_grape
|
|
145
|
+
return unless ::Rails.configuration.datadog_trace[:auto_instrument_grape]
|
|
146
|
+
|
|
147
|
+
# patch the Grape library so that endpoints are traced
|
|
148
|
+
Datadog::Monkey.patch_module(:grape)
|
|
149
|
+
|
|
150
|
+
# update the Grape pin object
|
|
151
|
+
pin = Datadog::Pin.get_from(::Grape)
|
|
152
|
+
return unless pin && pin.enabled?
|
|
153
|
+
pin.tracer = ::Rails.configuration.datadog_trace[:tracer]
|
|
154
|
+
pin.service = ::Rails.configuration.datadog_trace[:default_grape_service]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# automatically instrument all Rails component
|
|
158
|
+
def self.auto_instrument
|
|
159
|
+
return unless ::Rails.configuration.datadog_trace[:auto_instrument]
|
|
160
|
+
Datadog::Tracer.log.debug('Enabling auto-instrumentation for core components')
|
|
161
|
+
|
|
162
|
+
# instrumenting Rails framework
|
|
163
|
+
Datadog::Contrib::Rails::ActionController.instrument()
|
|
164
|
+
Datadog::Contrib::Rails::ActionView.instrument()
|
|
165
|
+
Datadog::Contrib::Rails::ActiveRecord.instrument()
|
|
166
|
+
Datadog::Contrib::Rails::ActiveSupport.instrument()
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|