ddtrace 0.38.0

Sign up to get free protection for your applications and to get access to all the features.
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