ls-trace 0.1.1

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 (356) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +673 -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/.dockerignore +1 -0
  11. data/.env +24 -0
  12. data/.github/CODEOWNERS +1 -0
  13. data/.gitignore +59 -0
  14. data/.rspec +1 -0
  15. data/.rubocop.yml +77 -0
  16. data/.yardopts +5 -0
  17. data/Appraisals +820 -0
  18. data/CHANGELOG.md +1051 -0
  19. data/CONTRIBUTING.md +85 -0
  20. data/Gemfile +7 -0
  21. data/LICENSE +24 -0
  22. data/README.md +108 -0
  23. data/Rakefile +635 -0
  24. data/benchmarks/postgres_database.yml +9 -0
  25. data/benchmarks/sidekiq_test.rb +154 -0
  26. data/ddtrace.gemspec +63 -0
  27. data/docker-compose.yml +276 -0
  28. data/docs/DevelopmentGuide.md +195 -0
  29. data/docs/GettingStarted.md +1981 -0
  30. data/lib/ddtrace.rb +63 -0
  31. data/lib/ddtrace/analytics.rb +29 -0
  32. data/lib/ddtrace/augmentation.rb +13 -0
  33. data/lib/ddtrace/augmentation/method_wrapper.rb +20 -0
  34. data/lib/ddtrace/augmentation/method_wrapping.rb +38 -0
  35. data/lib/ddtrace/augmentation/shim.rb +102 -0
  36. data/lib/ddtrace/buffer.rb +119 -0
  37. data/lib/ddtrace/configuration.rb +30 -0
  38. data/lib/ddtrace/configuration/base.rb +82 -0
  39. data/lib/ddtrace/configuration/dependency_resolver.rb +24 -0
  40. data/lib/ddtrace/configuration/option.rb +55 -0
  41. data/lib/ddtrace/configuration/option_definition.rb +127 -0
  42. data/lib/ddtrace/configuration/option_definition_set.rb +18 -0
  43. data/lib/ddtrace/configuration/option_set.rb +6 -0
  44. data/lib/ddtrace/configuration/options.rb +107 -0
  45. data/lib/ddtrace/configuration/pin_setup.rb +30 -0
  46. data/lib/ddtrace/configuration/settings.rb +105 -0
  47. data/lib/ddtrace/context.rb +284 -0
  48. data/lib/ddtrace/context_flush.rb +132 -0
  49. data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +144 -0
  50. data/lib/ddtrace/contrib/action_pack/action_controller/patcher.rb +37 -0
  51. data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +27 -0
  52. data/lib/ddtrace/contrib/action_pack/ext.rb +16 -0
  53. data/lib/ddtrace/contrib/action_pack/integration.rb +36 -0
  54. data/lib/ddtrace/contrib/action_pack/patcher.rb +29 -0
  55. data/lib/ddtrace/contrib/action_pack/utils.rb +36 -0
  56. data/lib/ddtrace/contrib/action_view/configuration/settings.rb +26 -0
  57. data/lib/ddtrace/contrib/action_view/ext.rb +17 -0
  58. data/lib/ddtrace/contrib/action_view/instrumentation/partial_renderer.rb +78 -0
  59. data/lib/ddtrace/contrib/action_view/instrumentation/template_renderer.rb +167 -0
  60. data/lib/ddtrace/contrib/action_view/integration.rb +43 -0
  61. data/lib/ddtrace/contrib/action_view/patcher.rb +53 -0
  62. data/lib/ddtrace/contrib/action_view/utils.rb +32 -0
  63. data/lib/ddtrace/contrib/active_model_serializers/configuration/settings.rb +25 -0
  64. data/lib/ddtrace/contrib/active_model_serializers/event.rb +65 -0
  65. data/lib/ddtrace/contrib/active_model_serializers/events.rb +30 -0
  66. data/lib/ddtrace/contrib/active_model_serializers/events/render.rb +32 -0
  67. data/lib/ddtrace/contrib/active_model_serializers/events/serialize.rb +35 -0
  68. data/lib/ddtrace/contrib/active_model_serializers/ext.rb +17 -0
  69. data/lib/ddtrace/contrib/active_model_serializers/integration.rb +39 -0
  70. data/lib/ddtrace/contrib/active_model_serializers/patcher.rb +36 -0
  71. data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +46 -0
  72. data/lib/ddtrace/contrib/active_record/configuration/settings.rb +30 -0
  73. data/lib/ddtrace/contrib/active_record/event.rb +30 -0
  74. data/lib/ddtrace/contrib/active_record/events.rb +30 -0
  75. data/lib/ddtrace/contrib/active_record/events/instantiation.rb +57 -0
  76. data/lib/ddtrace/contrib/active_record/events/sql.rb +64 -0
  77. data/lib/ddtrace/contrib/active_record/ext.rb +21 -0
  78. data/lib/ddtrace/contrib/active_record/integration.rb +44 -0
  79. data/lib/ddtrace/contrib/active_record/patcher.rb +29 -0
  80. data/lib/ddtrace/contrib/active_record/utils.rb +76 -0
  81. data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +157 -0
  82. data/lib/ddtrace/contrib/active_support/cache/patcher.rb +62 -0
  83. data/lib/ddtrace/contrib/active_support/cache/redis.rb +47 -0
  84. data/lib/ddtrace/contrib/active_support/configuration/settings.rb +25 -0
  85. data/lib/ddtrace/contrib/active_support/ext.rb +21 -0
  86. data/lib/ddtrace/contrib/active_support/integration.rb +38 -0
  87. data/lib/ddtrace/contrib/active_support/notifications/event.rb +62 -0
  88. data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +66 -0
  89. data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +159 -0
  90. data/lib/ddtrace/contrib/active_support/patcher.rb +29 -0
  91. data/lib/ddtrace/contrib/analytics.rb +20 -0
  92. data/lib/ddtrace/contrib/aws/configuration/settings.rb +25 -0
  93. data/lib/ddtrace/contrib/aws/ext.rb +20 -0
  94. data/lib/ddtrace/contrib/aws/instrumentation.rb +56 -0
  95. data/lib/ddtrace/contrib/aws/integration.rb +36 -0
  96. data/lib/ddtrace/contrib/aws/parsed_context.rb +56 -0
  97. data/lib/ddtrace/contrib/aws/patcher.rb +49 -0
  98. data/lib/ddtrace/contrib/aws/services.rb +115 -0
  99. data/lib/ddtrace/contrib/concurrent_ruby/configuration/settings.rb +15 -0
  100. data/lib/ddtrace/contrib/concurrent_ruby/context_composite_executor_service.rb +35 -0
  101. data/lib/ddtrace/contrib/concurrent_ruby/ext.rb +11 -0
  102. data/lib/ddtrace/contrib/concurrent_ruby/future_patch.rb +23 -0
  103. data/lib/ddtrace/contrib/concurrent_ruby/integration.rb +32 -0
  104. data/lib/ddtrace/contrib/concurrent_ruby/patcher.rb +35 -0
  105. data/lib/ddtrace/contrib/configurable.rb +59 -0
  106. data/lib/ddtrace/contrib/configuration/resolver.rb +12 -0
  107. data/lib/ddtrace/contrib/configuration/settings.rb +35 -0
  108. data/lib/ddtrace/contrib/dalli/configuration/settings.rb +25 -0
  109. data/lib/ddtrace/contrib/dalli/ext.rb +17 -0
  110. data/lib/ddtrace/contrib/dalli/instrumentation.rb +50 -0
  111. data/lib/ddtrace/contrib/dalli/integration.rb +36 -0
  112. data/lib/ddtrace/contrib/dalli/patcher.rb +73 -0
  113. data/lib/ddtrace/contrib/dalli/quantize.rb +22 -0
  114. data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +25 -0
  115. data/lib/ddtrace/contrib/delayed_job/ext.rb +18 -0
  116. data/lib/ddtrace/contrib/delayed_job/integration.rb +32 -0
  117. data/lib/ddtrace/contrib/delayed_job/patcher.rb +34 -0
  118. data/lib/ddtrace/contrib/delayed_job/plugin.rb +57 -0
  119. data/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb +26 -0
  120. data/lib/ddtrace/contrib/elasticsearch/ext.rb +19 -0
  121. data/lib/ddtrace/contrib/elasticsearch/integration.rb +37 -0
  122. data/lib/ddtrace/contrib/elasticsearch/patcher.rb +124 -0
  123. data/lib/ddtrace/contrib/elasticsearch/quantize.rb +80 -0
  124. data/lib/ddtrace/contrib/ethon/configuration/settings.rb +26 -0
  125. data/lib/ddtrace/contrib/ethon/easy_patch.rb +139 -0
  126. data/lib/ddtrace/contrib/ethon/ext.rb +15 -0
  127. data/lib/ddtrace/contrib/ethon/integration.rb +31 -0
  128. data/lib/ddtrace/contrib/ethon/multi_patch.rb +80 -0
  129. data/lib/ddtrace/contrib/ethon/patcher.rb +27 -0
  130. data/lib/ddtrace/contrib/excon/configuration/settings.rb +28 -0
  131. data/lib/ddtrace/contrib/excon/ext.rb +14 -0
  132. data/lib/ddtrace/contrib/excon/integration.rb +32 -0
  133. data/lib/ddtrace/contrib/excon/middleware.rb +154 -0
  134. data/lib/ddtrace/contrib/excon/patcher.rb +34 -0
  135. data/lib/ddtrace/contrib/extensions.rb +59 -0
  136. data/lib/ddtrace/contrib/faraday/configuration/settings.rb +33 -0
  137. data/lib/ddtrace/contrib/faraday/ext.rb +14 -0
  138. data/lib/ddtrace/contrib/faraday/integration.rb +36 -0
  139. data/lib/ddtrace/contrib/faraday/middleware.rb +93 -0
  140. data/lib/ddtrace/contrib/faraday/patcher.rb +82 -0
  141. data/lib/ddtrace/contrib/faraday/rack_builder.rb +18 -0
  142. data/lib/ddtrace/contrib/grape/configuration/settings.rb +27 -0
  143. data/lib/ddtrace/contrib/grape/endpoint.rb +199 -0
  144. data/lib/ddtrace/contrib/grape/ext.rb +19 -0
  145. data/lib/ddtrace/contrib/grape/instrumentation.rb +33 -0
  146. data/lib/ddtrace/contrib/grape/integration.rb +36 -0
  147. data/lib/ddtrace/contrib/grape/patcher.rb +79 -0
  148. data/lib/ddtrace/contrib/graphql/configuration/settings.rb +27 -0
  149. data/lib/ddtrace/contrib/graphql/ext.rb +13 -0
  150. data/lib/ddtrace/contrib/graphql/integration.rb +38 -0
  151. data/lib/ddtrace/contrib/graphql/patcher.rb +63 -0
  152. data/lib/ddtrace/contrib/grpc/configuration/settings.rb +25 -0
  153. data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +74 -0
  154. data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +56 -0
  155. data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +73 -0
  156. data/lib/ddtrace/contrib/grpc/ext.rb +15 -0
  157. data/lib/ddtrace/contrib/grpc/integration.rb +36 -0
  158. data/lib/ddtrace/contrib/grpc/intercept_with_datadog.rb +49 -0
  159. data/lib/ddtrace/contrib/grpc/patcher.rb +78 -0
  160. data/lib/ddtrace/contrib/http/circuit_breaker.rb +63 -0
  161. data/lib/ddtrace/contrib/http/configuration/settings.rb +26 -0
  162. data/lib/ddtrace/contrib/http/ext.rb +14 -0
  163. data/lib/ddtrace/contrib/http/instrumentation.rb +114 -0
  164. data/lib/ddtrace/contrib/http/integration.rb +32 -0
  165. data/lib/ddtrace/contrib/http/patcher.rb +32 -0
  166. data/lib/ddtrace/contrib/integration.rb +16 -0
  167. data/lib/ddtrace/contrib/mongodb/configuration/settings.rb +28 -0
  168. data/lib/ddtrace/contrib/mongodb/ext.rb +20 -0
  169. data/lib/ddtrace/contrib/mongodb/instrumentation.rb +68 -0
  170. data/lib/ddtrace/contrib/mongodb/integration.rb +36 -0
  171. data/lib/ddtrace/contrib/mongodb/parsers.rb +68 -0
  172. data/lib/ddtrace/contrib/mongodb/patcher.rb +37 -0
  173. data/lib/ddtrace/contrib/mongodb/subscribers.rb +108 -0
  174. data/lib/ddtrace/contrib/mysql2/configuration/settings.rb +25 -0
  175. data/lib/ddtrace/contrib/mysql2/ext.rb +15 -0
  176. data/lib/ddtrace/contrib/mysql2/instrumentation.rb +60 -0
  177. data/lib/ddtrace/contrib/mysql2/integration.rb +32 -0
  178. data/lib/ddtrace/contrib/mysql2/patcher.rb +33 -0
  179. data/lib/ddtrace/contrib/patchable.rb +42 -0
  180. data/lib/ddtrace/contrib/patcher.rb +28 -0
  181. data/lib/ddtrace/contrib/racecar/configuration/settings.rb +25 -0
  182. data/lib/ddtrace/contrib/racecar/event.rb +67 -0
  183. data/lib/ddtrace/contrib/racecar/events.rb +30 -0
  184. data/lib/ddtrace/contrib/racecar/events/batch.rb +27 -0
  185. data/lib/ddtrace/contrib/racecar/events/message.rb +27 -0
  186. data/lib/ddtrace/contrib/racecar/ext.rb +21 -0
  187. data/lib/ddtrace/contrib/racecar/integration.rb +36 -0
  188. data/lib/ddtrace/contrib/racecar/patcher.rb +32 -0
  189. data/lib/ddtrace/contrib/rack/configuration/settings.rb +41 -0
  190. data/lib/ddtrace/contrib/rack/ext.rb +18 -0
  191. data/lib/ddtrace/contrib/rack/integration.rb +32 -0
  192. data/lib/ddtrace/contrib/rack/middlewares.rb +283 -0
  193. data/lib/ddtrace/contrib/rack/patcher.rb +72 -0
  194. data/lib/ddtrace/contrib/rack/request_queue.rb +39 -0
  195. data/lib/ddtrace/contrib/rails/configuration/settings.rb +80 -0
  196. data/lib/ddtrace/contrib/rails/ext.rb +12 -0
  197. data/lib/ddtrace/contrib/rails/framework.rb +100 -0
  198. data/lib/ddtrace/contrib/rails/integration.rb +37 -0
  199. data/lib/ddtrace/contrib/rails/middlewares.rb +38 -0
  200. data/lib/ddtrace/contrib/rails/patcher.rb +78 -0
  201. data/lib/ddtrace/contrib/rails/railtie.rb +17 -0
  202. data/lib/ddtrace/contrib/rails/utils.rb +20 -0
  203. data/lib/ddtrace/contrib/rake/configuration/settings.rb +27 -0
  204. data/lib/ddtrace/contrib/rake/ext.rb +18 -0
  205. data/lib/ddtrace/contrib/rake/instrumentation.rb +84 -0
  206. data/lib/ddtrace/contrib/rake/integration.rb +32 -0
  207. data/lib/ddtrace/contrib/rake/patcher.rb +36 -0
  208. data/lib/ddtrace/contrib/redis/configuration/settings.rb +25 -0
  209. data/lib/ddtrace/contrib/redis/ext.rb +18 -0
  210. data/lib/ddtrace/contrib/redis/integration.rb +36 -0
  211. data/lib/ddtrace/contrib/redis/patcher.rb +94 -0
  212. data/lib/ddtrace/contrib/redis/quantize.rb +47 -0
  213. data/lib/ddtrace/contrib/redis/tags.rb +38 -0
  214. data/lib/ddtrace/contrib/registerable.rb +33 -0
  215. data/lib/ddtrace/contrib/registry.rb +42 -0
  216. data/lib/ddtrace/contrib/resque/configuration/settings.rb +26 -0
  217. data/lib/ddtrace/contrib/resque/ext.rb +14 -0
  218. data/lib/ddtrace/contrib/resque/integration.rb +37 -0
  219. data/lib/ddtrace/contrib/resque/patcher.rb +35 -0
  220. data/lib/ddtrace/contrib/resque/resque_job.rb +76 -0
  221. data/lib/ddtrace/contrib/rest_client/configuration/settings.rb +26 -0
  222. data/lib/ddtrace/contrib/rest_client/ext.rb +14 -0
  223. data/lib/ddtrace/contrib/rest_client/integration.rb +31 -0
  224. data/lib/ddtrace/contrib/rest_client/patcher.rb +25 -0
  225. data/lib/ddtrace/contrib/rest_client/request_patch.rb +89 -0
  226. data/lib/ddtrace/contrib/sequel/configuration/settings.rb +23 -0
  227. data/lib/ddtrace/contrib/sequel/database.rb +61 -0
  228. data/lib/ddtrace/contrib/sequel/dataset.rb +62 -0
  229. data/lib/ddtrace/contrib/sequel/ext.rb +15 -0
  230. data/lib/ddtrace/contrib/sequel/integration.rb +32 -0
  231. data/lib/ddtrace/contrib/sequel/patcher.rb +39 -0
  232. data/lib/ddtrace/contrib/sequel/utils.rb +46 -0
  233. data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +24 -0
  234. data/lib/ddtrace/contrib/shoryuken/ext.rb +18 -0
  235. data/lib/ddtrace/contrib/shoryuken/integration.rb +35 -0
  236. data/lib/ddtrace/contrib/shoryuken/patcher.rb +30 -0
  237. data/lib/ddtrace/contrib/shoryuken/tracer.rb +45 -0
  238. data/lib/ddtrace/contrib/sidekiq/client_tracer.rb +43 -0
  239. data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +26 -0
  240. data/lib/ddtrace/contrib/sidekiq/ext.rb +21 -0
  241. data/lib/ddtrace/contrib/sidekiq/integration.rb +36 -0
  242. data/lib/ddtrace/contrib/sidekiq/patcher.rb +40 -0
  243. data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +58 -0
  244. data/lib/ddtrace/contrib/sidekiq/tracing.rb +28 -0
  245. data/lib/ddtrace/contrib/sinatra/configuration/settings.rb +34 -0
  246. data/lib/ddtrace/contrib/sinatra/env.rb +38 -0
  247. data/lib/ddtrace/contrib/sinatra/ext.rb +18 -0
  248. data/lib/ddtrace/contrib/sinatra/headers.rb +31 -0
  249. data/lib/ddtrace/contrib/sinatra/integration.rb +36 -0
  250. data/lib/ddtrace/contrib/sinatra/patcher.rb +33 -0
  251. data/lib/ddtrace/contrib/sinatra/tracer.rb +84 -0
  252. data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +72 -0
  253. data/lib/ddtrace/contrib/sucker_punch/configuration/settings.rb +25 -0
  254. data/lib/ddtrace/contrib/sucker_punch/exception_handler.rb +26 -0
  255. data/lib/ddtrace/contrib/sucker_punch/ext.rb +18 -0
  256. data/lib/ddtrace/contrib/sucker_punch/instrumentation.rb +70 -0
  257. data/lib/ddtrace/contrib/sucker_punch/integration.rb +36 -0
  258. data/lib/ddtrace/contrib/sucker_punch/patcher.rb +48 -0
  259. data/lib/ddtrace/correlation.rb +28 -0
  260. data/lib/ddtrace/diagnostics/health.rb +30 -0
  261. data/lib/ddtrace/distributed_tracing/headers/b3.rb +44 -0
  262. data/lib/ddtrace/distributed_tracing/headers/b3_single.rb +56 -0
  263. data/lib/ddtrace/distributed_tracing/headers/datadog.rb +42 -0
  264. data/lib/ddtrace/distributed_tracing/headers/headers.rb +70 -0
  265. data/lib/ddtrace/distributed_tracing/headers/helpers.rb +45 -0
  266. data/lib/ddtrace/encoding.rb +65 -0
  267. data/lib/ddtrace/environment.rb +23 -0
  268. data/lib/ddtrace/error.rb +27 -0
  269. data/lib/ddtrace/ext/analytics.rb +11 -0
  270. data/lib/ddtrace/ext/app_types.rb +11 -0
  271. data/lib/ddtrace/ext/diagnostics.rb +25 -0
  272. data/lib/ddtrace/ext/distributed.rb +33 -0
  273. data/lib/ddtrace/ext/errors.rb +10 -0
  274. data/lib/ddtrace/ext/forced_tracing.rb +25 -0
  275. data/lib/ddtrace/ext/http.rb +46 -0
  276. data/lib/ddtrace/ext/manual_tracing.rb +9 -0
  277. data/lib/ddtrace/ext/metrics.rb +15 -0
  278. data/lib/ddtrace/ext/net.rb +10 -0
  279. data/lib/ddtrace/ext/priority.rb +16 -0
  280. data/lib/ddtrace/ext/runtime.rb +26 -0
  281. data/lib/ddtrace/ext/sql.rb +8 -0
  282. data/lib/ddtrace/ext/transport.rb +17 -0
  283. data/lib/ddtrace/forced_tracing.rb +36 -0
  284. data/lib/ddtrace/logger.rb +39 -0
  285. data/lib/ddtrace/metrics.rb +215 -0
  286. data/lib/ddtrace/monkey.rb +58 -0
  287. data/lib/ddtrace/opentracer.rb +40 -0
  288. data/lib/ddtrace/opentracer/binary_propagator.rb +24 -0
  289. data/lib/ddtrace/opentracer/carrier.rb +6 -0
  290. data/lib/ddtrace/opentracer/distributed_headers.rb +52 -0
  291. data/lib/ddtrace/opentracer/global_tracer.rb +15 -0
  292. data/lib/ddtrace/opentracer/propagator.rb +22 -0
  293. data/lib/ddtrace/opentracer/rack_propagator.rb +60 -0
  294. data/lib/ddtrace/opentracer/scope.rb +15 -0
  295. data/lib/ddtrace/opentracer/scope_manager.rb +6 -0
  296. data/lib/ddtrace/opentracer/span.rb +98 -0
  297. data/lib/ddtrace/opentracer/span_context.rb +14 -0
  298. data/lib/ddtrace/opentracer/span_context_factory.rb +23 -0
  299. data/lib/ddtrace/opentracer/text_map_propagator.rb +75 -0
  300. data/lib/ddtrace/opentracer/thread_local_scope.rb +30 -0
  301. data/lib/ddtrace/opentracer/thread_local_scope_manager.rb +40 -0
  302. data/lib/ddtrace/opentracer/tracer.rb +208 -0
  303. data/lib/ddtrace/patcher.rb +47 -0
  304. data/lib/ddtrace/pin.rb +114 -0
  305. data/lib/ddtrace/pipeline.rb +46 -0
  306. data/lib/ddtrace/pipeline/span_filter.rb +38 -0
  307. data/lib/ddtrace/pipeline/span_processor.rb +20 -0
  308. data/lib/ddtrace/propagation/grpc_propagator.rb +61 -0
  309. data/lib/ddtrace/propagation/http_propagator.rb +75 -0
  310. data/lib/ddtrace/provider.rb +21 -0
  311. data/lib/ddtrace/quantization/hash.rb +103 -0
  312. data/lib/ddtrace/quantization/http.rb +86 -0
  313. data/lib/ddtrace/runtime/cgroup.rb +44 -0
  314. data/lib/ddtrace/runtime/class_count.rb +17 -0
  315. data/lib/ddtrace/runtime/container.rb +73 -0
  316. data/lib/ddtrace/runtime/gc.rb +16 -0
  317. data/lib/ddtrace/runtime/identity.rb +41 -0
  318. data/lib/ddtrace/runtime/metrics.rb +93 -0
  319. data/lib/ddtrace/runtime/object_space.rb +19 -0
  320. data/lib/ddtrace/runtime/socket.rb +14 -0
  321. data/lib/ddtrace/runtime/thread_count.rb +16 -0
  322. data/lib/ddtrace/sampler.rb +195 -0
  323. data/lib/ddtrace/span.rb +260 -0
  324. data/lib/ddtrace/sync_writer.rb +62 -0
  325. data/lib/ddtrace/tracer.rb +459 -0
  326. data/lib/ddtrace/transport/http.rb +91 -0
  327. data/lib/ddtrace/transport/http/adapters/net.rb +112 -0
  328. data/lib/ddtrace/transport/http/adapters/registry.rb +24 -0
  329. data/lib/ddtrace/transport/http/adapters/test.rb +77 -0
  330. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +64 -0
  331. data/lib/ddtrace/transport/http/api.rb +46 -0
  332. data/lib/ddtrace/transport/http/api/endpoint.rb +27 -0
  333. data/lib/ddtrace/transport/http/api/fallbacks.rb +22 -0
  334. data/lib/ddtrace/transport/http/api/instance.rb +29 -0
  335. data/lib/ddtrace/transport/http/api/map.rb +14 -0
  336. data/lib/ddtrace/transport/http/api/spec.rb +15 -0
  337. data/lib/ddtrace/transport/http/builder.rb +165 -0
  338. data/lib/ddtrace/transport/http/client.rb +107 -0
  339. data/lib/ddtrace/transport/http/env.rb +48 -0
  340. data/lib/ddtrace/transport/http/response.rb +26 -0
  341. data/lib/ddtrace/transport/http/statistics.rb +30 -0
  342. data/lib/ddtrace/transport/http/traces.rb +140 -0
  343. data/lib/ddtrace/transport/parcel.rb +13 -0
  344. data/lib/ddtrace/transport/request.rb +13 -0
  345. data/lib/ddtrace/transport/response.rb +49 -0
  346. data/lib/ddtrace/transport/statistics.rb +72 -0
  347. data/lib/ddtrace/transport/traces.rb +33 -0
  348. data/lib/ddtrace/utils.rb +65 -0
  349. data/lib/ddtrace/utils/database.rb +25 -0
  350. data/lib/ddtrace/utils/time.rb +14 -0
  351. data/lib/ddtrace/vendor/active_record/connection_specification.rb +301 -0
  352. data/lib/ddtrace/version.rb +12 -0
  353. data/lib/ddtrace/workers.rb +125 -0
  354. data/lib/ddtrace/writer.rb +157 -0
  355. data/tasks/release_gem.rake +28 -0
  356. metadata +682 -0
@@ -0,0 +1,260 @@
1
+ require 'time'
2
+ require 'thread'
3
+
4
+ require 'ddtrace/utils'
5
+ require 'ddtrace/ext/errors'
6
+ require 'ddtrace/ext/priority'
7
+ require 'ddtrace/analytics'
8
+ require 'ddtrace/forced_tracing'
9
+
10
+ module Datadog
11
+ # Represents a logical unit of work in the system. Each trace consists of one or more spans.
12
+ # Each span consists of a start time and a duration. For example, a span can describe the time
13
+ # spent on a distributed call on a separate machine, or the time spent in a small component
14
+ # within a larger operation. Spans can be nested within each other, and in those instances
15
+ # will have a parent-child relationship.
16
+ #
17
+ # rubocop:disable Metrics/ClassLength
18
+ class Span
19
+ prepend Analytics::Span
20
+ prepend ForcedTracing::Span
21
+
22
+ # The max value for a \Span identifier.
23
+ # Span and trace identifiers should be strictly positive and strictly inferior to this limit.
24
+ #
25
+ # Limited to 63-bit positive integers, as some other languages might be limited to this,
26
+ # and IDs need to be easy to port across various languages and platforms.
27
+ MAX_ID = 2**63
28
+
29
+ # While we only generate 63-bit integers due to limitations in other languages, we support
30
+ # parsing 64-bit integers for distributed tracing since an upstream system may generate one
31
+ EXTERNAL_MAX_ID = 2**64
32
+
33
+ attr_accessor :name, :service, :resource, :span_type,
34
+ :start_time, :end_time,
35
+ :span_id, :trace_id, :parent_id,
36
+ :status, :sampled,
37
+ :tracer, :context
38
+
39
+ attr_reader :parent
40
+ # Create a new span linked to the given tracer. Call the \Tracer method <tt>start_span()</tt>
41
+ # and then <tt>finish()</tt> once the tracer operation is over.
42
+ #
43
+ # * +service+: the service name for this span
44
+ # * +resource+: the resource this span refers, or +name+ if it's missing
45
+ # * +span_type+: the type of the span (such as +http+, +db+ and so on)
46
+ # * +parent_id+: the identifier of the parent span
47
+ # * +trace_id+: the identifier of the root span for this trace
48
+ # * +context+: the context of the span
49
+ def initialize(tracer, name, options = {})
50
+ @tracer = tracer
51
+
52
+ @name = name
53
+ @service = options.fetch(:service, nil)
54
+ @resource = options.fetch(:resource, name)
55
+ @span_type = options.fetch(:span_type, nil)
56
+
57
+ @span_id = Datadog::Utils.next_id
58
+ @parent_id = options.fetch(:parent_id, 0)
59
+ @trace_id = options.fetch(:trace_id, Datadog::Utils.next_id)
60
+
61
+ @context = options.fetch(:context, nil)
62
+
63
+ @meta = {}
64
+ @metrics = {}
65
+ @status = 0
66
+
67
+ @parent = nil
68
+ @sampled = true
69
+
70
+ @start_time = nil # set by Tracer.start_span
71
+ @end_time = nil # set by Span.finish
72
+
73
+ @allocation_count_start = now_allocations
74
+ @allocation_count_finish = @allocation_count_start
75
+ end
76
+
77
+ # Set the given key / value tag pair on the span. Keys and values
78
+ # must be strings. A valid example is:
79
+ #
80
+ # span.set_tag('http.method', request.method)
81
+ def set_tag(key, value = nil)
82
+ @meta[key] = value.to_s
83
+ rescue StandardError => e
84
+ Datadog::Tracer.log.debug("Unable to set the tag #{key}, ignoring it. Caused by: #{e}")
85
+ end
86
+
87
+ # Return the tag with the given key, nil if it doesn't exist.
88
+ def get_tag(key)
89
+ @meta[key]
90
+ end
91
+
92
+ # This method sets a tag with a floating point value for the given key. It acts
93
+ # like `set_tag()` and it simply add a tag without further processing.
94
+ def set_metric(key, value)
95
+ # enforce that the value is a floating point number
96
+ value = Float(value)
97
+ @metrics[key] = value
98
+ rescue StandardError => e
99
+ Datadog::Tracer.log.debug("Unable to set the metric #{key}, ignoring it. Caused by: #{e}")
100
+ end
101
+
102
+ # Return the metric with the given key, nil if it doesn't exist.
103
+ def get_metric(key)
104
+ @metrics[key]
105
+ end
106
+
107
+ # Mark the span with the given error.
108
+ def set_error(e)
109
+ e = Error.build_from(e)
110
+
111
+ @status = Ext::Errors::STATUS
112
+ set_tag(Ext::Errors::TYPE, e.type) unless e.type.empty?
113
+ set_tag(Ext::Errors::MSG, e.message) unless e.message.empty?
114
+ set_tag(Ext::Errors::STACK, e.backtrace) unless e.backtrace.empty?
115
+ end
116
+
117
+ # Mark the span finished at the current time and submit it.
118
+ def finish(finish_time = nil)
119
+ # A span should not be finished twice. Note that this is not thread-safe,
120
+ # finish is called from multiple threads, a given span might be finished
121
+ # several times. Again, one should not do this, so this test is more a
122
+ # fallback to avoid very bad things and protect you in most common cases.
123
+ return if finished?
124
+
125
+ @allocation_count_finish = now_allocations
126
+
127
+ # Provide a default start_time if unset, but this should have been set by start_span.
128
+ # Using now here causes 0-duration spans, still, this is expected, as we never
129
+ # explicitely say when it started.
130
+ @start_time ||= Time.now.utc
131
+
132
+ @end_time = finish_time.nil? ? Time.now.utc : finish_time # finish this
133
+
134
+ # Finish does not really do anything if the span is not bound to a tracer and a context.
135
+ return self if @tracer.nil? || @context.nil?
136
+
137
+ # spans without a service would be dropped, so here we provide a default.
138
+ # This should really never happen with integrations in contrib, as a default
139
+ # service is always set. It's only for custom instrumentation.
140
+ @service ||= @tracer.default_service unless @tracer.nil?
141
+
142
+ begin
143
+ @context.close_span(self)
144
+ @tracer.record(self)
145
+ rescue StandardError => e
146
+ Datadog::Tracer.log.debug("error recording finished trace: #{e}")
147
+ end
148
+ self
149
+ end
150
+
151
+ # Return whether the span is finished or not.
152
+ def finished?
153
+ !@end_time.nil?
154
+ end
155
+
156
+ # Return a string representation of the span.
157
+ def to_s
158
+ "Span(name:#{@name},sid:#{@span_id},tid:#{@trace_id},pid:#{@parent_id})"
159
+ end
160
+
161
+ # DEPRECATED: remove this function in the next release, replaced by ``parent=``
162
+ def set_parent(parent)
163
+ self.parent = parent
164
+ end
165
+
166
+ # Set this span's parent, inheriting any properties not explicitly set.
167
+ # If the parent is nil, set the span zero values.
168
+ def parent=(parent)
169
+ @parent = parent
170
+
171
+ if parent.nil?
172
+ @trace_id = @span_id
173
+ @parent_id = 0
174
+ else
175
+ @trace_id = parent.trace_id
176
+ @parent_id = parent.span_id
177
+ @service ||= parent.service
178
+ @sampled = parent.sampled
179
+ end
180
+ end
181
+
182
+ def allocations
183
+ @allocation_count_finish - @allocation_count_start
184
+ end
185
+
186
+ # Return the hash representation of the current span.
187
+ def to_hash
188
+ h = {
189
+ span_id: @span_id,
190
+ parent_id: @parent_id,
191
+ trace_id: @trace_id,
192
+ name: @name,
193
+ service: @service,
194
+ resource: @resource,
195
+ type: @span_type,
196
+ meta: @meta,
197
+ metrics: @metrics,
198
+ allocations: allocations,
199
+ error: @status
200
+ }
201
+
202
+ if !@start_time.nil? && !@end_time.nil?
203
+ h[:start] = (@start_time.to_f * 1e9).to_i
204
+ h[:duration] = ((@end_time - @start_time) * 1e9).to_i
205
+ end
206
+
207
+ h
208
+ end
209
+
210
+ # Return a human readable version of the span
211
+ def pretty_print(q)
212
+ start_time = (@start_time.to_f * 1e9).to_i rescue '-'
213
+ end_time = (@end_time.to_f * 1e9).to_i rescue '-'
214
+ duration = ((@end_time - @start_time) * 1e9).to_i rescue 0
215
+ q.group 0 do
216
+ q.breakable
217
+ q.text "Name: #{@name}\n"
218
+ q.text "Span ID: #{@span_id}\n"
219
+ q.text "Parent ID: #{@parent_id}\n"
220
+ q.text "Trace ID: #{@trace_id}\n"
221
+ q.text "Type: #{@span_type}\n"
222
+ q.text "Service: #{@service}\n"
223
+ q.text "Resource: #{@resource}\n"
224
+ q.text "Error: #{@status}\n"
225
+ q.text "Start: #{start_time}\n"
226
+ q.text "End: #{end_time}\n"
227
+ q.text "Duration: #{duration}\n"
228
+ q.text "Allocations: #{allocations}\n"
229
+ q.group(2, 'Tags: [', "]\n") do
230
+ q.breakable
231
+ q.seplist @meta.each do |key, value|
232
+ q.text "#{key} => #{value}"
233
+ end
234
+ end
235
+ q.group(2, 'Metrics: [', ']') do
236
+ q.breakable
237
+ q.seplist @metrics.each do |key, value|
238
+ q.text "#{key} => #{value}"
239
+ end
240
+ end
241
+ end
242
+ end
243
+
244
+ private
245
+
246
+ if defined?(JRUBY_VERSION) || Gem::Version.new(RUBY_VERSION) < Gem::Version.new(VERSION::MINIMUM_RUBY_VERSION)
247
+ def now_allocations
248
+ 0
249
+ end
250
+ elsif Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.0')
251
+ def now_allocations
252
+ GC.stat.fetch(:total_allocated_object)
253
+ end
254
+ else
255
+ def now_allocations
256
+ GC.stat(:total_allocated_objects)
257
+ end
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,62 @@
1
+ require 'ddtrace/ext/net'
2
+ require 'ddtrace/runtime/socket'
3
+ require 'ddtrace/runtime/metrics'
4
+
5
+ module Datadog
6
+ # SyncWriter flushes both services and traces synchronously
7
+ class SyncWriter
8
+ attr_reader \
9
+ :runtime_metrics,
10
+ :transport
11
+
12
+ def initialize(options = {})
13
+ @transport = options.fetch(:transport) do
14
+ transport_options = options.fetch(:transport_options, {})
15
+ Transport::HTTP.default(transport_options)
16
+ end
17
+
18
+ # Runtime metrics
19
+ @runtime_metrics = options.fetch(:runtime_metrics) do
20
+ Runtime::Metrics.new
21
+ end
22
+ end
23
+
24
+ def write(trace, services = nil)
25
+ unless services.nil?
26
+ Datadog::Patcher.do_once('SyncWriter#write') do
27
+ Datadog::Tracer.log.warn(%(
28
+ write: Writing services has been deprecated and no longer need to be provided.
29
+ write(traces, services) can be updted to write(traces)
30
+ ))
31
+ end
32
+ end
33
+
34
+ perform_concurrently(
35
+ proc { flush_trace(trace) }
36
+ )
37
+ rescue => e
38
+ Tracer.log.debug(e)
39
+ end
40
+
41
+ private
42
+
43
+ def perform_concurrently(*tasks)
44
+ tasks.map { |task| Thread.new(&task) }.each(&:join)
45
+ end
46
+
47
+ def flush_trace(trace)
48
+ processed_traces = Pipeline.process!([trace])
49
+ inject_hostname!(processed_traces.first) if Datadog.configuration.report_hostname
50
+ transport.send(:traces, processed_traces)
51
+ end
52
+
53
+ def inject_hostname!(trace)
54
+ unless trace.first.nil?
55
+ hostname = Datadog::Runtime::Socket.hostname
56
+ unless hostname.nil? || hostname.empty?
57
+ trace.first.set_tag(Ext::NET::TAG_HOSTNAME, hostname)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,459 @@
1
+ require 'pp'
2
+ require 'thread'
3
+ require 'logger'
4
+ require 'pathname'
5
+
6
+ require 'ddtrace/span'
7
+ require 'ddtrace/context'
8
+ require 'ddtrace/context_flush'
9
+ require 'ddtrace/provider'
10
+ require 'ddtrace/logger'
11
+ require 'ddtrace/writer'
12
+ require 'ddtrace/sampler'
13
+ require 'ddtrace/correlation'
14
+
15
+ # \Datadog global namespace that includes all tracing functionality for Tracer and Span classes.
16
+ module Datadog
17
+ # A \Tracer keeps track of the time spent by an application processing a single operation. For
18
+ # example, a trace can be used to track the entire time spent processing a complicated web request.
19
+ # Even though the request may require multiple resources and machines to handle the request, all
20
+ # of these function calls and sub-requests would be encapsulated within a single trace.
21
+ # rubocop:disable Metrics/ClassLength
22
+ class Tracer
23
+ attr_reader :sampler, :tags, :provider
24
+ attr_accessor :enabled, :writer
25
+ attr_writer :default_service
26
+
27
+ ALLOWED_SPAN_OPTIONS = [:service, :resource, :span_type].freeze
28
+ DEFAULT_ON_ERROR = proc { |span, error| span.set_error(error) unless span.nil? }
29
+
30
+ # Global, memoized, lazy initialized instance of a logger that is used within the the Datadog
31
+ # namespace. This logger outputs to +STDOUT+ by default, and is considered thread-safe.
32
+ def self.log
33
+ unless defined? @logger
34
+ @logger = Datadog::Logger.new(STDOUT)
35
+ @logger.level = Logger::WARN
36
+ end
37
+ @logger
38
+ end
39
+
40
+ # Override the default logger with a custom one.
41
+ def self.log=(logger)
42
+ return unless logger
43
+ return unless logger.respond_to? :methods
44
+ return unless logger.respond_to? :error
45
+ if logger.respond_to? :methods
46
+ unimplemented = Logger.new(STDOUT).methods - logger.methods
47
+ unless unimplemented.empty?
48
+ logger.error("logger #{logger} does not implement #{unimplemented}")
49
+ return
50
+ end
51
+ end
52
+ @logger = logger
53
+ end
54
+
55
+ # Activate the debug mode providing more information related to tracer usage
56
+ # Default to Warn level unless using custom logger
57
+ def self.debug_logging=(value)
58
+ if value
59
+ log.level = Logger::DEBUG
60
+ elsif log.is_a?(Datadog::Logger)
61
+ log.level = Logger::WARN
62
+ end
63
+ end
64
+
65
+ # Return if the debug mode is activated or not
66
+ def self.debug_logging
67
+ log.level == Logger::DEBUG
68
+ end
69
+
70
+ def services
71
+ # Only log each deprecation warning once (safeguard against log spam)
72
+ Datadog::Patcher.do_once('Tracer#set_service_info') do
73
+ Datadog::Tracer.log.warn('services: Usage of Tracer.services has been deprecated')
74
+ end
75
+
76
+ {}
77
+ end
78
+
79
+ # Shorthand that calls the `shutdown!` method of a registered worker.
80
+ # It's useful to ensure that the Trace Buffer is properly flushed before
81
+ # shutting down the application.
82
+ #
83
+ # For instance:
84
+ #
85
+ # tracer.trace('operation_name', service='rake_tasks') do |span|
86
+ # span.set_tag('task.name', 'script')
87
+ # end
88
+ #
89
+ # tracer.shutdown!
90
+ #
91
+ def shutdown!
92
+ return if !@enabled || @writer.worker.nil?
93
+ @writer.worker.stop
94
+ end
95
+
96
+ # Return the current active \Context for this traced execution. This method is
97
+ # automatically called when calling Tracer.trace or Tracer.start_span,
98
+ # but it can be used in the application code during manual instrumentation.
99
+ #
100
+ # This method makes use of a \ContextProvider that is automatically set during the tracer
101
+ # initialization, or while using a library instrumentation.
102
+ def call_context
103
+ @provider.context
104
+ end
105
+
106
+ # Initialize a new \Tracer used to create, sample and submit spans that measure the
107
+ # time of sections of code. Available +options+ are:
108
+ #
109
+ # * +enabled+: set if the tracer submits or not spans to the local agent. It's enabled
110
+ # by default.
111
+ def initialize(options = {})
112
+ @enabled = options.fetch(:enabled, true)
113
+ @writer = options.fetch(:writer, Datadog::Writer.new)
114
+ @sampler = options.fetch(:sampler, Datadog::AllSampler.new)
115
+
116
+ @provider = options.fetch(:context_provider, Datadog::DefaultContextProvider.new)
117
+ @provider ||= Datadog::DefaultContextProvider.new # @provider should never be nil
118
+
119
+ @context_flush = options[:partial_flush] ? Datadog::ContextFlush.new(options) : nil
120
+
121
+ @mutex = Mutex.new
122
+ @tags = {}
123
+ end
124
+
125
+ # Updates the current \Tracer instance, so that the tracer can be configured after the
126
+ # initialization. Available +options+ are:
127
+ #
128
+ # * +enabled+: set if the tracer submits or not spans to the trace agent
129
+ # * +hostname+: change the location of the trace agent
130
+ # * +port+: change the port of the trace agent
131
+ #
132
+ # For instance, if the trace agent runs in a different location, just:
133
+ #
134
+ # tracer.configure(hostname: 'agent.service.consul', port: '8777')
135
+ #
136
+ def configure(options = {})
137
+ enabled = options.fetch(:enabled, nil)
138
+
139
+ # Those are rare "power-user" options.
140
+ sampler = options.fetch(:sampler, nil)
141
+ max_spans_before_partial_flush = options.fetch(:max_spans_before_partial_flush, nil)
142
+ min_spans_before_partial_flush = options.fetch(:min_spans_before_partial_flush, nil)
143
+ partial_flush_timeout = options.fetch(:partial_flush_timeout, nil)
144
+
145
+ @enabled = enabled unless enabled.nil?
146
+ @sampler = sampler unless sampler.nil?
147
+
148
+ configure_writer(options)
149
+
150
+ @context_flush = Datadog::ContextFlush.new(options) unless min_spans_before_partial_flush.nil? &&
151
+ max_spans_before_partial_flush.nil? &&
152
+ partial_flush_timeout.nil?
153
+ end
154
+
155
+ # Set the information about the given service. A valid example is:
156
+ #
157
+ # tracer.set_service_info('web-application', 'rails', 'web')
158
+ #
159
+ # set_service_info is deprecated, no service information needs to be tracked
160
+ def set_service_info(service, app, app_type)
161
+ # Only log each deprecation warning once (safeguard against log spam)
162
+ Datadog::Patcher.do_once('Tracer#set_service_info') do
163
+ Datadog::Tracer.log.warn(%(
164
+ set_service_info: Usage of set_service_info has been deprecated,
165
+ service information no longer needs to be reported to the trace agent.
166
+ ))
167
+ end
168
+ end
169
+
170
+ # A default value for service. One should really override this one
171
+ # for non-root spans which have a parent. However, root spans without
172
+ # a service would be invalid and rejected.
173
+ def default_service
174
+ return @default_service if instance_variable_defined?(:@default_service) && @default_service
175
+ begin
176
+ @default_service = File.basename($PROGRAM_NAME, '.*')
177
+ rescue StandardError => e
178
+ Datadog::Tracer.log.error("unable to guess default service: #{e}")
179
+ @default_service = 'ruby'.freeze
180
+ end
181
+ @default_service
182
+ end
183
+
184
+ # Set the given key / value tag pair at the tracer level. These tags will be
185
+ # appended to each span created by the tracer. Keys and values must be strings.
186
+ # A valid example is:
187
+ #
188
+ # tracer.set_tags('env' => 'prod', 'component' => 'core')
189
+ def set_tags(tags)
190
+ @tags.update(tags)
191
+ end
192
+
193
+ # Guess context and parent from child_of entry.
194
+ def guess_context_and_parent(child_of)
195
+ # call_context should not be in this code path, as start_span
196
+ # should never try and pick an existing context, but only get
197
+ # it from the parameters passed to it (child_of)
198
+ return [Datadog::Context.new, nil] unless child_of
199
+
200
+ return [child_of, child_of.current_span] if child_of.is_a?(Context)
201
+
202
+ [child_of.context, child_of]
203
+ end
204
+
205
+ # Return a span that will trace an operation called \name. This method allows
206
+ # parenting passing \child_of as an option. If it's missing, the newly created span is a
207
+ # root span. Available options are:
208
+ #
209
+ # * +service+: the service name for this span
210
+ # * +resource+: the resource this span refers, or \name if it's missing
211
+ # * +span_type+: the type of the span (such as \http, \db and so on)
212
+ # * +child_of+: a \Span or a \Context instance representing the parent for this span.
213
+ # * +start_time+: when the span actually starts (defaults to \now)
214
+ # * +tags+: extra tags which should be added to the span.
215
+ def start_span(name, options = {})
216
+ start_time = options.fetch(:start_time, Time.now.utc)
217
+
218
+ tags = options.fetch(:tags, {})
219
+
220
+ span_options = options.select do |k, _v|
221
+ # Filter options, we want no side effects with unexpected args.
222
+ ALLOWED_SPAN_OPTIONS.include?(k)
223
+ end
224
+
225
+ ctx, parent = guess_context_and_parent(options[:child_of])
226
+ span_options[:context] = ctx unless ctx.nil?
227
+
228
+ span = Span.new(self, name, span_options)
229
+ if parent.nil?
230
+ # root span
231
+ @sampler.sample!(span)
232
+ span.set_tag('system.pid', Process.pid)
233
+
234
+ if ctx && ctx.trace_id
235
+ span.trace_id = ctx.trace_id
236
+ span.parent_id = ctx.span_id unless ctx.span_id.nil?
237
+ end
238
+ else
239
+ # child span
240
+ span.parent = parent # sets service, trace_id, parent_id, sampled
241
+ end
242
+ tags.each { |k, v| span.set_tag(k, v) } unless tags.empty?
243
+ @tags.each { |k, v| span.set_tag(k, v) } unless @tags.empty?
244
+ span.start_time = start_time
245
+
246
+ # this could at some point be optional (start_active_span vs start_manual_span)
247
+ ctx.add_span(span) unless ctx.nil?
248
+
249
+ span
250
+ end
251
+
252
+ # Return a +span+ that will trace an operation called +name+. You could trace your code
253
+ # using a <tt>do-block</tt> like:
254
+ #
255
+ # tracer.trace('web.request') do |span|
256
+ # span.service = 'my-web-site'
257
+ # span.resource = '/'
258
+ # span.set_tag('http.method', request.request_method)
259
+ # do_something()
260
+ # end
261
+ #
262
+ # The <tt>tracer.trace()</tt> method can also be used without a block in this way:
263
+ #
264
+ # span = tracer.trace('web.request', service: 'my-web-site')
265
+ # do_something()
266
+ # span.finish()
267
+ #
268
+ # Remember that in this case, calling <tt>span.finish()</tt> is mandatory.
269
+ #
270
+ # When a Trace is started, <tt>trace()</tt> will store the created span; subsequent spans will
271
+ # become it's children and will inherit some properties:
272
+ #
273
+ # parent = tracer.trace('parent') # has no parent span
274
+ # child = tracer.trace('child') # is a child of 'parent'
275
+ # child.finish()
276
+ # parent.finish()
277
+ # parent2 = tracer.trace('parent2') # has no parent span
278
+ # parent2.finish()
279
+ #
280
+ # Available options are:
281
+ #
282
+ # * +service+: the service name for this span
283
+ # * +resource+: the resource this span refers, or \name if it's missing
284
+ # * +span_type+: the type of the span (such as \http, \db and so on)
285
+ # * +tags+: extra tags which should be added to the span.
286
+ def trace(name, options = {})
287
+ options[:child_of] = call_context
288
+
289
+ # call the finish only if a block is given; this ensures
290
+ # that a call to tracer.trace() without a block, returns
291
+ # a span that should be manually finished.
292
+ if block_given?
293
+ span = nil
294
+ return_value = nil
295
+
296
+ begin
297
+ begin
298
+ span = start_span(name, options)
299
+ # rubocop:disable Lint/UselessAssignment
300
+ rescue StandardError => e
301
+ Datadog::Tracer.log.debug('Failed to start span: #{e}')
302
+ ensure
303
+ return_value = yield(span)
304
+ end
305
+ # rubocop:disable Lint/RescueException
306
+ # Here we really want to catch *any* exception, not only StandardError,
307
+ # as we really have no clue of what is in the block,
308
+ # and it is user code which should be executed no matter what.
309
+ # It's not a problem since we re-raise it afterwards so for example a
310
+ # SignalException::Interrupt would still bubble up.
311
+ rescue Exception => e
312
+ (options[:on_error] || DEFAULT_ON_ERROR).call(span, e)
313
+ raise e
314
+ ensure
315
+ span.finish unless span.nil?
316
+ end
317
+
318
+ return_value
319
+ else
320
+ start_span(name, options)
321
+ end
322
+ end
323
+
324
+ # Record the given +context+. For compatibility with previous versions,
325
+ # +context+ can also be a span. It is similar to the +child_of+ argument,
326
+ # method will figure out what to do, submitting a +span+ for recording
327
+ # is like trying to record its +context+.
328
+ def record(context)
329
+ context = context.context if context.is_a?(Datadog::Span)
330
+ return if context.nil?
331
+ trace, sampled = context.get
332
+
333
+ # If context flushing is configured...
334
+ if @context_flush
335
+ if sampled
336
+ if trace.nil? || trace.empty?
337
+ @context_flush.each_partial_trace(context) do |t|
338
+ write(t)
339
+ end
340
+ else
341
+ write(trace)
342
+ end
343
+ end
344
+ # Default behavior
345
+ else
346
+ ready = !trace.nil? && !trace.empty? && sampled
347
+ write(trace) if ready
348
+ end
349
+ end
350
+
351
+ # Return the current active span or +nil+.
352
+ def active_span
353
+ call_context.current_span
354
+ end
355
+
356
+ # Return the current active root span or +nil+.
357
+ def active_root_span
358
+ call_context.current_root_span
359
+ end
360
+
361
+ # Return a CorrelationIdentifier for active span
362
+ def active_correlation
363
+ Datadog::Correlation.identifier_from_context(call_context)
364
+ end
365
+
366
+ # Send the trace to the writer to enqueue the spans list in the agent
367
+ # sending queue.
368
+ def write(trace)
369
+ return if @writer.nil? || !@enabled
370
+
371
+ if Datadog::Tracer.debug_logging
372
+ Datadog::Tracer.log.debug("Writing #{trace.length} spans (enabled: #{@enabled})")
373
+ str = String.new('')
374
+ PP.pp(trace, str)
375
+ Datadog::Tracer.log.debug(str)
376
+ end
377
+
378
+ @writer.write(trace)
379
+ end
380
+
381
+ # TODO: Move this kind of configuration building out of the tracer.
382
+ # Tracer should not have this kind of knowledge of writer.
383
+ # rubocop:disable Metrics/PerceivedComplexity
384
+ # rubocop:disable Metrics/CyclomaticComplexity
385
+ # rubocop:disable Metrics/MethodLength
386
+ def configure_writer(options = {})
387
+ hostname = options.fetch(:hostname, nil)
388
+ port = options.fetch(:port, nil)
389
+ sampler = options.fetch(:sampler, nil)
390
+ priority_sampling = options.fetch(:priority_sampling, nil)
391
+ writer = options.fetch(:writer, nil)
392
+ transport_options = options.fetch(:transport_options, {})
393
+
394
+ # Compile writer options
395
+ writer_options = options.fetch(:writer_options, {})
396
+ rebuild_writer = !writer_options.empty?
397
+
398
+ # Re-build the sampler and writer if priority sampling is enabled,
399
+ # but neither are configured. Verify the sampler isn't already a
400
+ # priority sampler too, so we don't wrap one with another.
401
+ if options.key?(:writer)
402
+ if writer.priority_sampler.nil?
403
+ deactivate_priority_sampling!(sampler)
404
+ else
405
+ activate_priority_sampling!(writer.priority_sampler)
406
+ end
407
+ elsif priority_sampling != false && !@sampler.is_a?(PrioritySampler)
408
+ writer_options[:priority_sampler] = activate_priority_sampling!(@sampler)
409
+ rebuild_writer = true
410
+ elsif priority_sampling == false
411
+ deactivate_priority_sampling!(sampler)
412
+ rebuild_writer = true
413
+ elsif @sampler.is_a?(PrioritySampler)
414
+ # Make sure to add sampler to options if transport is rebuilt.
415
+ writer_options[:priority_sampler] = @sampler
416
+ end
417
+
418
+ # Apply options to transport
419
+ if transport_options.is_a?(Proc)
420
+ transport_options = { on_build: transport_options }
421
+ rebuild_writer = true
422
+ end
423
+
424
+ if hostname || port
425
+ transport_options[:hostname] = hostname unless hostname.nil?
426
+ transport_options[:port] = port unless port.nil?
427
+ rebuild_writer = true
428
+ end
429
+
430
+ writer_options[:transport_options] = transport_options
431
+
432
+ if rebuild_writer || writer
433
+ # Make sure old writer is shut down before throwing away.
434
+ # Don't want additional threads running...
435
+ @writer.stop unless writer.nil?
436
+ @writer = writer || Writer.new(writer_options)
437
+ end
438
+ end
439
+
440
+ def activate_priority_sampling!(base_sampler = nil)
441
+ @sampler = if base_sampler.is_a?(PrioritySampler)
442
+ base_sampler
443
+ else
444
+ PrioritySampler.new(base_sampler: base_sampler)
445
+ end
446
+ end
447
+
448
+ def deactivate_priority_sampling!(base_sampler = nil)
449
+ @sampler = base_sampler || Datadog::AllSampler.new if @sampler.is_a?(PrioritySampler)
450
+ end
451
+
452
+ private \
453
+ :activate_priority_sampling!,
454
+ :configure_writer,
455
+ :deactivate_priority_sampling!,
456
+ :guess_context_and_parent,
457
+ :write
458
+ end
459
+ end