ddtrace 0.38.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 (433) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +492 -0
  3. data/.circleci/images/primary/Dockerfile-2.0.0 +73 -0
  4. data/.circleci/images/primary/Dockerfile-2.1.10 +73 -0
  5. data/.circleci/images/primary/Dockerfile-2.2.10 +73 -0
  6. data/.circleci/images/primary/Dockerfile-2.3.8 +75 -0
  7. data/.circleci/images/primary/Dockerfile-2.4.6 +73 -0
  8. data/.circleci/images/primary/Dockerfile-2.5.6 +73 -0
  9. data/.circleci/images/primary/Dockerfile-2.6.4 +73 -0
  10. data/.circleci/images/primary/Dockerfile-2.7.0 +73 -0
  11. data/.circleci/images/primary/Dockerfile-jruby-9.2 +77 -0
  12. data/.dockerignore +1 -0
  13. data/.env +26 -0
  14. data/.github/CODEOWNERS +1 -0
  15. data/.gitignore +61 -0
  16. data/.gitlab-ci.yml +26 -0
  17. data/.rspec +1 -0
  18. data/.rubocop.yml +85 -0
  19. data/.yardopts +5 -0
  20. data/Appraisals +961 -0
  21. data/CHANGELOG.md +1402 -0
  22. data/CONTRIBUTING.md +85 -0
  23. data/Gemfile +7 -0
  24. data/LICENSE +6 -0
  25. data/LICENSE.Apache +200 -0
  26. data/LICENSE.BSD3 +24 -0
  27. data/NOTICE +4 -0
  28. data/README.md +23 -0
  29. data/Rakefile +753 -0
  30. data/benchmarks/postgres_database.yml +9 -0
  31. data/benchmarks/sidekiq_test.rb +154 -0
  32. data/ddtrace.gemspec +71 -0
  33. data/docker-compose.yml +370 -0
  34. data/docs/DevelopmentGuide.md +195 -0
  35. data/docs/GettingStarted.md +2224 -0
  36. data/lib/ddtrace.rb +76 -0
  37. data/lib/ddtrace/analytics.rb +36 -0
  38. data/lib/ddtrace/augmentation.rb +13 -0
  39. data/lib/ddtrace/augmentation/method_wrapper.rb +20 -0
  40. data/lib/ddtrace/augmentation/method_wrapping.rb +38 -0
  41. data/lib/ddtrace/augmentation/shim.rb +102 -0
  42. data/lib/ddtrace/buffer.rb +119 -0
  43. data/lib/ddtrace/chunker.rb +34 -0
  44. data/lib/ddtrace/configuration.rb +53 -0
  45. data/lib/ddtrace/configuration/base.rb +84 -0
  46. data/lib/ddtrace/configuration/components.rb +154 -0
  47. data/lib/ddtrace/configuration/dependency_resolver.rb +24 -0
  48. data/lib/ddtrace/configuration/option.rb +64 -0
  49. data/lib/ddtrace/configuration/option_definition.rb +123 -0
  50. data/lib/ddtrace/configuration/option_definition_set.rb +18 -0
  51. data/lib/ddtrace/configuration/option_set.rb +6 -0
  52. data/lib/ddtrace/configuration/options.rb +112 -0
  53. data/lib/ddtrace/configuration/pin_setup.rb +31 -0
  54. data/lib/ddtrace/configuration/settings.rb +273 -0
  55. data/lib/ddtrace/context.rb +305 -0
  56. data/lib/ddtrace/context_flush.rb +69 -0
  57. data/lib/ddtrace/context_provider.rb +50 -0
  58. data/lib/ddtrace/contrib/action_cable/configuration/settings.rb +25 -0
  59. data/lib/ddtrace/contrib/action_cable/event.rb +65 -0
  60. data/lib/ddtrace/contrib/action_cable/events.rb +33 -0
  61. data/lib/ddtrace/contrib/action_cable/events/broadcast.rb +49 -0
  62. data/lib/ddtrace/contrib/action_cable/events/perform_action.rb +55 -0
  63. data/lib/ddtrace/contrib/action_cable/events/transmit.rb +50 -0
  64. data/lib/ddtrace/contrib/action_cable/ext.rb +23 -0
  65. data/lib/ddtrace/contrib/action_cable/instrumentation.rb +31 -0
  66. data/lib/ddtrace/contrib/action_cable/integration.rb +38 -0
  67. data/lib/ddtrace/contrib/action_cable/patcher.rb +27 -0
  68. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +148 -0
  69. data/lib/ddtrace/contrib/action_pack/action_controller/patcher.rb +25 -0
  70. data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +27 -0
  71. data/lib/ddtrace/contrib/action_pack/ext.rb +16 -0
  72. data/lib/ddtrace/contrib/action_pack/integration.rb +38 -0
  73. data/lib/ddtrace/contrib/action_pack/patcher.rb +23 -0
  74. data/lib/ddtrace/contrib/action_pack/utils.rb +36 -0
  75. data/lib/ddtrace/contrib/action_view/configuration/settings.rb +26 -0
  76. data/lib/ddtrace/contrib/action_view/event.rb +39 -0
  77. data/lib/ddtrace/contrib/action_view/events.rb +30 -0
  78. data/lib/ddtrace/contrib/action_view/events/render_partial.rb +45 -0
  79. data/lib/ddtrace/contrib/action_view/events/render_template.rb +48 -0
  80. data/lib/ddtrace/contrib/action_view/ext.rb +17 -0
  81. data/lib/ddtrace/contrib/action_view/instrumentation/partial_renderer.rb +74 -0
  82. data/lib/ddtrace/contrib/action_view/instrumentation/template_renderer.rb +167 -0
  83. data/lib/ddtrace/contrib/action_view/integration.rb +45 -0
  84. data/lib/ddtrace/contrib/action_view/patcher.rb +47 -0
  85. data/lib/ddtrace/contrib/action_view/utils.rb +32 -0
  86. data/lib/ddtrace/contrib/active_model_serializers/configuration/settings.rb +25 -0
  87. data/lib/ddtrace/contrib/active_model_serializers/event.rb +68 -0
  88. data/lib/ddtrace/contrib/active_model_serializers/events.rb +30 -0
  89. data/lib/ddtrace/contrib/active_model_serializers/events/render.rb +32 -0
  90. data/lib/ddtrace/contrib/active_model_serializers/events/serialize.rb +35 -0
  91. data/lib/ddtrace/contrib/active_model_serializers/ext.rb +17 -0
  92. data/lib/ddtrace/contrib/active_model_serializers/integration.rb +40 -0
  93. data/lib/ddtrace/contrib/active_model_serializers/patcher.rb +29 -0
  94. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +45 -0
  95. data/lib/ddtrace/contrib/active_record/configuration/settings.rb +30 -0
  96. data/lib/ddtrace/contrib/active_record/event.rb +30 -0
  97. data/lib/ddtrace/contrib/active_record/events.rb +30 -0
  98. data/lib/ddtrace/contrib/active_record/events/instantiation.rb +60 -0
  99. data/lib/ddtrace/contrib/active_record/events/sql.rb +64 -0
  100. data/lib/ddtrace/contrib/active_record/ext.rb +21 -0
  101. data/lib/ddtrace/contrib/active_record/integration.rb +46 -0
  102. data/lib/ddtrace/contrib/active_record/patcher.rb +23 -0
  103. data/lib/ddtrace/contrib/active_record/utils.rb +76 -0
  104. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +157 -0
  105. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +48 -0
  106. data/lib/ddtrace/contrib/active_support/cache/redis.rb +47 -0
  107. data/lib/ddtrace/contrib/active_support/configuration/settings.rb +25 -0
  108. data/lib/ddtrace/contrib/active_support/ext.rb +21 -0
  109. data/lib/ddtrace/contrib/active_support/integration.rb +40 -0
  110. data/lib/ddtrace/contrib/active_support/notifications/event.rb +64 -0
  111. data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +66 -0
  112. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +159 -0
  113. data/lib/ddtrace/contrib/active_support/patcher.rb +23 -0
  114. data/lib/ddtrace/contrib/analytics.rb +24 -0
  115. data/lib/ddtrace/contrib/aws/configuration/settings.rb +25 -0
  116. data/lib/ddtrace/contrib/aws/ext.rb +20 -0
  117. data/lib/ddtrace/contrib/aws/instrumentation.rb +56 -0
  118. data/lib/ddtrace/contrib/aws/integration.rb +42 -0
  119. data/lib/ddtrace/contrib/aws/parsed_context.rb +56 -0
  120. data/lib/ddtrace/contrib/aws/patcher.rb +49 -0
  121. data/lib/ddtrace/contrib/aws/services.rb +115 -0
  122. data/lib/ddtrace/contrib/concurrent_ruby/configuration/settings.rb +15 -0
  123. data/lib/ddtrace/contrib/concurrent_ruby/context_composite_executor_service.rb +41 -0
  124. data/lib/ddtrace/contrib/concurrent_ruby/ext.rb +11 -0
  125. data/lib/ddtrace/contrib/concurrent_ruby/future_patch.rb +23 -0
  126. data/lib/ddtrace/contrib/concurrent_ruby/integration.rb +38 -0
  127. data/lib/ddtrace/contrib/concurrent_ruby/patcher.rb +28 -0
  128. data/lib/ddtrace/contrib/configurable.rb +76 -0
  129. data/lib/ddtrace/contrib/configuration/resolver.rb +16 -0
  130. data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +39 -0
  131. data/lib/ddtrace/contrib/configuration/settings.rb +53 -0
  132. data/lib/ddtrace/contrib/dalli/configuration/settings.rb +25 -0
  133. data/lib/ddtrace/contrib/dalli/ext.rb +17 -0
  134. data/lib/ddtrace/contrib/dalli/instrumentation.rb +50 -0
  135. data/lib/ddtrace/contrib/dalli/integration.rb +38 -0
  136. data/lib/ddtrace/contrib/dalli/patcher.rb +63 -0
  137. data/lib/ddtrace/contrib/dalli/quantize.rb +22 -0
  138. data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +25 -0
  139. data/lib/ddtrace/contrib/delayed_job/ext.rb +18 -0
  140. data/lib/ddtrace/contrib/delayed_job/integration.rb +38 -0
  141. data/lib/ddtrace/contrib/delayed_job/patcher.rb +28 -0
  142. data/lib/ddtrace/contrib/delayed_job/plugin.rb +61 -0
  143. data/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb +26 -0
  144. data/lib/ddtrace/contrib/elasticsearch/ext.rb +19 -0
  145. data/lib/ddtrace/contrib/elasticsearch/integration.rb +39 -0
  146. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +117 -0
  147. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +80 -0
  148. data/lib/ddtrace/contrib/ethon/configuration/settings.rb +27 -0
  149. data/lib/ddtrace/contrib/ethon/easy_patch.rb +148 -0
  150. data/lib/ddtrace/contrib/ethon/ext.rb +15 -0
  151. data/lib/ddtrace/contrib/ethon/integration.rb +43 -0
  152. data/lib/ddtrace/contrib/ethon/multi_patch.rb +80 -0
  153. data/lib/ddtrace/contrib/ethon/patcher.rb +25 -0
  154. data/lib/ddtrace/contrib/excon/configuration/settings.rb +28 -0
  155. data/lib/ddtrace/contrib/excon/ext.rb +14 -0
  156. data/lib/ddtrace/contrib/excon/integration.rb +43 -0
  157. data/lib/ddtrace/contrib/excon/middleware.rb +157 -0
  158. data/lib/ddtrace/contrib/excon/patcher.rb +27 -0
  159. data/lib/ddtrace/contrib/extensions.rb +93 -0
  160. data/lib/ddtrace/contrib/faraday/configuration/settings.rb +33 -0
  161. data/lib/ddtrace/contrib/faraday/connection.rb +18 -0
  162. data/lib/ddtrace/contrib/faraday/ext.rb +14 -0
  163. data/lib/ddtrace/contrib/faraday/integration.rb +43 -0
  164. data/lib/ddtrace/contrib/faraday/middleware.rb +83 -0
  165. data/lib/ddtrace/contrib/faraday/patcher.rb +80 -0
  166. data/lib/ddtrace/contrib/faraday/rack_builder.rb +18 -0
  167. data/lib/ddtrace/contrib/grape/configuration/settings.rb +27 -0
  168. data/lib/ddtrace/contrib/grape/endpoint.rb +208 -0
  169. data/lib/ddtrace/contrib/grape/ext.rb +19 -0
  170. data/lib/ddtrace/contrib/grape/instrumentation.rb +33 -0
  171. data/lib/ddtrace/contrib/grape/integration.rb +39 -0
  172. data/lib/ddtrace/contrib/grape/patcher.rb +73 -0
  173. data/lib/ddtrace/contrib/graphql/configuration/settings.rb +27 -0
  174. data/lib/ddtrace/contrib/graphql/ext.rb +13 -0
  175. data/lib/ddtrace/contrib/graphql/integration.rb +39 -0
  176. data/lib/ddtrace/contrib/graphql/patcher.rb +60 -0
  177. data/lib/ddtrace/contrib/grpc/configuration/settings.rb +25 -0
  178. data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +74 -0
  179. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +54 -0
  180. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +76 -0
  181. data/lib/ddtrace/contrib/grpc/ext.rb +15 -0
  182. data/lib/ddtrace/contrib/grpc/integration.rb +38 -0
  183. data/lib/ddtrace/contrib/grpc/intercept_with_datadog.rb +49 -0
  184. data/lib/ddtrace/contrib/grpc/patcher.rb +68 -0
  185. data/lib/ddtrace/contrib/http/circuit_breaker.rb +39 -0
  186. data/lib/ddtrace/contrib/http/configuration/settings.rb +27 -0
  187. data/lib/ddtrace/contrib/http/ext.rb +14 -0
  188. data/lib/ddtrace/contrib/http/instrumentation.rb +175 -0
  189. data/lib/ddtrace/contrib/http/integration.rb +45 -0
  190. data/lib/ddtrace/contrib/http/patcher.rb +26 -0
  191. data/lib/ddtrace/contrib/http_annotation_helper.rb +10 -0
  192. data/lib/ddtrace/contrib/httprb/configuration/settings.rb +27 -0
  193. data/lib/ddtrace/contrib/httprb/ext.rb +14 -0
  194. data/lib/ddtrace/contrib/httprb/instrumentation.rb +163 -0
  195. data/lib/ddtrace/contrib/httprb/integration.rb +43 -0
  196. data/lib/ddtrace/contrib/httprb/patcher.rb +35 -0
  197. data/lib/ddtrace/contrib/integration.rb +16 -0
  198. data/lib/ddtrace/contrib/kafka/configuration/settings.rb +25 -0
  199. data/lib/ddtrace/contrib/kafka/consumer_event.rb +14 -0
  200. data/lib/ddtrace/contrib/kafka/consumer_group_event.rb +14 -0
  201. data/lib/ddtrace/contrib/kafka/event.rb +51 -0
  202. data/lib/ddtrace/contrib/kafka/events.rb +44 -0
  203. data/lib/ddtrace/contrib/kafka/events/connection/request.rb +34 -0
  204. data/lib/ddtrace/contrib/kafka/events/consumer/process_batch.rb +41 -0
  205. data/lib/ddtrace/contrib/kafka/events/consumer/process_message.rb +39 -0
  206. data/lib/ddtrace/contrib/kafka/events/consumer_group/heartbeat.rb +39 -0
  207. data/lib/ddtrace/contrib/kafka/events/consumer_group/join_group.rb +29 -0
  208. data/lib/ddtrace/contrib/kafka/events/consumer_group/leave_group.rb +29 -0
  209. data/lib/ddtrace/contrib/kafka/events/consumer_group/sync_group.rb +29 -0
  210. data/lib/ddtrace/contrib/kafka/events/produce_operation/send_messages.rb +32 -0
  211. data/lib/ddtrace/contrib/kafka/events/producer/deliver_messages.rb +35 -0
  212. data/lib/ddtrace/contrib/kafka/ext.rb +38 -0
  213. data/lib/ddtrace/contrib/kafka/integration.rb +39 -0
  214. data/lib/ddtrace/contrib/kafka/patcher.rb +26 -0
  215. data/lib/ddtrace/contrib/mongodb/configuration/settings.rb +28 -0
  216. data/lib/ddtrace/contrib/mongodb/ext.rb +20 -0
  217. data/lib/ddtrace/contrib/mongodb/instrumentation.rb +67 -0
  218. data/lib/ddtrace/contrib/mongodb/integration.rb +38 -0
  219. data/lib/ddtrace/contrib/mongodb/parsers.rb +68 -0
  220. data/lib/ddtrace/contrib/mongodb/patcher.rb +31 -0
  221. data/lib/ddtrace/contrib/mongodb/subscribers.rb +108 -0
  222. data/lib/ddtrace/contrib/mysql2/configuration/settings.rb +25 -0
  223. data/lib/ddtrace/contrib/mysql2/ext.rb +15 -0
  224. data/lib/ddtrace/contrib/mysql2/instrumentation.rb +60 -0
  225. data/lib/ddtrace/contrib/mysql2/integration.rb +38 -0
  226. data/lib/ddtrace/contrib/mysql2/patcher.rb +27 -0
  227. data/lib/ddtrace/contrib/patchable.rb +59 -0
  228. data/lib/ddtrace/contrib/patcher.rb +62 -0
  229. data/lib/ddtrace/contrib/presto/configuration/settings.rb +25 -0
  230. data/lib/ddtrace/contrib/presto/ext.rb +25 -0
  231. data/lib/ddtrace/contrib/presto/instrumentation.rb +107 -0
  232. data/lib/ddtrace/contrib/presto/integration.rb +38 -0
  233. data/lib/ddtrace/contrib/presto/patcher.rb +30 -0
  234. data/lib/ddtrace/contrib/racecar/configuration/settings.rb +25 -0
  235. data/lib/ddtrace/contrib/racecar/event.rb +71 -0
  236. data/lib/ddtrace/contrib/racecar/events.rb +30 -0
  237. data/lib/ddtrace/contrib/racecar/events/batch.rb +27 -0
  238. data/lib/ddtrace/contrib/racecar/events/message.rb +27 -0
  239. data/lib/ddtrace/contrib/racecar/ext.rb +21 -0
  240. data/lib/ddtrace/contrib/racecar/integration.rb +39 -0
  241. data/lib/ddtrace/contrib/racecar/patcher.rb +26 -0
  242. data/lib/ddtrace/contrib/rack/configuration/settings.rb +41 -0
  243. data/lib/ddtrace/contrib/rack/ext.rb +18 -0
  244. data/lib/ddtrace/contrib/rack/integration.rb +38 -0
  245. data/lib/ddtrace/contrib/rack/middlewares.rb +290 -0
  246. data/lib/ddtrace/contrib/rack/patcher.rb +107 -0
  247. data/lib/ddtrace/contrib/rack/request_queue.rb +39 -0
  248. data/lib/ddtrace/contrib/rails/configuration/settings.rb +83 -0
  249. data/lib/ddtrace/contrib/rails/ext.rb +13 -0
  250. data/lib/ddtrace/contrib/rails/framework.rb +124 -0
  251. data/lib/ddtrace/contrib/rails/integration.rb +44 -0
  252. data/lib/ddtrace/contrib/rails/middlewares.rb +38 -0
  253. data/lib/ddtrace/contrib/rails/patcher.rb +74 -0
  254. data/lib/ddtrace/contrib/rails/railtie.rb +17 -0
  255. data/lib/ddtrace/contrib/rails/utils.rb +20 -0
  256. data/lib/ddtrace/contrib/rake/configuration/settings.rb +27 -0
  257. data/lib/ddtrace/contrib/rake/ext.rb +18 -0
  258. data/lib/ddtrace/contrib/rake/instrumentation.rb +88 -0
  259. data/lib/ddtrace/contrib/rake/integration.rb +38 -0
  260. data/lib/ddtrace/contrib/rake/patcher.rb +30 -0
  261. data/lib/ddtrace/contrib/redis/configuration/resolver.rb +36 -0
  262. data/lib/ddtrace/contrib/redis/configuration/settings.rb +25 -0
  263. data/lib/ddtrace/contrib/redis/ext.rb +18 -0
  264. data/lib/ddtrace/contrib/redis/integration.rb +42 -0
  265. data/lib/ddtrace/contrib/redis/patcher.rb +97 -0
  266. data/lib/ddtrace/contrib/redis/quantize.rb +47 -0
  267. data/lib/ddtrace/contrib/redis/tags.rb +38 -0
  268. data/lib/ddtrace/contrib/redis/vendor/resolver.rb +159 -0
  269. data/lib/ddtrace/contrib/registerable.rb +33 -0
  270. data/lib/ddtrace/contrib/registry.rb +42 -0
  271. data/lib/ddtrace/contrib/resque/configuration/settings.rb +26 -0
  272. data/lib/ddtrace/contrib/resque/ext.rb +14 -0
  273. data/lib/ddtrace/contrib/resque/integration.rb +47 -0
  274. data/lib/ddtrace/contrib/resque/patcher.rb +29 -0
  275. data/lib/ddtrace/contrib/resque/resque_job.rb +80 -0
  276. data/lib/ddtrace/contrib/rest_client/configuration/settings.rb +26 -0
  277. data/lib/ddtrace/contrib/rest_client/ext.rb +14 -0
  278. data/lib/ddtrace/contrib/rest_client/integration.rb +38 -0
  279. data/lib/ddtrace/contrib/rest_client/patcher.rb +23 -0
  280. data/lib/ddtrace/contrib/rest_client/request_patch.rb +89 -0
  281. data/lib/ddtrace/contrib/sequel/configuration/settings.rb +23 -0
  282. data/lib/ddtrace/contrib/sequel/database.rb +61 -0
  283. data/lib/ddtrace/contrib/sequel/dataset.rb +62 -0
  284. data/lib/ddtrace/contrib/sequel/ext.rb +15 -0
  285. data/lib/ddtrace/contrib/sequel/integration.rb +38 -0
  286. data/lib/ddtrace/contrib/sequel/patcher.rb +33 -0
  287. data/lib/ddtrace/contrib/sequel/utils.rb +46 -0
  288. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +24 -0
  289. data/lib/ddtrace/contrib/shoryuken/ext.rb +18 -0
  290. data/lib/ddtrace/contrib/shoryuken/integration.rb +39 -0
  291. data/lib/ddtrace/contrib/shoryuken/patcher.rb +24 -0
  292. data/lib/ddtrace/contrib/shoryuken/tracer.rb +49 -0
  293. data/lib/ddtrace/contrib/sidekiq/client_tracer.rb +43 -0
  294. data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +31 -0
  295. data/lib/ddtrace/contrib/sidekiq/ext.rb +24 -0
  296. data/lib/ddtrace/contrib/sidekiq/integration.rb +38 -0
  297. data/lib/ddtrace/contrib/sidekiq/patcher.rb +41 -0
  298. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +67 -0
  299. data/lib/ddtrace/contrib/sidekiq/tracing.rb +45 -0
  300. data/lib/ddtrace/contrib/sinatra/configuration/settings.rb +34 -0
  301. data/lib/ddtrace/contrib/sinatra/env.rb +58 -0
  302. data/lib/ddtrace/contrib/sinatra/ext.rb +24 -0
  303. data/lib/ddtrace/contrib/sinatra/headers.rb +31 -0
  304. data/lib/ddtrace/contrib/sinatra/integration.rb +38 -0
  305. data/lib/ddtrace/contrib/sinatra/patcher.rb +28 -0
  306. data/lib/ddtrace/contrib/sinatra/tracer.rb +150 -0
  307. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +78 -0
  308. data/lib/ddtrace/contrib/sucker_punch/configuration/settings.rb +25 -0
  309. data/lib/ddtrace/contrib/sucker_punch/exception_handler.rb +26 -0
  310. data/lib/ddtrace/contrib/sucker_punch/ext.rb +18 -0
  311. data/lib/ddtrace/contrib/sucker_punch/instrumentation.rb +84 -0
  312. data/lib/ddtrace/contrib/sucker_punch/integration.rb +38 -0
  313. data/lib/ddtrace/contrib/sucker_punch/patcher.rb +42 -0
  314. data/lib/ddtrace/correlation.rb +38 -0
  315. data/lib/ddtrace/diagnostics/environment_logger.rb +278 -0
  316. data/lib/ddtrace/diagnostics/health.rb +33 -0
  317. data/lib/ddtrace/distributed_tracing/headers/b3.rb +44 -0
  318. data/lib/ddtrace/distributed_tracing/headers/b3_single.rb +56 -0
  319. data/lib/ddtrace/distributed_tracing/headers/datadog.rb +42 -0
  320. data/lib/ddtrace/distributed_tracing/headers/headers.rb +70 -0
  321. data/lib/ddtrace/distributed_tracing/headers/helpers.rb +45 -0
  322. data/lib/ddtrace/encoding.rb +69 -0
  323. data/lib/ddtrace/environment.rb +31 -0
  324. data/lib/ddtrace/error.rb +27 -0
  325. data/lib/ddtrace/event.rb +52 -0
  326. data/lib/ddtrace/ext/analytics.rb +12 -0
  327. data/lib/ddtrace/ext/app_types.rb +11 -0
  328. data/lib/ddtrace/ext/correlation.rb +11 -0
  329. data/lib/ddtrace/ext/diagnostics.rb +35 -0
  330. data/lib/ddtrace/ext/distributed.rb +33 -0
  331. data/lib/ddtrace/ext/environment.rb +16 -0
  332. data/lib/ddtrace/ext/errors.rb +10 -0
  333. data/lib/ddtrace/ext/forced_tracing.rb +25 -0
  334. data/lib/ddtrace/ext/http.rb +46 -0
  335. data/lib/ddtrace/ext/manual_tracing.rb +9 -0
  336. data/lib/ddtrace/ext/metrics.rb +15 -0
  337. data/lib/ddtrace/ext/net.rb +10 -0
  338. data/lib/ddtrace/ext/priority.rb +16 -0
  339. data/lib/ddtrace/ext/runtime.rb +26 -0
  340. data/lib/ddtrace/ext/sampling.rb +16 -0
  341. data/lib/ddtrace/ext/sql.rb +8 -0
  342. data/lib/ddtrace/ext/transport.rb +17 -0
  343. data/lib/ddtrace/forced_tracing.rb +36 -0
  344. data/lib/ddtrace/logger.rb +40 -0
  345. data/lib/ddtrace/metrics.rb +222 -0
  346. data/lib/ddtrace/monkey.rb +58 -0
  347. data/lib/ddtrace/opentelemetry/extensions.rb +13 -0
  348. data/lib/ddtrace/opentelemetry/span.rb +33 -0
  349. data/lib/ddtrace/opentracer.rb +40 -0
  350. data/lib/ddtrace/opentracer/binary_propagator.rb +24 -0
  351. data/lib/ddtrace/opentracer/carrier.rb +6 -0
  352. data/lib/ddtrace/opentracer/distributed_headers.rb +52 -0
  353. data/lib/ddtrace/opentracer/global_tracer.rb +15 -0
  354. data/lib/ddtrace/opentracer/propagator.rb +22 -0
  355. data/lib/ddtrace/opentracer/rack_propagator.rb +60 -0
  356. data/lib/ddtrace/opentracer/scope.rb +15 -0
  357. data/lib/ddtrace/opentracer/scope_manager.rb +6 -0
  358. data/lib/ddtrace/opentracer/span.rb +98 -0
  359. data/lib/ddtrace/opentracer/span_context.rb +14 -0
  360. data/lib/ddtrace/opentracer/span_context_factory.rb +23 -0
  361. data/lib/ddtrace/opentracer/text_map_propagator.rb +75 -0
  362. data/lib/ddtrace/opentracer/thread_local_scope.rb +30 -0
  363. data/lib/ddtrace/opentracer/thread_local_scope_manager.rb +40 -0
  364. data/lib/ddtrace/opentracer/tracer.rb +208 -0
  365. data/lib/ddtrace/patcher.rb +47 -0
  366. data/lib/ddtrace/pin.rb +138 -0
  367. data/lib/ddtrace/pipeline.rb +46 -0
  368. data/lib/ddtrace/pipeline/span_filter.rb +38 -0
  369. data/lib/ddtrace/pipeline/span_processor.rb +20 -0
  370. data/lib/ddtrace/propagation/grpc_propagator.rb +61 -0
  371. data/lib/ddtrace/propagation/http_propagator.rb +75 -0
  372. data/lib/ddtrace/quantization/hash.rb +103 -0
  373. data/lib/ddtrace/quantization/http.rb +86 -0
  374. data/lib/ddtrace/runtime/cgroup.rb +44 -0
  375. data/lib/ddtrace/runtime/class_count.rb +17 -0
  376. data/lib/ddtrace/runtime/container.rb +73 -0
  377. data/lib/ddtrace/runtime/gc.rb +16 -0
  378. data/lib/ddtrace/runtime/identity.rb +41 -0
  379. data/lib/ddtrace/runtime/metrics.rb +96 -0
  380. data/lib/ddtrace/runtime/object_space.rb +19 -0
  381. data/lib/ddtrace/runtime/socket.rb +14 -0
  382. data/lib/ddtrace/runtime/thread_count.rb +16 -0
  383. data/lib/ddtrace/sampler.rb +292 -0
  384. data/lib/ddtrace/sampling.rb +2 -0
  385. data/lib/ddtrace/sampling/matcher.rb +57 -0
  386. data/lib/ddtrace/sampling/rate_limiter.rb +127 -0
  387. data/lib/ddtrace/sampling/rule.rb +61 -0
  388. data/lib/ddtrace/sampling/rule_sampler.rb +125 -0
  389. data/lib/ddtrace/span.rb +307 -0
  390. data/lib/ddtrace/sync_writer.rb +67 -0
  391. data/lib/ddtrace/tracer.rb +439 -0
  392. data/lib/ddtrace/transport/http.rb +91 -0
  393. data/lib/ddtrace/transport/http/adapters/net.rb +120 -0
  394. data/lib/ddtrace/transport/http/adapters/registry.rb +24 -0
  395. data/lib/ddtrace/transport/http/adapters/test.rb +81 -0
  396. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +68 -0
  397. data/lib/ddtrace/transport/http/api.rb +46 -0
  398. data/lib/ddtrace/transport/http/api/endpoint.rb +27 -0
  399. data/lib/ddtrace/transport/http/api/fallbacks.rb +22 -0
  400. data/lib/ddtrace/transport/http/api/instance.rb +33 -0
  401. data/lib/ddtrace/transport/http/api/map.rb +14 -0
  402. data/lib/ddtrace/transport/http/api/spec.rb +15 -0
  403. data/lib/ddtrace/transport/http/builder.rb +163 -0
  404. data/lib/ddtrace/transport/http/client.rb +50 -0
  405. data/lib/ddtrace/transport/http/env.rb +48 -0
  406. data/lib/ddtrace/transport/http/response.rb +26 -0
  407. data/lib/ddtrace/transport/http/statistics.rb +30 -0
  408. data/lib/ddtrace/transport/http/traces.rb +143 -0
  409. data/lib/ddtrace/transport/io.rb +26 -0
  410. data/lib/ddtrace/transport/io/client.rb +76 -0
  411. data/lib/ddtrace/transport/io/response.rb +25 -0
  412. data/lib/ddtrace/transport/io/traces.rb +91 -0
  413. data/lib/ddtrace/transport/parcel.rb +13 -0
  414. data/lib/ddtrace/transport/request.rb +13 -0
  415. data/lib/ddtrace/transport/response.rb +60 -0
  416. data/lib/ddtrace/transport/statistics.rb +72 -0
  417. data/lib/ddtrace/transport/traces.rb +183 -0
  418. data/lib/ddtrace/utils.rb +65 -0
  419. data/lib/ddtrace/utils/database.rb +25 -0
  420. data/lib/ddtrace/utils/time.rb +14 -0
  421. data/lib/ddtrace/vendor/active_record/connection_specification.rb +301 -0
  422. data/lib/ddtrace/version.rb +12 -0
  423. data/lib/ddtrace/worker.rb +20 -0
  424. data/lib/ddtrace/workers.rb +117 -0
  425. data/lib/ddtrace/workers/async.rb +165 -0
  426. data/lib/ddtrace/workers/loop.rb +105 -0
  427. data/lib/ddtrace/workers/polling.rb +48 -0
  428. data/lib/ddtrace/workers/queue.rb +39 -0
  429. data/lib/ddtrace/workers/runtime_metrics.rb +47 -0
  430. data/lib/ddtrace/workers/trace_writer.rb +202 -0
  431. data/lib/ddtrace/writer.rb +175 -0
  432. data/tasks/release_gem.rake +28 -0
  433. metadata +815 -0
@@ -0,0 +1,2 @@
1
+ require 'ddtrace/sampling/rule'
2
+ require 'ddtrace/sampling/rule_sampler'
@@ -0,0 +1,57 @@
1
+ module Datadog
2
+ module Sampling
3
+ # Checks if a span conforms to a matching criteria.
4
+ class Matcher
5
+ # Returns `true` if the span should conforms to this rule, `false` otherwise
6
+ #
7
+ # @abstract
8
+ # @param [Span] span
9
+ # @return [Boolean]
10
+ def match?(span)
11
+ raise NotImplementedError
12
+ end
13
+ end
14
+
15
+ # A \Matcher that supports matching a span by
16
+ # operation name and/or service name.
17
+ class SimpleMatcher < Matcher
18
+ # Returns `true` for case equality (===) with any object
19
+ MATCH_ALL = Class.new do
20
+ # DEV: A class that implements `#===` is ~20% faster than
21
+ # DEV: a `Proc` that always returns `true`.
22
+ def ===(other)
23
+ true
24
+ end
25
+ end.new
26
+
27
+ attr_reader :name, :service
28
+
29
+ # @param name [String,Regexp,Proc] Matcher for case equality (===) with the span name, defaults to always match
30
+ # @param service [String,Regexp,Proc] Matcher for case equality (===) with the service name, defaults to always match
31
+ def initialize(name: MATCH_ALL, service: MATCH_ALL)
32
+ @name = name
33
+ @service = service
34
+ end
35
+
36
+ def match?(span)
37
+ name === span.name && service === span.service
38
+ end
39
+ end
40
+
41
+ # A \Matcher that allows for arbitrary span matching
42
+ # based on the return value of a provided block.
43
+ class ProcMatcher < Matcher
44
+ attr_reader :block
45
+
46
+ # @yield [name, service] Provides span name and service to the block
47
+ # @yieldreturn [Boolean] Whether the span conforms to this matcher
48
+ def initialize(&block)
49
+ @block = block
50
+ end
51
+
52
+ def match?(span)
53
+ block.call(span.name, span.service)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,127 @@
1
+ require 'ddtrace/utils/time'
2
+
3
+ module Datadog
4
+ module Sampling
5
+ # Checks for rate limiting on a resource.
6
+ class RateLimiter
7
+ # Checks if resource of specified size can be
8
+ # conforms with the current limit.
9
+ #
10
+ # Implementations of this method are not guaranteed
11
+ # to be side-effect free.
12
+ #
13
+ # @return [Boolean] whether a resource conforms with the current limit
14
+ def allow?(size); end
15
+
16
+ # The effective rate limiting ratio based on
17
+ # recent calls to `allow?`.
18
+ #
19
+ # @return [Float] recent allowance ratio
20
+ def effective_rate; end
21
+ end
22
+
23
+ # Implementation of the Token Bucket metering algorithm
24
+ # for rate limiting.
25
+ #
26
+ # @see https://en.wikipedia.org/wiki/Token_bucket Token bucket
27
+ class TokenBucket < RateLimiter
28
+ attr_reader :rate, :max_tokens
29
+
30
+ # @param rate [Numeric] Allowance rate, in units per second
31
+ # if rate is negative, always allow
32
+ # if rate is zero, never allow
33
+ # @param max_tokens [Numeric] Limit of available tokens
34
+ def initialize(rate, max_tokens = rate)
35
+ @rate = rate
36
+ @max_tokens = max_tokens
37
+
38
+ @tokens = max_tokens
39
+ @total_messages = 0
40
+ @conforming_messages = 0
41
+ @last_refill = Utils::Time.get_time
42
+ end
43
+
44
+ # Checks if a message of provided +size+
45
+ # conforms with the current bucket limit.
46
+ #
47
+ # If it does, return +true+ and remove +size+
48
+ # tokens from the bucket.
49
+ # If it does not, return +false+ without affecting
50
+ # the tokens form the bucket.
51
+ #
52
+ # @return [Boolean] +true+ if message conforms with current bucket limit
53
+ def allow?(size)
54
+ return false if @rate.zero?
55
+ return true if @rate < 0
56
+
57
+ refill_since_last_message
58
+
59
+ increment_total_count
60
+
61
+ return false if @tokens < size
62
+
63
+ increment_conforming_count
64
+
65
+ @tokens -= size
66
+
67
+ true
68
+ end
69
+
70
+ # Ratio of 'conformance' per 'total messages' checked
71
+ # on this bucket.
72
+ #
73
+ # Returns +1.0+ when no messages have been checked yet.
74
+ #
75
+ # @return [Float] Conformance ratio, between +[0,1]+
76
+ def effective_rate
77
+ return 0.0 if @rate.zero?
78
+ return 1.0 if @rate < 0 || @total_messages.zero?
79
+
80
+ @conforming_messages.to_f / @total_messages
81
+ end
82
+
83
+ # @return [Numeric] number of tokens currently available
84
+ def available_tokens
85
+ @tokens
86
+ end
87
+
88
+ private
89
+
90
+ def refill_since_last_message
91
+ now = Utils::Time.get_time
92
+ elapsed = now - @last_refill
93
+
94
+ refill_tokens(@rate * elapsed)
95
+
96
+ @last_refill = now
97
+ end
98
+
99
+ def refill_tokens(size)
100
+ @tokens += size
101
+ @tokens = @max_tokens if @tokens > @max_tokens
102
+ end
103
+
104
+ def increment_total_count
105
+ @total_messages += 1
106
+ end
107
+
108
+ def increment_conforming_count
109
+ @conforming_messages += 1
110
+ end
111
+ end
112
+
113
+ # \RateLimiter that accepts all resources,
114
+ # with no limits.
115
+ class UnlimitedLimiter < RateLimiter
116
+ # @return [Boolean] always +true+
117
+ def allow?(_)
118
+ true
119
+ end
120
+
121
+ # @return [Float] always 100%
122
+ def effective_rate
123
+ 1.0
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,61 @@
1
+ require 'forwardable'
2
+
3
+ require 'ddtrace/sampling/matcher'
4
+ require 'ddtrace/sampler'
5
+
6
+ module Datadog
7
+ module Sampling
8
+ # Sampling rule that dictates if a span matches
9
+ # a specific criteria and what sampling strategy to
10
+ # apply in case of a positive match.
11
+ class Rule
12
+ extend Forwardable
13
+
14
+ attr_reader :matcher, :sampler
15
+
16
+ # @param [Matcher] matcher A matcher to verify span conformity against
17
+ # @param [Sampler] sampler A sampler to be consulted on a positive match
18
+ def initialize(matcher, sampler)
19
+ @matcher = matcher
20
+ @sampler = sampler
21
+ end
22
+
23
+ # Evaluates if the provided `span` conforms to the `matcher`.
24
+ #
25
+ # @param [Span] span
26
+ # @return [Boolean] whether this rules applies to the span
27
+ # @return [NilClass] if the matcher fails errs during evaluation
28
+ def match?(span)
29
+ @matcher.match?(span)
30
+ rescue => e
31
+ Datadog.logger.error("Matcher failed. Cause: #{e.message} Source: #{e.backtrace.first}")
32
+ nil
33
+ end
34
+
35
+ def_delegators :@sampler, :sample?, :sample_rate
36
+ end
37
+
38
+ # A \Rule that matches a span based on
39
+ # operation name and/or service name and
40
+ # applies a fixed sampling to matching spans.
41
+ class SimpleRule < Rule
42
+ # @param name [String,Regexp,Proc] Matcher for case equality (===) with the span name, defaults to always match
43
+ # @param service [String,Regexp,Proc] Matcher for case equality (===) with the service name, defaults to always match
44
+ # @param sample_rate [Float] Sampling rate between +[0,1]+
45
+ def initialize(name: SimpleMatcher::MATCH_ALL, service: SimpleMatcher::MATCH_ALL, sample_rate: 1.0)
46
+ # We want to allow 0.0 to drop all traces, but \RateSampler
47
+ # considers 0.0 an invalid rate and falls back to 100% sampling.
48
+ #
49
+ # We address that here by not setting the rate in the constructor,
50
+ # but using the setter method.
51
+ #
52
+ # We don't want to make this change directly to \RateSampler
53
+ # because it breaks its current contract to existing users.
54
+ sampler = Datadog::RateSampler.new
55
+ sampler.sample_rate = sample_rate
56
+
57
+ super(SimpleMatcher.new(name: name, service: service), sampler)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,125 @@
1
+ require 'forwardable'
2
+
3
+ require 'ddtrace/ext/priority'
4
+
5
+ require 'ddtrace/ext/sampling'
6
+ require 'ddtrace/sampler'
7
+ require 'ddtrace/sampling/rate_limiter'
8
+
9
+ module Datadog
10
+ module Sampling
11
+ # Span {Sampler} that applies a set of {Rule}s to decide
12
+ # on sampling outcome. Then, a rate limiter is applied.
13
+ #
14
+ # If a span does not conform to any rules, a default
15
+ # sampling strategy is applied.
16
+ class RuleSampler
17
+ extend Forwardable
18
+
19
+ AGENT_RATE_METRIC_KEY = '_dd.agent_psr'.freeze
20
+
21
+ attr_reader :rules, :rate_limiter, :default_sampler
22
+
23
+ # @param rules [Array<Rule>] ordered list of rules to be applied to a span
24
+ # @param rate_limit [Float] number of traces per second, defaults to +100+
25
+ # @param rate_limiter [RateLimiter] limiter applied after rule matching
26
+ # @param default_sample_rate [Float] fallback sample rate when no rules apply to a span,
27
+ # between +[0,1]+, defaults to +1+
28
+ # @param default_sampler [Sample] fallback strategy when no rules apply to a span
29
+ def initialize(rules = [],
30
+ rate_limit: Datadog.configuration.sampling.rate_limit,
31
+ rate_limiter: nil,
32
+ default_sample_rate: Datadog.configuration.sampling.default_rate,
33
+ default_sampler: nil)
34
+
35
+ @rules = rules
36
+
37
+ @rate_limiter = if rate_limiter
38
+ rate_limiter
39
+ elsif rate_limit
40
+ Datadog::Sampling::TokenBucket.new(rate_limit)
41
+ else
42
+ Datadog::Sampling::UnlimitedLimiter.new
43
+ end
44
+
45
+ @default_sampler = if default_sampler
46
+ default_sampler
47
+ elsif default_sample_rate
48
+ # We want to allow 0.0 to drop all traces, but \RateSampler
49
+ # considers 0.0 an invalid rate and falls back to 100% sampling.
50
+ #
51
+ # We address that here by not setting the rate in the constructor,
52
+ # but using the setter method.
53
+ #
54
+ # We don't want to make this change directly to \RateSampler
55
+ # because it breaks its current contract to existing users.
56
+ Datadog::RateSampler.new.tap { |s| s.sample_rate = default_sample_rate }
57
+ else
58
+ RateByServiceSampler.new(1.0, env: -> { Datadog.tracer.tags[:env] })
59
+ end
60
+ end
61
+
62
+ # /RuleSampler's components (it's rate limiter, for example) are
63
+ # not be guaranteed to be size-effect free.
64
+ # It is not possible to guarantee that a call to {#sample?} will
65
+ # return the same result as a successive call to {#sample!} with the same span.
66
+ #
67
+ # Use {#sample!} instead
68
+ def sample?(_span)
69
+ raise 'RuleSampler cannot be evaluated without side-effects'
70
+ end
71
+
72
+ def sample!(span)
73
+ sampled = sample_span(span) do |s|
74
+ @default_sampler.sample!(s).tap do
75
+ # We want to make sure the span is tagged with the agent-derived
76
+ # service rate. Retrieve this from the rate by service sampler.
77
+ # Only do this if it was set by a RateByServiceSampler.
78
+ if @default_sampler.is_a?(RateByServiceSampler)
79
+ s.set_metric(AGENT_RATE_METRIC_KEY, @default_sampler.sample_rate(span))
80
+ end
81
+ end
82
+ end
83
+
84
+ sampled.tap do
85
+ span.sampled = sampled
86
+ end
87
+ end
88
+
89
+ def update(*args)
90
+ return false unless @default_sampler.respond_to?(:update)
91
+ @default_sampler.update(*args)
92
+ end
93
+
94
+ private
95
+
96
+ def sample_span(span)
97
+ rule = @rules.find { |r| r.match?(span) }
98
+
99
+ return yield(span) if rule.nil?
100
+
101
+ sampled = rule.sample?(span)
102
+ sample_rate = rule.sample_rate(span)
103
+
104
+ set_rule_metrics(span, sample_rate)
105
+
106
+ return false unless sampled
107
+
108
+ rate_limiter.allow?(1).tap do
109
+ set_limiter_metrics(span, rate_limiter.effective_rate)
110
+ end
111
+ rescue StandardError => e
112
+ Datadog.logger.error("Rule sampling failed. Cause: #{e.message} Source: #{e.backtrace.first}")
113
+ yield(span)
114
+ end
115
+
116
+ def set_rule_metrics(span, sample_rate)
117
+ span.set_metric(Ext::Sampling::RULE_SAMPLE_RATE, sample_rate)
118
+ end
119
+
120
+ def set_limiter_metrics(span, limiter_rate)
121
+ span.set_metric(Ext::Sampling::RATE_LIMITER_RATE, limiter_rate)
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,307 @@
1
+ require 'time'
2
+ require 'thread'
3
+
4
+ require 'ddtrace/utils'
5
+ require 'ddtrace/ext/errors'
6
+ require 'ddtrace/ext/priority'
7
+ require 'ddtrace/environment'
8
+ require 'ddtrace/analytics'
9
+ require 'ddtrace/forced_tracing'
10
+ require 'ddtrace/diagnostics/health'
11
+
12
+ module Datadog
13
+ # Represents a logical unit of work in the system. Each trace consists of one or more spans.
14
+ # Each span consists of a start time and a duration. For example, a span can describe the time
15
+ # spent on a distributed call on a separate machine, or the time spent in a small component
16
+ # within a larger operation. Spans can be nested within each other, and in those instances
17
+ # will have a parent-child relationship.
18
+ #
19
+ # rubocop:disable Metrics/ClassLength
20
+ class Span
21
+ prepend Analytics::Span
22
+ prepend ForcedTracing::Span
23
+
24
+ # The max value for a \Span identifier.
25
+ # Span and trace identifiers should be strictly positive and strictly inferior to this limit.
26
+ #
27
+ # Limited to 63-bit positive integers, as some other languages might be limited to this,
28
+ # and IDs need to be easy to port across various languages and platforms.
29
+ MAX_ID = 2**63
30
+
31
+ # While we only generate 63-bit integers due to limitations in other languages, we support
32
+ # parsing 64-bit integers for distributed tracing since an upstream system may generate one
33
+ EXTERNAL_MAX_ID = 2**64
34
+
35
+ # This limit is for numeric tags because uint64 could end up rounded.
36
+ NUMERIC_TAG_SIZE_RANGE = (-2**53..2**53)
37
+
38
+ attr_accessor :name, :service, :resource, :span_type,
39
+ :start_time, :end_time,
40
+ :span_id, :trace_id, :parent_id,
41
+ :status, :sampled,
42
+ :tracer, :context
43
+
44
+ attr_reader :parent
45
+ # Create a new span linked to the given tracer. Call the \Tracer method <tt>start_span()</tt>
46
+ # and then <tt>finish()</tt> once the tracer operation is over.
47
+ #
48
+ # * +service+: the service name for this span
49
+ # * +resource+: the resource this span refers, or +name+ if it's missing
50
+ # * +span_type+: the type of the span (such as +http+, +db+ and so on)
51
+ # * +parent_id+: the identifier of the parent span
52
+ # * +trace_id+: the identifier of the root span for this trace
53
+ # * +context+: the context of the span
54
+ def initialize(tracer, name, options = {})
55
+ @tracer = tracer
56
+
57
+ @name = name
58
+ @service = options.fetch(:service, nil)
59
+ @resource = options.fetch(:resource, name)
60
+ @span_type = options.fetch(:span_type, nil)
61
+
62
+ @span_id = Datadog::Utils.next_id
63
+ @parent_id = options.fetch(:parent_id, 0)
64
+ @trace_id = options.fetch(:trace_id, Datadog::Utils.next_id)
65
+
66
+ @context = options.fetch(:context, nil)
67
+
68
+ @meta = {}
69
+ @metrics = {}
70
+ @status = 0
71
+
72
+ @parent = nil
73
+ @sampled = true
74
+
75
+ @start_time = nil # set by Tracer.start_span
76
+ @end_time = nil # set by Span.finish
77
+
78
+ @allocation_count_start = now_allocations
79
+ @allocation_count_finish = @allocation_count_start
80
+ end
81
+
82
+ # Set the given key / value tag pair on the span. Keys and values
83
+ # must be strings. A valid example is:
84
+ #
85
+ # span.set_tag('http.method', request.method)
86
+ def set_tag(key, value = nil)
87
+ # Keys must be unique between tags and metrics
88
+ @metrics.delete(key)
89
+
90
+ # Ensure `http.status_code` is always a string so it is added to
91
+ # @meta instead of @metrics
92
+ # DEV: This is necessary because the agent looks to `meta['http.status_code']` for
93
+ # tagging necessary metrics
94
+ value = value.to_s if key == Ext::HTTP::STATUS_CODE
95
+
96
+ # NOTE: Adding numeric tags as metrics is stop-gap support
97
+ # for numeric typed tags. Eventually they will become
98
+ # tags again.
99
+ # Any numeric that is not an integer greater than max size is logged as a metric.
100
+ # Everything else gets logged as a tag.
101
+ if value.is_a?(Numeric) && !(value.is_a?(Integer) && !NUMERIC_TAG_SIZE_RANGE.cover?(value))
102
+ set_metric(key, value)
103
+ else
104
+ @meta[key] = value.to_s
105
+ end
106
+ rescue StandardError => e
107
+ Datadog.logger.debug("Unable to set the tag #{key}, ignoring it. Caused by: #{e}")
108
+ end
109
+
110
+ # Sets tags from given hash, for each key in hash it sets the tag with that key
111
+ # and associated value from the hash. It is shortcut for `set_tag`. Keys and values
112
+ # of the hash must be strings. Note that nested hashes are not supported.
113
+ # A valid example is:
114
+ #
115
+ # span.set_tags({ "http.method" => "GET", "user.id" => "234" })
116
+ def set_tags(tags)
117
+ tags.each { |k, v| set_tag(k, v) }
118
+ end
119
+
120
+ # This method removes a tag for the given key.
121
+ def clear_tag(key)
122
+ @meta.delete(key)
123
+ end
124
+
125
+ # Return the tag with the given key, nil if it doesn't exist.
126
+ def get_tag(key)
127
+ @meta[key] || @metrics[key]
128
+ end
129
+
130
+ # This method sets a tag with a floating point value for the given key. It acts
131
+ # like `set_tag()` and it simply add a tag without further processing.
132
+ def set_metric(key, value)
133
+ # Keys must be unique between tags and metrics
134
+ @meta.delete(key)
135
+
136
+ # enforce that the value is a floating point number
137
+ value = Float(value)
138
+ @metrics[key] = value
139
+ rescue StandardError => e
140
+ Datadog.logger.debug("Unable to set the metric #{key}, ignoring it. Caused by: #{e}")
141
+ end
142
+
143
+ # This method removes a metric for the given key. It acts like {#remove_tag}.
144
+ def clear_metric(key)
145
+ @metrics.delete(key)
146
+ end
147
+
148
+ # Return the metric with the given key, nil if it doesn't exist.
149
+ def get_metric(key)
150
+ @metrics[key] || @meta[key]
151
+ end
152
+
153
+ # Mark the span with the given error.
154
+ def set_error(e)
155
+ e = Error.build_from(e)
156
+
157
+ @status = Ext::Errors::STATUS
158
+ set_tag(Ext::Errors::TYPE, e.type) unless e.type.empty?
159
+ set_tag(Ext::Errors::MSG, e.message) unless e.message.empty?
160
+ set_tag(Ext::Errors::STACK, e.backtrace) unless e.backtrace.empty?
161
+ end
162
+
163
+ # Mark the span finished at the current time and submit it.
164
+ def finish(finish_time = nil)
165
+ # A span should not be finished twice. Note that this is not thread-safe,
166
+ # finish is called from multiple threads, a given span might be finished
167
+ # several times. Again, one should not do this, so this test is more a
168
+ # fallback to avoid very bad things and protect you in most common cases.
169
+ return if finished?
170
+
171
+ @allocation_count_finish = now_allocations
172
+
173
+ # Provide a default start_time if unset, but this should have been set by start_span.
174
+ # Using now here causes 0-duration spans, still, this is expected, as we never
175
+ # explicitely say when it started.
176
+ @start_time ||= Time.now.utc
177
+
178
+ @end_time = finish_time.nil? ? Time.now.utc : finish_time # finish this
179
+
180
+ # Finish does not really do anything if the span is not bound to a tracer and a context.
181
+ return self if @tracer.nil? || @context.nil?
182
+
183
+ # spans without a service would be dropped, so here we provide a default.
184
+ # This should really never happen with integrations in contrib, as a default
185
+ # service is always set. It's only for custom instrumentation.
186
+ @service ||= (@tracer && @tracer.default_service)
187
+
188
+ begin
189
+ @context.close_span(self)
190
+ @tracer.record(self)
191
+ rescue StandardError => e
192
+ Datadog.logger.debug("error recording finished trace: #{e}")
193
+ Datadog.health_metrics.error_span_finish(1, tags: ["error:#{e.class.name}"])
194
+ end
195
+ self
196
+ end
197
+
198
+ # Return whether the span is finished or not.
199
+ def finished?
200
+ !@end_time.nil?
201
+ end
202
+
203
+ # Return a string representation of the span.
204
+ def to_s
205
+ "Span(name:#{@name},sid:#{@span_id},tid:#{@trace_id},pid:#{@parent_id})"
206
+ end
207
+
208
+ # DEPRECATED: remove this function in the next release, replaced by ``parent=``
209
+ def set_parent(parent)
210
+ self.parent = parent
211
+ end
212
+
213
+ # Set this span's parent, inheriting any properties not explicitly set.
214
+ # If the parent is nil, set the span zero values.
215
+ def parent=(parent)
216
+ @parent = parent
217
+
218
+ if parent.nil?
219
+ @trace_id = @span_id
220
+ @parent_id = 0
221
+ else
222
+ @trace_id = parent.trace_id
223
+ @parent_id = parent.span_id
224
+ @service ||= parent.service
225
+ @sampled = parent.sampled
226
+ end
227
+ end
228
+
229
+ def allocations
230
+ @allocation_count_finish - @allocation_count_start
231
+ end
232
+
233
+ # Return the hash representation of the current span.
234
+ def to_hash
235
+ h = {
236
+ span_id: @span_id,
237
+ parent_id: @parent_id,
238
+ trace_id: @trace_id,
239
+ name: @name,
240
+ service: @service,
241
+ resource: @resource,
242
+ type: @span_type,
243
+ meta: @meta,
244
+ metrics: @metrics,
245
+ allocations: allocations,
246
+ error: @status
247
+ }
248
+
249
+ if !@start_time.nil? && !@end_time.nil?
250
+ h[:start] = (@start_time.to_f * 1e9).to_i
251
+ h[:duration] = ((@end_time - @start_time) * 1e9).to_i
252
+ end
253
+
254
+ h
255
+ end
256
+
257
+ # Return a human readable version of the span
258
+ def pretty_print(q)
259
+ start_time = (@start_time.to_f * 1e9).to_i rescue '-'
260
+ end_time = (@end_time.to_f * 1e9).to_i rescue '-'
261
+ duration = ((@end_time - @start_time) * 1e9).to_i rescue 0
262
+ q.group 0 do
263
+ q.breakable
264
+ q.text "Name: #{@name}\n"
265
+ q.text "Span ID: #{@span_id}\n"
266
+ q.text "Parent ID: #{@parent_id}\n"
267
+ q.text "Trace ID: #{@trace_id}\n"
268
+ q.text "Type: #{@span_type}\n"
269
+ q.text "Service: #{@service}\n"
270
+ q.text "Resource: #{@resource}\n"
271
+ q.text "Error: #{@status}\n"
272
+ q.text "Start: #{start_time}\n"
273
+ q.text "End: #{end_time}\n"
274
+ q.text "Duration: #{duration}\n"
275
+ q.text "Allocations: #{allocations}\n"
276
+ q.group(2, 'Tags: [', "]\n") do
277
+ q.breakable
278
+ q.seplist @meta.each do |key, value|
279
+ q.text "#{key} => #{value}"
280
+ end
281
+ end
282
+ q.group(2, 'Metrics: [', ']') do
283
+ q.breakable
284
+ q.seplist @metrics.each do |key, value|
285
+ q.text "#{key} => #{value}"
286
+ end
287
+ end
288
+ end
289
+ end
290
+
291
+ private
292
+
293
+ if defined?(JRUBY_VERSION) || Gem::Version.new(RUBY_VERSION) < Gem::Version.new(VERSION::MINIMUM_RUBY_VERSION)
294
+ def now_allocations
295
+ 0
296
+ end
297
+ elsif Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.0')
298
+ def now_allocations
299
+ GC.stat.fetch(:total_allocated_object)
300
+ end
301
+ else
302
+ def now_allocations
303
+ GC.stat(:total_allocated_objects)
304
+ end
305
+ end
306
+ end
307
+ end