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.
@@ -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
@@ -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
@@ -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('Set pin #{pin.service} on #{obj.class}.')
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('Get pin from #{obj.class}.')
48
+ Datadog::Tracer.log.debug("Get pin from #{self.class}.")
49
49
  @datadog_pin
50
50
  end
51
51
  end
@@ -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.
@@ -9,6 +9,7 @@ module Datadog
9
9
  # so that the Transport is thread-safe.
10
10
  class HTTPTransport
11
11
  attr_accessor :hostname, :port
12
+ attr_reader :traces_endpoint, :services_endpoint
12
13
 
13
14
  # seconds before the transport timeout
14
15
  TIMEOUT = 1
@@ -1,8 +1,8 @@
1
1
  module Datadog
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 3
5
- PATCH = 1
4
+ MINOR = 4
5
+ PATCH = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
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.3.1
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-23 00:00:00.000000000 Z
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: '10.0'
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: '10.0'
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.43'
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.43'
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.0'
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.0'
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.5.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