ddtrace 0.3.1 → 0.4.0
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 +4 -4
- data/Appraisals +52 -48
- data/README.md +6 -6
- data/Rakefile +29 -26
- data/circle.yml +28 -25
- data/ddtrace.gemspec +3 -4
- data/docs/GettingStarted +94 -49
- data/gemfiles/rails5_mysql2.gemfile +1 -1
- data/gemfiles/rails5_postgres.gemfile +1 -1
- data/gemfiles/rails5_postgres_redis.gemfile +1 -1
- data/lib/ddtrace.rb +15 -13
- data/lib/ddtrace/contrib/elasticsearch/core.rb +4 -2
- data/lib/ddtrace/contrib/http/patcher.rb +131 -0
- data/lib/ddtrace/contrib/rails/action_view.rb +3 -0
- data/lib/ddtrace/contrib/rails/active_record.rb +3 -0
- data/lib/ddtrace/contrib/rails/active_support.rb +3 -0
- data/lib/ddtrace/contrib/rails/core_extensions.rb +17 -0
- data/lib/ddtrace/contrib/rails/framework.rb +17 -16
- data/lib/ddtrace/contrib/redis/patcher.rb +83 -3
- data/lib/ddtrace/contrib/sinatra/tracer.rb +181 -0
- data/lib/ddtrace/monkey.rb +15 -1
- data/lib/ddtrace/pin.rb +2 -2
- data/lib/ddtrace/span.rb +2 -2
- data/lib/ddtrace/transport.rb +1 -0
- data/lib/ddtrace/version.rb +2 -2
- metadata +11 -24
- data/lib/ddtrace/contrib/redis/core.rb +0 -72
@@ -0,0 +1,181 @@
|
|
1
|
+
|
2
|
+
require 'sinatra/base'
|
3
|
+
|
4
|
+
require 'ddtrace/ext/app_types'
|
5
|
+
require 'ddtrace/ext/errors'
|
6
|
+
require 'ddtrace/ext/http'
|
7
|
+
|
8
|
+
sinatra_vs = Gem::Version.new(Sinatra::VERSION)
|
9
|
+
sinatra_min_vs = Gem::Version.new('1.4.0')
|
10
|
+
if sinatra_vs < sinatra_min_vs
|
11
|
+
raise "sinatra version #{sinatra_vs} is not supported yet " \
|
12
|
+
+ "(supporting versions >=#{sinatra_min_vs})"
|
13
|
+
end
|
14
|
+
|
15
|
+
Datadog::Tracer.log.info("activating instrumentation for sinatra #{sinatra_vs}")
|
16
|
+
|
17
|
+
module Datadog
|
18
|
+
module Contrib
|
19
|
+
module Sinatra
|
20
|
+
# TracerCfg is used to manipulate the configuration of the Sinatra
|
21
|
+
# tracing extension.
|
22
|
+
class TracerCfg
|
23
|
+
DEFAULT_CFG = {
|
24
|
+
enabled: true,
|
25
|
+
default_service: 'sinatra',
|
26
|
+
tracer: Datadog.tracer,
|
27
|
+
debug: false,
|
28
|
+
trace_agent_hostname: Datadog::Writer::HOSTNAME,
|
29
|
+
trace_agent_port: Datadog::Writer::PORT
|
30
|
+
}.freeze()
|
31
|
+
|
32
|
+
attr_accessor :cfg
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@cfg = DEFAULT_CFG.dup()
|
36
|
+
end
|
37
|
+
|
38
|
+
def configure(**args)
|
39
|
+
args.each do |name, value|
|
40
|
+
self[name] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
apply()
|
44
|
+
end
|
45
|
+
|
46
|
+
def apply
|
47
|
+
Datadog::Tracer.debug_logging = @cfg[:debug]
|
48
|
+
|
49
|
+
tracer = @cfg[:tracer]
|
50
|
+
|
51
|
+
tracer.enabled = @cfg[:enabled]
|
52
|
+
tracer.configure(hostname: @cfg[:trace_agent_hostname],
|
53
|
+
port: @cfg[:trace_agent_port])
|
54
|
+
|
55
|
+
tracer.set_service_info(@cfg[:default_service], 'sinatra',
|
56
|
+
Datadog::Ext::AppTypes::WEB)
|
57
|
+
end
|
58
|
+
|
59
|
+
def [](key)
|
60
|
+
raise ArgumentError, "unknown setting '#{key}'" unless @cfg.key? key
|
61
|
+
@cfg[key]
|
62
|
+
end
|
63
|
+
|
64
|
+
def []=(key, value)
|
65
|
+
raise ArgumentError, "unknown setting '#{key}'" unless @cfg.key? key
|
66
|
+
@cfg[key] = value
|
67
|
+
end
|
68
|
+
|
69
|
+
def enabled?
|
70
|
+
@cfg[:enabled] && @cfg[:tracer]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Datadog::Contrib::Sinatra::Tracer is a Sinatra extension which traces
|
75
|
+
# requests.
|
76
|
+
module Tracer
|
77
|
+
def route(verb, action, *)
|
78
|
+
# Keep track of the route name when the app is instantiated for an
|
79
|
+
# incoming request.
|
80
|
+
condition do
|
81
|
+
@datadog_route = action
|
82
|
+
end
|
83
|
+
|
84
|
+
super
|
85
|
+
end
|
86
|
+
|
87
|
+
# rubocop:disable Metrics/AbcSize
|
88
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
89
|
+
# rubocop:disable Metrics/MethodLength
|
90
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
91
|
+
def self.registered(app)
|
92
|
+
::Sinatra::Base.module_eval do
|
93
|
+
def render(engine, data, *)
|
94
|
+
cfg = settings.datadog_tracer
|
95
|
+
|
96
|
+
output = ''
|
97
|
+
if cfg.enabled?
|
98
|
+
tracer = cfg[:tracer]
|
99
|
+
tracer.trace('sinatra.render_template') do |span|
|
100
|
+
# If data is a string, it is a literal template and we don't
|
101
|
+
# want to record it.
|
102
|
+
span.set_tag('sinatra.template_name', data) if data.is_a? Symbol
|
103
|
+
output = super
|
104
|
+
end
|
105
|
+
else
|
106
|
+
output = super
|
107
|
+
end
|
108
|
+
|
109
|
+
output
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
app.set :datadog_tracer, TracerCfg.new()
|
114
|
+
|
115
|
+
app.configure do
|
116
|
+
app.settings.datadog_tracer.apply()
|
117
|
+
end
|
118
|
+
|
119
|
+
app.before do
|
120
|
+
cfg = settings.datadog_tracer
|
121
|
+
return unless cfg.enabled?
|
122
|
+
|
123
|
+
if instance_variable_defined? :@datadog_request_span
|
124
|
+
if @datadog_request_span
|
125
|
+
Datadog::Tracer.log.error('request span active in :before hook')
|
126
|
+
@datadog_request_span.finish()
|
127
|
+
@datadog_request_span = nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
tracer = cfg[:tracer]
|
132
|
+
|
133
|
+
span = tracer.trace('sinatra.request',
|
134
|
+
service: cfg.cfg[:default_service],
|
135
|
+
span_type: Datadog::Ext::HTTP::TYPE)
|
136
|
+
span.set_tag(Datadog::Ext::HTTP::URL, request.path)
|
137
|
+
span.set_tag(Datadog::Ext::HTTP::METHOD, request.request_method)
|
138
|
+
|
139
|
+
@datadog_request_span = span
|
140
|
+
end
|
141
|
+
|
142
|
+
app.after do
|
143
|
+
cfg = settings.datadog_tracer
|
144
|
+
return unless cfg.enabled?
|
145
|
+
|
146
|
+
span = @datadog_request_span
|
147
|
+
begin
|
148
|
+
unless span
|
149
|
+
Datadog::Tracer.log.error('missing request span in :after hook')
|
150
|
+
return
|
151
|
+
end
|
152
|
+
|
153
|
+
span.resource = "#{request.request_method} #{@datadog_route}"
|
154
|
+
span.set_tag('sinatra.route.path', @datadog_route)
|
155
|
+
span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.status)
|
156
|
+
|
157
|
+
if response.server_error?
|
158
|
+
span.status = 1
|
159
|
+
|
160
|
+
err = env['sinatra.error']
|
161
|
+
if err
|
162
|
+
span.set_tag(Datadog::Ext::Errors::TYPE, err.class)
|
163
|
+
span.set_tag(Datadog::Ext::Errors::MSG, err.message)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
span.finish()
|
168
|
+
ensure
|
169
|
+
@datadog_request_span = nil
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# rubocop:disable Style/Documentation
|
179
|
+
module Sinatra
|
180
|
+
register Datadog::Contrib::Sinatra::Tracer
|
181
|
+
end
|
data/lib/ddtrace/monkey.rb
CHANGED
@@ -4,19 +4,21 @@ require 'thread'
|
|
4
4
|
# because patchers do not include any 3rd party module nor even our
|
5
5
|
# patching code, which is required on demand, when patching.
|
6
6
|
require 'ddtrace/contrib/elasticsearch/patcher'
|
7
|
+
require 'ddtrace/contrib/http/patcher'
|
7
8
|
require 'ddtrace/contrib/redis/patcher'
|
8
9
|
|
9
10
|
module Datadog
|
10
11
|
# Monkey is used for monkey-patching 3rd party libs.
|
11
12
|
module Monkey
|
12
13
|
@patched = []
|
13
|
-
@autopatch_modules = { elasticsearch: true, redis: true }
|
14
|
+
@autopatch_modules = { elasticsearch: true, http: true, redis: true }
|
14
15
|
# Patchers should expose 2 methods:
|
15
16
|
# - patch, which applies our patch if needed. Should be idempotent,
|
16
17
|
# can be call twice but should just do nothing the second time.
|
17
18
|
# - patched?, which returns true if the module has been succesfully
|
18
19
|
# patched (patching might have failed if requirements were not here)
|
19
20
|
@patchers = { elasticsearch: Datadog::Contrib::Elasticsearch::Patcher,
|
21
|
+
http: Datadog::Contrib::HTTP::Patcher,
|
20
22
|
redis: Datadog::Contrib::Redis::Patcher }
|
21
23
|
@mutex = Mutex.new
|
22
24
|
|
@@ -56,5 +58,17 @@ module Datadog
|
|
56
58
|
end
|
57
59
|
patched
|
58
60
|
end
|
61
|
+
|
62
|
+
def without_warnings
|
63
|
+
# This is typically used when monkey patching functions such as
|
64
|
+
# intialize, which Ruby advices you not to. Use cautiously.
|
65
|
+
v = $VERBOSE
|
66
|
+
$VERBOSE = nil
|
67
|
+
begin
|
68
|
+
yield
|
69
|
+
ensure
|
70
|
+
$VERBOSE = v
|
71
|
+
end
|
72
|
+
end
|
59
73
|
end
|
60
74
|
end
|
data/lib/ddtrace/pin.rb
CHANGED
@@ -36,7 +36,7 @@ module Datadog
|
|
36
36
|
unless obj.respond_to? :datadog_pin=
|
37
37
|
obj.instance_exec do
|
38
38
|
def datadog_pin=(pin)
|
39
|
-
Datadog::Tracer.log.debug(
|
39
|
+
Datadog::Tracer.log.debug("Set pin #{pin.service} on #{self.class}.")
|
40
40
|
@datadog_pin = pin
|
41
41
|
end
|
42
42
|
end
|
@@ -45,7 +45,7 @@ module Datadog
|
|
45
45
|
unless obj.respond_to? :datadog_pin
|
46
46
|
obj.instance_exec do
|
47
47
|
def datadog_pin
|
48
|
-
Datadog::Tracer.log.debug(
|
48
|
+
Datadog::Tracer.log.debug("Get pin from #{self.class}.")
|
49
49
|
@datadog_pin
|
50
50
|
end
|
51
51
|
end
|
data/lib/ddtrace/span.rb
CHANGED
@@ -67,9 +67,9 @@ module Datadog
|
|
67
67
|
def set_error(e)
|
68
68
|
return if e.nil?
|
69
69
|
@status = 1
|
70
|
-
@meta[Datadog::Ext::Errors::MSG] = e.message
|
70
|
+
@meta[Datadog::Ext::Errors::MSG] = e.message if e.respond_to?(:message) && e.message
|
71
71
|
@meta[Datadog::Ext::Errors::TYPE] = e.class.to_s
|
72
|
-
@meta[Datadog::Ext::Errors::STACK] = e.backtrace.join("\n")
|
72
|
+
@meta[Datadog::Ext::Errors::STACK] = e.backtrace.join("\n") if e.respond_to?(:backtrace) && e.backtrace
|
73
73
|
end
|
74
74
|
|
75
75
|
# Mark the span finished at the current time and submit it.
|
data/lib/ddtrace/transport.rb
CHANGED
data/lib/ddtrace/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -24,62 +24,48 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '1.12'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1.12'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rake
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
33
|
+
version: '12.0'
|
48
34
|
type: :development
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
40
|
+
version: '12.0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: rubocop
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
47
|
+
version: '0.47'
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
54
|
+
version: '0.47'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: minitest
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: '5.
|
61
|
+
version: '5.10'
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: '5.
|
68
|
+
version: '5.10'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: appraisal
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,6 +117,7 @@ files:
|
|
131
117
|
- lib/ddtrace/contrib/elasticsearch/core.rb
|
132
118
|
- lib/ddtrace/contrib/elasticsearch/patcher.rb
|
133
119
|
- lib/ddtrace/contrib/elasticsearch/quantize.rb
|
120
|
+
- lib/ddtrace/contrib/http/patcher.rb
|
134
121
|
- lib/ddtrace/contrib/rails/action_controller.rb
|
135
122
|
- lib/ddtrace/contrib/rails/action_view.rb
|
136
123
|
- lib/ddtrace/contrib/rails/active_record.rb
|
@@ -138,10 +125,10 @@ files:
|
|
138
125
|
- lib/ddtrace/contrib/rails/core_extensions.rb
|
139
126
|
- lib/ddtrace/contrib/rails/framework.rb
|
140
127
|
- lib/ddtrace/contrib/rails/utils.rb
|
141
|
-
- lib/ddtrace/contrib/redis/core.rb
|
142
128
|
- lib/ddtrace/contrib/redis/patcher.rb
|
143
129
|
- lib/ddtrace/contrib/redis/quantize.rb
|
144
130
|
- lib/ddtrace/contrib/redis/tags.rb
|
131
|
+
- lib/ddtrace/contrib/sinatra/tracer.rb
|
145
132
|
- lib/ddtrace/encoding.rb
|
146
133
|
- lib/ddtrace/ext/app_types.rb
|
147
134
|
- lib/ddtrace/ext/cache.rb
|
@@ -180,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
167
|
version: '0'
|
181
168
|
requirements: []
|
182
169
|
rubyforge_project:
|
183
|
-
rubygems_version: 2.
|
170
|
+
rubygems_version: 2.6.9
|
184
171
|
signing_key:
|
185
172
|
specification_version: 4
|
186
173
|
summary: Datadog tracing code for your Ruby applications
|
@@ -1,72 +0,0 @@
|
|
1
|
-
require 'ddtrace/ext/app_types'
|
2
|
-
require 'ddtrace/contrib/redis/tags'
|
3
|
-
require 'ddtrace/contrib/redis/quantize'
|
4
|
-
|
5
|
-
module Datadog
|
6
|
-
module Contrib
|
7
|
-
module Redis
|
8
|
-
SERVICE = 'redis'.freeze
|
9
|
-
|
10
|
-
DRIVER = 'redis.driver'.freeze
|
11
|
-
|
12
|
-
# TracedRedis is a wrapper so that caller can pin on parent object without knowing about client member.
|
13
|
-
module TracedRedis
|
14
|
-
def datadog_pin=(pin)
|
15
|
-
# Forward the pin to client, which actually traces calls.
|
16
|
-
Datadog::Pin.onto(client, pin)
|
17
|
-
end
|
18
|
-
|
19
|
-
def datadog_pin
|
20
|
-
# Get the pin from client, which actually traces calls.
|
21
|
-
Datadog::Pin.get_from(client)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Datadog APM Redis integration.
|
26
|
-
module TracedRedisClient
|
27
|
-
def initialize(*args)
|
28
|
-
pin = Datadog::Pin.new(SERVICE, app: 'redis', app_type: Datadog::Ext::AppTypes::DB)
|
29
|
-
pin.onto(self)
|
30
|
-
super(*args)
|
31
|
-
end
|
32
|
-
|
33
|
-
def call(*args, &block)
|
34
|
-
pin = Datadog::Pin.get_from(self)
|
35
|
-
return super(*args, &block) unless pin
|
36
|
-
|
37
|
-
response = nil
|
38
|
-
pin.tracer.trace('redis.command') do |span|
|
39
|
-
span.service = pin.service
|
40
|
-
span.span_type = Datadog::Ext::Redis::TYPE
|
41
|
-
span.resource = Datadog::Contrib::Redis::Quantize.format_command_args(*args)
|
42
|
-
span.set_tag(Datadog::Ext::Redis::RAWCMD, span.resource)
|
43
|
-
Datadog::Contrib::Redis::Tags.set_common_tags(self, span)
|
44
|
-
|
45
|
-
response = super(*args, &block)
|
46
|
-
end
|
47
|
-
|
48
|
-
response
|
49
|
-
end
|
50
|
-
|
51
|
-
def call_pipeline(*args, &block)
|
52
|
-
pin = Datadog::Pin.get_from(self)
|
53
|
-
return super(*args, &block) unless pin
|
54
|
-
|
55
|
-
response = nil
|
56
|
-
pin.tracer.trace('redis.command') do |span|
|
57
|
-
span.service = pin.service
|
58
|
-
span.span_type = Datadog::Ext::Redis::TYPE
|
59
|
-
commands = args[0].commands.map { |c| Datadog::Contrib::Redis::Quantize.format_command_args(c) }
|
60
|
-
span.resource = commands.join("\n")
|
61
|
-
span.set_tag(Datadog::Ext::Redis::RAWCMD, span.resource)
|
62
|
-
Datadog::Contrib::Redis::Tags.set_common_tags(self, span)
|
63
|
-
|
64
|
-
response = super(*args, &block)
|
65
|
-
end
|
66
|
-
|
67
|
-
response
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|