ddtrace 0.41.0 → 0.46.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 (332) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +223 -126
  3. data/.circleci/images/primary/Dockerfile-3.0.0 +73 -0
  4. data/.github/workflows/add-milestone-to-pull-requests.yml +42 -0
  5. data/.github/workflows/create-next-milestone.yml +20 -0
  6. data/.rubocop.yml +250 -7
  7. data/.rubocop_todo.yml +396 -0
  8. data/.simplecov +3 -0
  9. data/Appraisals +429 -135
  10. data/CHANGELOG.md +1158 -354
  11. data/CONTRIBUTING.md +2 -2
  12. data/Gemfile +40 -3
  13. data/README.md +1 -0
  14. data/Rakefile +236 -29
  15. data/ddtrace.gemspec +4 -35
  16. data/docker-compose.yml +30 -0
  17. data/docs/DevelopmentGuide.md +40 -2
  18. data/docs/GettingStarted.md +186 -16
  19. data/integration/README.md +68 -0
  20. data/integration/apps/rack/.dockerignore +1 -0
  21. data/integration/apps/rack/.envrc.sample +1 -0
  22. data/integration/apps/rack/.gitignore +4 -0
  23. data/integration/apps/rack/.rspec +1 -0
  24. data/integration/apps/rack/Dockerfile +25 -0
  25. data/integration/apps/rack/Dockerfile-ci +11 -0
  26. data/integration/apps/rack/Gemfile +24 -0
  27. data/integration/apps/rack/README.md +93 -0
  28. data/integration/apps/rack/app/acme.rb +80 -0
  29. data/integration/apps/rack/app/datadog.rb +17 -0
  30. data/integration/apps/rack/bin/run +22 -0
  31. data/integration/apps/rack/bin/setup +17 -0
  32. data/integration/apps/rack/bin/test +24 -0
  33. data/integration/apps/rack/config.ru +6 -0
  34. data/integration/apps/rack/config/puma.rb +14 -0
  35. data/integration/apps/rack/config/unicorn.rb +23 -0
  36. data/integration/apps/rack/docker-compose.ci.yml +62 -0
  37. data/integration/apps/rack/docker-compose.yml +78 -0
  38. data/integration/apps/rack/script/build-images +38 -0
  39. data/integration/apps/rack/script/ci +50 -0
  40. data/integration/apps/rack/spec/integration/basic_spec.rb +10 -0
  41. data/integration/apps/rack/spec/spec_helper.rb +16 -0
  42. data/integration/apps/rack/spec/support/integration_helper.rb +22 -0
  43. data/integration/apps/rails-five/.dockerignore +1 -0
  44. data/integration/apps/rails-five/.env +3 -0
  45. data/integration/apps/rails-five/.envrc.sample +1 -0
  46. data/integration/apps/rails-five/.gitignore +30 -0
  47. data/integration/apps/rails-five/Dockerfile +25 -0
  48. data/integration/apps/rails-five/Dockerfile-ci +11 -0
  49. data/integration/apps/rails-five/Gemfile +104 -0
  50. data/integration/apps/rails-five/README.md +94 -0
  51. data/integration/apps/rails-five/Rakefile +6 -0
  52. data/integration/apps/rails-five/app/channels/application_cable/channel.rb +4 -0
  53. data/integration/apps/rails-five/app/channels/application_cable/connection.rb +4 -0
  54. data/integration/apps/rails-five/app/controllers/application_controller.rb +2 -0
  55. data/integration/apps/rails-five/app/controllers/basic_controller.rb +36 -0
  56. data/integration/apps/rails-five/app/controllers/concerns/.keep +0 -0
  57. data/integration/apps/rails-five/app/controllers/health_controller.rb +9 -0
  58. data/integration/apps/rails-five/app/controllers/jobs_controller.rb +12 -0
  59. data/integration/apps/rails-five/app/jobs/application_job.rb +2 -0
  60. data/integration/apps/rails-five/app/jobs/test_job.rb +12 -0
  61. data/integration/apps/rails-five/app/mailers/application_mailer.rb +4 -0
  62. data/integration/apps/rails-five/app/models/application_record.rb +3 -0
  63. data/integration/apps/rails-five/app/models/concerns/.keep +0 -0
  64. data/integration/apps/rails-five/app/models/test.rb +2 -0
  65. data/integration/apps/rails-five/app/views/layouts/mailer.html.erb +13 -0
  66. data/integration/apps/rails-five/app/views/layouts/mailer.text.erb +1 -0
  67. data/integration/apps/rails-five/bin/bundle +3 -0
  68. data/integration/apps/rails-five/bin/rails +9 -0
  69. data/integration/apps/rails-five/bin/rake +9 -0
  70. data/integration/apps/rails-five/bin/run +24 -0
  71. data/integration/apps/rails-five/bin/setup +27 -0
  72. data/integration/apps/rails-five/bin/spring +17 -0
  73. data/integration/apps/rails-five/bin/test +21 -0
  74. data/integration/apps/rails-five/bin/update +28 -0
  75. data/integration/apps/rails-five/config.ru +5 -0
  76. data/integration/apps/rails-five/config/application.rb +97 -0
  77. data/integration/apps/rails-five/config/boot.rb +4 -0
  78. data/integration/apps/rails-five/config/cable.yml +10 -0
  79. data/integration/apps/rails-five/config/credentials.yml.enc +1 -0
  80. data/integration/apps/rails-five/config/database.yml +28 -0
  81. data/integration/apps/rails-five/config/environment.rb +5 -0
  82. data/integration/apps/rails-five/config/environments/development.rb +51 -0
  83. data/integration/apps/rails-five/config/environments/production.rb +82 -0
  84. data/integration/apps/rails-five/config/environments/test.rb +43 -0
  85. data/integration/apps/rails-five/config/initializers/datadog.rb +18 -0
  86. data/integration/apps/rails-five/config/initializers/filter_parameter_logging.rb +4 -0
  87. data/integration/apps/rails-five/config/initializers/resque.rb +4 -0
  88. data/integration/apps/rails-five/config/initializers/rollbar.rb +5 -0
  89. data/integration/apps/rails-five/config/initializers/wrap_parameters.rb +14 -0
  90. data/integration/apps/rails-five/config/locales/en.yml +33 -0
  91. data/integration/apps/rails-five/config/puma.rb +24 -0
  92. data/integration/apps/rails-five/config/routes.rb +11 -0
  93. data/integration/apps/rails-five/config/spring.rb +6 -0
  94. data/integration/apps/rails-five/config/unicorn.rb +29 -0
  95. data/integration/apps/rails-five/db/migrate/20190927215052_create_tests.rb +11 -0
  96. data/integration/apps/rails-five/db/schema.rb +23 -0
  97. data/integration/apps/rails-five/db/seeds.rb +7 -0
  98. data/integration/apps/rails-five/docker-compose.ci.yml +98 -0
  99. data/integration/apps/rails-five/docker-compose.yml +100 -0
  100. data/integration/apps/rails-five/lib/tasks/.keep +0 -0
  101. data/integration/apps/rails-five/log/.keep +0 -0
  102. data/integration/apps/rails-five/public/robots.txt +1 -0
  103. data/integration/apps/rails-five/script/build-images +35 -0
  104. data/integration/apps/rails-five/script/ci +50 -0
  105. data/integration/apps/rails-five/spec/integration/basic_spec.rb +10 -0
  106. data/integration/apps/rails-five/spec/spec_helper.rb +16 -0
  107. data/integration/apps/rails-five/spec/support/integration_helper.rb +22 -0
  108. data/integration/apps/rails-five/storage/.keep +0 -0
  109. data/integration/apps/rails-five/tmp/.keep +0 -0
  110. data/integration/apps/rails-five/vendor/.keep +0 -0
  111. data/integration/apps/ruby/.dockerignore +1 -0
  112. data/integration/apps/ruby/.envrc.sample +1 -0
  113. data/integration/apps/ruby/.gitignore +2 -0
  114. data/integration/apps/ruby/Dockerfile +25 -0
  115. data/integration/apps/ruby/Dockerfile-ci +11 -0
  116. data/integration/apps/ruby/Gemfile +11 -0
  117. data/integration/apps/ruby/README.md +70 -0
  118. data/integration/apps/ruby/agent.yaml +3 -0
  119. data/integration/apps/ruby/app/datadog.rb +13 -0
  120. data/integration/apps/ruby/app/fibonacci.rb +58 -0
  121. data/integration/apps/ruby/bin/run +20 -0
  122. data/integration/apps/ruby/bin/setup +17 -0
  123. data/integration/apps/ruby/bin/test +21 -0
  124. data/integration/apps/ruby/docker-compose.ci.yml +51 -0
  125. data/integration/apps/ruby/docker-compose.yml +63 -0
  126. data/integration/apps/ruby/script/build-images +38 -0
  127. data/integration/apps/ruby/script/ci +50 -0
  128. data/integration/images/agent/Dockerfile +2 -0
  129. data/integration/images/agent/agent.yaml +3 -0
  130. data/integration/images/include/datadog/analyzer.rb +71 -0
  131. data/integration/images/include/datadog/demo_env.rb +101 -0
  132. data/integration/images/include/http-health-check +33 -0
  133. data/integration/images/ruby/2.0/Dockerfile +54 -0
  134. data/integration/images/ruby/2.1/Dockerfile +54 -0
  135. data/integration/images/ruby/2.2/Dockerfile +54 -0
  136. data/integration/images/ruby/2.3/Dockerfile +70 -0
  137. data/integration/images/ruby/2.4/Dockerfile +54 -0
  138. data/integration/images/ruby/2.5/Dockerfile +54 -0
  139. data/integration/images/ruby/2.6/Dockerfile +54 -0
  140. data/integration/images/ruby/2.7/Dockerfile +54 -0
  141. data/integration/images/ruby/3.0/Dockerfile +54 -0
  142. data/integration/images/wrk/Dockerfile +33 -0
  143. data/integration/images/wrk/scripts/entrypoint.sh +17 -0
  144. data/integration/images/wrk/scripts/scenarios/basic/default.lua +1 -0
  145. data/integration/images/wrk/scripts/scenarios/basic/fibonacci.lua +1 -0
  146. data/integration/script/build-images +43 -0
  147. data/lib/ddtrace.rb +10 -5
  148. data/lib/ddtrace/analytics.rb +2 -0
  149. data/lib/ddtrace/auto_instrument.rb +3 -0
  150. data/lib/ddtrace/auto_instrument_base.rb +6 -0
  151. data/lib/ddtrace/buffer.rb +230 -134
  152. data/lib/ddtrace/configuration.rb +21 -5
  153. data/lib/ddtrace/configuration/base.rb +1 -1
  154. data/lib/ddtrace/configuration/components.rb +2 -2
  155. data/lib/ddtrace/configuration/option_definition.rb +1 -3
  156. data/lib/ddtrace/configuration/options.rb +2 -3
  157. data/lib/ddtrace/configuration/settings.rb +21 -5
  158. data/lib/ddtrace/context.rb +23 -6
  159. data/lib/ddtrace/context_provider.rb +18 -5
  160. data/lib/ddtrace/contrib/action_cable/event.rb +1 -0
  161. data/lib/ddtrace/contrib/action_cable/integration.rb +7 -0
  162. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +1 -3
  163. data/lib/ddtrace/contrib/action_pack/integration.rb +7 -0
  164. data/lib/ddtrace/contrib/action_view/event.rb +1 -5
  165. data/lib/ddtrace/contrib/action_view/events/render_partial.rb +1 -0
  166. data/lib/ddtrace/contrib/action_view/events/render_template.rb +1 -0
  167. data/lib/ddtrace/contrib/action_view/integration.rb +7 -0
  168. data/lib/ddtrace/contrib/action_view/utils.rb +1 -1
  169. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +17 -5
  170. data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
  171. data/lib/ddtrace/contrib/active_record/utils.rb +68 -21
  172. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +104 -3
  173. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +21 -0
  174. data/lib/ddtrace/contrib/active_support/ext.rb +3 -0
  175. data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
  176. data/lib/ddtrace/contrib/active_support/notifications/event.rb +12 -1
  177. data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +1 -0
  178. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +9 -5
  179. data/lib/ddtrace/contrib/auto_instrument.rb +49 -0
  180. data/lib/ddtrace/contrib/aws/instrumentation.rb +2 -1
  181. data/lib/ddtrace/contrib/aws/patcher.rb +1 -1
  182. data/lib/ddtrace/contrib/aws/services.rb +2 -0
  183. data/lib/ddtrace/contrib/configurable.rb +2 -0
  184. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +6 -8
  185. data/lib/ddtrace/contrib/cucumber/configuration/settings.rb +28 -0
  186. data/lib/ddtrace/contrib/cucumber/ext.rb +17 -0
  187. data/lib/ddtrace/contrib/cucumber/formatter.rb +98 -0
  188. data/lib/ddtrace/contrib/cucumber/instrumentation.rb +24 -0
  189. data/lib/ddtrace/contrib/cucumber/integration.rb +45 -0
  190. data/lib/ddtrace/contrib/cucumber/patcher.rb +23 -0
  191. data/lib/ddtrace/contrib/dalli/patcher.rb +0 -38
  192. data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +2 -0
  193. data/lib/ddtrace/contrib/delayed_job/ext.rb +2 -0
  194. data/lib/ddtrace/contrib/delayed_job/plugin.rb +38 -15
  195. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +3 -2
  196. data/lib/ddtrace/contrib/ethon/easy_patch.rb +11 -10
  197. data/lib/ddtrace/contrib/ethon/ext.rb +1 -0
  198. data/lib/ddtrace/contrib/excon/middleware.rb +9 -7
  199. data/lib/ddtrace/contrib/extensions.rb +28 -1
  200. data/lib/ddtrace/contrib/faraday/middleware.rb +1 -3
  201. data/lib/ddtrace/contrib/faraday/patcher.rb +0 -36
  202. data/lib/ddtrace/contrib/grape/configuration/settings.rb +7 -0
  203. data/lib/ddtrace/contrib/grape/endpoint.rb +47 -21
  204. data/lib/ddtrace/contrib/grape/ext.rb +1 -0
  205. data/lib/ddtrace/contrib/grape/patcher.rb +0 -42
  206. data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +8 -8
  207. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +1 -1
  208. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +1 -0
  209. data/lib/ddtrace/contrib/grpc/patcher.rb +0 -36
  210. data/lib/ddtrace/contrib/http/circuit_breaker.rb +1 -3
  211. data/lib/ddtrace/contrib/http/instrumentation.rb +7 -7
  212. data/lib/ddtrace/contrib/httpclient/configuration/settings.rb +32 -0
  213. data/lib/ddtrace/contrib/httpclient/ext.rb +17 -0
  214. data/lib/ddtrace/contrib/httpclient/instrumentation.rb +151 -0
  215. data/lib/ddtrace/contrib/httpclient/integration.rb +43 -0
  216. data/lib/ddtrace/contrib/httpclient/patcher.rb +35 -0
  217. data/lib/ddtrace/contrib/httprb/instrumentation.rb +5 -6
  218. data/lib/ddtrace/contrib/kafka/event.rb +1 -1
  219. data/lib/ddtrace/contrib/mongodb/instrumentation.rb +2 -0
  220. data/lib/ddtrace/contrib/mongodb/subscribers.rb +2 -3
  221. data/lib/ddtrace/contrib/patchable.rb +18 -7
  222. data/lib/ddtrace/contrib/patcher.rb +1 -1
  223. data/lib/ddtrace/contrib/qless/configuration/settings.rb +35 -0
  224. data/lib/ddtrace/contrib/qless/ext.rb +20 -0
  225. data/lib/ddtrace/contrib/qless/integration.rb +38 -0
  226. data/lib/ddtrace/contrib/qless/patcher.rb +35 -0
  227. data/lib/ddtrace/contrib/qless/qless_job.rb +73 -0
  228. data/lib/ddtrace/contrib/qless/tracer_cleaner.rb +33 -0
  229. data/lib/ddtrace/contrib/que/configuration/settings.rb +1 -0
  230. data/lib/ddtrace/contrib/que/ext.rb +19 -19
  231. data/lib/ddtrace/contrib/que/tracer.rb +3 -2
  232. data/lib/ddtrace/contrib/racecar/event.rb +1 -0
  233. data/lib/ddtrace/contrib/rack/configuration/settings.rb +3 -3
  234. data/lib/ddtrace/contrib/rack/integration.rb +7 -0
  235. data/lib/ddtrace/contrib/rack/middlewares.rb +6 -11
  236. data/lib/ddtrace/contrib/rack/patcher.rb +1 -3
  237. data/lib/ddtrace/contrib/rack/request_queue.rb +6 -1
  238. data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +10 -0
  239. data/lib/ddtrace/contrib/rails/patcher.rb +19 -5
  240. data/lib/ddtrace/contrib/rails/utils.rb +4 -0
  241. data/lib/ddtrace/contrib/rake/instrumentation.rb +4 -2
  242. data/lib/ddtrace/contrib/rake/integration.rb +1 -1
  243. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +3 -1
  244. data/lib/ddtrace/contrib/redis/configuration/settings.rb +5 -0
  245. data/lib/ddtrace/contrib/redis/ext.rb +1 -0
  246. data/lib/ddtrace/contrib/redis/patcher.rb +20 -3
  247. data/lib/ddtrace/contrib/redis/quantize.rb +28 -0
  248. data/lib/ddtrace/contrib/redis/tags.rb +5 -1
  249. data/lib/ddtrace/contrib/redis/vendor/LICENSE +20 -0
  250. data/lib/ddtrace/contrib/redis/vendor/resolver.rb +6 -7
  251. data/lib/ddtrace/contrib/registry.rb +2 -2
  252. data/lib/ddtrace/contrib/resque/configuration/settings.rb +1 -0
  253. data/lib/ddtrace/contrib/resque/integration.rb +1 -1
  254. data/lib/ddtrace/contrib/resque/resque_job.rb +3 -1
  255. data/lib/ddtrace/contrib/rest_client/request_patch.rb +1 -3
  256. data/lib/ddtrace/contrib/rspec/configuration/settings.rb +28 -0
  257. data/lib/ddtrace/contrib/rspec/example.rb +75 -0
  258. data/lib/ddtrace/contrib/rspec/ext.rb +16 -0
  259. data/lib/ddtrace/contrib/rspec/integration.rb +46 -0
  260. data/lib/ddtrace/contrib/rspec/patcher.rb +23 -0
  261. data/lib/ddtrace/contrib/sequel/utils.rb +5 -6
  262. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +1 -0
  263. data/lib/ddtrace/contrib/shoryuken/tracer.rb +3 -1
  264. data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +1 -0
  265. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +5 -7
  266. data/lib/ddtrace/contrib/sidekiq/tracing.rb +0 -1
  267. data/lib/ddtrace/contrib/sinatra/env.rb +1 -3
  268. data/lib/ddtrace/contrib/sinatra/headers.rb +1 -3
  269. data/lib/ddtrace/contrib/sinatra/tracer.rb +1 -3
  270. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +5 -5
  271. data/lib/ddtrace/contrib/sneakers/configuration/settings.rb +1 -0
  272. data/lib/ddtrace/contrib/sneakers/ext.rb +11 -11
  273. data/lib/ddtrace/contrib/sneakers/tracer.rb +16 -21
  274. data/lib/ddtrace/contrib/status_code_matcher.rb +69 -0
  275. data/lib/ddtrace/correlation.rb +1 -0
  276. data/lib/ddtrace/diagnostics/environment_logger.rb +2 -1
  277. data/lib/ddtrace/distributed_tracing/headers/headers.rb +1 -0
  278. data/lib/ddtrace/distributed_tracing/headers/helpers.rb +1 -3
  279. data/lib/ddtrace/ext/app_types.rb +1 -0
  280. data/lib/ddtrace/ext/ci.rb +297 -0
  281. data/lib/ddtrace/ext/distributed.rb +8 -2
  282. data/lib/ddtrace/ext/git.rb +11 -0
  283. data/lib/ddtrace/ext/http.rb +1 -1
  284. data/lib/ddtrace/ext/runtime.rb +2 -1
  285. data/lib/ddtrace/ext/test.rb +24 -0
  286. data/lib/ddtrace/forced_tracing.rb +2 -0
  287. data/lib/ddtrace/logger.rb +1 -1
  288. data/lib/ddtrace/metrics.rb +10 -6
  289. data/lib/ddtrace/opentracer/distributed_headers.rb +3 -0
  290. data/lib/ddtrace/opentracer/span.rb +2 -6
  291. data/lib/ddtrace/opentracer/thread_local_scope.rb +1 -0
  292. data/lib/ddtrace/patcher.rb +2 -3
  293. data/lib/ddtrace/pin.rb +3 -52
  294. data/lib/ddtrace/pipeline/span_filter.rb +1 -1
  295. data/lib/ddtrace/propagation/grpc_propagator.rb +17 -4
  296. data/lib/ddtrace/propagation/http_propagator.rb +17 -2
  297. data/lib/ddtrace/quantization/http.rb +1 -0
  298. data/lib/ddtrace/runtime/cgroup.rb +1 -1
  299. data/lib/ddtrace/runtime/container.rb +2 -2
  300. data/lib/ddtrace/runtime/identity.rb +4 -5
  301. data/lib/ddtrace/sampler.rb +1 -1
  302. data/lib/ddtrace/sampling/rate_limiter.rb +65 -16
  303. data/lib/ddtrace/sampling/rule_sampler.rb +1 -0
  304. data/lib/ddtrace/span.rb +7 -7
  305. data/lib/ddtrace/sync_writer.rb +7 -10
  306. data/lib/ddtrace/tracer.rb +23 -10
  307. data/lib/ddtrace/transport/http.rb +1 -3
  308. data/lib/ddtrace/transport/http/adapters/net.rb +9 -4
  309. data/lib/ddtrace/transport/http/adapters/registry.rb +1 -0
  310. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +2 -4
  311. data/lib/ddtrace/transport/http/builder.rb +2 -0
  312. data/lib/ddtrace/transport/http/traces.rb +2 -3
  313. data/lib/ddtrace/transport/io.rb +1 -1
  314. data/lib/ddtrace/transport/traces.rb +3 -0
  315. data/lib/ddtrace/utils.rb +10 -11
  316. data/lib/ddtrace/utils/forking.rb +52 -0
  317. data/lib/ddtrace/utils/time.rb +25 -1
  318. data/lib/ddtrace/vendor/active_record/MIT-LICENSE +20 -0
  319. data/lib/ddtrace/version.rb +1 -1
  320. data/lib/ddtrace/workers.rb +5 -0
  321. data/lib/ddtrace/workers/async.rb +8 -0
  322. data/lib/ddtrace/workers/loop.rb +3 -0
  323. data/lib/ddtrace/workers/polling.rb +1 -0
  324. data/lib/ddtrace/workers/runtime_metrics.rb +7 -3
  325. data/lib/ddtrace/workers/trace_writer.rb +9 -10
  326. data/lib/ddtrace/writer.rb +22 -4
  327. metadata +168 -358
  328. data/lib/ddtrace/augmentation.rb +0 -13
  329. data/lib/ddtrace/augmentation/method_wrapper.rb +0 -20
  330. data/lib/ddtrace/augmentation/method_wrapping.rb +0 -38
  331. data/lib/ddtrace/augmentation/shim.rb +0 -102
  332. data/lib/ddtrace/monkey.rb +0 -58
@@ -0,0 +1,54 @@
1
+ FROM ruby:3.0
2
+
3
+ ENV DEBIAN_FRONTEND=noninteractive
4
+
5
+ # Install prerequisites
6
+ RUN set -ex && \
7
+ echo "===> Installing dependencies" && \
8
+ apt-get -y update && \
9
+ apt-get install -y --force-yes --no-install-recommends \
10
+ curl wget tar gzip gnupg apt-transport-https ca-certificates tzdata locales && \
11
+ \
12
+ echo "===> Installing NodeJS" && \
13
+ apt-get install -y --force-yes --no-install-recommends nodejs && \
14
+ \
15
+ echo "===> Installing Yarn" && \
16
+ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
17
+ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
18
+ apt-get update && \
19
+ apt-get install -y --force-yes --no-install-recommends yarn && \
20
+ \
21
+ echo "===> Installing database libraries" && \
22
+ apt-get install -y --force-yes --no-install-recommends \
23
+ postgresql-client sqlite3 && \
24
+ \
25
+ echo "===> Installing dev tools" && \
26
+ mkdir -p /usr/share/man/man1 && \
27
+ apt-get install -y --force-yes --no-install-recommends \
28
+ sudo git openssh-client rsync vim \
29
+ net-tools netcat parallel unzip zip bzip2 && \
30
+ \
31
+ echo "===> Cleaning up" && \
32
+ rm -rf /var/lib/apt/lists/*;
33
+
34
+ # Set timezone to UTC by default
35
+ RUN ln -sf /usr/share/zoneinfo/Etc/UTC /etc/localtime
36
+
37
+ # Set language
38
+ RUN locale-gen en_US.UTF-8
39
+ ENV LANG en_US.UTF-8
40
+ ENV LANGUAGE en_US:en
41
+
42
+ # Install RubyGems
43
+ RUN gem update --system
44
+ RUN mkdir -p "$GEM_HOME" && chmod -R 777 "$GEM_HOME"
45
+
46
+ # Upgrade RubyGems and Bundler
47
+ RUN gem update --system
48
+ RUN gem install bundler
49
+ ENV BUNDLE_SILENCE_ROOT_WARNING 1
50
+
51
+ # Setup demo environment includes
52
+ COPY ./include /vendor/dd-demo
53
+ ENV RUBYLIB /vendor/dd-demo
54
+ ENV RUBYOPT -rdatadog/demo_env
@@ -0,0 +1,33 @@
1
+ FROM debian:jessie
2
+
3
+ RUN echo "===> Installing tools..." && \
4
+ apt-get -y update && \
5
+ apt-get -y install build-essential curl && \
6
+ \
7
+ echo "===> Installing wrk" && \
8
+ WRK_VERSION=$(curl -L https://github.com/wg/wrk/raw/master/CHANGES 2>/dev/null | \
9
+ egrep '^wrk' | head -n 1 | awk '{print $2}') && \
10
+ echo $WRK_VERSION && \
11
+ mkdir /opt/wrk && \
12
+ cd /opt/wrk && \
13
+ curl -L https://github.com/wg/wrk/archive/$WRK_VERSION.tar.gz | \
14
+ tar zx --strip 1 && \
15
+ make && \
16
+ cp wrk /usr/local/bin/ && \
17
+ \
18
+ echo "===> Cleaning the system" && \
19
+ apt-get -f -y --auto-remove remove build-essential && \
20
+ apt-get clean && \
21
+ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /opt/wrk/
22
+
23
+ # Setup directory
24
+ RUN mkdir /scripts
25
+ RUN mkdir /data
26
+ WORKDIR /scripts
27
+
28
+ # Add scripts
29
+ COPY ./include /vendor/dd-demo
30
+ COPY ./wrk/scripts /scripts
31
+
32
+ # Set entrypoint
33
+ ENTRYPOINT ["./entrypoint.sh"]
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ bash /vendor/dd-demo/http-health-check
3
+
4
+ # Start the load test
5
+ echo "== Starting load test... =="
6
+
7
+ if [[ $# -eq 0 ]] ; then
8
+ echo "** No load test specified: pass wrk args as a command. **"
9
+ echo "== Load test aborted. =="
10
+ exit 1
11
+ else
12
+ COMMAND="wrk $@"
13
+ echo "Command: $COMMAND"
14
+ /bin/bash -c "$COMMAND"
15
+ echo "== Load test done. =="
16
+ exit 0
17
+ fi
@@ -0,0 +1 @@
1
+ wrk.method = "GET"
@@ -0,0 +1 @@
1
+ wrk.method = "GET"
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ INTEGRATION_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
5
+ INTEGRATION_DIR=${INTEGRATION_SCRIPT_DIR%/script}
6
+ cd $INTEGRATION_DIR
7
+
8
+ # Parse options
9
+ while getopts ":v:" opt; do
10
+ case $opt in
11
+ v)
12
+ APP_RUBY_VERSION=$OPTARG
13
+ ;;
14
+ \?)
15
+ echo "Invalid option: -$OPTARG" >&2
16
+ exit 1
17
+ ;;
18
+ :)
19
+ echo "Option -$OPTARG requires an argument." >&2
20
+ exit 1
21
+ ;;
22
+ esac
23
+ done
24
+
25
+ echo "== Building base images... =="
26
+ # "wrk" not necessary for CI: will be auto-built by local apps via docker-compose.
27
+ # docker build -t datadog/dd-apm-demo:wrk -f $INTEGRATION_DIR/images/wrk/Dockerfile $INTEGRATION_DIR/images
28
+ docker build -t datadog/dd-apm-demo:agent -f $INTEGRATION_DIR/images/agent/Dockerfile $INTEGRATION_DIR/images/agent
29
+
30
+ if [ -v APP_RUBY_VERSION ]; then
31
+ docker build -t datadog/dd-apm-demo:rb-$APP_RUBY_VERSION -f $INTEGRATION_DIR/images/ruby/$APP_RUBY_VERSION/Dockerfile $INTEGRATION_DIR/images
32
+ else
33
+ docker build -t datadog/dd-apm-demo:rb-2.0 -f $INTEGRATION_DIR/images/ruby/2.0/Dockerfile $INTEGRATION_DIR/images
34
+ docker build -t datadog/dd-apm-demo:rb-2.1 -f $INTEGRATION_DIR/images/ruby/2.1/Dockerfile $INTEGRATION_DIR/images
35
+ docker build -t datadog/dd-apm-demo:rb-2.2 -f $INTEGRATION_DIR/images/ruby/2.2/Dockerfile $INTEGRATION_DIR/images
36
+ docker build -t datadog/dd-apm-demo:rb-2.3 -f $INTEGRATION_DIR/images/ruby/2.3/Dockerfile $INTEGRATION_DIR/images
37
+ docker build -t datadog/dd-apm-demo:rb-2.4 -f $INTEGRATION_DIR/images/ruby/2.4/Dockerfile $INTEGRATION_DIR/images
38
+ docker build -t datadog/dd-apm-demo:rb-2.5 -f $INTEGRATION_DIR/images/ruby/2.5/Dockerfile $INTEGRATION_DIR/images
39
+ docker build -t datadog/dd-apm-demo:rb-2.6 -f $INTEGRATION_DIR/images/ruby/2.6/Dockerfile $INTEGRATION_DIR/images
40
+ docker build -t datadog/dd-apm-demo:rb-2.7 -f $INTEGRATION_DIR/images/ruby/2.7/Dockerfile $INTEGRATION_DIR/images
41
+ docker build -t datadog/dd-apm-demo:rb-3.0 -f $INTEGRATION_DIR/images/ruby/3.0/Dockerfile $INTEGRATION_DIR/images
42
+ fi
43
+ echo "== Done building base images. =="
data/lib/ddtrace.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'thread'
2
-
3
1
  # During development, we load `ddtrace` by through `ddtrace.gemspec`,
4
2
  # which in turn eager loads 'ddtrace/version'.
5
3
  #
@@ -15,13 +13,13 @@ require 'ddtrace/quantization/http'
15
13
  require 'ddtrace/pipeline'
16
14
  require 'ddtrace/configuration'
17
15
  require 'ddtrace/patcher'
18
- require 'ddtrace/augmentation'
19
16
  require 'ddtrace/metrics'
17
+ require 'ddtrace/auto_instrument_base'
20
18
 
21
19
  # \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
22
20
  module Datadog
23
- extend Augmentation
24
21
  extend Configuration
22
+ extend AutoInstrumentBase
25
23
 
26
24
  # Load and extend Contrib by default
27
25
  require 'ddtrace/contrib/extensions'
@@ -31,6 +29,10 @@ module Datadog
31
29
  require 'ddtrace/opentelemetry/extensions'
32
30
  extend OpenTelemetry::Extensions
33
31
 
32
+ # Load and extend AutoInstrument
33
+ require 'ddtrace/contrib/auto_instrument'
34
+ extend Contrib::AutoInstrument
35
+
34
36
  # Add shutdown hook:
35
37
  # Ensures the tracer has an opportunity to flush traces
36
38
  # and cleanup before terminating the process.
@@ -45,6 +47,7 @@ require 'ddtrace/contrib/active_record/integration'
45
47
  require 'ddtrace/contrib/active_support/integration'
46
48
  require 'ddtrace/contrib/aws/integration'
47
49
  require 'ddtrace/contrib/concurrent_ruby/integration'
50
+ require 'ddtrace/contrib/cucumber/integration'
48
51
  require 'ddtrace/contrib/dalli/integration'
49
52
  require 'ddtrace/contrib/delayed_job/integration'
50
53
  require 'ddtrace/contrib/elasticsearch/integration'
@@ -55,6 +58,7 @@ require 'ddtrace/contrib/grape/integration'
55
58
  require 'ddtrace/contrib/graphql/integration'
56
59
  require 'ddtrace/contrib/grpc/integration'
57
60
  require 'ddtrace/contrib/http/integration'
61
+ require 'ddtrace/contrib/httpclient/integration'
58
62
  require 'ddtrace/contrib/httprb/integration'
59
63
  require 'ddtrace/contrib/integration'
60
64
  require 'ddtrace/contrib/kafka/integration'
@@ -62,6 +66,7 @@ require 'ddtrace/contrib/presto/integration'
62
66
  require 'ddtrace/contrib/que/integration'
63
67
  require 'ddtrace/contrib/mysql2/integration'
64
68
  require 'ddtrace/contrib/mongodb/integration'
69
+ require 'ddtrace/contrib/qless/integration'
65
70
  require 'ddtrace/contrib/racecar/integration'
66
71
  require 'ddtrace/contrib/rack/integration'
67
72
  require 'ddtrace/contrib/rails/integration'
@@ -69,10 +74,10 @@ require 'ddtrace/contrib/rake/integration'
69
74
  require 'ddtrace/contrib/redis/integration'
70
75
  require 'ddtrace/contrib/resque/integration'
71
76
  require 'ddtrace/contrib/rest_client/integration'
77
+ require 'ddtrace/contrib/rspec/integration'
72
78
  require 'ddtrace/contrib/sequel/integration'
73
79
  require 'ddtrace/contrib/shoryuken/integration'
74
80
  require 'ddtrace/contrib/sidekiq/integration'
75
81
  require 'ddtrace/contrib/sinatra/integration'
76
82
  require 'ddtrace/contrib/sneakers/integration'
77
83
  require 'ddtrace/contrib/sucker_punch/integration'
78
- require 'ddtrace/monkey'
@@ -6,11 +6,13 @@ module Datadog
6
6
  class << self
7
7
  def set_sample_rate(span, sample_rate)
8
8
  return if span.nil? || !sample_rate.is_a?(Numeric)
9
+
9
10
  span.set_metric(Datadog::Ext::Analytics::TAG_SAMPLE_RATE, sample_rate)
10
11
  end
11
12
 
12
13
  def set_measured(span, value = true)
13
14
  return if span.nil?
15
+
14
16
  # rubocop:disable Style/MultipleComparison
15
17
  value = value == true || value == 1 ? 1 : 0
16
18
  span.set_metric(Datadog::Ext::Analytics::TAG_MEASURED, value)
@@ -0,0 +1,3 @@
1
+ require 'ddtrace'
2
+
3
+ Datadog.add_auto_instrument
@@ -0,0 +1,6 @@
1
+ module Datadog
2
+ # base methods stubbed for adding auto instrument extensions
3
+ module AutoInstrumentBase
4
+ def add_auto_instrument; end
5
+ end
6
+ end
@@ -1,136 +1,179 @@
1
- require 'thread'
2
1
  require 'ddtrace/diagnostics/health'
3
2
  require 'ddtrace/runtime/object_space'
4
3
 
5
4
  # Trace buffer that accumulates traces for a consumer.
6
5
  # Consumption can happen from a different thread.
7
6
  module Datadog
8
- # Aggregate metrics:
9
- # They reflect buffer activity since last #pop.
10
- # These may not be as accurate or as granular, but they
11
- # don't use as much network traffic as live stats.
12
- class MeasuredBuffer
13
- def initialize
14
- @buffer_accepted = 0
15
- @buffer_accepted_lengths = 0
16
- @buffer_dropped = 0
17
- @buffer_spans = 0
7
+ # Buffer that stores objects. The buffer has a maximum size and when
8
+ # the buffer is full, a random object is discarded.
9
+ class Buffer
10
+ def initialize(max_size)
11
+ @max_size = max_size
12
+ @items = []
13
+ @closed = false
18
14
  end
19
15
 
20
- def measure_accept(trace)
21
- @buffer_accepted += 1
22
- @buffer_accepted_lengths += trace.length
16
+ # Add a new ``item`` in the local queue. This method doesn't block the execution
17
+ # even if the buffer is full. In that case, a random item is discarded.
18
+ def push(item)
19
+ return if closed?
23
20
 
24
- @buffer_spans += trace.length
25
- rescue StandardError => e
26
- Datadog.logger.debug("Failed to measure queue accept. Cause: #{e.message} Source: #{e.backtrace.first}")
21
+ full? ? replace!(item) : add!(item)
22
+ item
27
23
  end
28
24
 
29
- def measure_drop(trace)
30
- @buffer_dropped += 1
25
+ # A bulk push alternative to +#push+. Use this method if
26
+ # pushing more than one item for efficiency.
27
+ def concat(items)
28
+ return if closed?
31
29
 
32
- @buffer_spans -= trace.length
33
- rescue StandardError => e
34
- Datadog.logger.debug("Failed to measure queue drop. Cause: #{e.message} Source: #{e.backtrace.first}")
30
+ # Segment items into underflow and overflow
31
+ underflow, overflow = overflow_segments(items)
32
+
33
+ # Concatenate items do not exceed capacity.
34
+ add_all!(underflow) unless underflow.nil?
35
+
36
+ # Iteratively replace items, to ensure pseudo-random replacement.
37
+ overflow.each { |item| replace!(item) } unless overflow.nil?
35
38
  end
36
39
 
37
- def measure_pop(traces)
38
- # Accepted, cumulative totals
39
- Datadog.health_metrics.queue_accepted(@buffer_accepted)
40
- Datadog.health_metrics.queue_accepted_lengths(@buffer_accepted_lengths)
40
+ # Stored items are returned and the local buffer is reset.
41
+ def pop
42
+ drain!
43
+ end
41
44
 
42
- # Dropped, cumulative totals
43
- Datadog.health_metrics.queue_dropped(@buffer_dropped)
44
- # TODO: are we missing a +queue_dropped_lengths+ metric?
45
+ # Return the current number of stored traces.
46
+ def length
47
+ @items.length
48
+ end
45
49
 
46
- # Queue gauges, current values
47
- Datadog.health_metrics.queue_max_length(@max_size)
48
- Datadog.health_metrics.queue_spans(@buffer_spans)
49
- Datadog.health_metrics.queue_length(traces.length)
50
+ # Return if the buffer is empty.
51
+ def empty?
52
+ @items.empty?
53
+ end
50
54
 
51
- # Reset aggregated metrics
52
- @buffer_accepted = 0
53
- @buffer_accepted_lengths = 0
54
- @buffer_dropped = 0
55
- @buffer_spans = 0
56
- rescue StandardError => e
57
- Datadog.logger.debug("Failed to measure queue. Cause: #{e.message} Source: #{e.backtrace.first}")
55
+ # Closes this buffer, preventing further pushing.
56
+ # Draining is still allowed.
57
+ def close
58
+ @closed = true
59
+ end
60
+
61
+ def closed?
62
+ @closed
63
+ end
64
+
65
+ protected
66
+
67
+ # Segment items into two distinct segments: underflow and overflow.
68
+ # Underflow are items that will fit into buffer.
69
+ # Overflow are items that will exceed capacity, after underflow is added.
70
+ # Returns each array, and nil if there is no underflow/overflow.
71
+ def overflow_segments(items)
72
+ underflow = nil
73
+ overflow = nil
74
+
75
+ overflow_size = @max_size > 0 ? (@items.length + items.length) - @max_size : 0
76
+
77
+ if overflow_size > 0
78
+ # Items will overflow
79
+ if overflow_size < items.length
80
+ # Partial overflow
81
+ underflow_end_index = items.length - overflow_size - 1
82
+ underflow = items[0..underflow_end_index]
83
+ overflow = items[(underflow_end_index + 1)..-1]
84
+ else
85
+ # Total overflow
86
+ overflow = items
87
+ end
88
+ else
89
+ # Items do not exceed capacity.
90
+ underflow = items
91
+ end
92
+
93
+ [underflow, overflow]
94
+ end
95
+
96
+ def full?
97
+ @max_size > 0 && @items.length >= @max_size
98
+ end
99
+
100
+ def add_all!(items)
101
+ @items.concat(items)
102
+ end
103
+
104
+ def add!(item)
105
+ @items << item
106
+ end
107
+
108
+ def replace!(item)
109
+ # Choose random item to be replaced
110
+ replace_index = rand(@items.length)
111
+
112
+ # Replace random item
113
+ discarded_item = @items[replace_index]
114
+ @items[replace_index] = item
115
+
116
+ # Return discarded item
117
+ discarded_item
118
+ end
119
+
120
+ def drain!
121
+ items = @items
122
+ @items = []
123
+ items
58
124
  end
59
125
  end
60
126
 
61
- # Trace buffer that stores application traces and
127
+ # Buffer that stores objects, has a maximum size, and
62
128
  # can be safely used concurrently on any environment.
63
129
  #
64
130
  # This implementation uses a {Mutex} around public methods, incurring
65
- # overhead in order to ensure full thread-safety.
131
+ # overhead in order to ensure thread-safety.
66
132
  #
67
133
  # This is implementation is recommended for non-CRuby environments.
68
- # If using CRuby, {Datadog::CRubyTraceBuffer} is a faster implementation with minimal compromise.
69
- class ThreadSafeBuffer < MeasuredBuffer
134
+ # If using CRuby, {Datadog::CRubyBuffer} is a faster implementation with minimal compromise.
135
+ class ThreadSafeBuffer < Buffer
70
136
  def initialize(max_size)
71
- super()
72
-
73
- @max_size = max_size
137
+ super
74
138
 
75
- @mutex = Mutex.new()
76
- @traces = []
77
- @closed = false
139
+ @mutex = Mutex.new
78
140
  end
79
141
 
80
- # Add a new ``trace`` in the local queue. This method doesn't block the execution
81
- # even if the buffer is full. In that case, a random trace is discarded.
82
- def push(trace)
83
- @mutex.synchronize do
84
- return if @closed
85
- len = @traces.length
86
- if len < @max_size || @max_size <= 0
87
- @traces << trace
88
- else
89
- # we should replace a random trace with the new one
90
- replace_index = rand(len)
91
- replaced_trace = @traces[replace_index]
92
- @traces[replace_index] = trace
93
- measure_drop(replaced_trace)
94
- end
142
+ # Add a new ``item`` in the local queue. This method doesn't block the execution
143
+ # even if the buffer is full. In that case, a random item is discarded.
144
+ def push(item)
145
+ synchronize { super }
146
+ end
95
147
 
96
- measure_accept(trace)
97
- end
148
+ def concat(items)
149
+ synchronize { super }
98
150
  end
99
151
 
100
152
  # Return the current number of stored traces.
101
153
  def length
102
- @mutex.synchronize do
103
- return @traces.length
104
- end
154
+ synchronize { super }
105
155
  end
106
156
 
107
157
  # Return if the buffer is empty.
108
158
  def empty?
109
- @mutex.synchronize do
110
- return @traces.empty?
111
- end
159
+ synchronize { super }
112
160
  end
113
161
 
114
162
  # Stored traces are returned and the local buffer is reset.
115
163
  def pop
116
- @mutex.synchronize do
117
- traces = @traces
118
- @traces = []
119
-
120
- measure_pop(traces)
121
-
122
- return traces
123
- end
164
+ synchronize { super }
124
165
  end
125
166
 
126
167
  def close
127
- @mutex.synchronize do
128
- @closed = true
129
- end
168
+ synchronize { super }
169
+ end
170
+
171
+ def synchronize(&block)
172
+ @mutex.synchronize(&block)
130
173
  end
131
174
  end
132
175
 
133
- # Trace buffer that stores application traces and
176
+ # Buffer that stores objects, has a maximum size, and
134
177
  # can be safely used concurrently with CRuby.
135
178
  #
136
179
  # Under extreme concurrency scenarios, this class can exceed
@@ -151,80 +194,133 @@ module Datadog
151
194
  #
152
195
  # @see spec/ddtrace/benchmark/buffer_benchmark_spec.rb Buffer benchmarks
153
196
  # @see https://github.com/ruby-concurrency/concurrent-ruby/blob/c1114a0c6891d9634f019f1f9fe58dcae8658964/lib/concurrent-ruby/concurrent/array.rb#L23-L27
154
- class CRubyTraceBuffer < MeasuredBuffer
155
- def initialize(max_size)
156
- super()
197
+ class CRubyBuffer < Buffer
198
+ # Add a new ``trace`` in the local queue. This method doesn't block the execution
199
+ # even if the buffer is full. In that case, a random trace is discarded.
200
+ def replace!(item)
201
+ # we should replace a random trace with the new one
202
+ replace_index = rand(@items.size)
203
+ replaced_trace = @items.delete_at(replace_index)
204
+ @items << item
205
+
206
+ # We might have deleted an element right when the buffer
207
+ # was drained, thus +replaced_trace+ will be +nil+.
208
+ # In that case, nothing was replaced, and this method
209
+ # performed a simple insertion into the buffer.
210
+ replaced_trace
211
+ end
212
+ end
157
213
 
158
- @max_size = max_size
214
+ # Health metrics for trace buffers.
215
+ module MeasuredBuffer
216
+ def initialize(*_)
217
+ super
159
218
 
160
- @traces = []
161
- @closed = false
219
+ @buffer_accepted = 0
220
+ @buffer_accepted_lengths = 0
221
+ @buffer_dropped = 0
222
+ @buffer_spans = 0
162
223
  end
163
224
 
164
- # Add a new ``trace`` in the local queue. This method doesn't block the execution
165
- # even if the buffer is full. In that case, a random trace is discarded.
166
- def push(trace)
167
- return if @closed
168
- len = @traces.length
169
- if len < @max_size || @max_size <= 0
170
- @traces << trace
171
- else
172
- # we should replace a random trace with the new one
173
- replace_index = rand(len)
174
- replaced_trace = @traces.delete_at(replace_index)
175
- @traces << trace
176
-
177
- # Check if we deleted the element right when the buffer
178
- # was popped. In that case we didn't actually delete anything,
179
- # we just inserted into a newly cleared buffer instead.
180
- measure_drop(replaced_trace) if replaced_trace
181
- end
225
+ def add!(trace)
226
+ super
182
227
 
228
+ # Emit health metrics
183
229
  measure_accept(trace)
184
230
  end
185
231
 
186
- # Return the current number of stored traces.
187
- def length
188
- @traces.length
189
- end
232
+ def add_all!(traces)
233
+ super
190
234
 
191
- # Return if the buffer is empty.
192
- def empty?
193
- @traces.empty?
235
+ # Emit health metrics
236
+ traces.each { |trace| measure_accept(trace) }
194
237
  end
195
238
 
196
- # Return all traces stored and reset buffer.
197
- def pop
198
- traces = @traces.pop(VERY_LARGE_INTEGER)
239
+ def replace!(trace)
240
+ discarded_trace = super
199
241
 
200
- measure_pop(traces)
242
+ # Emit health metrics
243
+ measure_accept(trace)
244
+ measure_drop(discarded_trace) if discarded_trace
245
+
246
+ discarded_trace
247
+ end
201
248
 
249
+ # Stored traces are returned and the local buffer is reset.
250
+ def drain!
251
+ traces = super
252
+ measure_pop(traces)
202
253
  traces
203
254
  end
204
255
 
205
- # Very large value, to ensure that we drain the whole buffer.
206
- # 1<<62-1 happens to be the largest integer that can be stored inline in CRuby.
207
- VERY_LARGE_INTEGER = 1 << 62 - 1
256
+ def measure_accept(trace)
257
+ @buffer_accepted += 1
258
+ @buffer_accepted_lengths += trace.length
208
259
 
209
- def close
210
- @closed = true
260
+ @buffer_spans += trace.length
261
+ rescue StandardError => e
262
+ Datadog.logger.debug("Failed to measure queue accept. Cause: #{e.message} Source: #{e.backtrace.first}")
211
263
  end
264
+
265
+ def measure_drop(trace)
266
+ @buffer_dropped += 1
267
+
268
+ @buffer_spans -= trace.length
269
+ rescue StandardError => e
270
+ Datadog.logger.debug("Failed to measure queue drop. Cause: #{e.message} Source: #{e.backtrace.first}")
271
+ end
272
+
273
+ def measure_pop(traces)
274
+ # Accepted, cumulative totals
275
+ Datadog.health_metrics.queue_accepted(@buffer_accepted)
276
+ Datadog.health_metrics.queue_accepted_lengths(@buffer_accepted_lengths)
277
+
278
+ # Dropped, cumulative totals
279
+ Datadog.health_metrics.queue_dropped(@buffer_dropped)
280
+ # TODO: are we missing a +queue_dropped_lengths+ metric?
281
+
282
+ # Queue gauges, current values
283
+ Datadog.health_metrics.queue_max_length(@max_size)
284
+ Datadog.health_metrics.queue_spans(@buffer_spans)
285
+ Datadog.health_metrics.queue_length(traces.length)
286
+
287
+ # Reset aggregated metrics
288
+ @buffer_accepted = 0
289
+ @buffer_accepted_lengths = 0
290
+ @buffer_dropped = 0
291
+ @buffer_spans = 0
292
+ rescue StandardError => e
293
+ Datadog.logger.debug("Failed to measure queue. Cause: #{e.message} Source: #{e.backtrace.first}")
294
+ end
295
+ end
296
+
297
+ # Trace buffer that stores application traces, has a maximum size, and
298
+ # can be safely used concurrently on any environment.
299
+ #
300
+ # @see {Datadog::ThreadSafeBuffer}
301
+ class ThreadSafeTraceBuffer < ThreadSafeBuffer
302
+ prepend MeasuredBuffer
212
303
  end
213
304
 
214
- # Choose default TraceBuffer implementation for current platform.
215
- BUFFER_IMPLEMENTATION = if Datadog::Ext::Runtime::RUBY_ENGINE == 'ruby'
216
- CRubyTraceBuffer
217
- else
218
- ThreadSafeBuffer
219
- end
220
- private_constant :BUFFER_IMPLEMENTATION
305
+ # Trace buffer that stores application traces, has a maximum size, and
306
+ # can be safely used concurrently with CRuby.
307
+ #
308
+ # @see {Datadog::CRubyBuffer}
309
+ class CRubyTraceBuffer < CRubyBuffer
310
+ prepend MeasuredBuffer
311
+ end
221
312
 
222
313
  # Trace buffer that stores application traces. The buffer has a maximum size and when
223
314
  # the buffer is full, a random trace is discarded. This class is thread-safe and is used
224
315
  # automatically by the ``Tracer`` instance when a ``Span`` is finished.
225
316
  #
317
+ # We choose the default TraceBuffer implementation for current platform dynamically here.
318
+ #
226
319
  # TODO We should restructure this module, so that classes are not declared at top-level ::Datadog.
227
320
  # TODO Making such a change is potentially breaking for users manually configuring the tracer.
228
- class TraceBuffer < BUFFER_IMPLEMENTATION
229
- end
321
+ TraceBuffer = if Datadog::Ext::Runtime::RUBY_ENGINE == 'ruby'
322
+ CRubyTraceBuffer
323
+ else
324
+ ThreadSafeTraceBuffer
325
+ end
230
326
  end