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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +673 -0
- data/.circleci/images/primary/Dockerfile-2.0.0 +73 -0
- data/.circleci/images/primary/Dockerfile-2.1.10 +73 -0
- data/.circleci/images/primary/Dockerfile-2.2.10 +73 -0
- data/.circleci/images/primary/Dockerfile-2.3.8 +75 -0
- data/.circleci/images/primary/Dockerfile-2.4.6 +73 -0
- data/.circleci/images/primary/Dockerfile-2.5.6 +73 -0
- data/.circleci/images/primary/Dockerfile-2.6.4 +73 -0
- data/.dockerignore +1 -0
- data/.env +24 -0
- data/.github/CODEOWNERS +1 -0
- data/.gitignore +59 -0
- data/.rspec +1 -0
- data/.rubocop.yml +77 -0
- data/.yardopts +5 -0
- data/Appraisals +820 -0
- data/CHANGELOG.md +1051 -0
- data/CONTRIBUTING.md +85 -0
- data/Gemfile +7 -0
- data/LICENSE +24 -0
- data/README.md +108 -0
- data/Rakefile +635 -0
- data/benchmarks/postgres_database.yml +9 -0
- data/benchmarks/sidekiq_test.rb +154 -0
- data/ddtrace.gemspec +63 -0
- data/docker-compose.yml +276 -0
- data/docs/DevelopmentGuide.md +195 -0
- data/docs/GettingStarted.md +1981 -0
- data/lib/ddtrace.rb +63 -0
- data/lib/ddtrace/analytics.rb +29 -0
- data/lib/ddtrace/augmentation.rb +13 -0
- data/lib/ddtrace/augmentation/method_wrapper.rb +20 -0
- data/lib/ddtrace/augmentation/method_wrapping.rb +38 -0
- data/lib/ddtrace/augmentation/shim.rb +102 -0
- data/lib/ddtrace/buffer.rb +119 -0
- data/lib/ddtrace/configuration.rb +30 -0
- data/lib/ddtrace/configuration/base.rb +82 -0
- data/lib/ddtrace/configuration/dependency_resolver.rb +24 -0
- data/lib/ddtrace/configuration/option.rb +55 -0
- data/lib/ddtrace/configuration/option_definition.rb +127 -0
- data/lib/ddtrace/configuration/option_definition_set.rb +18 -0
- data/lib/ddtrace/configuration/option_set.rb +6 -0
- data/lib/ddtrace/configuration/options.rb +107 -0
- data/lib/ddtrace/configuration/pin_setup.rb +30 -0
- data/lib/ddtrace/configuration/settings.rb +105 -0
- data/lib/ddtrace/context.rb +284 -0
- data/lib/ddtrace/context_flush.rb +132 -0
- data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +144 -0
- data/lib/ddtrace/contrib/action_pack/action_controller/patcher.rb +37 -0
- data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +27 -0
- data/lib/ddtrace/contrib/action_pack/ext.rb +16 -0
- data/lib/ddtrace/contrib/action_pack/integration.rb +36 -0
- data/lib/ddtrace/contrib/action_pack/patcher.rb +29 -0
- data/lib/ddtrace/contrib/action_pack/utils.rb +36 -0
- data/lib/ddtrace/contrib/action_view/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/action_view/ext.rb +17 -0
- data/lib/ddtrace/contrib/action_view/instrumentation/partial_renderer.rb +78 -0
- data/lib/ddtrace/contrib/action_view/instrumentation/template_renderer.rb +167 -0
- data/lib/ddtrace/contrib/action_view/integration.rb +43 -0
- data/lib/ddtrace/contrib/action_view/patcher.rb +53 -0
- data/lib/ddtrace/contrib/action_view/utils.rb +32 -0
- data/lib/ddtrace/contrib/active_model_serializers/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/active_model_serializers/event.rb +65 -0
- data/lib/ddtrace/contrib/active_model_serializers/events.rb +30 -0
- data/lib/ddtrace/contrib/active_model_serializers/events/render.rb +32 -0
- data/lib/ddtrace/contrib/active_model_serializers/events/serialize.rb +35 -0
- data/lib/ddtrace/contrib/active_model_serializers/ext.rb +17 -0
- data/lib/ddtrace/contrib/active_model_serializers/integration.rb +39 -0
- data/lib/ddtrace/contrib/active_model_serializers/patcher.rb +36 -0
- data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +46 -0
- data/lib/ddtrace/contrib/active_record/configuration/settings.rb +30 -0
- data/lib/ddtrace/contrib/active_record/event.rb +30 -0
- data/lib/ddtrace/contrib/active_record/events.rb +30 -0
- data/lib/ddtrace/contrib/active_record/events/instantiation.rb +57 -0
- data/lib/ddtrace/contrib/active_record/events/sql.rb +64 -0
- data/lib/ddtrace/contrib/active_record/ext.rb +21 -0
- data/lib/ddtrace/contrib/active_record/integration.rb +44 -0
- data/lib/ddtrace/contrib/active_record/patcher.rb +29 -0
- data/lib/ddtrace/contrib/active_record/utils.rb +76 -0
- data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +157 -0
- data/lib/ddtrace/contrib/active_support/cache/patcher.rb +62 -0
- data/lib/ddtrace/contrib/active_support/cache/redis.rb +47 -0
- data/lib/ddtrace/contrib/active_support/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/active_support/ext.rb +21 -0
- data/lib/ddtrace/contrib/active_support/integration.rb +38 -0
- data/lib/ddtrace/contrib/active_support/notifications/event.rb +62 -0
- data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +66 -0
- data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +159 -0
- data/lib/ddtrace/contrib/active_support/patcher.rb +29 -0
- data/lib/ddtrace/contrib/analytics.rb +20 -0
- data/lib/ddtrace/contrib/aws/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/aws/ext.rb +20 -0
- data/lib/ddtrace/contrib/aws/instrumentation.rb +56 -0
- data/lib/ddtrace/contrib/aws/integration.rb +36 -0
- data/lib/ddtrace/contrib/aws/parsed_context.rb +56 -0
- data/lib/ddtrace/contrib/aws/patcher.rb +49 -0
- data/lib/ddtrace/contrib/aws/services.rb +115 -0
- data/lib/ddtrace/contrib/concurrent_ruby/configuration/settings.rb +15 -0
- data/lib/ddtrace/contrib/concurrent_ruby/context_composite_executor_service.rb +35 -0
- data/lib/ddtrace/contrib/concurrent_ruby/ext.rb +11 -0
- data/lib/ddtrace/contrib/concurrent_ruby/future_patch.rb +23 -0
- data/lib/ddtrace/contrib/concurrent_ruby/integration.rb +32 -0
- data/lib/ddtrace/contrib/concurrent_ruby/patcher.rb +35 -0
- data/lib/ddtrace/contrib/configurable.rb +59 -0
- data/lib/ddtrace/contrib/configuration/resolver.rb +12 -0
- data/lib/ddtrace/contrib/configuration/settings.rb +35 -0
- data/lib/ddtrace/contrib/dalli/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/dalli/ext.rb +17 -0
- data/lib/ddtrace/contrib/dalli/instrumentation.rb +50 -0
- data/lib/ddtrace/contrib/dalli/integration.rb +36 -0
- data/lib/ddtrace/contrib/dalli/patcher.rb +73 -0
- data/lib/ddtrace/contrib/dalli/quantize.rb +22 -0
- data/lib/ddtrace/contrib/delayed_job/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/delayed_job/ext.rb +18 -0
- data/lib/ddtrace/contrib/delayed_job/integration.rb +32 -0
- data/lib/ddtrace/contrib/delayed_job/patcher.rb +34 -0
- data/lib/ddtrace/contrib/delayed_job/plugin.rb +57 -0
- data/lib/ddtrace/contrib/elasticsearch/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/elasticsearch/ext.rb +19 -0
- data/lib/ddtrace/contrib/elasticsearch/integration.rb +37 -0
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +124 -0
- data/lib/ddtrace/contrib/elasticsearch/quantize.rb +80 -0
- data/lib/ddtrace/contrib/ethon/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/ethon/easy_patch.rb +139 -0
- data/lib/ddtrace/contrib/ethon/ext.rb +15 -0
- data/lib/ddtrace/contrib/ethon/integration.rb +31 -0
- data/lib/ddtrace/contrib/ethon/multi_patch.rb +80 -0
- data/lib/ddtrace/contrib/ethon/patcher.rb +27 -0
- data/lib/ddtrace/contrib/excon/configuration/settings.rb +28 -0
- data/lib/ddtrace/contrib/excon/ext.rb +14 -0
- data/lib/ddtrace/contrib/excon/integration.rb +32 -0
- data/lib/ddtrace/contrib/excon/middleware.rb +154 -0
- data/lib/ddtrace/contrib/excon/patcher.rb +34 -0
- data/lib/ddtrace/contrib/extensions.rb +59 -0
- data/lib/ddtrace/contrib/faraday/configuration/settings.rb +33 -0
- data/lib/ddtrace/contrib/faraday/ext.rb +14 -0
- data/lib/ddtrace/contrib/faraday/integration.rb +36 -0
- data/lib/ddtrace/contrib/faraday/middleware.rb +93 -0
- data/lib/ddtrace/contrib/faraday/patcher.rb +82 -0
- data/lib/ddtrace/contrib/faraday/rack_builder.rb +18 -0
- data/lib/ddtrace/contrib/grape/configuration/settings.rb +27 -0
- data/lib/ddtrace/contrib/grape/endpoint.rb +199 -0
- data/lib/ddtrace/contrib/grape/ext.rb +19 -0
- data/lib/ddtrace/contrib/grape/instrumentation.rb +33 -0
- data/lib/ddtrace/contrib/grape/integration.rb +36 -0
- data/lib/ddtrace/contrib/grape/patcher.rb +79 -0
- data/lib/ddtrace/contrib/graphql/configuration/settings.rb +27 -0
- data/lib/ddtrace/contrib/graphql/ext.rb +13 -0
- data/lib/ddtrace/contrib/graphql/integration.rb +38 -0
- data/lib/ddtrace/contrib/graphql/patcher.rb +63 -0
- data/lib/ddtrace/contrib/grpc/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +74 -0
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/client.rb +56 -0
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +73 -0
- data/lib/ddtrace/contrib/grpc/ext.rb +15 -0
- data/lib/ddtrace/contrib/grpc/integration.rb +36 -0
- data/lib/ddtrace/contrib/grpc/intercept_with_datadog.rb +49 -0
- data/lib/ddtrace/contrib/grpc/patcher.rb +78 -0
- data/lib/ddtrace/contrib/http/circuit_breaker.rb +63 -0
- data/lib/ddtrace/contrib/http/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/http/ext.rb +14 -0
- data/lib/ddtrace/contrib/http/instrumentation.rb +114 -0
- data/lib/ddtrace/contrib/http/integration.rb +32 -0
- data/lib/ddtrace/contrib/http/patcher.rb +32 -0
- data/lib/ddtrace/contrib/integration.rb +16 -0
- data/lib/ddtrace/contrib/mongodb/configuration/settings.rb +28 -0
- data/lib/ddtrace/contrib/mongodb/ext.rb +20 -0
- data/lib/ddtrace/contrib/mongodb/instrumentation.rb +68 -0
- data/lib/ddtrace/contrib/mongodb/integration.rb +36 -0
- data/lib/ddtrace/contrib/mongodb/parsers.rb +68 -0
- data/lib/ddtrace/contrib/mongodb/patcher.rb +37 -0
- data/lib/ddtrace/contrib/mongodb/subscribers.rb +108 -0
- data/lib/ddtrace/contrib/mysql2/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/mysql2/ext.rb +15 -0
- data/lib/ddtrace/contrib/mysql2/instrumentation.rb +60 -0
- data/lib/ddtrace/contrib/mysql2/integration.rb +32 -0
- data/lib/ddtrace/contrib/mysql2/patcher.rb +33 -0
- data/lib/ddtrace/contrib/patchable.rb +42 -0
- data/lib/ddtrace/contrib/patcher.rb +28 -0
- data/lib/ddtrace/contrib/racecar/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/racecar/event.rb +67 -0
- data/lib/ddtrace/contrib/racecar/events.rb +30 -0
- data/lib/ddtrace/contrib/racecar/events/batch.rb +27 -0
- data/lib/ddtrace/contrib/racecar/events/message.rb +27 -0
- data/lib/ddtrace/contrib/racecar/ext.rb +21 -0
- data/lib/ddtrace/contrib/racecar/integration.rb +36 -0
- data/lib/ddtrace/contrib/racecar/patcher.rb +32 -0
- data/lib/ddtrace/contrib/rack/configuration/settings.rb +41 -0
- data/lib/ddtrace/contrib/rack/ext.rb +18 -0
- data/lib/ddtrace/contrib/rack/integration.rb +32 -0
- data/lib/ddtrace/contrib/rack/middlewares.rb +283 -0
- data/lib/ddtrace/contrib/rack/patcher.rb +72 -0
- data/lib/ddtrace/contrib/rack/request_queue.rb +39 -0
- data/lib/ddtrace/contrib/rails/configuration/settings.rb +80 -0
- data/lib/ddtrace/contrib/rails/ext.rb +12 -0
- data/lib/ddtrace/contrib/rails/framework.rb +100 -0
- data/lib/ddtrace/contrib/rails/integration.rb +37 -0
- data/lib/ddtrace/contrib/rails/middlewares.rb +38 -0
- data/lib/ddtrace/contrib/rails/patcher.rb +78 -0
- data/lib/ddtrace/contrib/rails/railtie.rb +17 -0
- data/lib/ddtrace/contrib/rails/utils.rb +20 -0
- data/lib/ddtrace/contrib/rake/configuration/settings.rb +27 -0
- data/lib/ddtrace/contrib/rake/ext.rb +18 -0
- data/lib/ddtrace/contrib/rake/instrumentation.rb +84 -0
- data/lib/ddtrace/contrib/rake/integration.rb +32 -0
- data/lib/ddtrace/contrib/rake/patcher.rb +36 -0
- data/lib/ddtrace/contrib/redis/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/redis/ext.rb +18 -0
- data/lib/ddtrace/contrib/redis/integration.rb +36 -0
- data/lib/ddtrace/contrib/redis/patcher.rb +94 -0
- data/lib/ddtrace/contrib/redis/quantize.rb +47 -0
- data/lib/ddtrace/contrib/redis/tags.rb +38 -0
- data/lib/ddtrace/contrib/registerable.rb +33 -0
- data/lib/ddtrace/contrib/registry.rb +42 -0
- data/lib/ddtrace/contrib/resque/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/resque/ext.rb +14 -0
- data/lib/ddtrace/contrib/resque/integration.rb +37 -0
- data/lib/ddtrace/contrib/resque/patcher.rb +35 -0
- data/lib/ddtrace/contrib/resque/resque_job.rb +76 -0
- data/lib/ddtrace/contrib/rest_client/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/rest_client/ext.rb +14 -0
- data/lib/ddtrace/contrib/rest_client/integration.rb +31 -0
- data/lib/ddtrace/contrib/rest_client/patcher.rb +25 -0
- data/lib/ddtrace/contrib/rest_client/request_patch.rb +89 -0
- data/lib/ddtrace/contrib/sequel/configuration/settings.rb +23 -0
- data/lib/ddtrace/contrib/sequel/database.rb +61 -0
- data/lib/ddtrace/contrib/sequel/dataset.rb +62 -0
- data/lib/ddtrace/contrib/sequel/ext.rb +15 -0
- data/lib/ddtrace/contrib/sequel/integration.rb +32 -0
- data/lib/ddtrace/contrib/sequel/patcher.rb +39 -0
- data/lib/ddtrace/contrib/sequel/utils.rb +46 -0
- data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +24 -0
- data/lib/ddtrace/contrib/shoryuken/ext.rb +18 -0
- data/lib/ddtrace/contrib/shoryuken/integration.rb +35 -0
- data/lib/ddtrace/contrib/shoryuken/patcher.rb +30 -0
- data/lib/ddtrace/contrib/shoryuken/tracer.rb +45 -0
- data/lib/ddtrace/contrib/sidekiq/client_tracer.rb +43 -0
- data/lib/ddtrace/contrib/sidekiq/configuration/settings.rb +26 -0
- data/lib/ddtrace/contrib/sidekiq/ext.rb +21 -0
- data/lib/ddtrace/contrib/sidekiq/integration.rb +36 -0
- data/lib/ddtrace/contrib/sidekiq/patcher.rb +40 -0
- data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +58 -0
- data/lib/ddtrace/contrib/sidekiq/tracing.rb +28 -0
- data/lib/ddtrace/contrib/sinatra/configuration/settings.rb +34 -0
- data/lib/ddtrace/contrib/sinatra/env.rb +38 -0
- data/lib/ddtrace/contrib/sinatra/ext.rb +18 -0
- data/lib/ddtrace/contrib/sinatra/headers.rb +31 -0
- data/lib/ddtrace/contrib/sinatra/integration.rb +36 -0
- data/lib/ddtrace/contrib/sinatra/patcher.rb +33 -0
- data/lib/ddtrace/contrib/sinatra/tracer.rb +84 -0
- data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +72 -0
- data/lib/ddtrace/contrib/sucker_punch/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/sucker_punch/exception_handler.rb +26 -0
- data/lib/ddtrace/contrib/sucker_punch/ext.rb +18 -0
- data/lib/ddtrace/contrib/sucker_punch/instrumentation.rb +70 -0
- data/lib/ddtrace/contrib/sucker_punch/integration.rb +36 -0
- data/lib/ddtrace/contrib/sucker_punch/patcher.rb +48 -0
- data/lib/ddtrace/correlation.rb +28 -0
- data/lib/ddtrace/diagnostics/health.rb +30 -0
- data/lib/ddtrace/distributed_tracing/headers/b3.rb +44 -0
- data/lib/ddtrace/distributed_tracing/headers/b3_single.rb +56 -0
- data/lib/ddtrace/distributed_tracing/headers/datadog.rb +42 -0
- data/lib/ddtrace/distributed_tracing/headers/headers.rb +70 -0
- data/lib/ddtrace/distributed_tracing/headers/helpers.rb +45 -0
- data/lib/ddtrace/encoding.rb +65 -0
- data/lib/ddtrace/environment.rb +23 -0
- data/lib/ddtrace/error.rb +27 -0
- data/lib/ddtrace/ext/analytics.rb +11 -0
- data/lib/ddtrace/ext/app_types.rb +11 -0
- data/lib/ddtrace/ext/diagnostics.rb +25 -0
- data/lib/ddtrace/ext/distributed.rb +33 -0
- data/lib/ddtrace/ext/errors.rb +10 -0
- data/lib/ddtrace/ext/forced_tracing.rb +25 -0
- data/lib/ddtrace/ext/http.rb +46 -0
- data/lib/ddtrace/ext/manual_tracing.rb +9 -0
- data/lib/ddtrace/ext/metrics.rb +15 -0
- data/lib/ddtrace/ext/net.rb +10 -0
- data/lib/ddtrace/ext/priority.rb +16 -0
- data/lib/ddtrace/ext/runtime.rb +26 -0
- data/lib/ddtrace/ext/sql.rb +8 -0
- data/lib/ddtrace/ext/transport.rb +17 -0
- data/lib/ddtrace/forced_tracing.rb +36 -0
- data/lib/ddtrace/logger.rb +39 -0
- data/lib/ddtrace/metrics.rb +215 -0
- data/lib/ddtrace/monkey.rb +58 -0
- data/lib/ddtrace/opentracer.rb +40 -0
- data/lib/ddtrace/opentracer/binary_propagator.rb +24 -0
- data/lib/ddtrace/opentracer/carrier.rb +6 -0
- data/lib/ddtrace/opentracer/distributed_headers.rb +52 -0
- data/lib/ddtrace/opentracer/global_tracer.rb +15 -0
- data/lib/ddtrace/opentracer/propagator.rb +22 -0
- data/lib/ddtrace/opentracer/rack_propagator.rb +60 -0
- data/lib/ddtrace/opentracer/scope.rb +15 -0
- data/lib/ddtrace/opentracer/scope_manager.rb +6 -0
- data/lib/ddtrace/opentracer/span.rb +98 -0
- data/lib/ddtrace/opentracer/span_context.rb +14 -0
- data/lib/ddtrace/opentracer/span_context_factory.rb +23 -0
- data/lib/ddtrace/opentracer/text_map_propagator.rb +75 -0
- data/lib/ddtrace/opentracer/thread_local_scope.rb +30 -0
- data/lib/ddtrace/opentracer/thread_local_scope_manager.rb +40 -0
- data/lib/ddtrace/opentracer/tracer.rb +208 -0
- data/lib/ddtrace/patcher.rb +47 -0
- data/lib/ddtrace/pin.rb +114 -0
- data/lib/ddtrace/pipeline.rb +46 -0
- data/lib/ddtrace/pipeline/span_filter.rb +38 -0
- data/lib/ddtrace/pipeline/span_processor.rb +20 -0
- data/lib/ddtrace/propagation/grpc_propagator.rb +61 -0
- data/lib/ddtrace/propagation/http_propagator.rb +75 -0
- data/lib/ddtrace/provider.rb +21 -0
- data/lib/ddtrace/quantization/hash.rb +103 -0
- data/lib/ddtrace/quantization/http.rb +86 -0
- data/lib/ddtrace/runtime/cgroup.rb +44 -0
- data/lib/ddtrace/runtime/class_count.rb +17 -0
- data/lib/ddtrace/runtime/container.rb +73 -0
- data/lib/ddtrace/runtime/gc.rb +16 -0
- data/lib/ddtrace/runtime/identity.rb +41 -0
- data/lib/ddtrace/runtime/metrics.rb +93 -0
- data/lib/ddtrace/runtime/object_space.rb +19 -0
- data/lib/ddtrace/runtime/socket.rb +14 -0
- data/lib/ddtrace/runtime/thread_count.rb +16 -0
- data/lib/ddtrace/sampler.rb +195 -0
- data/lib/ddtrace/span.rb +260 -0
- data/lib/ddtrace/sync_writer.rb +62 -0
- data/lib/ddtrace/tracer.rb +459 -0
- data/lib/ddtrace/transport/http.rb +91 -0
- data/lib/ddtrace/transport/http/adapters/net.rb +112 -0
- data/lib/ddtrace/transport/http/adapters/registry.rb +24 -0
- data/lib/ddtrace/transport/http/adapters/test.rb +77 -0
- data/lib/ddtrace/transport/http/adapters/unix_socket.rb +64 -0
- data/lib/ddtrace/transport/http/api.rb +46 -0
- data/lib/ddtrace/transport/http/api/endpoint.rb +27 -0
- data/lib/ddtrace/transport/http/api/fallbacks.rb +22 -0
- data/lib/ddtrace/transport/http/api/instance.rb +29 -0
- data/lib/ddtrace/transport/http/api/map.rb +14 -0
- data/lib/ddtrace/transport/http/api/spec.rb +15 -0
- data/lib/ddtrace/transport/http/builder.rb +165 -0
- data/lib/ddtrace/transport/http/client.rb +107 -0
- data/lib/ddtrace/transport/http/env.rb +48 -0
- data/lib/ddtrace/transport/http/response.rb +26 -0
- data/lib/ddtrace/transport/http/statistics.rb +30 -0
- data/lib/ddtrace/transport/http/traces.rb +140 -0
- data/lib/ddtrace/transport/parcel.rb +13 -0
- data/lib/ddtrace/transport/request.rb +13 -0
- data/lib/ddtrace/transport/response.rb +49 -0
- data/lib/ddtrace/transport/statistics.rb +72 -0
- data/lib/ddtrace/transport/traces.rb +33 -0
- data/lib/ddtrace/utils.rb +65 -0
- data/lib/ddtrace/utils/database.rb +25 -0
- data/lib/ddtrace/utils/time.rb +14 -0
- data/lib/ddtrace/vendor/active_record/connection_specification.rb +301 -0
- data/lib/ddtrace/version.rb +12 -0
- data/lib/ddtrace/workers.rb +125 -0
- data/lib/ddtrace/writer.rb +157 -0
- data/tasks/release_gem.rake +28 -0
- metadata +682 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
# \Context is used to keep track of a hierarchy of spans for the current
|
|
5
|
+
# execution flow. During each logical execution, the same \Context is
|
|
6
|
+
# used to represent a single logical trace, even if the trace is built
|
|
7
|
+
# asynchronously.
|
|
8
|
+
#
|
|
9
|
+
# A single code execution may use multiple \Context if part of the execution
|
|
10
|
+
# must not be related to the current tracing. As example, a delayed job may
|
|
11
|
+
# compose a standalone trace instead of being related to the same trace that
|
|
12
|
+
# generates the job itself. On the other hand, if it's part of the same
|
|
13
|
+
# \Context, it will be related to the original trace.
|
|
14
|
+
#
|
|
15
|
+
# This data structure is thread-safe.
|
|
16
|
+
# rubocop:disable Metrics/ClassLength
|
|
17
|
+
class Context
|
|
18
|
+
# 100k spans is about a 100Mb footprint
|
|
19
|
+
DEFAULT_MAX_LENGTH = 100_000
|
|
20
|
+
|
|
21
|
+
attr_reader :max_length
|
|
22
|
+
|
|
23
|
+
# Initialize a new thread-safe \Context.
|
|
24
|
+
def initialize(options = {})
|
|
25
|
+
@mutex = Mutex.new
|
|
26
|
+
# max_length is the amount of spans above which, for a given trace,
|
|
27
|
+
# the context will simply drop and ignore spans, avoiding high memory usage.
|
|
28
|
+
@max_length = options.fetch(:max_length, DEFAULT_MAX_LENGTH)
|
|
29
|
+
reset(options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def trace_id
|
|
33
|
+
@mutex.synchronize do
|
|
34
|
+
@parent_trace_id
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def span_id
|
|
39
|
+
@mutex.synchronize do
|
|
40
|
+
@parent_span_id
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def sampling_priority
|
|
45
|
+
@mutex.synchronize do
|
|
46
|
+
@sampling_priority
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def sampling_priority=(priority)
|
|
51
|
+
@mutex.synchronize do
|
|
52
|
+
@sampling_priority = priority
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def origin
|
|
57
|
+
@mutex.synchronize do
|
|
58
|
+
@origin
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def origin=(origin)
|
|
63
|
+
@mutex.synchronize do
|
|
64
|
+
@origin = origin
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Return the last active span that corresponds to the last inserted
|
|
69
|
+
# item in the trace list. This cannot be considered as the current active
|
|
70
|
+
# span in asynchronous environments, because some spans can be closed
|
|
71
|
+
# earlier while child spans still need to finish their traced execution.
|
|
72
|
+
def current_span
|
|
73
|
+
@mutex.synchronize do
|
|
74
|
+
return @current_span
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def current_root_span
|
|
79
|
+
@mutex.synchronize do
|
|
80
|
+
return @current_root_span
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Add a span to the context trace list, keeping it as the last active span.
|
|
85
|
+
def add_span(span)
|
|
86
|
+
@mutex.synchronize do
|
|
87
|
+
# If hitting the hard limit, just drop spans. This is really a rare case
|
|
88
|
+
# as it means despite the soft limit, the hard limit is reached, so the trace
|
|
89
|
+
# by default has 10000 spans, all of which belong to unfinished parts of a
|
|
90
|
+
# larger trace. This is a catch-all to reduce global memory usage.
|
|
91
|
+
if @max_length > 0 && @trace.length >= @max_length
|
|
92
|
+
Datadog::Tracer.log.debug("context full, ignoring span #{span.name}")
|
|
93
|
+
# Detach the span from any context, it's being dropped and ignored.
|
|
94
|
+
span.context = nil
|
|
95
|
+
return
|
|
96
|
+
end
|
|
97
|
+
set_current_span(span)
|
|
98
|
+
@current_root_span = span if @trace.empty?
|
|
99
|
+
@trace << span
|
|
100
|
+
span.context = self
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Mark a span as a finished, increasing the internal counter to prevent
|
|
105
|
+
# cycles inside _trace list.
|
|
106
|
+
def close_span(span)
|
|
107
|
+
@mutex.synchronize do
|
|
108
|
+
@finished_spans += 1
|
|
109
|
+
# Current span is only meaningful for linear tree-like traces,
|
|
110
|
+
# in other cases, this is just broken and one should rely
|
|
111
|
+
# on per-instrumentation code to retrieve handle parent/child relations.
|
|
112
|
+
set_current_span(span.parent)
|
|
113
|
+
return if span.tracer.nil?
|
|
114
|
+
return unless Datadog::Tracer.debug_logging
|
|
115
|
+
if span.parent.nil? && !check_finished_spans
|
|
116
|
+
opened_spans = @trace.length - @finished_spans
|
|
117
|
+
Datadog::Tracer.log.debug("root span #{span.name} closed but has #{opened_spans} unfinished spans:")
|
|
118
|
+
@trace.each do |s|
|
|
119
|
+
Datadog::Tracer.log.debug("unfinished span: #{s}") unless s.finished?
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Returns if the trace for the current Context is finished or not. A \Context
|
|
126
|
+
# is considered finished if all spans in this context are finished.
|
|
127
|
+
def finished?
|
|
128
|
+
@mutex.synchronize do
|
|
129
|
+
return check_finished_spans
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Returns true if the context is sampled, that is, if it should be kept
|
|
134
|
+
# and sent to the trace agent.
|
|
135
|
+
def sampled?
|
|
136
|
+
@mutex.synchronize do
|
|
137
|
+
return @sampled
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Returns both the trace list generated in the current context and
|
|
142
|
+
# if the context is sampled or not. It returns nil, nil if the ``Context`` is
|
|
143
|
+
# not finished. If a trace is returned, the \Context will be reset so that it
|
|
144
|
+
# can be re-used immediately.
|
|
145
|
+
#
|
|
146
|
+
# This operation is thread-safe.
|
|
147
|
+
def get
|
|
148
|
+
@mutex.synchronize do
|
|
149
|
+
trace = @trace
|
|
150
|
+
sampled = @sampled
|
|
151
|
+
|
|
152
|
+
attach_sampling_priority if sampled && @sampling_priority
|
|
153
|
+
attach_origin if @origin
|
|
154
|
+
|
|
155
|
+
# still return sampled attribute, even if context is not finished
|
|
156
|
+
return nil, sampled unless check_finished_spans()
|
|
157
|
+
|
|
158
|
+
reset
|
|
159
|
+
[trace, sampled]
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Return a string representation of the context.
|
|
164
|
+
def to_s
|
|
165
|
+
@mutex.synchronize do
|
|
166
|
+
# rubocop:disable Metrics/LineLength
|
|
167
|
+
"Context(trace.length:#{@trace.length},sampled:#{@sampled},finished_spans:#{@finished_spans},current_span:#{@current_span})"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
private
|
|
172
|
+
|
|
173
|
+
def reset(options = {})
|
|
174
|
+
@trace = []
|
|
175
|
+
@parent_trace_id = options.fetch(:trace_id, nil)
|
|
176
|
+
@parent_span_id = options.fetch(:span_id, nil)
|
|
177
|
+
@sampled = options.fetch(:sampled, false)
|
|
178
|
+
@sampling_priority = options.fetch(:sampling_priority, nil)
|
|
179
|
+
@origin = options.fetch(:origin, nil)
|
|
180
|
+
@finished_spans = 0
|
|
181
|
+
@current_span = nil
|
|
182
|
+
@current_root_span = nil
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def set_current_span(span)
|
|
186
|
+
@current_span = span
|
|
187
|
+
if span
|
|
188
|
+
@parent_trace_id = span.trace_id
|
|
189
|
+
@parent_span_id = span.span_id
|
|
190
|
+
@sampled = span.sampled
|
|
191
|
+
else
|
|
192
|
+
@parent_span_id = nil
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Returns if the trace for the current Context is finished or not.
|
|
197
|
+
# Low-level internal function, not thread-safe.
|
|
198
|
+
def check_finished_spans
|
|
199
|
+
@finished_spans > 0 && @trace.length == @finished_spans
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def attach_sampling_priority
|
|
203
|
+
@current_root_span.set_metric(
|
|
204
|
+
Ext::DistributedTracing::SAMPLING_PRIORITY_KEY,
|
|
205
|
+
@sampling_priority
|
|
206
|
+
)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def attach_origin
|
|
210
|
+
@current_root_span.set_tag(
|
|
211
|
+
Ext::DistributedTracing::ORIGIN_KEY,
|
|
212
|
+
@origin
|
|
213
|
+
)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Return the start time of the root span, or nil if there are no spans or this is undefined.
|
|
217
|
+
def start_time
|
|
218
|
+
@mutex.synchronize do
|
|
219
|
+
return nil if @trace.empty?
|
|
220
|
+
@trace[0].start_time
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Return the length of the current trace held by this context.
|
|
225
|
+
def length
|
|
226
|
+
@mutex.synchronize do
|
|
227
|
+
@trace.length
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Iterate on each span within the trace. This is thread safe.
|
|
232
|
+
def each_span
|
|
233
|
+
@mutex.synchronize do
|
|
234
|
+
@trace.each do |span|
|
|
235
|
+
yield span
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Delete any span matching the condition. This is thread safe.
|
|
241
|
+
def delete_span_if
|
|
242
|
+
@mutex.synchronize do
|
|
243
|
+
@trace.delete_if do |span|
|
|
244
|
+
finished = span.finished?
|
|
245
|
+
delete_span = yield span
|
|
246
|
+
if delete_span
|
|
247
|
+
# We need to detach the span from the context, else, some code
|
|
248
|
+
# finishing it afterwards would mess up with the number of
|
|
249
|
+
# finished_spans and possibly cause other side effects.
|
|
250
|
+
span.context = nil
|
|
251
|
+
# Acknowledge there's one span less to finish, if needed.
|
|
252
|
+
# It's very important to keep this balanced.
|
|
253
|
+
@finished_spans -= 1 if finished
|
|
254
|
+
end
|
|
255
|
+
delete_span
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# ThreadLocalContext can be used as a tracer global reference to create
|
|
262
|
+
# a different \Context for each thread. In synchronous tracer, this
|
|
263
|
+
# is required to prevent multiple threads sharing the same \Context
|
|
264
|
+
# in different executions.
|
|
265
|
+
class ThreadLocalContext
|
|
266
|
+
# ThreadLocalContext can be used as a tracer global reference to create
|
|
267
|
+
# a different \Context for each thread. In synchronous tracer, this
|
|
268
|
+
# is required to prevent multiple threads sharing the same \Context
|
|
269
|
+
# in different executions.
|
|
270
|
+
def initialize
|
|
271
|
+
self.local = Datadog::Context.new
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Override the thread-local context with a new context.
|
|
275
|
+
def local=(ctx)
|
|
276
|
+
Thread.current[:datadog_context] = ctx
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Return the thread-local context.
|
|
280
|
+
def local
|
|
281
|
+
Thread.current[:datadog_context] ||= Datadog::Context.new
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
require 'ddtrace/context'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
# \ContextFlush is used to cap context size and avoid it using too much memory.
|
|
7
|
+
# It performs memory flushes when required.
|
|
8
|
+
class ContextFlush
|
|
9
|
+
# by default, soft and hard limits are the same
|
|
10
|
+
DEFAULT_MAX_SPANS_BEFORE_PARTIAL_FLUSH = Datadog::Context::DEFAULT_MAX_LENGTH
|
|
11
|
+
# by default, never do a partial flush
|
|
12
|
+
DEFAULT_MIN_SPANS_BEFORE_PARTIAL_FLUSH = Datadog::Context::DEFAULT_MAX_LENGTH
|
|
13
|
+
# timeout should be lower than the trace agent window
|
|
14
|
+
DEFAULT_PARTIAL_FLUSH_TIMEOUT = 10
|
|
15
|
+
|
|
16
|
+
private_constant :DEFAULT_MAX_SPANS_BEFORE_PARTIAL_FLUSH
|
|
17
|
+
private_constant :DEFAULT_MIN_SPANS_BEFORE_PARTIAL_FLUSH
|
|
18
|
+
private_constant :DEFAULT_PARTIAL_FLUSH_TIMEOUT
|
|
19
|
+
|
|
20
|
+
def initialize(options = {})
|
|
21
|
+
# max_spans_before_partial_flush is the amount of spans collected before
|
|
22
|
+
# the context starts to partially flush parts of traces. With a setting of 10k,
|
|
23
|
+
# the memory overhead is about 10Mb per thread/context (depends on spans metadata,
|
|
24
|
+
# this is just an order of magnitude).
|
|
25
|
+
@max_spans_before_partial_flush = options.fetch(:max_spans_before_partial_flush,
|
|
26
|
+
DEFAULT_MAX_SPANS_BEFORE_PARTIAL_FLUSH)
|
|
27
|
+
# min_spans_before_partial_flush is the minimum number of spans required
|
|
28
|
+
# for a partial flush to happen on a timeout. This is to prevent partial flush
|
|
29
|
+
# of traces which last a very long time but yet have few spans.
|
|
30
|
+
@min_spans_before_partial_flush = options.fetch(:min_spans_before_partial_flush,
|
|
31
|
+
DEFAULT_MIN_SPANS_BEFORE_PARTIAL_FLUSH)
|
|
32
|
+
# partial_flush_timeout is the limit (in seconds) above which the context
|
|
33
|
+
# considers flushing parts of the trace. Partial flushes should not be done too
|
|
34
|
+
# late else the agent rejects them with a "too far in the past" error.
|
|
35
|
+
@partial_flush_timeout = options.fetch(:partial_flush_timeout,
|
|
36
|
+
DEFAULT_PARTIAL_FLUSH_TIMEOUT)
|
|
37
|
+
@partial_traces = []
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_children(m, spans, ids, leaf)
|
|
41
|
+
spans << leaf
|
|
42
|
+
ids.add(leaf.span_id)
|
|
43
|
+
|
|
44
|
+
if m[leaf.span_id]
|
|
45
|
+
m[leaf.span_id].each do |sub|
|
|
46
|
+
add_children(m, spans, ids, sub)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def partial_traces(context)
|
|
52
|
+
# 1st step, taint all parents of an unfinished span as unflushable
|
|
53
|
+
unflushable_ids = Set.new
|
|
54
|
+
|
|
55
|
+
context.send(:each_span) do |span|
|
|
56
|
+
next if span.finished? || unflushable_ids.include?(span.span_id)
|
|
57
|
+
unflushable_ids.add span.span_id
|
|
58
|
+
while span.parent
|
|
59
|
+
span = span.parent
|
|
60
|
+
unflushable_ids.add span.span_id
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# 2nd step, find all spans which are at the border between flushable and unflushable
|
|
65
|
+
# Along the road, collect a reverse-tree which allows direct walking from parents to
|
|
66
|
+
# children but only for the ones we're interested it.
|
|
67
|
+
roots = []
|
|
68
|
+
children_map = {}
|
|
69
|
+
context.send(:each_span) do |span|
|
|
70
|
+
# There's no point in trying to put the real root in those partial roots, if
|
|
71
|
+
# it's flushable, the default algorithm would figure way more quickly.
|
|
72
|
+
if span.parent && !unflushable_ids.include?(span.span_id)
|
|
73
|
+
if unflushable_ids.include?(span.parent.span_id)
|
|
74
|
+
# span is flushable but is parent is not
|
|
75
|
+
roots << span
|
|
76
|
+
else
|
|
77
|
+
# span is flushable and its parent is too, build the reverse
|
|
78
|
+
# parent to child map for this one, it will be useful
|
|
79
|
+
children_map[span.parent.span_id] ||= []
|
|
80
|
+
children_map[span.parent.span_id] << span
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# 3rd step, find all children, as this can be costly, only perform it for partial roots
|
|
86
|
+
partial_traces = []
|
|
87
|
+
all_ids = Set.new
|
|
88
|
+
roots.each do |root|
|
|
89
|
+
spans = []
|
|
90
|
+
add_children(children_map, spans, all_ids, root)
|
|
91
|
+
partial_traces << spans
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
return [nil, nil] if partial_traces.empty?
|
|
95
|
+
[partial_traces, all_ids]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def partial_flush(context)
|
|
99
|
+
traces, flushed_ids = partial_traces(context)
|
|
100
|
+
return nil unless traces && flushed_ids
|
|
101
|
+
|
|
102
|
+
# We need to reject by span ID and not by value, because a span
|
|
103
|
+
# value may be altered (typical example: it's finished by some other thread)
|
|
104
|
+
# since we lock only the context, not all the spans which belong to it.
|
|
105
|
+
context.send(:delete_span_if) { |span| flushed_ids.include? span.span_id }
|
|
106
|
+
traces
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Performs an operation which each partial trace it can get from the context.
|
|
110
|
+
def each_partial_trace(context)
|
|
111
|
+
start_time = context.send(:start_time)
|
|
112
|
+
length = context.send(:length)
|
|
113
|
+
# Stop and do not flush anything if there are not enough spans.
|
|
114
|
+
return if length <= @min_spans_before_partial_flush
|
|
115
|
+
# If there are enough spans, but not too many, check for start time.
|
|
116
|
+
# If timeout is not given or 0, then wait
|
|
117
|
+
return if length <= @max_spans_before_partial_flush &&
|
|
118
|
+
(@partial_flush_timeout.nil? || @partial_flush_timeout <= 0 ||
|
|
119
|
+
(start_time && start_time > Time.now.utc - @partial_flush_timeout))
|
|
120
|
+
# Here, either the trace is old or we have too many spans, flush it.
|
|
121
|
+
traces = partial_flush(context)
|
|
122
|
+
return unless traces
|
|
123
|
+
traces.each do |trace|
|
|
124
|
+
yield trace
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private :add_children
|
|
129
|
+
private :partial_traces
|
|
130
|
+
private :partial_flush
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'ddtrace/ext/http'
|
|
2
|
+
|
|
3
|
+
require 'ddtrace/contrib/action_pack/ext'
|
|
4
|
+
require 'ddtrace/contrib/action_pack/utils'
|
|
5
|
+
require 'ddtrace/contrib/rack/middlewares'
|
|
6
|
+
|
|
7
|
+
module Datadog
|
|
8
|
+
module Contrib
|
|
9
|
+
module ActionPack
|
|
10
|
+
module ActionController
|
|
11
|
+
# Instrumentation for ActionController components
|
|
12
|
+
module Instrumentation
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def start_processing(payload)
|
|
16
|
+
# trace the execution
|
|
17
|
+
tracer = Datadog.configuration[:action_pack][:tracer]
|
|
18
|
+
service = Datadog.configuration[:action_pack][:controller_service]
|
|
19
|
+
type = Datadog::Ext::HTTP::TYPE_INBOUND
|
|
20
|
+
span = tracer.trace(Ext::SPAN_ACTION_CONTROLLER, service: service, span_type: type)
|
|
21
|
+
|
|
22
|
+
# attach the current span to the tracing context
|
|
23
|
+
tracing_context = payload.fetch(:tracing_context)
|
|
24
|
+
tracing_context[:dd_request_span] = span
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
Datadog::Tracer.log.error(e.message)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def finish_processing(payload)
|
|
30
|
+
# retrieve the tracing context and the latest active span
|
|
31
|
+
tracing_context = payload.fetch(:tracing_context)
|
|
32
|
+
env = payload.fetch(:env)
|
|
33
|
+
span = tracing_context[:dd_request_span]
|
|
34
|
+
return unless span && !span.finished?
|
|
35
|
+
|
|
36
|
+
begin
|
|
37
|
+
# Set the resource name, if it's still the default name
|
|
38
|
+
if span.resource == span.name
|
|
39
|
+
span.resource = "#{payload.fetch(:controller)}##{payload.fetch(:action)}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Set the resource name of the Rack request span unless this is an exception controller.
|
|
43
|
+
unless exception_controller?(payload)
|
|
44
|
+
rack_request_span = env[Datadog::Contrib::Rack::TraceMiddleware::RACK_REQUEST_SPAN]
|
|
45
|
+
rack_request_span.resource = span.resource if rack_request_span
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Set analytics sample rate
|
|
49
|
+
Utils.set_analytics_sample_rate(span)
|
|
50
|
+
|
|
51
|
+
# Associate with runtime metrics
|
|
52
|
+
Datadog.runtime_metrics.associate_with_span(span)
|
|
53
|
+
|
|
54
|
+
span.set_tag(Ext::TAG_ROUTE_ACTION, payload.fetch(:action))
|
|
55
|
+
span.set_tag(Ext::TAG_ROUTE_CONTROLLER, payload.fetch(:controller))
|
|
56
|
+
|
|
57
|
+
exception = payload[:exception_object]
|
|
58
|
+
if exception.nil?
|
|
59
|
+
# [christian] in some cases :status is not defined,
|
|
60
|
+
# rather than firing an error, simply acknowledge we don't know it.
|
|
61
|
+
status = payload.fetch(:status, '?').to_s
|
|
62
|
+
span.status = 1 if status.starts_with?('5')
|
|
63
|
+
elsif Utils.exception_is_error?(exception)
|
|
64
|
+
span.set_error(exception)
|
|
65
|
+
end
|
|
66
|
+
ensure
|
|
67
|
+
span.finish
|
|
68
|
+
end
|
|
69
|
+
rescue StandardError => e
|
|
70
|
+
Datadog::Tracer.log.error(e.message)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def exception_controller?(payload)
|
|
74
|
+
exception_controller_class = Datadog.configuration[:action_pack][:exception_controller]
|
|
75
|
+
controller = payload.fetch(:controller)
|
|
76
|
+
headers = payload.fetch(:headers)
|
|
77
|
+
|
|
78
|
+
# If no exception controller class has been set,
|
|
79
|
+
# guess whether this is an exception controller from the headers.
|
|
80
|
+
if exception_controller_class.nil?
|
|
81
|
+
!headers[:request_exception].nil?
|
|
82
|
+
# If an exception controller class has been specified,
|
|
83
|
+
# check if the controller is a kind of the exception controller class.
|
|
84
|
+
elsif exception_controller_class.is_a?(Class) || exception_controller_class.is_a?(Module)
|
|
85
|
+
controller <= exception_controller_class
|
|
86
|
+
# Otherwise if the exception controller class is some other value (like false)
|
|
87
|
+
# assume that this controller doesn't handle exceptions.
|
|
88
|
+
else
|
|
89
|
+
false
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Instrumentation for ActionController::Metal
|
|
94
|
+
module Metal
|
|
95
|
+
def process_action(*args)
|
|
96
|
+
# mutable payload with a tracing context that is used in two different
|
|
97
|
+
# signals; it propagates the request span so that it can be finished
|
|
98
|
+
# no matter what
|
|
99
|
+
payload = {
|
|
100
|
+
controller: self.class,
|
|
101
|
+
action: action_name,
|
|
102
|
+
env: request.env,
|
|
103
|
+
headers: {
|
|
104
|
+
# The exception this controller was given in the request,
|
|
105
|
+
# which is typical if the controller is configured to handle exceptions.
|
|
106
|
+
request_exception: request.headers['action_dispatch.exception']
|
|
107
|
+
},
|
|
108
|
+
tracing_context: {}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
begin
|
|
112
|
+
# process and catch request exceptions
|
|
113
|
+
Instrumentation.start_processing(payload)
|
|
114
|
+
result = super(*args)
|
|
115
|
+
status = datadog_response_status
|
|
116
|
+
payload[:status] = status unless status.nil?
|
|
117
|
+
result
|
|
118
|
+
# rubocop:disable Lint/RescueException
|
|
119
|
+
rescue Exception => e
|
|
120
|
+
payload[:exception] = [e.class.name, e.message]
|
|
121
|
+
payload[:exception_object] = e
|
|
122
|
+
raise e
|
|
123
|
+
end
|
|
124
|
+
# rubocop:enable Lint/RescueException
|
|
125
|
+
ensure
|
|
126
|
+
Instrumentation.finish_processing(payload)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def datadog_response_status
|
|
130
|
+
case response
|
|
131
|
+
when ::ActionDispatch::Response
|
|
132
|
+
response.status
|
|
133
|
+
when Array
|
|
134
|
+
# Likely a Rack response array: first element is the status.
|
|
135
|
+
status = response.first
|
|
136
|
+
status.class <= Integer ? status : nil
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|