ddtrace 0.44.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +183 -15
  3. data/.circleci/images/primary/Dockerfile-2.0.0 +11 -1
  4. data/.circleci/images/primary/Dockerfile-2.1.10 +11 -1
  5. data/.circleci/images/primary/Dockerfile-2.2.10 +11 -1
  6. data/.circleci/images/primary/Dockerfile-2.3.8 +10 -0
  7. data/.circleci/images/primary/Dockerfile-2.4.6 +10 -0
  8. data/.circleci/images/primary/Dockerfile-2.5.6 +10 -0
  9. data/.circleci/images/primary/Dockerfile-2.6.4 +10 -0
  10. data/.circleci/images/primary/Dockerfile-2.7.0 +10 -0
  11. data/.circleci/images/primary/Dockerfile-jruby-9.2-latest +88 -0
  12. data/.circleci/images/primary/{Dockerfile-jruby-9.2 → Dockerfile-jruby-9.2.0.0} +1 -5
  13. data/.circleci/images/primary/Dockerfile-truffleruby-21.0.0 +73 -0
  14. data/.github/workflows/create-next-milestone.yml +2 -2
  15. data/.gitlab-ci.yml +18 -18
  16. data/.rubocop.yml +269 -7
  17. data/.rubocop_todo.yml +438 -0
  18. data/.simplecov +6 -0
  19. data/Appraisals +87 -9
  20. data/CHANGELOG.md +238 -1
  21. data/Gemfile +63 -3
  22. data/LICENSE-3rdparty.csv +2 -0
  23. data/README.md +1 -0
  24. data/Rakefile +65 -25
  25. data/bin/ddtracerb +15 -0
  26. data/ddtrace.gemspec +9 -36
  27. data/docker-compose.yml +75 -7
  28. data/docs/DevelopmentGuide.md +28 -0
  29. data/docs/GettingStarted.md +162 -68
  30. data/docs/ProfilingDevelopment.md +88 -0
  31. data/integration/README.md +67 -0
  32. data/integration/apps/rack/.dockerignore +1 -0
  33. data/integration/apps/rack/.envrc.sample +1 -0
  34. data/integration/apps/rack/.gitignore +4 -0
  35. data/integration/apps/rack/.rspec +1 -0
  36. data/integration/apps/rack/Dockerfile +28 -0
  37. data/integration/apps/rack/Dockerfile-ci +11 -0
  38. data/integration/apps/rack/Gemfile +24 -0
  39. data/integration/apps/rack/README.md +93 -0
  40. data/integration/apps/rack/app/acme.rb +80 -0
  41. data/integration/apps/rack/app/datadog.rb +17 -0
  42. data/integration/apps/rack/bin/run +22 -0
  43. data/integration/apps/rack/bin/setup +17 -0
  44. data/integration/apps/rack/bin/test +24 -0
  45. data/integration/apps/rack/config.ru +6 -0
  46. data/integration/apps/rack/config/puma.rb +14 -0
  47. data/integration/apps/rack/config/unicorn.rb +23 -0
  48. data/integration/apps/rack/docker-compose.ci.yml +62 -0
  49. data/integration/apps/rack/docker-compose.yml +78 -0
  50. data/integration/apps/rack/script/build-images +38 -0
  51. data/integration/apps/rack/script/ci +50 -0
  52. data/integration/apps/rack/spec/integration/basic_spec.rb +10 -0
  53. data/integration/apps/rack/spec/spec_helper.rb +16 -0
  54. data/integration/apps/rack/spec/support/integration_helper.rb +22 -0
  55. data/integration/apps/rails-five/.dockerignore +1 -0
  56. data/integration/apps/rails-five/.env +3 -0
  57. data/integration/apps/rails-five/.envrc.sample +1 -0
  58. data/integration/apps/rails-five/.gitignore +30 -0
  59. data/integration/apps/rails-five/Dockerfile +25 -0
  60. data/integration/apps/rails-five/Dockerfile-ci +11 -0
  61. data/integration/apps/rails-five/Gemfile +104 -0
  62. data/integration/apps/rails-five/README.md +94 -0
  63. data/integration/apps/rails-five/Rakefile +6 -0
  64. data/integration/apps/rails-five/app/channels/application_cable/channel.rb +4 -0
  65. data/integration/apps/rails-five/app/channels/application_cable/connection.rb +4 -0
  66. data/integration/apps/rails-five/app/controllers/application_controller.rb +2 -0
  67. data/integration/apps/rails-five/app/controllers/basic_controller.rb +36 -0
  68. data/integration/apps/rails-five/app/controllers/concerns/.keep +0 -0
  69. data/integration/apps/rails-five/app/controllers/health_controller.rb +9 -0
  70. data/integration/apps/rails-five/app/controllers/jobs_controller.rb +12 -0
  71. data/integration/apps/rails-five/app/jobs/application_job.rb +2 -0
  72. data/integration/apps/rails-five/app/jobs/test_job.rb +12 -0
  73. data/integration/apps/rails-five/app/mailers/application_mailer.rb +4 -0
  74. data/integration/apps/rails-five/app/models/application_record.rb +3 -0
  75. data/integration/apps/rails-five/app/models/concerns/.keep +0 -0
  76. data/integration/apps/rails-five/app/models/test.rb +2 -0
  77. data/integration/apps/rails-five/app/views/layouts/mailer.html.erb +13 -0
  78. data/integration/apps/rails-five/app/views/layouts/mailer.text.erb +1 -0
  79. data/integration/apps/rails-five/bin/bundle +3 -0
  80. data/integration/apps/rails-five/bin/rails +9 -0
  81. data/integration/apps/rails-five/bin/rake +9 -0
  82. data/integration/apps/rails-five/bin/run +24 -0
  83. data/integration/apps/rails-five/bin/setup +27 -0
  84. data/integration/apps/rails-five/bin/spring +17 -0
  85. data/integration/apps/rails-five/bin/test +21 -0
  86. data/integration/apps/rails-five/bin/update +28 -0
  87. data/integration/apps/rails-five/config.ru +5 -0
  88. data/integration/apps/rails-five/config/application.rb +97 -0
  89. data/integration/apps/rails-five/config/boot.rb +4 -0
  90. data/integration/apps/rails-five/config/cable.yml +10 -0
  91. data/integration/apps/rails-five/config/credentials.yml.enc +1 -0
  92. data/integration/apps/rails-five/config/database.yml +28 -0
  93. data/integration/apps/rails-five/config/environment.rb +5 -0
  94. data/integration/apps/rails-five/config/environments/development.rb +51 -0
  95. data/integration/apps/rails-five/config/environments/production.rb +82 -0
  96. data/integration/apps/rails-five/config/environments/test.rb +43 -0
  97. data/integration/apps/rails-five/config/initializers/datadog.rb +18 -0
  98. data/integration/apps/rails-five/config/initializers/filter_parameter_logging.rb +4 -0
  99. data/integration/apps/rails-five/config/initializers/resque.rb +4 -0
  100. data/integration/apps/rails-five/config/initializers/rollbar.rb +5 -0
  101. data/integration/apps/rails-five/config/initializers/wrap_parameters.rb +14 -0
  102. data/integration/apps/rails-five/config/locales/en.yml +33 -0
  103. data/integration/apps/rails-five/config/puma.rb +24 -0
  104. data/integration/apps/rails-five/config/routes.rb +11 -0
  105. data/integration/apps/rails-five/config/spring.rb +6 -0
  106. data/integration/apps/rails-five/config/unicorn.rb +29 -0
  107. data/integration/apps/rails-five/db/migrate/20190927215052_create_tests.rb +11 -0
  108. data/integration/apps/rails-five/db/schema.rb +23 -0
  109. data/integration/apps/rails-five/db/seeds.rb +7 -0
  110. data/integration/apps/rails-five/docker-compose.ci.yml +98 -0
  111. data/integration/apps/rails-five/docker-compose.yml +100 -0
  112. data/integration/apps/rails-five/lib/tasks/.keep +0 -0
  113. data/integration/apps/rails-five/log/.keep +0 -0
  114. data/integration/apps/rails-five/public/robots.txt +1 -0
  115. data/integration/apps/rails-five/script/build-images +35 -0
  116. data/integration/apps/rails-five/script/ci +50 -0
  117. data/integration/apps/rails-five/spec/integration/basic_spec.rb +10 -0
  118. data/integration/apps/rails-five/spec/spec_helper.rb +16 -0
  119. data/integration/apps/rails-five/spec/support/integration_helper.rb +22 -0
  120. data/integration/apps/rails-five/storage/.keep +0 -0
  121. data/integration/apps/rails-five/tmp/.keep +0 -0
  122. data/integration/apps/rails-five/vendor/.keep +0 -0
  123. data/integration/apps/ruby/.dockerignore +1 -0
  124. data/integration/apps/ruby/.envrc.sample +1 -0
  125. data/integration/apps/ruby/.gitignore +2 -0
  126. data/integration/apps/ruby/Dockerfile +25 -0
  127. data/integration/apps/ruby/Dockerfile-ci +11 -0
  128. data/integration/apps/ruby/Gemfile +11 -0
  129. data/integration/apps/ruby/README.md +70 -0
  130. data/integration/apps/ruby/agent.yaml +3 -0
  131. data/integration/apps/ruby/app/datadog.rb +13 -0
  132. data/integration/apps/ruby/app/fibonacci.rb +58 -0
  133. data/integration/apps/ruby/bin/run +20 -0
  134. data/integration/apps/ruby/bin/setup +17 -0
  135. data/integration/apps/ruby/bin/test +21 -0
  136. data/integration/apps/ruby/docker-compose.ci.yml +51 -0
  137. data/integration/apps/ruby/docker-compose.yml +63 -0
  138. data/integration/apps/ruby/script/build-images +38 -0
  139. data/integration/apps/ruby/script/ci +50 -0
  140. data/integration/images/agent/Dockerfile +2 -0
  141. data/integration/images/agent/agent.yaml +3 -0
  142. data/integration/images/include/datadog/analyzer.rb +71 -0
  143. data/integration/images/include/datadog/demo_env.rb +101 -0
  144. data/integration/images/include/http-health-check +33 -0
  145. data/integration/images/ruby/2.0/Dockerfile +54 -0
  146. data/integration/images/ruby/2.1/Dockerfile +54 -0
  147. data/integration/images/ruby/2.2/Dockerfile +54 -0
  148. data/integration/images/ruby/2.3/Dockerfile +70 -0
  149. data/integration/images/ruby/2.4/Dockerfile +54 -0
  150. data/integration/images/ruby/2.5/Dockerfile +54 -0
  151. data/integration/images/ruby/2.6/Dockerfile +54 -0
  152. data/integration/images/ruby/2.7/Dockerfile +54 -0
  153. data/integration/images/ruby/3.0/Dockerfile +54 -0
  154. data/integration/images/wrk/Dockerfile +33 -0
  155. data/integration/images/wrk/scripts/entrypoint.sh +17 -0
  156. data/integration/images/wrk/scripts/scenarios/basic/default.lua +1 -0
  157. data/integration/images/wrk/scripts/scenarios/basic/fibonacci.lua +1 -0
  158. data/integration/script/build-images +43 -0
  159. data/lib/ddtrace.rb +8 -5
  160. data/lib/ddtrace/analytics.rb +2 -0
  161. data/lib/ddtrace/auto_instrument.rb +3 -0
  162. data/lib/ddtrace/auto_instrument_base.rb +6 -0
  163. data/lib/ddtrace/buffer.rb +4 -4
  164. data/lib/ddtrace/configuration.rb +121 -26
  165. data/lib/ddtrace/configuration/base.rb +1 -1
  166. data/lib/ddtrace/configuration/components.rb +87 -5
  167. data/lib/ddtrace/configuration/option_definition.rb +1 -3
  168. data/lib/ddtrace/configuration/options.rb +4 -7
  169. data/lib/ddtrace/configuration/settings.rb +48 -3
  170. data/lib/ddtrace/context.rb +5 -6
  171. data/lib/ddtrace/context_provider.rb +0 -1
  172. data/lib/ddtrace/contrib/action_cable/event.rb +1 -0
  173. data/lib/ddtrace/contrib/action_cable/integration.rb +7 -0
  174. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +1 -3
  175. data/lib/ddtrace/contrib/action_pack/integration.rb +7 -0
  176. data/lib/ddtrace/contrib/action_view/event.rb +1 -1
  177. data/lib/ddtrace/contrib/action_view/integration.rb +7 -0
  178. data/lib/ddtrace/contrib/action_view/utils.rb +1 -1
  179. data/lib/ddtrace/contrib/active_record/configuration/makara_resolver.rb +30 -0
  180. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +107 -18
  181. data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
  182. data/lib/ddtrace/contrib/active_record/utils.rb +57 -20
  183. data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
  184. data/lib/ddtrace/contrib/active_support/notifications/event.rb +2 -1
  185. data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +1 -0
  186. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +9 -5
  187. data/lib/ddtrace/contrib/auto_instrument.rb +49 -0
  188. data/lib/ddtrace/contrib/aws/patcher.rb +1 -0
  189. data/lib/ddtrace/contrib/aws/services.rb +2 -0
  190. data/lib/ddtrace/contrib/configurable.rb +63 -39
  191. data/lib/ddtrace/contrib/configuration/resolver.rb +70 -5
  192. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +19 -20
  193. data/lib/ddtrace/contrib/configuration/settings.rb +7 -6
  194. data/lib/ddtrace/contrib/cucumber/configuration/settings.rb +0 -10
  195. data/lib/ddtrace/contrib/cucumber/ext.rb +0 -2
  196. data/lib/ddtrace/contrib/cucumber/formatter.rb +5 -11
  197. data/lib/ddtrace/contrib/cucumber/integration.rb +5 -0
  198. data/lib/ddtrace/contrib/dalli/patcher.rb +0 -38
  199. data/lib/ddtrace/contrib/delayed_job/plugin.rb +0 -1
  200. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -0
  201. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +3 -2
  202. data/lib/ddtrace/contrib/ethon/easy_patch.rb +10 -9
  203. data/lib/ddtrace/contrib/excon/middleware.rb +2 -6
  204. data/lib/ddtrace/contrib/extensions.rb +53 -3
  205. data/lib/ddtrace/contrib/faraday/middleware.rb +1 -3
  206. data/lib/ddtrace/contrib/faraday/patcher.rb +0 -36
  207. data/lib/ddtrace/contrib/grape/endpoint.rb +8 -15
  208. data/lib/ddtrace/contrib/grape/patcher.rb +0 -42
  209. data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +8 -8
  210. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +1 -0
  211. data/lib/ddtrace/contrib/grpc/patcher.rb +0 -36
  212. data/lib/ddtrace/contrib/http/circuit_breaker.rb +1 -3
  213. data/lib/ddtrace/contrib/http/instrumentation.rb +5 -5
  214. data/lib/ddtrace/contrib/httpclient/configuration/settings.rb +32 -0
  215. data/lib/ddtrace/contrib/httpclient/ext.rb +17 -0
  216. data/lib/ddtrace/contrib/httpclient/instrumentation.rb +147 -0
  217. data/lib/ddtrace/contrib/httpclient/integration.rb +43 -0
  218. data/lib/ddtrace/contrib/httpclient/patcher.rb +38 -0
  219. data/lib/ddtrace/contrib/httprb/instrumentation.rb +14 -20
  220. data/lib/ddtrace/contrib/httprb/patcher.rb +5 -2
  221. data/lib/ddtrace/contrib/mongodb/instrumentation.rb +2 -0
  222. data/lib/ddtrace/contrib/mongodb/subscribers.rb +2 -3
  223. data/lib/ddtrace/contrib/patchable.rb +18 -7
  224. data/lib/ddtrace/contrib/patcher.rb +9 -6
  225. data/lib/ddtrace/contrib/presto/patcher.rb +5 -2
  226. data/lib/ddtrace/contrib/qless/qless_job.rb +1 -0
  227. data/lib/ddtrace/contrib/qless/tracer_cleaner.rb +1 -0
  228. data/lib/ddtrace/contrib/que/ext.rb +19 -19
  229. data/lib/ddtrace/contrib/que/tracer.rb +1 -1
  230. data/lib/ddtrace/contrib/racecar/event.rb +1 -0
  231. data/lib/ddtrace/contrib/rack/configuration/settings.rb +3 -3
  232. data/lib/ddtrace/contrib/rack/integration.rb +7 -0
  233. data/lib/ddtrace/contrib/rack/middlewares.rb +6 -11
  234. data/lib/ddtrace/contrib/rack/patcher.rb +1 -3
  235. data/lib/ddtrace/contrib/rack/request_queue.rb +6 -1
  236. data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +10 -0
  237. data/lib/ddtrace/contrib/rails/patcher.rb +6 -2
  238. data/lib/ddtrace/contrib/rails/utils.rb +4 -0
  239. data/lib/ddtrace/contrib/rake/instrumentation.rb +4 -2
  240. data/lib/ddtrace/contrib/rake/integration.rb +1 -1
  241. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +11 -4
  242. data/lib/ddtrace/contrib/redis/quantize.rb +1 -0
  243. data/lib/ddtrace/contrib/redis/vendor/LICENSE +20 -0
  244. data/lib/ddtrace/contrib/redis/vendor/resolver.rb +6 -7
  245. data/lib/ddtrace/contrib/registry.rb +2 -2
  246. data/lib/ddtrace/contrib/resque/configuration/settings.rb +17 -1
  247. data/lib/ddtrace/contrib/resque/integration.rb +1 -1
  248. data/lib/ddtrace/contrib/resque/patcher.rb +4 -4
  249. data/lib/ddtrace/contrib/resque/resque_job.rb +24 -1
  250. data/lib/ddtrace/contrib/rest_client/request_patch.rb +1 -3
  251. data/lib/ddtrace/contrib/rspec/configuration/settings.rb +0 -10
  252. data/lib/ddtrace/contrib/rspec/example.rb +24 -10
  253. data/lib/ddtrace/contrib/rspec/ext.rb +0 -3
  254. data/lib/ddtrace/contrib/rspec/integration.rb +6 -1
  255. data/lib/ddtrace/contrib/rspec/patcher.rb +0 -2
  256. data/lib/ddtrace/contrib/sequel/utils.rb +5 -6
  257. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +1 -0
  258. data/lib/ddtrace/contrib/shoryuken/tracer.rb +7 -4
  259. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +2 -7
  260. data/lib/ddtrace/contrib/sidekiq/tracing.rb +0 -1
  261. data/lib/ddtrace/contrib/sinatra/env.rb +1 -3
  262. data/lib/ddtrace/contrib/sinatra/headers.rb +1 -3
  263. data/lib/ddtrace/contrib/sinatra/tracer.rb +1 -3
  264. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +3 -3
  265. data/lib/ddtrace/contrib/sneakers/ext.rb +11 -11
  266. data/lib/ddtrace/contrib/sneakers/tracer.rb +2 -4
  267. data/lib/ddtrace/contrib/status_code_matcher.rb +5 -3
  268. data/lib/ddtrace/correlation.rb +1 -0
  269. data/lib/ddtrace/diagnostics/environment_logger.rb +3 -2
  270. data/lib/ddtrace/distributed_tracing/headers/headers.rb +1 -0
  271. data/lib/ddtrace/distributed_tracing/headers/helpers.rb +1 -3
  272. data/lib/ddtrace/error.rb +2 -0
  273. data/lib/ddtrace/ext/ci.rb +43 -10
  274. data/lib/ddtrace/ext/distributed.rb +1 -1
  275. data/lib/ddtrace/ext/git.rb +0 -1
  276. data/lib/ddtrace/ext/http.rb +1 -1
  277. data/lib/ddtrace/ext/profiling.rb +52 -0
  278. data/lib/ddtrace/ext/runtime.rb +3 -1
  279. data/lib/ddtrace/ext/transport.rb +1 -0
  280. data/lib/ddtrace/forced_tracing.rb +2 -0
  281. data/lib/ddtrace/logger.rb +1 -1
  282. data/lib/ddtrace/metrics.rb +14 -6
  283. data/lib/ddtrace/opentracer/distributed_headers.rb +3 -0
  284. data/lib/ddtrace/opentracer/span.rb +2 -6
  285. data/lib/ddtrace/opentracer/thread_local_scope.rb +1 -0
  286. data/lib/ddtrace/patcher.rb +25 -4
  287. data/lib/ddtrace/pin.rb +8 -61
  288. data/lib/ddtrace/pipeline/span_filter.rb +1 -1
  289. data/lib/ddtrace/profiling.rb +54 -0
  290. data/lib/ddtrace/profiling/backtrace_location.rb +32 -0
  291. data/lib/ddtrace/profiling/buffer.rb +41 -0
  292. data/lib/ddtrace/profiling/collectors/stack.rb +253 -0
  293. data/lib/ddtrace/profiling/encoding/profile.rb +31 -0
  294. data/lib/ddtrace/profiling/event.rb +13 -0
  295. data/lib/ddtrace/profiling/events/stack.rb +102 -0
  296. data/lib/ddtrace/profiling/exporter.rb +23 -0
  297. data/lib/ddtrace/profiling/ext/cpu.rb +54 -0
  298. data/lib/ddtrace/profiling/ext/cthread.rb +134 -0
  299. data/lib/ddtrace/profiling/ext/forking.rb +97 -0
  300. data/lib/ddtrace/profiling/flush.rb +41 -0
  301. data/lib/ddtrace/profiling/pprof/builder.rb +121 -0
  302. data/lib/ddtrace/profiling/pprof/converter.rb +85 -0
  303. data/lib/ddtrace/profiling/pprof/message_set.rb +12 -0
  304. data/lib/ddtrace/profiling/pprof/payload.rb +18 -0
  305. data/lib/ddtrace/profiling/pprof/pprof.proto +212 -0
  306. data/lib/ddtrace/profiling/pprof/pprof_pb.rb +81 -0
  307. data/lib/ddtrace/profiling/pprof/stack_sample.rb +90 -0
  308. data/lib/ddtrace/profiling/pprof/string_table.rb +10 -0
  309. data/lib/ddtrace/profiling/pprof/template.rb +114 -0
  310. data/lib/ddtrace/profiling/preload.rb +3 -0
  311. data/lib/ddtrace/profiling/profiler.rb +28 -0
  312. data/lib/ddtrace/profiling/recorder.rb +87 -0
  313. data/lib/ddtrace/profiling/scheduler.rb +84 -0
  314. data/lib/ddtrace/profiling/tasks/setup.rb +77 -0
  315. data/lib/ddtrace/profiling/transport/client.rb +12 -0
  316. data/lib/ddtrace/profiling/transport/http.rb +122 -0
  317. data/lib/ddtrace/profiling/transport/http/api.rb +43 -0
  318. data/lib/ddtrace/profiling/transport/http/api/endpoint.rb +90 -0
  319. data/lib/ddtrace/profiling/transport/http/api/instance.rb +36 -0
  320. data/lib/ddtrace/profiling/transport/http/api/spec.rb +40 -0
  321. data/lib/ddtrace/profiling/transport/http/builder.rb +28 -0
  322. data/lib/ddtrace/profiling/transport/http/client.rb +33 -0
  323. data/lib/ddtrace/profiling/transport/http/response.rb +21 -0
  324. data/lib/ddtrace/profiling/transport/io.rb +30 -0
  325. data/lib/ddtrace/profiling/transport/io/client.rb +27 -0
  326. data/lib/ddtrace/profiling/transport/io/response.rb +16 -0
  327. data/lib/ddtrace/profiling/transport/parcel.rb +17 -0
  328. data/lib/ddtrace/profiling/transport/request.rb +15 -0
  329. data/lib/ddtrace/profiling/transport/response.rb +8 -0
  330. data/lib/ddtrace/propagation/grpc_propagator.rb +1 -0
  331. data/lib/ddtrace/propagation/http_propagator.rb +17 -2
  332. data/lib/ddtrace/quantization/http.rb +1 -0
  333. data/lib/ddtrace/runtime/cgroup.rb +2 -2
  334. data/lib/ddtrace/runtime/container.rb +32 -26
  335. data/lib/ddtrace/runtime/identity.rb +8 -0
  336. data/lib/ddtrace/sampler.rb +1 -1
  337. data/lib/ddtrace/sampling/rule_sampler.rb +4 -9
  338. data/lib/ddtrace/span.rb +7 -7
  339. data/lib/ddtrace/sync_writer.rb +12 -12
  340. data/lib/ddtrace/tasks/exec.rb +48 -0
  341. data/lib/ddtrace/tasks/help.rb +14 -0
  342. data/lib/ddtrace/tracer.rb +28 -5
  343. data/lib/ddtrace/transport/http.rb +15 -8
  344. data/lib/ddtrace/transport/http/adapters/net.rb +27 -8
  345. data/lib/ddtrace/transport/http/adapters/registry.rb +1 -0
  346. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +2 -4
  347. data/lib/ddtrace/transport/http/builder.rb +7 -1
  348. data/lib/ddtrace/transport/http/env.rb +8 -0
  349. data/lib/ddtrace/transport/http/traces.rb +2 -3
  350. data/lib/ddtrace/transport/io.rb +1 -1
  351. data/lib/ddtrace/transport/io/client.rb +15 -8
  352. data/lib/ddtrace/transport/io/response.rb +1 -3
  353. data/lib/ddtrace/transport/io/traces.rb +6 -0
  354. data/lib/ddtrace/transport/parcel.rb +4 -0
  355. data/lib/ddtrace/transport/traces.rb +18 -1
  356. data/lib/ddtrace/utils/compression.rb +27 -0
  357. data/lib/ddtrace/utils/object_set.rb +41 -0
  358. data/lib/ddtrace/utils/only_once.rb +40 -0
  359. data/lib/ddtrace/utils/sequence.rb +17 -0
  360. data/lib/ddtrace/utils/string_table.rb +45 -0
  361. data/lib/ddtrace/utils/time.rb +32 -1
  362. data/lib/ddtrace/vendor/active_record/MIT-LICENSE +20 -0
  363. data/lib/ddtrace/vendor/multipart-post/LICENSE +11 -0
  364. data/lib/ddtrace/vendor/multipart-post/multipart.rb +12 -0
  365. data/lib/ddtrace/vendor/multipart-post/multipart/post.rb +8 -0
  366. data/lib/ddtrace/vendor/multipart-post/multipart/post/composite_read_io.rb +116 -0
  367. data/lib/ddtrace/vendor/multipart-post/multipart/post/multipartable.rb +57 -0
  368. data/lib/ddtrace/vendor/multipart-post/multipart/post/parts.rb +135 -0
  369. data/lib/ddtrace/vendor/multipart-post/multipart/post/version.rb +9 -0
  370. data/lib/ddtrace/vendor/multipart-post/net/http/post/multipart.rb +32 -0
  371. data/lib/ddtrace/version.rb +3 -1
  372. data/lib/ddtrace/workers.rb +5 -0
  373. data/lib/ddtrace/workers/async.rb +11 -3
  374. data/lib/ddtrace/workers/loop.rb +17 -3
  375. data/lib/ddtrace/workers/polling.rb +1 -0
  376. data/lib/ddtrace/workers/queue.rb +1 -0
  377. data/lib/ddtrace/workers/runtime_metrics.rb +14 -1
  378. data/lib/ddtrace/workers/trace_writer.rb +10 -10
  379. data/lib/ddtrace/writer.rb +7 -4
  380. metadata +213 -379
  381. data/lib/ddtrace/augmentation.rb +0 -13
  382. data/lib/ddtrace/augmentation/method_wrapper.rb +0 -20
  383. data/lib/ddtrace/augmentation/method_wrapping.rb +0 -38
  384. data/lib/ddtrace/augmentation/shim.rb +0 -102
  385. data/lib/ddtrace/contrib/rspec/example_group.rb +0 -61
  386. data/lib/ddtrace/monkey.rb +0 -58
@@ -0,0 +1,41 @@
1
+ require 'ddtrace/buffer'
2
+ require 'ddtrace/utils/string_table'
3
+ require 'ddtrace/utils/object_set'
4
+
5
+ module Datadog
6
+ module Profiling
7
+ # Profiling buffer that stores profiling events. The buffer has a maximum size and when
8
+ # the buffer is full, a random event is discarded. This class is thread-safe.
9
+ class Buffer < Datadog::ThreadSafeBuffer
10
+ def initialize(*args)
11
+ super
12
+ @caches = {}
13
+ @string_table = Utils::StringTable.new
14
+ end
15
+
16
+ def cache(cache_name)
17
+ synchronize do
18
+ @caches[cache_name] ||= Utils::ObjectSet.new
19
+ end
20
+ end
21
+
22
+ def string_table
23
+ synchronize do
24
+ @string_table
25
+ end
26
+ end
27
+
28
+ protected
29
+
30
+ def drain!
31
+ items = super
32
+
33
+ # Clear caches
34
+ @caches = {}
35
+ @string_table = Utils::StringTable.new
36
+
37
+ items
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,253 @@
1
+ require 'ddtrace/profiling/backtrace_location'
2
+ require 'ddtrace/profiling/events/stack'
3
+ require 'ddtrace/utils/only_once'
4
+ require 'ddtrace/utils/time'
5
+ require 'ddtrace/worker'
6
+ require 'ddtrace/workers/polling'
7
+
8
+ module Datadog
9
+ module Profiling
10
+ module Collectors
11
+ # Collects stack trace samples from Ruby threads for both CPU-time (if available) and wall-clock.
12
+ # Runs on its own background thread.
13
+ #
14
+ class Stack < Worker
15
+ include Workers::Polling
16
+
17
+ DEFAULT_MAX_TIME_USAGE_PCT = 2.0
18
+ MIN_INTERVAL = 0.01
19
+ THREAD_LAST_CPU_TIME_KEY = :datadog_profiler_last_cpu_time
20
+
21
+ attr_reader \
22
+ :recorder,
23
+ :max_frames,
24
+ :ignore_thread,
25
+ :max_time_usage_pct,
26
+ :thread_api
27
+
28
+ def initialize(
29
+ recorder,
30
+ max_frames: nil,
31
+ ignore_thread: nil,
32
+ max_time_usage_pct: DEFAULT_MAX_TIME_USAGE_PCT,
33
+ thread_api: Thread,
34
+ fork_policy: Workers::Async::Thread::FORK_POLICY_RESTART, # Restart in forks by default
35
+ interval: MIN_INTERVAL,
36
+ enabled: true
37
+ )
38
+ @recorder = recorder
39
+ # TODO: Make this a required named argument after we drop support for Ruby 2.0
40
+ @max_frames = max_frames || raise(ArgumentError, 'missing keyword :max_frames')
41
+ @ignore_thread = ignore_thread
42
+ @max_time_usage_pct = max_time_usage_pct
43
+ @thread_api = thread_api
44
+
45
+ # Workers::Async::Thread settings
46
+ self.fork_policy = fork_policy
47
+
48
+ # Workers::IntervalLoop settings
49
+ self.loop_base_interval = interval
50
+
51
+ # Workers::Polling settings
52
+ self.enabled = enabled
53
+
54
+ @warn_about_missing_cpu_time_instrumentation_only_once = Datadog::Utils::OnlyOnce.new
55
+ end
56
+
57
+ def start
58
+ @last_wall_time = Datadog::Utils::Time.get_time
59
+ reset_cpu_time_tracking
60
+ perform
61
+ end
62
+
63
+ def perform
64
+ collect_and_wait
65
+ end
66
+
67
+ def loop_back_off?
68
+ false
69
+ end
70
+
71
+ def collect_and_wait
72
+ run_time = Datadog::Utils::Time.measure do
73
+ collect_events
74
+ end
75
+
76
+ # Update wait time to throttle profiling
77
+ self.loop_wait_time = compute_wait_time(run_time)
78
+ end
79
+
80
+ def collect_events
81
+ events = []
82
+
83
+ # Compute wall time interval
84
+ current_wall_time = Datadog::Utils::Time.get_time
85
+ last_wall_time = if instance_variable_defined?(:@last_wall_time)
86
+ @last_wall_time
87
+ else
88
+ current_wall_time
89
+ end
90
+
91
+ wall_time_interval_ns = ((current_wall_time - last_wall_time).round(9) * 1e9).to_i
92
+ @last_wall_time = current_wall_time
93
+
94
+ # Collect backtraces from each thread
95
+ thread_api.list.each do |thread|
96
+ next unless thread.alive?
97
+ next if ignore_thread.is_a?(Proc) && ignore_thread.call(thread)
98
+
99
+ event = collect_thread_event(thread, wall_time_interval_ns)
100
+ events << event unless event.nil?
101
+ end
102
+
103
+ # Send events to recorder
104
+ recorder.push(events) unless events.empty?
105
+
106
+ events
107
+ end
108
+
109
+ def collect_thread_event(thread, wall_time_interval_ns)
110
+ locations = thread.backtrace_locations
111
+ return if locations.nil?
112
+
113
+ # Get actual stack size then trim the stack
114
+ stack_size = locations.length
115
+ locations = locations[0..(max_frames - 1)]
116
+
117
+ # Convert backtrace locations into structs
118
+ locations = convert_backtrace_locations(locations)
119
+
120
+ thread_id = thread.respond_to?(:native_thread_id) ? thread.native_thread_id : thread.object_id
121
+ trace_id, span_id = get_trace_identifiers(thread)
122
+ cpu_time = get_cpu_time_interval!(thread)
123
+
124
+ Events::StackSample.new(
125
+ nil,
126
+ locations,
127
+ stack_size,
128
+ thread_id,
129
+ trace_id,
130
+ span_id,
131
+ cpu_time,
132
+ wall_time_interval_ns
133
+ )
134
+ end
135
+
136
+ def get_cpu_time_interval!(thread)
137
+ # Return if we can't get the current CPU time
138
+ unless thread.respond_to?(:cpu_time_instrumentation_installed?) && thread.cpu_time_instrumentation_installed?
139
+ warn_about_missing_cpu_time_instrumentation(thread)
140
+ return
141
+ end
142
+
143
+ current_cpu_time_ns = thread.cpu_time(:nanosecond)
144
+
145
+ # NOTE: This can still be nil even when all of the checks above passed because of a race: there's a bit of
146
+ # initialization that needs to be done by the thread itself, and it's possible for us to try to sample
147
+ # *before* the thread had time to finish the initialization
148
+ return unless current_cpu_time_ns
149
+
150
+ last_cpu_time_ns = (thread[THREAD_LAST_CPU_TIME_KEY] || current_cpu_time_ns)
151
+ interval = current_cpu_time_ns - last_cpu_time_ns
152
+
153
+ # Update CPU time for thread
154
+ thread[THREAD_LAST_CPU_TIME_KEY] = current_cpu_time_ns
155
+
156
+ # Return interval
157
+ interval
158
+ end
159
+
160
+ def get_trace_identifiers(thread)
161
+ return unless thread.is_a?(::Thread)
162
+ return unless Datadog.respond_to?(:tracer) && Datadog.tracer.respond_to?(:active_correlation)
163
+
164
+ identifier = Datadog.tracer.active_correlation(thread)
165
+ [identifier.trace_id, identifier.span_id]
166
+ end
167
+
168
+ def compute_wait_time(used_time)
169
+ # We took used_time to get the last sample.
170
+ #
171
+ # What we're computing here is -- if used_time corresponds to max_time_usage_pct of the time we should
172
+ # spend working, how much is (100% - max_time_usage_pct) of the time?
173
+ #
174
+ # For instance, if we took 10ms to sample, and max_time_usage_pct is 1%, then the other 99% is 990ms, which
175
+ # means we need to sleep for 990ms to guarantee that we don't spend more than 1% of the time working.
176
+ used_time_ns = used_time * 1e9
177
+ interval = (used_time_ns / (max_time_usage_pct / 100.0)) - used_time_ns
178
+ [interval / 1e9, MIN_INTERVAL].max
179
+ end
180
+
181
+ # Convert backtrace locations into structs
182
+ # Re-use old backtrace location objects if they already exist in the buffer
183
+ def convert_backtrace_locations(locations)
184
+ locations.collect do |location|
185
+ # Re-use existing BacktraceLocation if identical copy, otherwise build a new one.
186
+ recorder[Events::StackSample].cache(:backtrace_locations).fetch(
187
+ # Function name
188
+ location.base_label,
189
+ # Line number
190
+ location.lineno,
191
+ # Filename
192
+ location.path,
193
+ # Build function
194
+ &method(:build_backtrace_location)
195
+ )
196
+ end
197
+ end
198
+
199
+ def build_backtrace_location(_id, base_label, lineno, path)
200
+ string_table = recorder[Events::StackSample].string_table
201
+
202
+ Profiling::BacktraceLocation.new(
203
+ string_table.fetch_string(base_label),
204
+ lineno,
205
+ string_table.fetch_string(path)
206
+ )
207
+ end
208
+
209
+ private
210
+
211
+ def warn_about_missing_cpu_time_instrumentation(thread)
212
+ @warn_about_missing_cpu_time_instrumentation_only_once.run do
213
+ # Is the profiler thread instrumented? If it is, then we know instrumentation is available, but seems to be
214
+ # missing on this thread we just found.
215
+ #
216
+ # As far as we know, it can be missing due to one the following:
217
+ #
218
+ # a) The thread was started before we installed our instrumentation.
219
+ # In this case, the fix is to make sure ddtrace gets loaded before any other parts of the application.
220
+ #
221
+ # b) The thread was started using the Ruby native APIs (e.g. from a C extension such as ffi).
222
+ # We currently have no solution for this case; these threads will always be missing our CPU instrumentation.
223
+ #
224
+ # c) The thread was started with `Thread.start`/`Thread.fork` and hasn't yet enabled the instrumentation.
225
+ # When threads are started using these APIs, there's a small time window during which the thread has started
226
+ # but our code to apply the instrumentation hasn't run yet; in these cases it's just a matter of allowing
227
+ # it to run and our instrumentation to be applied.
228
+ #
229
+ if thread_api.current.respond_to?(:cpu_time) && thread_api.current.cpu_time
230
+ Datadog.logger.debug("Detected thread ('#{thread}') with missing CPU profiling instrumentation.")
231
+ end
232
+ end
233
+ end
234
+
235
+ # If the profiler is started for a while, stopped and then restarted OR whenever the process forks, we need to
236
+ # clean up the per-thread cpu time counters we keep, so that the first sample after starting doesn't end up with:
237
+ #
238
+ # a) negative time: At least on my test docker container, and on the reliability environment, after the process
239
+ # forks, the clock reference changes and (old cpu time - new cpu time) can be < 0
240
+ #
241
+ # b) large amount of time: if the profiler was started, then stopped for some amount of time, and then
242
+ # restarted, we don't want the first sample to be "blamed" for multiple minutes of CPU time
243
+ #
244
+ # By resetting the last cpu time seen, we start with a clean slate every time we start the stack collector.
245
+ def reset_cpu_time_tracking
246
+ thread_api.list.each do |thread|
247
+ thread[THREAD_LAST_CPU_TIME_KEY] = nil if thread[THREAD_LAST_CPU_TIME_KEY]
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,31 @@
1
+ require 'set'
2
+
3
+ require 'ddtrace/profiling/flush'
4
+ require 'ddtrace/profiling/pprof/template'
5
+
6
+ module Datadog
7
+ module Profiling
8
+ module Encoding
9
+ module Profile
10
+ # Encodes gathered data into the pprof format
11
+ module Protobuf
12
+ module_function
13
+
14
+ def encode(flush)
15
+ return unless flush
16
+
17
+ # Create a pprof template from the list of event types
18
+ event_classes = flush.event_groups.collect(&:event_class).uniq
19
+ template = Pprof::Template.for_event_classes(event_classes)
20
+
21
+ # Add all events to the pprof
22
+ flush.event_groups.each { |event_group| template.add_events!(event_group.event_class, event_group.events) }
23
+
24
+ # Build the profile and encode it
25
+ template.to_pprof
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module Datadog
2
+ module Profiling
3
+ # Describes a sample of some data obtained from the runtime.
4
+ class Event
5
+ attr_reader \
6
+ :timestamp
7
+
8
+ def initialize(timestamp = nil)
9
+ @timestamp = timestamp || Time.now.utc.to_f
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,102 @@
1
+ require 'ddtrace/profiling/event'
2
+
3
+ module Datadog
4
+ module Profiling
5
+ module Events
6
+ # Describes a stack profiling event
7
+ class Stack < Event
8
+ attr_reader \
9
+ :frames,
10
+ :hash,
11
+ :span_id,
12
+ :thread_id,
13
+ :total_frame_count,
14
+ :trace_id
15
+
16
+ def initialize(
17
+ timestamp,
18
+ frames,
19
+ total_frame_count,
20
+ thread_id,
21
+ trace_id,
22
+ span_id
23
+ )
24
+ super(timestamp)
25
+
26
+ @frames = frames
27
+ @total_frame_count = total_frame_count
28
+ @thread_id = thread_id
29
+ @trace_id = trace_id
30
+ @span_id = span_id
31
+
32
+ @hash = [
33
+ thread_id,
34
+ trace_id,
35
+ span_id,
36
+ [
37
+ frames.collect(&:hash),
38
+ total_frame_count
39
+ ]
40
+ ].hash
41
+ end
42
+ end
43
+
44
+ # Describes a stack sample
45
+ class StackSample < Stack
46
+ attr_reader \
47
+ :cpu_time_interval_ns,
48
+ :wall_time_interval_ns
49
+
50
+ def initialize(
51
+ timestamp,
52
+ frames,
53
+ total_frame_count,
54
+ thread_id,
55
+ trace_id,
56
+ span_id,
57
+ cpu_time_interval_ns,
58
+ wall_time_interval_ns
59
+ )
60
+ super(
61
+ timestamp,
62
+ frames,
63
+ total_frame_count,
64
+ thread_id,
65
+ trace_id,
66
+ span_id
67
+ )
68
+
69
+ @cpu_time_interval_ns = cpu_time_interval_ns
70
+ @wall_time_interval_ns = wall_time_interval_ns
71
+ end
72
+ end
73
+
74
+ # Describes a stack sample with exception
75
+ class StackExceptionSample < Stack
76
+ attr_reader \
77
+ :exception
78
+
79
+ def initialize(
80
+ timestamp,
81
+ frames,
82
+ total_frame_count,
83
+ thread_id,
84
+ trace_id,
85
+ span_id,
86
+ exception
87
+ )
88
+ super(
89
+ timestamp,
90
+ frames,
91
+ total_frame_count,
92
+ thread_id,
93
+ trace_id,
94
+ span_id
95
+ )
96
+
97
+ @exception = exception
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,23 @@
1
+ require 'ddtrace/profiling/transport/io/client'
2
+
3
+ module Datadog
4
+ module Profiling
5
+ # Writes profiling data to a given transport
6
+ class Exporter
7
+ attr_reader \
8
+ :transport
9
+
10
+ def initialize(transport)
11
+ unless transport.is_a?(Profiling::Transport::Client)
12
+ raise ArgumentError, 'Unsupported transport for profiling exporter.'
13
+ end
14
+
15
+ @transport = transport
16
+ end
17
+
18
+ def export(flush)
19
+ transport.send_profiling_flush(flush)
20
+ end
21
+ end
22
+ end
23
+ end