-
Notifications
You must be signed in to change notification settings - Fork 377
/
Copy pathframework.rb
148 lines (126 loc) · 5.89 KB
/
framework.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
require 'ddtrace/pin'
require 'ddtrace/ext/app_types'
require 'ddtrace/contrib/grape/endpoint'
require 'ddtrace/contrib/rack/middlewares'
require 'ddtrace/contrib/rails/core_extensions'
require 'ddtrace/contrib/rails/action_controller'
require 'ddtrace/contrib/rails/action_view'
require 'ddtrace/contrib/rails/active_record'
require 'ddtrace/contrib/rails/active_support'
require 'ddtrace/contrib/rails/utils'
# Rails < 3.1
if defined?(::ActiveRecord) && !defined?(::ActiveRecord::Base.connection_config)
ActiveRecord::Base.class_eval do
class << self
def connection_config
connection_pool.spec.config
end
end
end
end
module Datadog
module Contrib
# Instrument Rails.
module Rails
# Rails framework code, used to essentially:
# - handle configuration entries which are specific to Datadog tracing
# - instrument parts of the framework when needed
module Framework
# configure Datadog settings
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.configure(rails_config)
user_config = config[:config].datadog_trace rescue {}
Datadog.configuration.use(:rails, user_config)
tracer = Datadog.configuration[:rails][:tracer]
tracer.enabled = Datadog.configuration[:rails][:enabled]
tracer.class.debug_logging = Datadog.configuration[:rails][:debug]
tracer.configure(
hostname: Datadog.configuration[:rails][:trace_agent_hostname],
port: Datadog.configuration[:rails][:trace_agent_port]
)
tracer.set_tags(Datadog.configuration[:rails][:tags])
tracer.set_tags('env' => Datadog.configuration[:rails][:env]) if Datadog.configuration[:rails][:env]
tracer.set_service_info(
Datadog.configuration[:rails][:default_service],
'rack',
Datadog::Ext::AppTypes::WEB
)
tracer.set_service_info(
Datadog.configuration[:rails][:default_controller_service],
'rails',
Datadog::Ext::AppTypes::WEB
)
tracer.set_service_info(
Datadog.configuration[:rails][:default_cache_service],
'rails',
Datadog::Ext::AppTypes::CACHE
)
# By default, default service would be guessed from the script
# being executed, but here we know better, get it from Rails config.
tracer.default_service = Datadog.configuration[:rails][:default_service]
Datadog.configuration[:rack][:tracer] = tracer
Datadog.configuration[:rack][:default_service] = Datadog.configuration[:rails][:default_service]
Datadog.configuration[:rack][:distributed_tracing_enabled] = \
Datadog.configuration[:rails][:distributed_tracing_enabled]
if defined?(::ActiveRecord)
begin
# set default database service details and store it in the configuration
conn_cfg = ::ActiveRecord::Base.connection_config()
adapter_name = Datadog::Contrib::Rails::Utils.normalize_vendor(conn_cfg[:adapter])
Datadog.configuration[:rails][:default_database_service] ||= adapter_name
tracer.set_service_info(
Datadog.configuration[:rails][:default_database_service],
adapter_name,
Datadog::Ext::AppTypes::DB
)
rescue StandardError => e
Datadog::Tracer.log.warn("Unable to get database config (#{e}), skipping ActiveRecord instrumentation")
end
end
# update global configurations
::Rails.configuration.datadog_trace = Datadog.registry[:rails].to_h
end
def self.auto_instrument_redis
return unless Datadog.configuration[:rails][:auto_instrument_redis]
Datadog::Tracer.log.debug('Enabling auto-instrumentation for Redis client')
# patch the Redis library and reload the CacheStore if it was using Redis
Datadog::Monkey.patch_module(:redis)
# reload the cache store if it's available and it's using Redis
return unless defined?(::ActiveSupport::Cache::RedisStore) &&
defined?(::Rails.cache) &&
::Rails.cache.is_a?(::ActiveSupport::Cache::RedisStore)
Datadog::Tracer.log.debug('Enabling auto-instrumentation for redis-rails connector')
# backward compatibility: Rails 3.x doesn't have `cache=` method
cache_store = ::Rails.configuration.cache_store
cache_instance = ::ActiveSupport::Cache.lookup_store(cache_store)
if ::Rails::VERSION::MAJOR.to_i == 3
silence_warnings { Object.const_set 'RAILS_CACHE', cache_instance }
elsif ::Rails::VERSION::MAJOR.to_i > 3
::Rails.cache = cache_instance
end
end
def self.auto_instrument_grape
return unless Datadog.configuration[:rails][:auto_instrument_grape]
# patch the Grape library so that endpoints are traced
Datadog::Monkey.patch_module(:grape)
# update the Grape pin object
pin = Datadog::Pin.get_from(::Grape)
return unless pin && pin.enabled?
pin.tracer = Datadog.configuration[:rails][:tracer]
pin.service = Datadog.configuration[:rails][:default_grape_service]
end
# automatically instrument all Rails component
def self.auto_instrument
return unless Datadog.configuration[:rails][:auto_instrument]
Datadog::Tracer.log.debug('Enabling auto-instrumentation for core components')
# instrumenting Rails framework
Datadog::Contrib::Rails::ActionController.instrument()
Datadog::Contrib::Rails::ActionView.instrument()
Datadog::Contrib::Rails::ActiveRecord.instrument()
Datadog::Contrib::Rails::ActiveSupport.instrument()
end
end
end
end
end