ddtrace 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MmJhODJmN2VmNjMxNzY5OTg5NGE1NjEwOTgwZTE0MGU5ZTE1ZjJlYQ==
5
- data.tar.gz: !binary |-
6
- ZTg5OWNhMjdjMDlhNDVlNDMwN2MzODYzNDgyMGM5MTc1MmMwNzFhZg==
2
+ SHA1:
3
+ metadata.gz: 36285521893bb7e1b8ceaa8f28d5d0b2b5103239
4
+ data.tar.gz: 0108b54ce0043a1ac7acd4412ea8cae915e5fdd2
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZThkYmY4ZDQ2MjJiNGJkNTg5YTFjYTJhNmRmMWM1NTFiZGFjZGYzOGJhOTM1
10
- ZWU3ODc1MDExNDliNTgzMGM3YzZiOTE4ZTE0YTlkNWJmNjkzMzJlOGRhNzQz
11
- MzE2MTRhMDNkNzA3NmNmMmJmZWIzYmEwN2U3NzU1NmVhNjMzYWQ=
12
- data.tar.gz: !binary |-
13
- MWM3N2I4N2IxNDU5NDZhZTU2YWZmNGU2YmMyYjU2ZmZkNTk4YzgxMGVmZGIz
14
- YzM0ZDczYWVhZGMyMjhlNzQ1ZTJjMTBiNjRiNjc4YmIwMTE4ODgyYzE1MDEy
15
- NTFhYzFhZGFlNzdmN2M5Y2VhNWQ1ZmJjZDRiNDFjM2QxOWM2YWE=
6
+ metadata.gz: 1e41922419e9d96624ced8d265301dd1bf4aa2bb487b083a768ffb3282280e5c2f5a8551179016e87b53bd681bd26af9be69bb22e710db1b3bc0d77c3a53ef5d
7
+ data.tar.gz: c02b8907da2873100ba44f4abeee8ff9c2034869adea96406b69a8ff79357339bfdfc5da8c1d172d92b976f8232de0436d7d14104019405573e8ef7aaa6150fd
data/Appraisals CHANGED
@@ -92,9 +92,11 @@ end
92
92
  if RUBY_VERSION >= '2.2.2'
93
93
  appraise 'contrib' do
94
94
  gem 'elasticsearch-transport'
95
+ gem 'grape'
96
+ gem 'rack'
97
+ gem 'rack-test'
95
98
  gem 'redis'
96
99
  gem 'hiredis'
97
- gem 'rack-test'
98
100
  gem 'sinatra'
99
101
  gem 'sqlite3'
100
102
  gem 'activerecord'
@@ -105,8 +107,8 @@ else
105
107
  gem 'elasticsearch-transport'
106
108
  gem 'redis'
107
109
  gem 'hiredis'
108
- gem 'rack-test', '0.6.2'
109
110
  gem 'rack', '1.4.7'
111
+ gem 'rack-test'
110
112
  gem 'sinatra', '1.4.5'
111
113
  gem 'sqlite3'
112
114
  gem 'activerecord', '3.2.22.5'
data/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  ## Documentation
6
6
 
7
- You can find the latest documentation in the Datadog's [private repository][docs]
7
+ You can find the latest documentation on [rubydoc.info][docs]
8
8
 
9
- [docs]: http://gems.datadoghq.com/trace/docs/
9
+ [docs]: http://www.rubydoc.info/github/DataDog/dd-trace-rb/
10
10
 
11
11
  ## Getting started
12
12
 
@@ -25,6 +25,12 @@ If you're using ``Bundler``, just update your ``Gemfile`` as follows:
25
25
  gem 'ddtrace'
26
26
  ```
27
27
 
28
+ To use a development/preview version, use:
29
+
30
+ ```ruby
31
+ gem 'ddtrace', :github => 'DataDog/dd-trace-rb', :branch => 'me/my-feature-branch'
32
+ ```
33
+
28
34
  ### Quickstart (manual instrumentation)
29
35
 
30
36
  If you aren't using a supported framework instrumentation, you may want to to manually instrument your code.
@@ -34,7 +40,7 @@ to trace requests to the home page:
34
40
  ```ruby
35
41
  require 'ddtrace'
36
42
  require 'sinatra'
37
- require 'activerecord'
43
+ require 'active_record'
38
44
 
39
45
  # a generic tracer that you can use across your application
40
46
  tracer = Datadog.tracer
@@ -59,29 +65,30 @@ to trace requests to the home page:
59
65
  end
60
66
  ```
61
67
 
62
- ### Monkey patching
68
+ ### Quickstart (integration)
63
69
 
64
- By default, our monkey-patching is not active, you need to
65
- explicitly activate it by calling `Datadog::Monkey.patch_all`
66
- or `Datadog::Monkey.patch_module`
67
-
68
- This ultimately allows you to enable or disable tracing on a per-library basis.
69
-
70
- The example below shows the Redis case, but any other non-rails library
71
- should work the same way:
70
+ Instead of doing the above manually, whenever an integration is available,
71
+ you can activate it. The example above would become:
72
72
 
73
73
  ```ruby
74
-
75
- require 'redis'
76
74
  require 'ddtrace'
75
+ require 'sinatra'
76
+ require 'active_record'
77
77
 
78
- Datadog::Monkey.patch_all # you need to explicitly patch it
78
+ Datadog::Monkey.patch_all # monkey patch all available integrations
79
79
 
80
- # now do your Redis stuff, eg:
81
- redis = Redis.new
82
- redis.set 'foo', 'bar' # traced!
80
+ # now write your code naturally, it's traced automatically
81
+ get '/' do
82
+ @posts = Posts.order(created_at: :desc).limit(10)
83
+ erb :index
84
+ end
83
85
  ```
84
86
 
87
+ To know if a given framework or lib is supported by our client,
88
+ please consult our [integrations][contrib] list.
89
+
90
+ [contrib]: http://www.rubydoc.info/github/DataDog/dd-trace-rb/Datadog/Contrib
91
+
85
92
  ## Development
86
93
 
87
94
  ### Testing
@@ -91,21 +98,31 @@ Configure your environment through:
91
98
  $ bundle install
92
99
  $ appraisal install
93
100
 
94
- You can launch tests using the following rake command:
101
+ You can launch tests using the following Rake commands:
95
102
 
96
- $ rake test:main # tracer tests
97
- $ appraisal rails<version>-<database>rake test:rails # tests Rails matrix
98
- $ appraisal contrib rake test:redis # tests Redis integration
99
- $ appraisal contrib rake test:monkey # tests monkey patching
103
+ $ rake test:main # tracer tests
104
+ $ appraisal rails<version>-<database> rake test:rails # tests Rails matrix
105
+ $ appraisal contrib rake test:redis # tests Redis integration
106
+ ...
100
107
 
101
- Available appraisals are:
108
+ Run ``rake --tasks`` for the list of available Rake tasks.
102
109
 
103
- * ``rails{3,4,5}-postgres``: Rails with PostgreSQL
104
- * ``rails{3,4,5}-mysql2``: Rails with MySQL
105
- * ``contrib``: Other contrib libraries (Redis, ...)
110
+ Available appraisals are:
106
111
 
107
- jRuby includes only Rails 3.x and 4.x because the current implementation of jdbc drivers, don't support
108
- ActiveRecord 5.x.
112
+ * ``contrib``: default for integrations
113
+ * ``contrib-old``: default for integrations, with version suited for old Ruby (possibly unmaintained) versions
114
+ * ``rails3-mysql2``: Rails3 with Mysql
115
+ * ``rails3-postgres``: Rails 3 with Postgres
116
+ * ``rails3-postgres-redis``: Rails 3 with Postgres and Redis
117
+ * ``rails3-postgres-sidekiq``: Rails 3 with Postgres and Sidekiq
118
+ * ``rails4-mysql2``: Rails4 with Mysql
119
+ * ``rails4-postgres``: Rails 4 with Postgres
120
+ * ``rails4-postgres-redis``: Rails 4 with Postgres and Redis
121
+ * ``rails4-postgres-sidekiq``: Rails 4 with Postgres and Sidekiq
122
+ * ``rails5-mysql2``: Rails5 with Mysql
123
+ * ``rails5-postgres``: Rails 5 with Postgres
124
+ * ``rails5-postgres-redis``: Rails 5 with Postgres and Redis
125
+ * ``rails5-postgres-sidekiq``: Rails 5 with Postgres and Sidekiq
109
126
 
110
127
  The test suite requires many backing services (PostgreSQL, MySQL, Redis, ...) and we're using
111
128
  ``docker`` and ``docker-compose`` to start these services in the CI.
data/Rakefile CHANGED
@@ -44,7 +44,7 @@ namespace :test do
44
44
  t.test_files = FileList['test/contrib/rails/**/*active_job*_test.rb']
45
45
  end
46
46
 
47
- [:elasticsearch, :http, :redis, :sinatra, :sidekiq].each do |contrib|
47
+ [:elasticsearch, :http, :redis, :sinatra, :sidekiq, :rack, :grape].each do |contrib|
48
48
  Rake::TestTask.new(contrib) do |t|
49
49
  t.libs << %w[test lib]
50
50
  t.test_files = FileList["test/contrib/#{contrib}/*_test.rb"]
@@ -132,11 +132,14 @@ task :ci do
132
132
  sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:redis'
133
133
  sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:sinatra'
134
134
  sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:sidekiq'
135
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:rack'
136
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:grape'
135
137
  sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:monkey'
136
138
  sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:elasticsearch'
137
139
  sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:http'
138
140
  sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:redis'
139
141
  sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:sinatra'
142
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:rack'
140
143
  sh 'rvm $SIDEKIQ_OLD_VERSIONS --verbose do appraisal contrib-old rake test:sidekiq'
141
144
  when 2
142
145
  sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails3-mysql2 rake test:rails'
@@ -21,10 +21,17 @@ We strongly suggest pinning the version of the library you deploy.
21
21
  ## Quickstart
22
22
 
23
23
  The easiest way to get started with the tracing client is to instrument your web application. ``ddtrace`` gem
24
- provides auto instrumentation for the following web frameworks:
24
+ provides auto instrumentation for the following web frameworks and libraries:
25
25
 
26
26
  * [Ruby on Rails](#label-Ruby+on+Rails)
27
+ * [Sidekiq](#label-Sidekiq)
27
28
  * [Sinatra](#label-Sinatra)
29
+ * [Rack](#label-Rack)
30
+ * [Grape](#label-Grape)
31
+ * [Active Record](#label-Active+Record)
32
+ * [Elastic Search](#label-Elastic+Search)
33
+ * [Net/HTTP](#label-Net/HTTP)
34
+ * [Redis](#label-Redis)
28
35
 
29
36
  ## Web Frameworks
30
37
 
@@ -45,6 +52,7 @@ To enable the Rails auto instrumentation, create an initializer file in your ``c
45
52
  }
46
53
 
47
54
  If you're using Rails 3 or higher, your application will be listed as ``my-rails-app`` in your service list.
55
+ To integrate Rails instrumentation with third-party libraries such as Grape, please check the available settings below.
48
56
 
49
57
  #### Configure the tracer with initializers
50
58
 
@@ -57,9 +65,11 @@ of the Datadog tracer, you can override the following defaults:
57
65
  enabled: true,
58
66
  auto_instrument: false,
59
67
  auto_instrument_redis: false,
68
+ auto_instrument_grape: false,
60
69
  default_service: 'rails-app',
61
- default_database_service: 'postgresql',
70
+ default_controller_service: 'rails-controller',
62
71
  default_cache_service: 'rails-cache',
72
+ default_database_service: 'postgresql',
63
73
  template_base_path: 'views/',
64
74
  tracer: Datadog.tracer,
65
75
  debug: false,
@@ -77,10 +87,15 @@ Available settings are:
77
87
  with a condition, to enable the auto-instrumentation only for particular environments (production, staging, etc...).
78
88
  * ``auto_instrument_redis``: if set to ``true`` Redis calls will be traced as such. Calls to Redis cache may be
79
89
  still instrumented but you will not have the detail of low-level Redis calls.
90
+ * ``auto_instrument_grape``: if set to ``true`` and you're using a Grape application, all calls to your endpoints are
91
+ traced, including filters execution.
80
92
  * ``default_service``: set the service name used when tracing application requests. Defaults to ``rails-app``
93
+ * ``default_controller_service``: set the service name used when tracing a Rails action controller. Defaults to ``rails-controller``
94
+ * ``default_cache_service``: set the cache service name used when tracing cache activity. Defaults to ``rails-cache``
81
95
  * ``default_database_service``: set the database service name used when tracing database activity. Defaults to the
82
96
  current adapter name, so if you're using PostgreSQL it will be ``postgres``.
83
- * ``default_cache_service``: set the cache service name used when tracing cache activity. Defaults to ``rails-cache``
97
+ * ``default_grape_service``: set the service name used when tracing a Grape application mounted in your Rails router.
98
+ Defaults to ``grape``
84
99
  * ``template_base_path``: used when the template name is parsed in the auto instrumented code. If you don't store
85
100
  your templates in the ``views/`` folder, you may need to change this value
86
101
  * ``tracer``: is the global tracer used by the tracing application. Usually you don't need to change that value
@@ -129,20 +144,82 @@ Available settings are:
129
144
  * ``trace_agent_hostname``: set the hostname of the trace agent.
130
145
  * ``trace_agent_port``: set the port the trace agent is listening on.
131
146
 
147
+ ### Rack
148
+
149
+ The Rack integration provides a middleware that traces all requests before they reach the underlying framework
150
+ or application. It responds to the Rack minimal interface, providing reasonable values that can be
151
+ retrieved at the Rack level.
152
+ To start using the middleware in your generic Rack application, add it to your ``config.ru``:
153
+
154
+ # config.ru example
155
+ use Datadog::Contrib::Rack::TraceMiddleware
156
+
157
+ app = proc do |env|
158
+ [ 200, {'Content-Type' => 'text/plain'}, "OK" ]
159
+ end
160
+
161
+ run app
162
+
163
+ #### Configure the tracer
164
+
165
+ To modify the default middleware configuration, you can use middleware options as follows:
166
+
167
+ # config.ru example
168
+ use Datadog::Contrib::Rack::TraceMiddleware default_service: 'rack-stack'
169
+
170
+ app = proc do |env|
171
+ [ 200, {'Content-Type' => 'text/plain'}, "OK" ]
172
+ end
173
+
174
+ run app
175
+
176
+ Available settings are:
177
+
178
+ * ``tracer`` (default: ``Datadog.tracer``): set the tracer to use. Usually you don't need to change that value
179
+ unless you're already using a different initialized tracer somewhere else. If you need to change some
180
+ configurations such as the ``hostname``, use the [Tracer#configure](Datadog/Tracer.html#configure-instance_method)
181
+ method before adding the middleware
182
+ * ``default_service`` (default: ``rack``): set the service name used when the Rack request is traced
183
+
132
184
  ## Other libraries
133
185
 
134
- ### Redis
186
+ ### Grape
135
187
 
136
- The Redis integration will trace simple calls as well as pipelines.
188
+ The Grape integration adds the instrumentation to Grape endpoints and filters. This integration can work side by side
189
+ with other integrations like Rack and Rails. To activate your integration, use the ``patch_module`` function before
190
+ defining your Grape application:
137
191
 
138
- require 'redis'
192
+ # api.rb
193
+ require 'grape'
139
194
  require 'ddtrace'
140
195
 
141
- Datadog::Monkey.patch_module(:redis) # you need to explicitly patch it
196
+ Datadog::Monkey.patch_module(:grape)
142
197
 
143
- # now do your Redis stuff, eg:
144
- redis = Redis.new
145
- redis.set 'foo', 'bar' # traced!
198
+ # then define your application
199
+ class RackTestingAPI < Grape::API
200
+ desc 'main endpoint'
201
+ get :success do
202
+ 'Hello world!'
203
+ end
204
+ end
205
+
206
+ ### Active Record
207
+
208
+ Most of the time, Active Record is set up as part of a web framework (Rails, Sinatra...)
209
+ however it can be set up alone:
210
+
211
+ require 'tmpdir'
212
+ require 'sqlite3'
213
+ require 'active_record'
214
+ require 'ddtrace'
215
+
216
+ Datadog::Monkey.patch_module(:active_record) # explicitly patch it
217
+
218
+ Dir::Tmpname.create(['test', '.sqlite']) do |db|
219
+ conn = ActiveRecord::Base.establish_connection(adapter: 'sqlite3',
220
+ database: db)
221
+ conn.connection.execute('SELECT 42') # traced!
222
+ end
146
223
 
147
224
  ### Elastic Search
148
225
 
@@ -152,7 +229,7 @@ in the ``Client`` object:
152
229
  require 'elasticsearch/transport'
153
230
  require 'ddtrace'
154
231
 
155
- Datadog::Monkey.patch_module(:elasticsearch) # you need to explicitly patch it
232
+ Datadog::Monkey.patch_module(:elasticsearch) # explicitly patch it
156
233
 
157
234
  # now do your Elastic Search stuff, eg:
158
235
  client = Elasticsearch::Client.new url: 'http://127.0.0.1:9200'
@@ -170,7 +247,7 @@ Net::HTTP module.
170
247
  require 'net/http'
171
248
  require 'ddtrace'
172
249
 
173
- Datadog::Monkey.patch_module(:http) # you need to explicitly patch it
250
+ Datadog::Monkey.patch_module(:http) # explicitly patch it
174
251
 
175
252
  Net::HTTP.start('127.0.0.1', 8080) do |http|
176
253
  request = Net::HTTP::Get.new '/index'
@@ -179,6 +256,19 @@ Net::HTTP module.
179
256
 
180
257
  content = Net::HTTP.get(URI('http://127.0.0.1/index.html'))
181
258
 
259
+ ### Redis
260
+
261
+ The Redis integration will trace simple calls as well as pipelines.
262
+
263
+ require 'redis'
264
+ require 'ddtrace'
265
+
266
+ Datadog::Monkey.patch_module(:redis) # explicitly patch it
267
+
268
+ # now do your Redis stuff, eg:
269
+ redis = Redis.new
270
+ redis.set 'foo', 'bar' # traced!
271
+
182
272
  ### Sidekiq
183
273
 
184
274
  The Sidekiq integration is a server-side middleware which will trace job
@@ -242,7 +332,7 @@ to trace requests to the home page:
242
332
 
243
333
  require 'ddtrace'
244
334
  require 'sinatra'
245
- require 'activerecord'
335
+ require 'active_record'
246
336
 
247
337
  # a generic tracer that you can use across your application
248
338
  tracer = Datadog.tracer
@@ -372,7 +462,7 @@ for the first time:
372
462
 
373
463
  require 'ddtrace'
374
464
  require 'sinatra'
375
- require 'activerecord'
465
+ require 'active_record'
376
466
 
377
467
  # enable debug mode
378
468
  Datadog::Tracer.debug_logging = true
@@ -389,6 +479,23 @@ for the first time:
389
479
  Remember that the debug mode may affect your application performance and so it must not be used
390
480
  in a production environment.
391
481
 
482
+ ### Environment and tags
483
+
484
+ By default, the trace agent (not this library, but the program running in
485
+ the background collecting data from various clients) uses the tags
486
+ set in the agent config file, see our
487
+ [environments tutorial](https://app.datadoghq.com/apm/docs/tutorials/environments) for details.
488
+
489
+ These values can be overridden at the tracer level:
490
+
491
+ Datadog.tracer.set_tags('env' => 'prod')
492
+
493
+ This enables you to set this value on a per tracer basis, so you can have
494
+ for example several applications reporting for different environments on the same host.
495
+
496
+ Ultimately, tags can be set per span, but `env` should typically be the same
497
+ for all spans belonging to a given trace.
498
+
392
499
  ### Sampling
393
500
 
394
501
  `ddtrace` can perform trace sampling. While the trace agent already samples
@@ -401,6 +508,67 @@ overhead.
401
508
  sampler = Datadog::RateSampler.new(0.5) # sample 50% of the traces
402
509
  Datadog.tracer.configure(sampler: sampler)
403
510
 
511
+ ### Distributed Tracing
512
+
513
+ To trace requests across hosts, the spans on the secondary hosts must be linked together by setting ``trace_id`` and ``parent_id``:
514
+
515
+ def request_on_secondary_host(parent_trace_id, parent_span_id)
516
+ tracer.trace('web.request') do |span|
517
+ span.parent_id = parent_span_id
518
+ span.trace_id = parent_trace_id
519
+
520
+ # perform user code
521
+ end
522
+ end
523
+
524
+ Users can pass along the ``parent_trace_id`` and ``parent_span_id`` via whatever method best matches the RPC framework.
525
+
526
+ Below is an example using Net/HTTP and Sinatra, where we bypass the integrations to demo how distributed tracing works.
527
+
528
+ On the client:
529
+
530
+ require 'net/http'
531
+ require 'ddtrace'
532
+
533
+ # Do *not* monkey patch here, we do it "manually", to demo the feature
534
+ # Datadog::Monkey.patch_module(:http)
535
+
536
+ uri = URI('http://localhost:4567/')
537
+
538
+ Datadog.tracer.trace('web.call') do |span|
539
+ req = Net::HTTP::Get.new(uri)
540
+ req['x-ddtrace-parent_trace_id'] = span.trace_id.to_s
541
+ req['x-ddtrace-parent_span_id'] = span.span_id.to_s
542
+
543
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
544
+ http.request(req)
545
+ end
546
+
547
+ puts response.body
548
+ end
549
+
550
+ On the server:
551
+
552
+ require 'sinatra'
553
+ require 'ddtrace'
554
+
555
+ # Do *not* use Sinatra integration, we do it "manually", to demo the feature
556
+ # require 'ddtrace/contrib/sinatra/tracer'
557
+
558
+ get '/' do
559
+ parent_trace_id = request.env['HTTP_X_DDTRACE_PARENT_TRACE_ID']
560
+ parent_span_id = request.env['HTTP_X_DDTRACE_PARENT_SPAN_ID']
561
+
562
+ Datadog.tracer.trace('web.work') do |span|
563
+ if parent_trace_id && parent_span_id
564
+ span.trace_id = parent_trace_id.to_i
565
+ span.parent_id = parent_span_id.to_i
566
+ end
567
+
568
+ 'Hello world!'
569
+ end
570
+ end
571
+
404
572
  ### Supported Versions
405
573
 
406
574
  #### Ruby interpreters
@@ -3,13 +3,14 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "elasticsearch-transport"
6
+ gem "grape"
7
+ gem "rack"
8
+ gem "rack-test"
6
9
  gem "redis"
7
10
  gem "hiredis"
8
- gem "rack-test"
9
11
  gem "sinatra"
10
- gem 'sqlite3'
12
+ gem "sqlite3"
11
13
  gem "activerecord"
12
14
  gem "sidekiq"
13
- gem "activerecord"
14
15
 
15
16
  gemspec :path => "../"
@@ -5,9 +5,10 @@ source "https://rubygems.org"
5
5
  gem "elasticsearch-transport"
6
6
  gem "redis"
7
7
  gem "hiredis"
8
- gem "rack-test", "0.6.2"
9
8
  gem "rack", "1.4.7"
9
+ gem "rack-test"
10
10
  gem "sinatra", "1.4.5"
11
+ gem "sqlite3"
11
12
  gem "activerecord", "3.2.22.5"
12
13
  gem "sidekiq", "4.0.0"
13
14
 
@@ -31,13 +31,29 @@ if defined?(Rails::VERSION)
31
31
  require 'ddtrace/contrib/rails/framework'
32
32
 
33
33
  module Datadog
34
- # Run the auto instrumentation directly after initializers in
35
- # `config/initializers` are executed
34
+ # Railtie class initializes
36
35
  class Railtie < Rails::Railtie
36
+ # auto instrument Rails and third party components after
37
+ # the framework initialization
38
+ options = {}
37
39
  config.after_initialize do |app|
38
40
  Datadog::Contrib::Rails::Framework.configure(config: app.config)
39
41
  Datadog::Contrib::Rails::Framework.auto_instrument()
40
42
  Datadog::Contrib::Rails::Framework.auto_instrument_redis()
43
+ Datadog::Contrib::Rails::Framework.auto_instrument_grape()
44
+
45
+ # override Rack Middleware configurations with Rails
46
+ options.update(::Rails.configuration.datadog_trace)
47
+ end
48
+
49
+ # Configure datadog settings before building the middleware stack.
50
+ # This is required because the middleware stack is frozen after
51
+ # the initialization and so it's too late to add our tracing
52
+ # functionalities.
53
+ initializer :datadog_config, before: :build_middleware_stack do |app|
54
+ app.config.middleware.insert_before(
55
+ 0, Datadog::Contrib::Rack::TraceMiddleware, options
56
+ )
41
57
  end
42
58
  end
43
59
  end
@@ -18,6 +18,7 @@ module Datadog
18
18
  begin
19
19
  require 'ddtrace/contrib/rails/utils'
20
20
  require 'ddtrace/ext/sql'
21
+ require 'ddtrace/ext/app_types'
21
22
 
22
23
  patch_active_record()
23
24
 
@@ -50,11 +51,16 @@ module Datadog
50
51
  end
51
52
 
52
53
  def self.tracer
54
+ return Datadog.tracer unless datadog_trace
53
55
  @tracer ||= datadog_trace.fetch(:tracer)
54
56
  end
55
57
 
56
58
  def self.database_service
57
- @database_service ||= datadog_trace.fetch(:default_database_service, adapter_name())
59
+ @database_service ||= if defined?(::Sinatra)
60
+ datadog_trace.fetch(:default_database_service, adapter_name())
61
+ else
62
+ adapter_name()
63
+ end
58
64
  if @database_service
59
65
  tracer().set_service_info(@database_service, 'sinatra',
60
66
  Datadog::Ext::AppTypes::DB)
@@ -0,0 +1,164 @@
1
+ require 'ddtrace/ext/http'
2
+ require 'ddtrace/ext/errors'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ module Grape
7
+ # rubocop:disable Metrics/ModuleLength
8
+ # Endpoint module includes a list of subscribers to create
9
+ # traces when a Grape endpoint is hit
10
+ module Endpoint
11
+ KEY_RUN = 'datadog_grape_endpoint_run'.freeze
12
+ KEY_RENDER = 'datadog_grape_endpoint_render'.freeze
13
+
14
+ def self.subscribe
15
+ # Grape is instrumented only if it's available
16
+ return unless defined?(::Grape) && defined?(::ActiveSupport::Notifications)
17
+
18
+ # subscribe when a Grape endpoint is hit
19
+ ::ActiveSupport::Notifications.subscribe('endpoint_run.grape.start_process') do |*args|
20
+ endpoint_start_process(*args)
21
+ end
22
+ ::ActiveSupport::Notifications.subscribe('endpoint_run.grape') do |*args|
23
+ endpoint_run(*args)
24
+ end
25
+ ::ActiveSupport::Notifications.subscribe('endpoint_render.grape.start_render') do |*args|
26
+ endpoint_start_render(*args)
27
+ end
28
+ ::ActiveSupport::Notifications.subscribe('endpoint_render.grape') do |*args|
29
+ endpoint_render(*args)
30
+ end
31
+ ::ActiveSupport::Notifications.subscribe('endpoint_run_filters.grape') do |*args|
32
+ endpoint_run_filters(*args)
33
+ end
34
+ end
35
+
36
+ def self.endpoint_start_process(*)
37
+ return if Thread.current[KEY_RUN]
38
+
39
+ # retrieve the tracer from the PIN object
40
+ pin = Datadog::Pin.get_from(::Grape)
41
+ return unless pin && pin.enabled?
42
+
43
+ # store the beginning of a trace
44
+ tracer = pin.tracer
45
+ service = pin.service
46
+ type = Datadog::Ext::HTTP::TYPE
47
+ tracer.trace('grape.endpoint_run', service: service, span_type: type)
48
+
49
+ Thread.current[KEY_RUN] = true
50
+ rescue StandardError => e
51
+ Datadog::Tracer.log.error(e.message)
52
+ end
53
+
54
+ def self.endpoint_run(name, start, finish, id, payload)
55
+ return unless Thread.current[KEY_RUN]
56
+ Thread.current[KEY_RUN] = false
57
+
58
+ # retrieve the tracer from the PIN object
59
+ pin = Datadog::Pin.get_from(::Grape)
60
+ return unless pin && pin.enabled?
61
+
62
+ tracer = pin.tracer
63
+ span = tracer.active_span()
64
+ return unless span
65
+
66
+ begin
67
+ # collect endpoint details
68
+ api_view = payload[:endpoint].options[:for].to_s
69
+ path = payload[:endpoint].options[:path].join('/')
70
+ resource = "#{api_view}##{path}"
71
+ span.resource = resource
72
+
73
+ # set the request span resource if it's a `rack.request` span
74
+ request_span = payload[:env][:datadog_rack_request_span]
75
+ if !request_span.nil? && request_span.name == 'rack.request'
76
+ request_span.resource = resource
77
+ end
78
+
79
+ # catch thrown exceptions
80
+ span.set_error(payload[:exception_object]) unless payload[:exception_object].nil?
81
+
82
+ # ovverride the current span with this notification values
83
+ span.set_tag('grape.route.endpoint', api_view)
84
+ span.set_tag('grape.route.path', path)
85
+ ensure
86
+ span.start_time = start
87
+ span.finish_at(finish)
88
+ end
89
+ rescue StandardError => e
90
+ Datadog::Tracer.log.error(e.message)
91
+ end
92
+
93
+ def self.endpoint_start_render(*)
94
+ return if Thread.current[KEY_RENDER]
95
+
96
+ # retrieve the tracer from the PIN object
97
+ pin = Datadog::Pin.get_from(::Grape)
98
+ return unless pin && pin.enabled?
99
+
100
+ # store the beginning of a trace
101
+ tracer = pin.tracer
102
+ service = pin.service
103
+ type = Datadog::Ext::HTTP::TYPE
104
+ tracer.trace('grape.endpoint_render', service: service, span_type: type)
105
+
106
+ Thread.current[KEY_RENDER] = true
107
+ rescue StandardError => e
108
+ Datadog::Tracer.log.error(e.message)
109
+ end
110
+
111
+ def self.endpoint_render(name, start, finish, id, payload)
112
+ return unless Thread.current[KEY_RENDER]
113
+ Thread.current[KEY_RENDER] = false
114
+
115
+ # retrieve the tracer from the PIN object
116
+ pin = Datadog::Pin.get_from(::Grape)
117
+ return unless pin && pin.enabled?
118
+
119
+ tracer = pin.tracer
120
+ span = tracer.active_span()
121
+ return unless span
122
+
123
+ # catch thrown exceptions
124
+ begin
125
+ span.set_error(payload[:exception_object]) unless payload[:exception_object].nil?
126
+ ensure
127
+ span.start_time = start
128
+ span.finish_at(finish)
129
+ end
130
+ rescue StandardError => e
131
+ Datadog::Tracer.log.error(e.message)
132
+ end
133
+
134
+ def self.endpoint_run_filters(name, start, finish, id, payload)
135
+ # retrieve the tracer from the PIN object
136
+ pin = Datadog::Pin.get_from(::Grape)
137
+ return unless pin && pin.enabled?
138
+
139
+ # safe-guard to prevent submitting empty filters
140
+ zero_length = (finish - start).zero?
141
+ filters = payload[:filters]
142
+ type = payload[:type]
143
+ return if (!filters || filters.empty?) || !type || zero_length
144
+
145
+ tracer = pin.tracer
146
+ service = pin.service
147
+ type = Datadog::Ext::HTTP::TYPE
148
+ span = tracer.trace('grape.endpoint_run_filters', service: service, span_type: type)
149
+
150
+ begin
151
+ # catch thrown exceptions
152
+ span.set_error(payload[:exception_object]) unless payload[:exception_object].nil?
153
+ span.set_tag('grape.filter.type', type.to_s)
154
+ ensure
155
+ span.start_time = start
156
+ span.finish_at(finish)
157
+ end
158
+ rescue StandardError => e
159
+ Datadog::Tracer.log.error(e.message)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,73 @@
1
+ module Datadog
2
+ module Contrib
3
+ module Grape
4
+ SERVICE = 'grape'.freeze
5
+
6
+ # Patcher that introduces more instrumentation for Grape endpoints, so that
7
+ # new signals are executed at the beginning of each step (filters, render and run)
8
+ module Patcher
9
+ @patched = false
10
+
11
+ module_function
12
+
13
+ def patched?
14
+ @patched
15
+ end
16
+
17
+ def patch
18
+ if !@patched && defined?(::Grape)
19
+ begin
20
+ # do not require these by default, but only when actually patching
21
+ require 'ddtrace'
22
+ require 'ddtrace/ext/app_types'
23
+ require 'ddtrace/contrib/grape/endpoint'
24
+
25
+ @patched = true
26
+ # patch all endpoints
27
+ patch_endpoint_run()
28
+ patch_endpoint_render()
29
+
30
+ # attach a PIN object globally and set the service once
31
+ pin = Datadog::Pin.new(SERVICE, app: 'grape', app_type: Datadog::Ext::AppTypes::WEB)
32
+ pin.onto(::Grape)
33
+ if pin.tracer && pin.service
34
+ pin.tracer.set_service_info(pin.service, 'grape', pin.app_type)
35
+ end
36
+
37
+ # subscribe to ActiveSupport events
38
+ Datadog::Contrib::Grape::Endpoint.subscribe()
39
+ rescue StandardError => e
40
+ Datadog::Tracer.log.error("Unable to apply Grape integration: #{e}")
41
+ end
42
+ end
43
+ @patched
44
+ end
45
+
46
+ def patch_endpoint_run
47
+ ::Grape::Endpoint.class_eval do
48
+ alias_method :run_without_datadog, :run
49
+ def run(*args)
50
+ ::ActiveSupport::Notifications.instrument('endpoint_run.grape.start_process')
51
+ run_without_datadog(*args)
52
+ end
53
+ end
54
+ end
55
+
56
+ def patch_endpoint_render
57
+ ::Grape::Endpoint.class_eval do
58
+ class << self
59
+ alias_method :generate_api_method_without_datadog, :generate_api_method
60
+ def generate_api_method(*params, &block)
61
+ method_api = generate_api_method_without_datadog(*params, &block)
62
+ proc do |*args|
63
+ ::ActiveSupport::Notifications.instrument('endpoint_render.grape.start_render')
64
+ method_api.call(*args)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,103 @@
1
+ require 'ddtrace/ext/app_types'
2
+ require 'ddtrace/ext/http'
3
+
4
+ module Datadog
5
+ module Contrib
6
+ # Rack module includes middlewares that are required to trace any framework
7
+ # and application built on top of Rack.
8
+ module Rack
9
+ # TraceMiddleware ensures that the Rack Request is properly traced
10
+ # from the beginning to the end. The middleware adds the request span
11
+ # in the Rack environment so that it can be retrieved by the underlying
12
+ # application. If request tags are not set by the app, they will be set using
13
+ # information available at the Rack level.
14
+ class TraceMiddleware
15
+ DEFAULT_CONFIG = {
16
+ tracer: Datadog.tracer,
17
+ default_service: 'rack'
18
+ }.freeze
19
+
20
+ def initialize(app, options = {})
21
+ # update options with our configuration, unless it's already available
22
+ options[:tracer] ||= DEFAULT_CONFIG[:tracer]
23
+ options[:default_service] ||= DEFAULT_CONFIG[:default_service]
24
+
25
+ @app = app
26
+ @options = options
27
+ end
28
+
29
+ def configure
30
+ # ensure that the configuration is executed only once
31
+ return if @tracer && @service
32
+
33
+ # retrieve the current tracer and service
34
+ @tracer = @options.fetch(:tracer)
35
+ @service = @options.fetch(:default_service)
36
+
37
+ # configure the Rack service
38
+ @tracer.set_service_info(
39
+ @service,
40
+ 'rack',
41
+ Datadog::Ext::AppTypes::WEB
42
+ )
43
+ end
44
+
45
+ def call(env)
46
+ # configure the Rack middleware once
47
+ configure()
48
+
49
+ # start a new request span and attach it to the current Rack environment;
50
+ # we must ensure that the span `resource` is set later
51
+ request_span = @tracer.trace(
52
+ 'rack.request',
53
+ service: @service,
54
+ resource: nil,
55
+ span_type: Datadog::Ext::HTTP::TYPE
56
+ )
57
+ env[:datadog_rack_request_span] = request_span
58
+
59
+ # call the rest of the stack
60
+ status, headers, response = @app.call(env)
61
+ rescue StandardError => e
62
+ # catch exceptions that may be raised in the middleware chain
63
+ # Note: if a middleware catches an Exception without re raising,
64
+ # the Exception cannot be recorded here
65
+ request_span.set_error(e)
66
+ raise e
67
+ ensure
68
+ # the source of truth in Rack is the PATH_INFO key that holds the
69
+ # URL for the current request; some framework may override that
70
+ # value, especially during exception handling and because of that
71
+ # we prefer using the `REQUEST_URI` if this is available.
72
+ # NOTE: `REQUEST_URI` is Rails specific and may not apply for other frameworks
73
+ url = env['REQUEST_URI'] || env['PATH_INFO']
74
+
75
+ # Rack is a really low level interface and it doesn't provide any
76
+ # advanced functionality like routers. Because of that, we assume that
77
+ # the underlying framework or application has more knowledge about
78
+ # the result for this request; `resource` and `tags` are expected to
79
+ # be set in another level but if they're missing, reasonable defaults
80
+ # are used.
81
+ request_span.resource = "#{env['REQUEST_METHOD']} #{status}".strip unless request_span.resource
82
+ request_span.set_tag('http.method', env['REQUEST_METHOD']) if request_span.get_tag('http.method').nil?
83
+ request_span.set_tag('http.url', url) if request_span.get_tag('http.url').nil?
84
+ request_span.set_tag('http.status_code', status) if request_span.get_tag('http.status_code').nil? && status
85
+
86
+ # detect if the status code is a 5xx and flag the request span as an error
87
+ # unless it has been already set by the underlying framework
88
+ if status.to_s.start_with?('5') && request_span.status.zero?
89
+ request_span.status = 1
90
+ # in any case we don't touch the stacktrace if it has been set
91
+ if request_span.get_tag(Datadog::Ext::Errors::STACK).nil?
92
+ request_span.set_tag(Datadog::Ext::Errors::STACK, caller().join("\n"))
93
+ end
94
+ end
95
+
96
+ request_span.finish()
97
+
98
+ [status, headers, response]
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -24,9 +24,9 @@ module Datadog
24
24
  return if Thread.current[KEY]
25
25
 
26
26
  tracer = ::Rails.configuration.datadog_trace.fetch(:tracer)
27
- service = ::Rails.configuration.datadog_trace.fetch(:default_service)
27
+ service = ::Rails.configuration.datadog_trace.fetch(:default_controller_service)
28
28
  type = Datadog::Ext::HTTP::TYPE
29
- tracer.trace('rails.request', service: service, span_type: type)
29
+ tracer.trace('rails.action_controller', service: service, span_type: type)
30
30
 
31
31
  Thread.current[KEY] = true
32
32
  rescue StandardError => e
@@ -42,9 +42,14 @@ module Datadog
42
42
  return unless span
43
43
 
44
44
  begin
45
- span.resource = "#{payload.fetch(:controller)}##{payload.fetch(:action)}"
46
- span.set_tag(Datadog::Ext::HTTP::URL, payload.fetch(:path))
47
- span.set_tag(Datadog::Ext::HTTP::METHOD, payload.fetch(:method))
45
+ resource = "#{payload.fetch(:controller)}##{payload.fetch(:action)}"
46
+ span.resource = resource
47
+
48
+ # set the parent resource if it's a `rack.request` span
49
+ if !span.parent.nil? && span.parent.name == 'rack.request'
50
+ span.parent.resource = resource
51
+ end
52
+
48
53
  span.set_tag('rails.route.action', payload.fetch(:action))
49
54
  span.set_tag('rails.route.controller', payload.fetch(:controller))
50
55
 
@@ -54,18 +59,14 @@ module Datadog
54
59
  status = payload.fetch(:status, '?').to_s
55
60
  if status.starts_with?('5')
56
61
  span.status = 1
57
- span.set_tag(Datadog::Ext::Errors::STACK, caller().join('\n'))
62
+ span.set_tag(Datadog::Ext::Errors::STACK, caller().join("\n"))
58
63
  end
59
- span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, status)
60
64
  else
61
65
  error = payload[:exception]
62
66
  span.status = 1
63
67
  span.set_tag(Datadog::Ext::Errors::TYPE, error[0])
64
68
  span.set_tag(Datadog::Ext::Errors::MSG, error[1])
65
- span.set_tag(Datadog::Ext::Errors::STACK, caller().join('\n'))
66
- # [manu,christian]: it's right to have a 500? there are cases in Rails that let
67
- # user to recover the error after this point?
68
- span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, payload.fetch(:status, '500').to_s)
69
+ span.set_tag(Datadog::Ext::Errors::STACK, caller().join("\n"))
69
70
  end
70
71
  ensure
71
72
  span.start_time = start
@@ -1,5 +1,9 @@
1
+ require 'ddtrace/pin'
1
2
  require 'ddtrace/ext/app_types'
2
3
 
4
+ require 'ddtrace/contrib/grape/endpoint'
5
+ require 'ddtrace/contrib/rack/middlewares'
6
+
3
7
  require 'ddtrace/contrib/rails/core_extensions'
4
8
  require 'ddtrace/contrib/rails/action_controller'
5
9
  require 'ddtrace/contrib/rails/action_view'
@@ -20,8 +24,11 @@ module Datadog
20
24
  enabled: true,
21
25
  auto_instrument: false,
22
26
  auto_instrument_redis: false,
27
+ auto_instrument_grape: false,
23
28
  default_service: 'rails-app',
29
+ default_controller_service: 'rails-controller',
24
30
  default_cache_service: 'rails-cache',
31
+ default_grape_service: 'grape',
25
32
  template_base_path: 'views/',
26
33
  tracer: Datadog.tracer,
27
34
  debug: false,
@@ -57,6 +64,12 @@ module Datadog
57
64
  # set default service details
58
65
  datadog_config[:tracer].set_service_info(
59
66
  datadog_config[:default_service],
67
+ 'rack',
68
+ Datadog::Ext::AppTypes::WEB
69
+ )
70
+
71
+ datadog_config[:tracer].set_service_info(
72
+ datadog_config[:default_controller_service],
60
73
  'rails',
61
74
  Datadog::Ext::AppTypes::WEB
62
75
  )
@@ -115,6 +128,19 @@ module Datadog
115
128
  end
116
129
  end
117
130
 
131
+ def self.auto_instrument_grape
132
+ return unless ::Rails.configuration.datadog_trace[:auto_instrument_grape]
133
+
134
+ # patch the Grape library so that endpoints are traced
135
+ Datadog::Monkey.patch_module(:grape)
136
+
137
+ # update the Grape pin object
138
+ pin = Datadog::Pin.get_from(::Grape)
139
+ return unless pin && pin.enabled?
140
+ pin.tracer = ::Rails.configuration.datadog_trace[:tracer]
141
+ pin.service = ::Rails.configuration.datadog_trace[:default_grape_service]
142
+ end
143
+
118
144
  # automatically instrument all Rails component
119
145
  def self.auto_instrument
120
146
  return unless ::Rails.configuration.datadog_trace[:auto_instrument]
@@ -13,19 +13,24 @@ module Datadog
13
13
  end
14
14
 
15
15
  def add(severity, message = nil, progname = nil, &block)
16
- return super unless debug?
17
-
18
- # We are in debug mode, add stack trace to help debugging
19
16
  where = ''
20
- c = caller
21
- where = "(#{c[1]}) " if c.length > 1
22
17
 
23
- if block_given?
24
- super(severity, message, progname) do
25
- "#{where}#{yield}"
18
+ # We are in debug mode, or this is an error, add stack trace to help debugging
19
+ if debug? || severity >= ::Logger::ERROR
20
+ c = caller
21
+ where = "(#{c[1]}) " if c.length > 1
22
+ end
23
+
24
+ if message.nil?
25
+ if block_given?
26
+ super(severity, message, progname) do
27
+ "[#{self.progname}] #{where}#{yield}"
28
+ end
29
+ else
30
+ super(severity, message, "[#{self.progname}] #{where}#{progname}")
26
31
  end
27
32
  else
28
- super(severity, message, "#{where}#{progname}")
33
+ super(severity, "[#{self.progname}] #{where}#{message}")
29
34
  end
30
35
  end
31
36
 
@@ -5,14 +5,21 @@ require 'thread'
5
5
  # patching code, which is required on demand, when patching.
6
6
  require 'ddtrace/contrib/active_record/patcher'
7
7
  require 'ddtrace/contrib/elasticsearch/patcher'
8
- require 'ddtrace/contrib/http/patcher'
8
+ require 'ddtrace/contrib/grape/patcher'
9
9
  require 'ddtrace/contrib/redis/patcher'
10
+ require 'ddtrace/contrib/http/patcher'
10
11
 
11
12
  module Datadog
12
13
  # Monkey is used for monkey-patching 3rd party libs.
13
14
  module Monkey
14
15
  @patched = []
15
- @autopatch_modules = { elasticsearch: true, http: true, redis: true, active_record: false }
16
+ @autopatch_modules = {
17
+ elasticsearch: true,
18
+ http: true,
19
+ redis: true,
20
+ grape: true,
21
+ active_record: false
22
+ }
16
23
  # Patchers should expose 2 methods:
17
24
  # - patch, which applies our patch if needed. Should be idempotent,
18
25
  # can be call twice but should just do nothing the second time.
@@ -21,6 +28,7 @@ module Datadog
21
28
  @patchers = { elasticsearch: Datadog::Contrib::Elasticsearch::Patcher,
22
29
  http: Datadog::Contrib::HTTP::Patcher,
23
30
  redis: Datadog::Contrib::Redis::Patcher,
31
+ grape: Datadog::Contrib::Grape::Patcher,
24
32
  active_record: Datadog::Contrib::ActiveRecord::Patcher }
25
33
  @mutex = Mutex.new
26
34
 
@@ -37,7 +45,7 @@ module Datadog
37
45
  def patch_module(m)
38
46
  @mutex.synchronize do
39
47
  patcher = @patchers[m]
40
- raise 'Unsupported module #{m}' unless patcher
48
+ raise "Unsupported module #{m}" unless patcher
41
49
  patcher.patch
42
50
  end
43
51
  end
@@ -86,23 +86,25 @@ module Datadog
86
86
  @status = 1
87
87
  @meta[Datadog::Ext::Errors::MSG] = e.message if e.respond_to?(:message) && e.message
88
88
  @meta[Datadog::Ext::Errors::TYPE] = e.class.to_s
89
- @meta[Datadog::Ext::Errors::STACK] = e.backtrace.join('\n') if e.respond_to?(:backtrace) && e.backtrace
89
+ @meta[Datadog::Ext::Errors::STACK] = e.backtrace.join("\n") if e.respond_to?(:backtrace) && e.backtrace
90
90
  end
91
91
 
92
92
  # Mark the span finished at the current time and submit it.
93
- def finish
94
- finish_at(Time.now.utc)
95
- end
96
-
97
- # Mark the span finished at the given time and submit it.
98
- def finish_at(end_time)
99
- @end_time = end_time
93
+ def finish(finish_time = nil)
94
+ return if finished?
100
95
 
96
+ @end_time = finish_time.nil? ? Time.now.utc : finish_time
101
97
  @tracer.record(self) unless @tracer.nil?
102
-
103
98
  self
104
99
  end
105
100
 
101
+ # Proxy function that flag a span as finished with the given
102
+ # timestamp. This function is used for retro-compatibility.
103
+ # DEPRECATED: remove this function in the next release
104
+ def finish_at(finish_time)
105
+ finish(finish_time)
106
+ end
107
+
106
108
  # Return whether the span is finished or not.
107
109
  def finished?
108
110
  !@end_time.nil?
@@ -1,8 +1,8 @@
1
1
  module Datadog
2
2
  module VERSION
3
3
  MAJOR = 0
4
- MINOR = 6
5
- PATCH = 2
4
+ MINOR = 7
5
+ PATCH = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
metadata CHANGED
@@ -1,103 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddtrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.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-04-07 00:00:00.000000000 Z
11
+ date: 2017-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.5'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.47'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.47'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: minitest
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - ~>
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
61
  version: '5.10'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - ~>
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '5.10'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: appraisal
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - ~>
73
+ - - "~>"
60
74
  - !ruby/object:Gem::Version
61
75
  version: '2.1'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - ~>
80
+ - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '2.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: yard
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - ~>
87
+ - - "~>"
74
88
  - !ruby/object:Gem::Version
75
89
  version: '0.9'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - ~>
94
+ - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0.9'
83
- description: ! 'ddtrace is Datadog’s tracing client for Ruby. It is used to trace
84
- requests
85
-
97
+ description: |
98
+ ddtrace is Datadog’s tracing client for Ruby. It is used to trace requests
86
99
  as they flow across web servers, databases and microservices so that developers
87
-
88
100
  have great visiblity into bottlenecks and troublesome requests.
89
-
90
- '
91
101
  email:
92
102
  - dev@datadoghq.com
93
103
  executables: []
94
104
  extensions: []
95
105
  extra_rdoc_files: []
96
106
  files:
97
- - .env
98
- - .gitignore
99
- - .rubocop.yml
100
- - .yardopts
107
+ - ".env"
108
+ - ".gitignore"
109
+ - ".rubocop.yml"
110
+ - ".yardopts"
101
111
  - Appraisals
102
112
  - Gemfile
103
113
  - LICENSE
@@ -126,7 +136,10 @@ files:
126
136
  - lib/ddtrace/contrib/active_record/patcher.rb
127
137
  - lib/ddtrace/contrib/elasticsearch/patcher.rb
128
138
  - lib/ddtrace/contrib/elasticsearch/quantize.rb
139
+ - lib/ddtrace/contrib/grape/endpoint.rb
140
+ - lib/ddtrace/contrib/grape/patcher.rb
129
141
  - lib/ddtrace/contrib/http/patcher.rb
142
+ - lib/ddtrace/contrib/rack/middlewares.rb
130
143
  - lib/ddtrace/contrib/rails/action_controller.rb
131
144
  - lib/ddtrace/contrib/rails/action_view.rb
132
145
  - lib/ddtrace/contrib/rails/active_record.rb
@@ -169,17 +182,17 @@ require_paths:
169
182
  - lib
170
183
  required_ruby_version: !ruby/object:Gem::Requirement
171
184
  requirements:
172
- - - ! '>='
185
+ - - ">="
173
186
  - !ruby/object:Gem::Version
174
187
  version: 1.9.1
175
188
  required_rubygems_version: !ruby/object:Gem::Requirement
176
189
  requirements:
177
- - - ! '>='
190
+ - - ">="
178
191
  - !ruby/object:Gem::Version
179
192
  version: '0'
180
193
  requirements: []
181
194
  rubyforge_project:
182
- rubygems_version: 2.6.10
195
+ rubygems_version: 2.5.1
183
196
  signing_key:
184
197
  specification_version: 4
185
198
  summary: Datadog tracing code for your Ruby applications