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
data/lib/ddtrace/span.rb
ADDED
|
@@ -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
|