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.
- checksums.yaml +7 -0
- data/.env +11 -0
- data/.gitignore +59 -0
- data/.rubocop.yml +61 -0
- data/.yardopts +5 -0
- data/Appraisals +136 -0
- data/Gemfile +3 -0
- data/LICENSE +24 -0
- data/README.md +156 -0
- data/Rakefile +176 -0
- data/circle.yml +61 -0
- data/ddtrace.gemspec +44 -0
- data/docker-compose.yml +42 -0
- data/docs/GettingStarted.md +735 -0
- data/gemfiles/contrib.gemfile +16 -0
- data/gemfiles/contrib_old.gemfile +15 -0
- data/gemfiles/rails30_postgres.gemfile +10 -0
- data/gemfiles/rails30_postgres_sidekiq.gemfile +11 -0
- data/gemfiles/rails32_mysql2.gemfile +11 -0
- data/gemfiles/rails32_postgres.gemfile +10 -0
- data/gemfiles/rails32_postgres_redis.gemfile +11 -0
- data/gemfiles/rails32_postgres_sidekiq.gemfile +11 -0
- data/gemfiles/rails4_mysql2.gemfile +9 -0
- data/gemfiles/rails4_postgres.gemfile +9 -0
- data/gemfiles/rails4_postgres_redis.gemfile +10 -0
- data/gemfiles/rails4_postgres_sidekiq.gemfile +11 -0
- data/gemfiles/rails5_mysql2.gemfile +8 -0
- data/gemfiles/rails5_postgres.gemfile +8 -0
- data/gemfiles/rails5_postgres_redis.gemfile +9 -0
- data/gemfiles/rails5_postgres_sidekiq.gemfile +10 -0
- data/lib/ddtrace.rb +73 -0
- data/lib/ddtrace/buffer.rb +52 -0
- data/lib/ddtrace/context.rb +145 -0
- data/lib/ddtrace/contrib/active_record/patcher.rb +94 -0
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +108 -0
- data/lib/ddtrace/contrib/elasticsearch/quantize.rb +22 -0
- data/lib/ddtrace/contrib/grape/endpoint.rb +164 -0
- data/lib/ddtrace/contrib/grape/patcher.rb +73 -0
- data/lib/ddtrace/contrib/http/patcher.rb +156 -0
- data/lib/ddtrace/contrib/rack/middlewares.rb +150 -0
- data/lib/ddtrace/contrib/rails/action_controller.rb +81 -0
- data/lib/ddtrace/contrib/rails/action_view.rb +110 -0
- data/lib/ddtrace/contrib/rails/active_record.rb +56 -0
- data/lib/ddtrace/contrib/rails/active_support.rb +113 -0
- data/lib/ddtrace/contrib/rails/core_extensions.rb +137 -0
- data/lib/ddtrace/contrib/rails/framework.rb +171 -0
- data/lib/ddtrace/contrib/rails/middlewares.rb +32 -0
- data/lib/ddtrace/contrib/rails/utils.rb +43 -0
- data/lib/ddtrace/contrib/redis/patcher.rb +118 -0
- data/lib/ddtrace/contrib/redis/quantize.rb +30 -0
- data/lib/ddtrace/contrib/redis/tags.rb +19 -0
- data/lib/ddtrace/contrib/sidekiq/tracer.rb +103 -0
- data/lib/ddtrace/contrib/sinatra/tracer.rb +169 -0
- data/lib/ddtrace/distributed.rb +38 -0
- data/lib/ddtrace/encoding.rb +65 -0
- data/lib/ddtrace/error.rb +37 -0
- data/lib/ddtrace/ext/app_types.rb +10 -0
- data/lib/ddtrace/ext/cache.rb +7 -0
- data/lib/ddtrace/ext/distributed.rb +10 -0
- data/lib/ddtrace/ext/errors.rb +10 -0
- data/lib/ddtrace/ext/http.rb +11 -0
- data/lib/ddtrace/ext/net.rb +8 -0
- data/lib/ddtrace/ext/redis.rb +11 -0
- data/lib/ddtrace/ext/sql.rb +8 -0
- data/lib/ddtrace/logger.rb +39 -0
- data/lib/ddtrace/monkey.rb +84 -0
- data/lib/ddtrace/pin.rb +63 -0
- data/lib/ddtrace/provider.rb +21 -0
- data/lib/ddtrace/sampler.rb +49 -0
- data/lib/ddtrace/span.rb +222 -0
- data/lib/ddtrace/tracer.rb +310 -0
- data/lib/ddtrace/transport.rb +162 -0
- data/lib/ddtrace/utils.rb +16 -0
- data/lib/ddtrace/version.rb +9 -0
- data/lib/ddtrace/workers.rb +108 -0
- data/lib/ddtrace/writer.rb +118 -0
- metadata +208 -0
data/Rakefile
ADDED
|
@@ -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
|
data/circle.yml
ADDED
|
@@ -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
|
data/ddtrace.gemspec
ADDED
|
@@ -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
|
data/docker-compose.yml
ADDED
|
@@ -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.
|