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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.env +11 -0
  3. data/.gitignore +59 -0
  4. data/.rubocop.yml +61 -0
  5. data/.yardopts +5 -0
  6. data/Appraisals +136 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +24 -0
  9. data/README.md +156 -0
  10. data/Rakefile +176 -0
  11. data/circle.yml +61 -0
  12. data/ddtrace.gemspec +44 -0
  13. data/docker-compose.yml +42 -0
  14. data/docs/GettingStarted.md +735 -0
  15. data/gemfiles/contrib.gemfile +16 -0
  16. data/gemfiles/contrib_old.gemfile +15 -0
  17. data/gemfiles/rails30_postgres.gemfile +10 -0
  18. data/gemfiles/rails30_postgres_sidekiq.gemfile +11 -0
  19. data/gemfiles/rails32_mysql2.gemfile +11 -0
  20. data/gemfiles/rails32_postgres.gemfile +10 -0
  21. data/gemfiles/rails32_postgres_redis.gemfile +11 -0
  22. data/gemfiles/rails32_postgres_sidekiq.gemfile +11 -0
  23. data/gemfiles/rails4_mysql2.gemfile +9 -0
  24. data/gemfiles/rails4_postgres.gemfile +9 -0
  25. data/gemfiles/rails4_postgres_redis.gemfile +10 -0
  26. data/gemfiles/rails4_postgres_sidekiq.gemfile +11 -0
  27. data/gemfiles/rails5_mysql2.gemfile +8 -0
  28. data/gemfiles/rails5_postgres.gemfile +8 -0
  29. data/gemfiles/rails5_postgres_redis.gemfile +9 -0
  30. data/gemfiles/rails5_postgres_sidekiq.gemfile +10 -0
  31. data/lib/ddtrace.rb +73 -0
  32. data/lib/ddtrace/buffer.rb +52 -0
  33. data/lib/ddtrace/context.rb +145 -0
  34. data/lib/ddtrace/contrib/active_record/patcher.rb +94 -0
  35. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +108 -0
  36. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +22 -0
  37. data/lib/ddtrace/contrib/grape/endpoint.rb +164 -0
  38. data/lib/ddtrace/contrib/grape/patcher.rb +73 -0
  39. data/lib/ddtrace/contrib/http/patcher.rb +156 -0
  40. data/lib/ddtrace/contrib/rack/middlewares.rb +150 -0
  41. data/lib/ddtrace/contrib/rails/action_controller.rb +81 -0
  42. data/lib/ddtrace/contrib/rails/action_view.rb +110 -0
  43. data/lib/ddtrace/contrib/rails/active_record.rb +56 -0
  44. data/lib/ddtrace/contrib/rails/active_support.rb +113 -0
  45. data/lib/ddtrace/contrib/rails/core_extensions.rb +137 -0
  46. data/lib/ddtrace/contrib/rails/framework.rb +171 -0
  47. data/lib/ddtrace/contrib/rails/middlewares.rb +32 -0
  48. data/lib/ddtrace/contrib/rails/utils.rb +43 -0
  49. data/lib/ddtrace/contrib/redis/patcher.rb +118 -0
  50. data/lib/ddtrace/contrib/redis/quantize.rb +30 -0
  51. data/lib/ddtrace/contrib/redis/tags.rb +19 -0
  52. data/lib/ddtrace/contrib/sidekiq/tracer.rb +103 -0
  53. data/lib/ddtrace/contrib/sinatra/tracer.rb +169 -0
  54. data/lib/ddtrace/distributed.rb +38 -0
  55. data/lib/ddtrace/encoding.rb +65 -0
  56. data/lib/ddtrace/error.rb +37 -0
  57. data/lib/ddtrace/ext/app_types.rb +10 -0
  58. data/lib/ddtrace/ext/cache.rb +7 -0
  59. data/lib/ddtrace/ext/distributed.rb +10 -0
  60. data/lib/ddtrace/ext/errors.rb +10 -0
  61. data/lib/ddtrace/ext/http.rb +11 -0
  62. data/lib/ddtrace/ext/net.rb +8 -0
  63. data/lib/ddtrace/ext/redis.rb +11 -0
  64. data/lib/ddtrace/ext/sql.rb +8 -0
  65. data/lib/ddtrace/logger.rb +39 -0
  66. data/lib/ddtrace/monkey.rb +84 -0
  67. data/lib/ddtrace/pin.rb +63 -0
  68. data/lib/ddtrace/provider.rb +21 -0
  69. data/lib/ddtrace/sampler.rb +49 -0
  70. data/lib/ddtrace/span.rb +222 -0
  71. data/lib/ddtrace/tracer.rb +310 -0
  72. data/lib/ddtrace/transport.rb +162 -0
  73. data/lib/ddtrace/utils.rb +16 -0
  74. data/lib/ddtrace/version.rb +9 -0
  75. data/lib/ddtrace/workers.rb +108 -0
  76. data/lib/ddtrace/writer.rb +118 -0
  77. metadata +208 -0
@@ -0,0 +1,176 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'ddtrace/version'
3
+ require 'rubocop/rake_task' if RUBY_VERSION >= '2.1.0'
4
+ require 'rake/testtask'
5
+ require 'appraisal'
6
+ require 'yard'
7
+
8
+ # rubocop:disable Metrics/BlockLength
9
+ namespace :test do
10
+ task all: [:main,
11
+ :rails, :railsredis, :railssidekiq, :railsactivejob,
12
+ :elasticsearch, :http, :redis, :sidekiq, :sinatra, :monkey]
13
+
14
+ Rake::TestTask.new(:main) do |t|
15
+ t.libs << %w[test lib]
16
+ t.test_files = FileList['test/**/*_test.rb'].reject do |path|
17
+ path.include?('contrib') ||
18
+ path.include?('benchmark') ||
19
+ path.include?('redis') ||
20
+ path.include?('monkey_test.rb')
21
+ end
22
+ end
23
+
24
+ Rake::TestTask.new(:rails) do |t|
25
+ t.libs << %w[test lib]
26
+ t.test_files = FileList['test/contrib/rails/**/*_test.rb'].reject do |path|
27
+ path.include?('redis') ||
28
+ path.include?('sidekiq') ||
29
+ path.include?('active_job') ||
30
+ path.include?('disable_env')
31
+ end
32
+ end
33
+
34
+ Rake::TestTask.new(:railsredis) do |t|
35
+ t.libs << %w[test lib]
36
+ t.test_files = FileList['test/contrib/rails/**/*redis*_test.rb']
37
+ end
38
+
39
+ Rake::TestTask.new(:railssidekiq) do |t|
40
+ t.libs << %w[test lib]
41
+ t.test_files = FileList['test/contrib/rails/**/*sidekiq*_test.rb']
42
+ end
43
+
44
+ Rake::TestTask.new(:railsactivejob) do |t|
45
+ t.libs << %w[test lib]
46
+ t.test_files = FileList['test/contrib/rails/**/*active_job*_test.rb']
47
+ end
48
+
49
+ Rake::TestTask.new(:railsdisableenv) do |t|
50
+ t.libs << %w[test lib]
51
+ t.test_files = FileList['test/contrib/rails/**/*disable_env*_test.rb']
52
+ end
53
+
54
+ [:elasticsearch, :http, :redis, :sinatra, :sidekiq, :rack, :grape].each do |contrib|
55
+ Rake::TestTask.new(contrib) do |t|
56
+ t.libs << %w[test lib]
57
+ t.test_files = FileList["test/contrib/#{contrib}/*_test.rb"]
58
+ end
59
+ end
60
+
61
+ Rake::TestTask.new(:monkey) do |t|
62
+ t.libs << %w[test lib]
63
+ t.test_files = FileList['test/monkey_test.rb']
64
+ end
65
+ end
66
+
67
+ Rake::TestTask.new(:benchmark) do |t|
68
+ t.libs << %w[test lib]
69
+ t.test_files = FileList['test/benchmark_test.rb']
70
+ end
71
+
72
+ if RUBY_VERSION >= '2.1.0'
73
+ RuboCop::RakeTask.new(:rubocop) do |t|
74
+ t.options << ['-D']
75
+ t.patterns = ['lib/**/*.rb', 'test/**/*.rb', 'Gemfile', 'Rakefile']
76
+ end
77
+ end
78
+
79
+ YARD::Rake::YardocTask.new(:docs) do |t|
80
+ t.options += ['--title', "ddtrace #{Datadog::VERSION::STRING} documentation"]
81
+ end
82
+
83
+ # Deploy tasks
84
+ S3_BUCKET = 'gems.datadoghq.com'.freeze
85
+ S3_DIR = ENV['S3_DIR']
86
+
87
+ desc 'create a new indexed repository'
88
+ task :'release:gem' do
89
+ raise 'Missing environment variable S3_DIR' if !S3_DIR || S3_DIR.empty?
90
+ # load existing deployed gems
91
+ sh "aws s3 cp --exclude 'docs/*' --recursive s3://#{S3_BUCKET}/#{S3_DIR}/ ./rubygems/"
92
+
93
+ # create folders
94
+ sh 'mkdir -p ./gems'
95
+ sh 'mkdir -p ./rubygems/gems/'
96
+ sh 'mkdir -p ./rubygems/quick/'
97
+
98
+ # copy previous builds
99
+ sh 'cp ./rubygems/gems/* ./gems/'
100
+
101
+ # build the gem
102
+ Rake::Task['build'].execute
103
+
104
+ # copy the output in the indexed folder
105
+ sh 'cp pkg/*.gem ./gems/'
106
+
107
+ # generate the gems index
108
+ sh 'gem generate_index'
109
+
110
+ # namespace everything under ./rubygems/
111
+ sh 'cp -r ./gems/* ./rubygems/gems/'
112
+ sh 'cp -r specs.* ./rubygems/'
113
+ sh 'cp -r latest_specs.* ./rubygems/'
114
+ sh 'cp -r prerelease_specs.* ./rubygems/'
115
+ sh 'cp -r ./quick/* ./rubygems/quick/'
116
+
117
+ # deploy a static gem registry
118
+ sh "aws s3 cp --recursive ./rubygems/ s3://#{S3_BUCKET}/#{S3_DIR}/"
119
+ end
120
+
121
+ desc 'release the docs website'
122
+ task :'release:docs' => :docs do
123
+ raise 'Missing environment variable S3_DIR' if !S3_DIR || S3_DIR.empty?
124
+ sh "aws s3 cp --recursive doc/ s3://#{S3_BUCKET}/#{S3_DIR}/docs/"
125
+ end
126
+
127
+ desc 'CI dependent task; it runs all parallel tests'
128
+ task :ci do
129
+ # CircleCI uses this environment to store the node index (starting from 0)
130
+ # check: https://circleci.com/docs/parallel-manual-setup/#env-splitting
131
+ case ENV['CIRCLE_NODE_INDEX'].to_i
132
+ when 0
133
+ sh 'rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do rake test:main'
134
+ sh 'rvm $LAST_STABLE --verbose do rake benchmark'
135
+ when 1
136
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:elasticsearch'
137
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:http'
138
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:redis'
139
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:sinatra'
140
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:sidekiq'
141
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:rack'
142
+ sh 'rvm $MRI_VERSIONS --verbose do appraisal contrib rake test:grape'
143
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:monkey'
144
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:elasticsearch'
145
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:http'
146
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:redis'
147
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:sinatra'
148
+ sh 'rvm $MRI_OLD_VERSIONS --verbose do appraisal contrib-old rake test:rack'
149
+ sh 'rvm $SIDEKIQ_OLD_VERSIONS --verbose do appraisal contrib-old rake test:sidekiq'
150
+ when 2
151
+ sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails30-postgres rake test:rails'
152
+ sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails30-postgres rake test:railsdisableenv'
153
+ sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails32-mysql2 rake test:rails'
154
+ sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails32-postgres rake test:rails'
155
+ sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails32-postgres-redis rake test:railsredis'
156
+ sh 'rvm $RAILS3_VERSIONS --verbose do appraisal rails32-postgres rake test:railsdisableenv'
157
+ sh 'rvm $RAILS4_VERSIONS --verbose do appraisal rails4-mysql2 rake test:rails'
158
+ sh 'rvm $RAILS4_VERSIONS --verbose do appraisal rails4-postgres rake test:rails'
159
+ sh 'rvm $RAILS4_VERSIONS --verbose do appraisal rails4-postgres-redis rake test:railsredis'
160
+ sh 'rvm $RAILS4_VERSIONS --verbose do appraisal rails4-postgres rake test:railsdisableenv'
161
+ sh 'rvm $RAILS3_SIDEKIQ_VERSIONS --verbose do appraisal rails30-postgres-sidekiq rake test:railssidekiq'
162
+ sh 'rvm $RAILS3_SIDEKIQ_VERSIONS --verbose do appraisal rails32-postgres-sidekiq rake test:railssidekiq'
163
+ sh 'rvm $RAILS4_SIDEKIQ_VERSIONS --verbose do appraisal rails4-postgres-sidekiq rake test:railssidekiq'
164
+ sh 'rvm $RAILS4_SIDEKIQ_VERSIONS --verbose do appraisal rails4-postgres-sidekiq rake test:railsactivejob'
165
+ sh 'rvm $RAILS5_VERSIONS --verbose do appraisal rails5-mysql2 rake test:rails'
166
+ sh 'rvm $RAILS5_VERSIONS --verbose do appraisal rails5-postgres rake test:rails'
167
+ sh 'rvm $RAILS5_VERSIONS --verbose do appraisal rails5-postgres-redis rake test:railsredis'
168
+ sh 'rvm $RAILS5_VERSIONS --verbose do appraisal rails5-postgres-sidekiq rake test:railssidekiq'
169
+ sh 'rvm $RAILS5_VERSIONS --verbose do appraisal rails5-postgres-sidekiq rake test:railsactivejob'
170
+ sh 'rvm $RAILS5_VERSIONS --verbose do appraisal rails5-postgres rake test:railsdisableenv'
171
+ else
172
+ puts 'Too many workers than parallel tasks'
173
+ end
174
+ end
175
+
176
+ task default: :test
@@ -0,0 +1,61 @@
1
+ machine:
2
+ services:
3
+ - docker
4
+ environment:
5
+ LAST_STABLE: 2.4.1
6
+ EARLY_STABLE: 2.2.7
7
+ MRI_VERSIONS: 2.4.1,2.3.4,2.2.7
8
+ MRI_OLD_VERSIONS: 2.1.10,2.0.0,1.9.3
9
+ SIDEKIQ_OLD_VERSIONS: 2.1.10,2.0.0
10
+ RAILS3_VERSIONS: 2.3.4,2.2.7,2.1.10,2.0.0,1.9.3
11
+ RAILS4_VERSIONS: 2.3.4,2.2.7,2.1.10
12
+ RAILS5_VERSIONS: 2.3.4,2.2.7
13
+ RAILS3_SIDEKIQ_VERSIONS: 2.1.10,2.0.0
14
+ RAILS4_SIDEKIQ_VERSIONS: 2.3.4,2.2.7
15
+ JRUBY_VERSIONS: jruby-9.1.5.0
16
+ AGENT_BUILD_PATH: "/home/ubuntu/agent"
17
+ TEST_DATADOG_INTEGRATION: 1
18
+
19
+ dependencies:
20
+ cache_directories:
21
+ # Cache Ruby binaries and gems
22
+ - "/opt/circleci/.rvm/"
23
+ pre:
24
+ # we should use an old docker-compose because CircleCI supports
25
+ # only docker-engine==1.9
26
+ - pip install docker-compose==1.7.1
27
+ - docker-compose up -d | cat
28
+ # installing dev dependencies
29
+ - gem update --system=2.6.11
30
+ - gem install builder
31
+ - gem update bundler
32
+ - bundle install
33
+ # configure Ruby interpreters
34
+ - rvm get head
35
+ - rvm install $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS
36
+ override:
37
+ - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do gem update --system=2.6.11
38
+ - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do gem install bundler
39
+ - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do bundle install
40
+ # [FIXME] appraisal does not work with jruby (problem with native ext, eg sqlite3)
41
+ - rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS --verbose do appraisal install
42
+
43
+ test:
44
+ override:
45
+ - rvm $EARLY_STABLE --verbose do rake rubocop
46
+ # TODO: integration tests should run with the master branch of the agent
47
+ - rake ci:
48
+ parallel: true
49
+
50
+ deployment:
51
+ develop:
52
+ branch: /(master)|(develop)/
53
+ # CircleCI is configured to provide VERSION_SUFFIX=$CIRCLE_BUILD_NUM
54
+ commands:
55
+ - S3_DIR=trace-dev rake release:docs
56
+ - S3_DIR=trace-dev rake release:gem
57
+ - cp -r ./rubygems/* $CIRCLE_ARTIFACTS
58
+ public:
59
+ tag: /v[0-9]+(\.[0-9]+)*/
60
+ commands:
61
+ - S3_DIR=trace rake release:docs
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'ddtrace/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'fair-ddtrace'
9
+ # spec.version = "#{Datadog::VERSION::STRING}#{ENV['VERSION_SUFFIX']}"
10
+ spec.version = '0.8.2.a'
11
+ spec.required_ruby_version = '>= 1.9.1'
12
+ spec.authors = ['Fair']
13
+ spec.email = ['catherinec@fair.com']
14
+
15
+ spec.summary = 'Fair fork of Datadog tracing code for your Ruby applications'
16
+ spec.description = <<-EOS
17
+ ddtrace is Datadog’s tracing client for Ruby. It is used to trace requests
18
+ as they flow across web servers, databases and microservices so that developers
19
+ have great visiblity into bottlenecks and troublesome requests.
20
+ Find the original version at: https://github.com/DataDog/dd-trace-rb
21
+ EOS
22
+
23
+ spec.homepage = 'https://github.com/wearefair/dd-trace-rb'
24
+ spec.license = 'BSD-3-Clause'
25
+
26
+ if spec.respond_to?(:metadata)
27
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
28
+ else
29
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
30
+ end
31
+
32
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ spec.bindir = 'exe'
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ['lib']
36
+
37
+ spec.add_dependency 'msgpack'
38
+
39
+ spec.add_development_dependency 'rake', '~> 10.5'
40
+ spec.add_development_dependency('rubocop', '~> 0.47') if RUBY_VERSION >= '2.1.0'
41
+ spec.add_development_dependency 'minitest', '= 5.10.1'
42
+ spec.add_development_dependency 'appraisal', '~> 2.1'
43
+ spec.add_development_dependency 'yard', '~> 0.9'
44
+ end
@@ -0,0 +1,42 @@
1
+ # remember to use this compose file __ONLY__ for development/testing purposes
2
+ postgres:
3
+ image: postgres:9.6
4
+ environment:
5
+ - POSTGRES_PASSWORD=$TEST_POSTGRES_PASSWORD
6
+ - POSTGRES_USER=$TEST_POSTGRES_USER
7
+ - POSTGRES_DB=$TEST_POSTGRES_DB
8
+ ports:
9
+ - "127.0.0.1:${TEST_POSTGRES_PORT}:5432"
10
+
11
+ mysql:
12
+ image: mysql:5.6
13
+ environment:
14
+ - MYSQL_ROOT_PASSWORD=$TEST_MYSQL_ROOT_PASSWORD
15
+ - MYSQL_PASSWORD=$TEST_MYSQL_PASSWORD
16
+ - MYSQL_USER=$TEST_MYSQL_USER
17
+ ports:
18
+ - "127.0.0.1:${TEST_MYSQL_PORT}:3306"
19
+
20
+ elasticsearch:
21
+ # Note: ES 5.0 dies with error:
22
+ # max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
23
+ # see https://github.com/docker-library/elasticsearch/issues/98 for details
24
+ # For now, just rely on a 2.X server.
25
+ image: elasticsearch:2.4
26
+ ports:
27
+ - "127.0.0.1:${TEST_ELASTICSEARCH_REST_PORT}:9200"
28
+ - "127.0.0.1:${TEST_ELASTICSEARCH_NATIVE_PORT}:9300"
29
+
30
+ redis:
31
+ image: redis:3.0
32
+ ports:
33
+ - "127.0.0.1:${TEST_REDIS_PORT}:6379"
34
+
35
+ ddagent:
36
+ image: datadog/docker-dd-agent
37
+ environment:
38
+ - DD_APM_ENABLED=true
39
+ - DD_BIND_HOST=0.0.0.0
40
+ - DD_API_KEY=invalid_key_but_this_is_fine
41
+ ports:
42
+ - "127.0.0.1:8126:8126"
@@ -0,0 +1,735 @@
1
+ # Datadog Trace Client
2
+
3
+ ``ddtrace`` is Datadog’s tracing client for Ruby. It is used to trace requests as they flow across web servers,
4
+ databases and microservices so that developers have great visiblity into bottlenecks and troublesome requests.
5
+
6
+ ## Install the gem
7
+
8
+ Install the tracing client, adding the following gem in your ``Gemfile``:
9
+
10
+ source 'https://rubygems.org'
11
+
12
+ # tracing gem
13
+ gem 'ddtrace'
14
+
15
+ If you're not using ``Bundler`` to manage your dependencies, you can install ``ddtrace`` with:
16
+
17
+ gem install ddtrace
18
+
19
+ We strongly suggest pinning the version of the library you deploy.
20
+
21
+ ## Quickstart
22
+
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 and libraries:
25
+
26
+ * [Ruby on Rails](#Ruby_on_Rails)
27
+ * [Sidekiq](#Sidekiq)
28
+ * [Sinatra](#Sinatra)
29
+ * [Rack](#Rack)
30
+ * [Grape](#Grape)
31
+ * [Active Record](#Active_Record)
32
+ * [Elastic Search](#Elastic_Search)
33
+ * [Net/HTTP](#Net_HTTP)
34
+ * [Redis](#Redis)
35
+
36
+ ## Web Frameworks
37
+
38
+ ### Ruby on Rails
39
+
40
+ The Rails integration will trace requests, database calls, templates rendering and cache read/write/delete
41
+ operations. The integration makes use of the Active Support Instrumentation, listening to the Notification API
42
+ so that any operation instrumented by the API is traced.
43
+
44
+ To enable the Rails auto instrumentation, create an initializer file in your ``config/`` folder:
45
+
46
+ # config/initializers/datadog-tracer.rb
47
+
48
+ Rails.configuration.datadog_trace = {
49
+ auto_instrument: true,
50
+ auto_instrument_redis: true,
51
+ default_service: 'my-rails-app'
52
+ }
53
+
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.
56
+
57
+ #### Configure the tracer with initializers
58
+
59
+ All tracing settings are namespaced under the ``Rails.configuration.datadog_tracer`` hash. To change the default behavior
60
+ of the Datadog tracer, you can override the following defaults:
61
+
62
+ # config/initializers/datadog-tracer.rb
63
+
64
+ Rails.configuration.datadog_trace = {
65
+ enabled: true,
66
+ auto_instrument: false,
67
+ auto_instrument_redis: false,
68
+ auto_instrument_grape: false,
69
+ default_service: 'rails-app',
70
+ default_controller_service: 'rails-controller',
71
+ default_cache_service: 'rails-cache',
72
+ default_database_service: 'postgresql',
73
+ template_base_path: 'views/',
74
+ tracer: Datadog.tracer,
75
+ debug: false,
76
+ trace_agent_hostname: 'localhost',
77
+ trace_agent_port: 8126,
78
+ env: nil,
79
+ tags: {}
80
+ }
81
+
82
+ Available settings are:
83
+
84
+ * ``enabled``: defines if the ``tracer`` is enabled or not. If set to ``false`` the code could be still instrumented
85
+ because of other settings, but no spans are sent to the local trace agent.
86
+ * ``auto_instrument``: if set to +true+ the code will be automatically instrumented. You may change this value
87
+ with a condition, to enable the auto-instrumentation only for particular environments (production, staging, etc...).
88
+ * ``auto_instrument_redis``: if set to ``true`` Redis calls will be traced as such. Calls to Redis cache may be
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.
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``
95
+ * ``default_database_service``: set the database service name used when tracing database activity. Defaults to the
96
+ current adapter name, so if you're using PostgreSQL it will be ``postgres``.
97
+ * ``default_grape_service``: set the service name used when tracing a Grape application mounted in your Rails router.
98
+ Defaults to ``grape``
99
+ * ``template_base_path``: used when the template name is parsed in the auto instrumented code. If you don't store
100
+ your templates in the ``views/`` folder, you may need to change this value
101
+ * ``tracer``: is the global tracer used by the tracing application. Usually you don't need to change that value
102
+ unless you're already using a different initialized ``tracer`` somewhere else
103
+ * ``debug``: set to true to enable debug logging.
104
+ * ``trace_agent_hostname``: set the hostname of the trace agent.
105
+ * ``trace_agent_port``: set the port the trace agent is listening on.
106
+ * ``env``: set the environment. Rails users may set it to ``Rails.env`` to use their application settings.
107
+ * ``tags``: set global tags that should be applied to all spans. Defaults to an empty hash
108
+
109
+ #### Disabling Rails auto-instrumentation
110
+
111
+ If you wish to disable all Rails auto-instrumentation, you need to set the env var ``DISABLE_DATADOG_RAILS``.
112
+
113
+ Eg, within Ruby:
114
+
115
+ ENV['DISABLE_DATADOG_RAILS'] = "1" # this must be done before ddtrace is included at all
116
+ require 'ddtrace'
117
+
118
+ Or, shell syntax, before launching Rails:
119
+
120
+ ```
121
+ export DISABLE_DATADOG_RAILS=1
122
+ ```
123
+
124
+ ### Sinatra
125
+
126
+ The Sinatra integration traces requests and template rendering. The integration is based on the
127
+ ``Datadog::Contrib::Sinatra::Tracer`` extension.
128
+
129
+ To start using the tracing client, make sure you import ``ddtrace`` and ``ddtrace/contrib/sinatra/tracer`` after
130
+ either ``sinatra`` or ``sinatra/base``:
131
+
132
+ require 'sinatra'
133
+ require 'ddtrace'
134
+ require 'ddtrace/contrib/sinatra/tracer'
135
+
136
+ get '/' do
137
+ 'Hello world!'
138
+ end
139
+
140
+ The tracing extension will be automatically activated.
141
+
142
+ #### Configure the tracer
143
+
144
+ To modify the default configuration, use the ``settings.datadog_tracer.configure`` method. For example,
145
+ to change the default service name and activate the debug mode:
146
+
147
+ configure do
148
+ settings.datadog_tracer.configure default_service: 'my-app', debug: true
149
+ end
150
+
151
+ Available settings are:
152
+
153
+ * ``enabled``: define if the ``tracer`` is enabled or not. If set to ``false``, the code is still instrumented
154
+ but no spans are sent to the local trace agent.
155
+ * ``default_service``: set the service name used when tracing application requests. Defaults to ``sinatra``
156
+ * ``tracer``: set the tracer to use. Usually you don't need to change that value
157
+ unless you're already using a different initialized tracer somewhere else
158
+ * ``debug``: set to ``true`` to enable debug logging.
159
+ * ``trace_agent_hostname``: set the hostname of the trace agent.
160
+ * ``trace_agent_port``: set the port the trace agent is listening on.
161
+
162
+ ### Rack
163
+
164
+ The Rack integration provides a middleware that traces all requests before they reach the underlying framework
165
+ or application. It responds to the Rack minimal interface, providing reasonable values that can be
166
+ retrieved at the Rack level.
167
+ To start using the middleware in your generic Rack application, add it to your ``config.ru``:
168
+
169
+ # config.ru example
170
+ require 'ddtrace/contrib/rack/middlewares'
171
+
172
+ use Datadog::Contrib::Rack::TraceMiddleware
173
+
174
+ app = proc do |env|
175
+ [ 200, {'Content-Type' => 'text/plain'}, "OK" ]
176
+ end
177
+
178
+ run app
179
+
180
+ Experimental distributed tracing support is available for this library.
181
+ You need to set the ``:distributed_tracing_enabled`` option to true, for example:
182
+
183
+ # config.ru example
184
+ require 'ddtrace/contrib/rack/middlewares'
185
+
186
+ use Datadog::Contrib::Rack::TraceMiddleware, distributed_tracing_enabled: true
187
+
188
+ app = proc do |env|
189
+ # trace and read 'x-datadog-trace-id' and 'x-datadog-parent-id'
190
+ [ 200, {'Content-Type' => 'text/plain'}, "OK" ]
191
+ end
192
+
193
+ See [distributed tracing](#Distributed_Tracing) for details.
194
+
195
+ #### Configure the tracer
196
+
197
+ To modify the default middleware configuration, you can use middleware options as follows:
198
+
199
+ # config.ru example
200
+ require 'ddtrace/contrib/rack/middlewares'
201
+
202
+ Datadog.tracer.configure(
203
+ enabled: true,
204
+ hostname: localhost,
205
+ port: 8126
206
+ )
207
+
208
+ use Datadog::Contrib::Rack::TraceMiddleware, default_service: 'rack-stack'
209
+
210
+ app = proc do |env|
211
+ [ 200, {'Content-Type' => 'text/plain'}, "OK" ]
212
+ end
213
+
214
+ run app
215
+
216
+ Available settings are:
217
+
218
+ * ``tracer`` (default: ``Datadog.tracer``): set the tracer to use. Usually you don't need to change that value
219
+ unless you're already using a different initialized tracer somewhere else. If you need to change some
220
+ configurations such as the ``hostname``, use the [Tracer#configure](Datadog/Tracer.html#configure-instance_method)
221
+ method before adding the middleware
222
+ * ``default_service`` (default: ``rack``): set the service name used when the Rack request is traced
223
+
224
+ ## Other libraries
225
+
226
+ ### Grape
227
+
228
+ The Grape integration adds the instrumentation to Grape endpoints and filters. This integration can work side by side
229
+ with other integrations like Rack and Rails. To activate your integration, use the ``patch_module`` function before
230
+ defining your Grape application:
231
+
232
+ # api.rb
233
+ require 'grape'
234
+ require 'ddtrace'
235
+
236
+ Datadog::Monkey.patch_module(:grape)
237
+
238
+ # then define your application
239
+ class RackTestingAPI < Grape::API
240
+ desc 'main endpoint'
241
+ get :success do
242
+ 'Hello world!'
243
+ end
244
+ end
245
+
246
+ ### Active Record
247
+
248
+ Most of the time, Active Record is set up as part of a web framework (Rails, Sinatra...)
249
+ however it can be set up alone:
250
+
251
+ require 'tmpdir'
252
+ require 'sqlite3'
253
+ require 'active_record'
254
+ require 'ddtrace'
255
+
256
+ Datadog::Monkey.patch_module(:active_record) # explicitly patch it
257
+
258
+ Dir::Tmpname.create(['test', '.sqlite']) do |db|
259
+ conn = ActiveRecord::Base.establish_connection(adapter: 'sqlite3',
260
+ database: db)
261
+ conn.connection.execute('SELECT 42') # traced!
262
+ end
263
+
264
+ ### Elastic Search
265
+
266
+ The Elasticsearch integration will trace any call to ``perform_request``
267
+ in the ``Client`` object:
268
+
269
+ require 'elasticsearch/transport'
270
+ require 'ddtrace'
271
+
272
+ Datadog::Monkey.patch_module(:elasticsearch) # explicitly patch it
273
+
274
+ # now do your Elastic Search stuff, eg:
275
+ client = Elasticsearch::Client.new url: 'http://127.0.0.1:9200'
276
+ response = client.perform_request 'GET', '_cluster/health'
277
+
278
+ Note that if you enable both Elasticsearch and Net/HTTP integrations then
279
+ for each call, two spans are created, one for Elasctisearch and one for Net/HTTP.
280
+ This typically happens if you call ``patch_all`` to enable all integrations by default.
281
+
282
+ ### Net/HTTP
283
+
284
+ The Net/HTTP integration will trace any HTTP call using the standard lib
285
+ Net::HTTP module.
286
+
287
+ require 'net/http'
288
+ require 'ddtrace'
289
+
290
+ Datadog::Monkey.patch_module(:http) # explicitly patch it
291
+
292
+ Net::HTTP.start('127.0.0.1', 8080) do |http|
293
+ request = Net::HTTP::Get.new '/index'
294
+ response = http.request request
295
+ end
296
+
297
+ content = Net::HTTP.get(URI('http://127.0.0.1/index.html'))
298
+
299
+ Experimental distributed tracing support is available for this library.
300
+ By default, this is disabled. You need to enable it, either on a per-connection basis,
301
+ by setting the ``:distributed_tracing_enabled`` config entry to ``true`` using
302
+ the ``Pin`` object attached to the client. Example:
303
+
304
+ require 'net/http'
305
+ require 'ddtrace'
306
+
307
+ Datadog::Monkey.patch_module(:http) # explicitly patch it
308
+
309
+ client = Net::HTTP.new(host, port)
310
+ Datadog::Pin.get_from(client).config = { distributed_tracing_enabled: true }
311
+ response = client.get('foo') # trace and send 'x-datadog-trace-id' and 'x-datadog-parent-id'
312
+
313
+ Or, by enabling distributed tracing for all HTTP calls:
314
+
315
+ require 'net/http'
316
+ require 'ddtrace'
317
+
318
+ Datadog::Monkey.patch_module(:http) # explicitly patch it
319
+
320
+ Datadog::Contrib::HTTP.distributed_tracing_enabled = true
321
+
322
+ See [distributed tracing](#Distributed_Tracing) for details.
323
+
324
+ ### Redis
325
+
326
+ The Redis integration will trace simple calls as well as pipelines.
327
+
328
+ require 'redis'
329
+ require 'ddtrace'
330
+
331
+ Datadog::Monkey.patch_module(:redis) # explicitly patch it
332
+
333
+ # now do your Redis stuff, eg:
334
+ redis = Redis.new
335
+ redis.set 'foo', 'bar' # traced!
336
+
337
+ ### Sidekiq
338
+
339
+ The Sidekiq integration is a server-side middleware which will trace job
340
+ executions. It can be added as any other Sidekiq middleware:
341
+
342
+ require 'sidekiq'
343
+ require 'ddtrace'
344
+ require 'ddtrace/contrib/sidekiq/tracer'
345
+
346
+ Sidekiq.configure_server do |config|
347
+ config.server_middleware do |chain|
348
+ chain.add(Datadog::Contrib::Sidekiq::Tracer)
349
+ end
350
+ end
351
+
352
+ #### Configure the tracer middleware
353
+
354
+ To modify the default configuration, simply pass arguments to the middleware.
355
+ For example, to change the default service name:
356
+
357
+ Sidekiq.configure_server do |config|
358
+ config.server_middleware do |chain|
359
+ chain.add(
360
+ Datadog::Contrib::Sidekiq::Tracer,
361
+ sidekiq_service: 'sidekiq-notifications'
362
+ )
363
+ end
364
+ end
365
+
366
+ Available settings are:
367
+
368
+ * ``enabled``: define if the ``tracer`` is enabled or not. If set to
369
+ ``false``, the code is still instrumented but no spans are sent to the local
370
+ trace agent.
371
+ * ``sidekiq_service``: set the service name used when tracing application
372
+ requests. Defaults to ``sidekiq``.
373
+ * ``tracer``: set the tracer to use. Usually you don't need to change that
374
+ value unless you're already using a different initialized tracer somewhere
375
+ else.
376
+ * ``debug``: set to ``true`` to enable debug logging.
377
+ * ``trace_agent_hostname``: set the hostname of the trace agent.
378
+ * ``trace_agent_port``: set the port the trace agent is listening on.
379
+
380
+ If you're using Sidekiq along with [Ruby on Rails](#label-Ruby+on+Rails) auto-instrumentation,
381
+ the Sidekiq middleware will re-use the Rails configuration defined in the initializer file before
382
+ giving precedence to the middleware settings. Inherited configurations are:
383
+
384
+ * ``enabled``
385
+ * ``tracer``
386
+ * ``debug``
387
+ * ``trace_agent_hostname``
388
+ * ``trace_agent_port``
389
+
390
+ ## Advanced usage
391
+
392
+ ### Manual Instrumentation
393
+
394
+ If you aren't using a supported framework instrumentation, you may want to to manually instrument your code.
395
+ Adding tracing to your code is very simple. As an example, let’s imagine we have a web server and we want
396
+ to trace requests to the home page:
397
+
398
+ require 'ddtrace'
399
+ require 'sinatra'
400
+ require 'active_record'
401
+
402
+ # a generic tracer that you can use across your application
403
+ tracer = Datadog.tracer
404
+
405
+ get '/' do
406
+ tracer.trace('web.request') do |span|
407
+ # set some span metadata
408
+ span.service = 'my-web-site'
409
+ span.resource = '/'
410
+
411
+ # trace the activerecord call
412
+ tracer.trace('posts.fetch') do
413
+ @posts = Posts.order(created_at: :desc).limit(10)
414
+ end
415
+
416
+ # add some attributes and metrics
417
+ span.set_tag('http.method', request.request_method)
418
+ span.set_tag('posts.count', @posts.length)
419
+
420
+ # trace the template rendering
421
+ tracer.trace('template.render') do
422
+ erb :index
423
+ end
424
+
425
+ # trace using start_span (fine-grain control, requires explicit call to finish)
426
+ child = tracer.start_span('child', child_of: span)
427
+ # do something
428
+ child.finish
429
+ end
430
+ end
431
+
432
+ ### Patching methods
433
+
434
+ Integrations such as Redis or Elasticsearch use monkey patching.
435
+
436
+ The available methods are:
437
+
438
+ * ``autopatch_modules``: returns a hash of all modules available for monkey patching,
439
+ the key is the name of the module and the value ``true`` or ``false``. If it is ``true``,
440
+ a call to ``patch_all`` will enable the module, if it is ``false``, it will do nothing.
441
+ * ``patch_all``: patches all modules which are supported. Make sure all the necessary
442
+ calls to ``require`` have been done before this is called, else monkey patching will
443
+ not work.
444
+ * ``patch_module``: patches a single module, regardless of its settings in the
445
+ ``autopatch_modules`` list.
446
+ * ``patch``: patches some modules, you should pass a hash like the one returned
447
+ by ``autopatch_modules``
448
+ * ``get_patched_modules``: returns the list of patched modules, a module has been
449
+ correctly patched only if it is in this hash, with a value set to ``true``.
450
+
451
+ Example:
452
+
453
+ require 'ddtrace'
454
+
455
+ puts Datadog::Monkey.autopatch_modules # lists all modules available for monkey patching
456
+ Datadog::Monkey.patch_module(:redis) # patch only one module
457
+ Datadog::Monkey.patch(elasticsearch: false, redis: true) # patch redis, but not elasticsearch
458
+ Datadog::Monkey.patch_all # patch all the available modules
459
+ puts Datadog::Monkey.get_patched_modules # tells wether modules are patched or not
460
+
461
+ It is safe to call ``patch_all``, ``patch_module`` or ``patch`` several times.
462
+ Make sure the library you want to patch is imported before you call ``patch_module``.
463
+ In doubt, check with ``get_patched_modules``.
464
+ Once a module is patched, it is not possible to unpatch it.
465
+
466
+ ### Patch Info (PIN)
467
+
468
+ The Patch Info, AKA ``Pin`` object, gives you control on the integration.
469
+
470
+ It has one class method:
471
+
472
+ * ``get_from``: returns the Pin object which has been pinned onto some random
473
+ object. It is safe to call ``get_from`` on any object, but it might return ``nil``.
474
+
475
+ Some instance methods:
476
+
477
+ * ``enabled?``: wether tracing is enabled for this object
478
+ * ``onto``: applies the patch information to some random object. It is the companion
479
+ function of ``get_from``.
480
+
481
+ Accessors:
482
+
483
+ * ``service``: service, you should typically set some meaningful value for this.
484
+ * ``app``: application name
485
+ * ``tags``: optional tags
486
+ * ``app_type``: application type
487
+ * ``name``: span name
488
+ * ``tracer``: the tracer object used for tracing
489
+
490
+ By default, a traced integration such as Redis or Elasticsearch carries a Pin object. Eg:
491
+
492
+ require 'redis'
493
+ require 'ddtrace'
494
+
495
+ Datadog::Monkey.patch_all
496
+
497
+ redis = Redis.new
498
+ pin = Datadog::Pin.get_from(redis)
499
+ pin.service = 'my-redis-cache'
500
+ puts redis.get 'my-key' # this will be traced as belonging to 'my-redis-cache' service
501
+ pin.tracer = nil
502
+ puts pin.enabled? # false
503
+ puts redis.get 'my-key' # this won't be traced, tracing has been disabled now
504
+
505
+ You can use this object to instrument your own code:
506
+
507
+ require 'ddtrace'
508
+ require 'ddtrace/ext/app_types'
509
+
510
+ class MyWebSite
511
+ def initialize
512
+ pin = Datadog::Pin.new('my-web-site', app_type: Datadog::Ext::AppTypes::WEB)
513
+ pin.onto(self)
514
+ end
515
+
516
+ def serve(something)
517
+ pin = Datadog::Pin.get_from(self)
518
+ pin.tracer.trace('serve') do |span|
519
+ span.resource = something
520
+ span.service = pin.service
521
+ # serve something here
522
+ end
523
+ end
524
+ end
525
+
526
+ ### Debug Mode
527
+
528
+ If you need to check locally what traces and spans are sent after each traced block, you can enable
529
+ a global debug mode for all tracers so that every time a trace is ready to be sent, the content will be
530
+ printed in the +STDOUT+. To enable the debug logging, add this code anywhere before using the tracer
531
+ for the first time:
532
+
533
+ require 'ddtrace'
534
+ require 'sinatra'
535
+ require 'active_record'
536
+
537
+ # enable debug mode
538
+ Datadog::Tracer.debug_logging = true
539
+
540
+ # use the tracer as usual
541
+ tracer = Datadog.tracer
542
+
543
+ get '/' do
544
+ tracer.trace('web.request') do |span|
545
+ # ...
546
+ end
547
+ end
548
+
549
+ Remember that the debug mode may affect your application performance and so it must not be used
550
+ in a production environment.
551
+
552
+ ### Using a custom logger
553
+
554
+ By default, all logs are processed by the default Ruby logger.
555
+ Typically, when using Rails, you should see the messages in your application log file.
556
+ Datadog client log messages are marked with ``[ddtrace]`` so you should be able
557
+ to isolate them from other messages.
558
+
559
+ Additionally, it is possible to override the default logger and replace it by a
560
+ custom one. This is done using the ``log`` attribute of the tracer.
561
+
562
+ f = File.new("my-custom.log", "w+") # Log messages should go there
563
+ Datadog::Tracer.log = Logger.new(f) # Overriding the default tracer
564
+ Datadog::Tracer.log.info { "this is typically called by tracing code" }
565
+
566
+ ### Environment and tags
567
+
568
+ By default, the trace agent (not this library, but the program running in
569
+ the background collecting data from various clients) uses the tags
570
+ set in the agent config file, see our
571
+ [environments tutorial](https://app.datadoghq.com/apm/docs/tutorials/environments) for details.
572
+
573
+ These values can be overridden at the tracer level:
574
+
575
+ Datadog.tracer.set_tags('env' => 'prod')
576
+
577
+ This enables you to set this value on a per tracer basis, so you can have
578
+ for example several applications reporting for different environments on the same host.
579
+
580
+ Ultimately, tags can be set per span, but `env` should typically be the same
581
+ for all spans belonging to a given trace.
582
+
583
+ ### Sampling
584
+
585
+ `ddtrace` can perform trace sampling. While the trace agent already samples
586
+ traces to reduce bandwidth usage, client sampling reduces performance
587
+ overhead.
588
+
589
+ `Datadog::RateSampler` samples a ratio of the traces. For example:
590
+
591
+ # Sample rate is between 0 (nothing sampled) to 1 (everything sampled).
592
+ sampler = Datadog::RateSampler.new(0.5) # sample 50% of the traces
593
+ Datadog.tracer.configure(sampler: sampler)
594
+
595
+ ### Distributed Tracing
596
+
597
+ To trace requests across hosts, the spans on the secondary hosts must be linked together by setting ``trace_id`` and ``parent_id``:
598
+
599
+ def request_on_secondary_host(parent_trace_id, parent_span_id)
600
+ tracer.trace('web.request') do |span|
601
+ span.parent_id = parent_span_id
602
+ span.trace_id = parent_trace_id
603
+
604
+ # perform user code
605
+ end
606
+ end
607
+
608
+ Users can pass along the ``parent_trace_id`` and ``parent_span_id`` via whatever method best matches the RPC framework.
609
+
610
+ Below is an example using Net/HTTP and Sinatra, where we bypass the integrations to demo how distributed tracing works.
611
+
612
+ On the client:
613
+
614
+ require 'net/http'
615
+ require 'ddtrace'
616
+
617
+ # Do *not* monkey patch here, we do it "manually", to demo the feature
618
+ # Datadog::Monkey.patch_module(:http)
619
+
620
+ uri = URI('http://localhost:4567/')
621
+
622
+ Datadog.tracer.trace('web.call') do |span|
623
+ req = Net::HTTP::Get.new(uri)
624
+ req['x-datadog-trace-id'] = span.trace_id.to_s
625
+ req['x-datadog-parent-id'] = span.span_id.to_s
626
+
627
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
628
+ http.request(req)
629
+ end
630
+
631
+ puts response.body
632
+ end
633
+
634
+ On the server:
635
+
636
+ require 'sinatra'
637
+ require 'ddtrace'
638
+
639
+ # Do *not* use Sinatra integration, we do it "manually", to demo the feature
640
+ # require 'ddtrace/contrib/sinatra/tracer'
641
+
642
+ get '/' do
643
+ parent_trace_id = request.env['HTTP_X_DATADOG_TRACE_ID']
644
+ parent_span_id = request.env['HTTP_X_DATADOG_PARENT_ID']
645
+
646
+ Datadog.tracer.trace('web.work') do |span|
647
+ if parent_trace_id && parent_span_id
648
+ span.trace_id = parent_trace_id.to_i
649
+ span.parent_id = parent_span_id.to_i
650
+ end
651
+
652
+ 'Hello world!'
653
+ end
654
+ end
655
+
656
+ [Rack](#Rack) and [Net/HTTP](#Net_HTTP) have experimental support for this, they
657
+ can send and receive these headers automatically and tie spans together automatically,
658
+ provided you pass a ``:distributed_tracing_enabled`` option set to ``true``.
659
+
660
+ This is disabled by default.
661
+
662
+ ### Troubleshooting
663
+
664
+ #### Logs
665
+
666
+ Your application log should contain informations and report problems
667
+ such as agent not being up and running. All logs generated by this
668
+ library should contain ``[ddtrace]``. Also see [how to use a custom logger](#Using_a_custom_logger)
669
+ to redirect these messages elsewhere.
670
+
671
+ The [Datadog Trace Agent](https://github.com/DataDog/datadog-trace-agent)
672
+ should by default be listening for traces on port 8126.
673
+
674
+ #### Hello World
675
+
676
+ Sometimes, setting up a complete application is complex, so in doubt,
677
+ try the small program below, which should be able to report traces
678
+ for a ``tracegen`` service:
679
+
680
+ require 'ddtrace'
681
+
682
+ loop do
683
+ Datadog.tracer.trace('hello-world') do |span|
684
+ span.service = 'tracegen'
685
+ span.resource = 'ruby'
686
+ sleep 1
687
+ end
688
+ end
689
+
690
+ ### Supported Versions
691
+
692
+ #### Ruby interpreters
693
+
694
+ The Datadog Trace Client has been tested with the following Ruby versions:
695
+
696
+ * Ruby MRI 1.9.1 (experimental)
697
+ * Ruby MRI 1.9.3
698
+ * Ruby MRI 2.0
699
+ * Ruby MRI 2.1
700
+ * Ruby MRI 2.2
701
+ * Ruby MRI 2.3
702
+ * Ruby MRI 2.4
703
+ * JRuby 9.1.5 (experimental)
704
+
705
+ Other versions aren't yet officially supported.
706
+
707
+ #### Ruby on Rails versions
708
+
709
+ The supported versions are:
710
+
711
+ * Rails 3.2 (MRI interpreter, JRuby is experimental)
712
+ * Rails 4.2 (MRI interpreter, JRuby is experimental)
713
+ * Rails 5.0 (MRI interpreter)
714
+
715
+ The currently supported web server are:
716
+ * Puma 2.16+ and 3.6+
717
+ * Unicorn 4.8+ and 5.1+
718
+ * Passenger 5.0+
719
+
720
+ #### Sinatra versions
721
+
722
+ Currently we are supporting Sinatra >= 1.4.0.
723
+
724
+ #### Sidekiq versions
725
+
726
+ Currently we are supporting Sidekiq >= 4.0.0.
727
+
728
+ ### Glossary
729
+
730
+ * ``Service``: The name of a set of processes that do the same job. Some examples are ``datadog-web-app`` or ``datadog-metrics-db``.
731
+ * ``Resource``: A particular query to a service. For a web application, some examples might be a URL stem like ``/user/home`` or a
732
+ handler function like ``web.user.home``. For a SQL database, a resource would be the SQL of the query itself like ``select * from users where id = ?``.
733
+ You can track thousands (not millions or billions) of unique resources per services, so prefer resources like ``/user/home`` rather than ``/user/home?id=123456789``.
734
+ * ``Span``: A span tracks a unit of work in a service, like querying a database or rendering a template. Spans are associated
735
+ with a service and optionally a resource. Spans have names, start times, durations and optional tags.