ddtrace 0.44.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +183 -15
- data/.circleci/images/primary/Dockerfile-2.0.0 +11 -1
- data/.circleci/images/primary/Dockerfile-2.1.10 +11 -1
- data/.circleci/images/primary/Dockerfile-2.2.10 +11 -1
- data/.circleci/images/primary/Dockerfile-2.3.8 +10 -0
- data/.circleci/images/primary/Dockerfile-2.4.6 +10 -0
- data/.circleci/images/primary/Dockerfile-2.5.6 +10 -0
- data/.circleci/images/primary/Dockerfile-2.6.4 +10 -0
- data/.circleci/images/primary/Dockerfile-2.7.0 +10 -0
- data/.circleci/images/primary/Dockerfile-jruby-9.2-latest +88 -0
- data/.circleci/images/primary/{Dockerfile-jruby-9.2 → Dockerfile-jruby-9.2.0.0} +1 -5
- data/.circleci/images/primary/Dockerfile-truffleruby-21.0.0 +73 -0
- data/.github/workflows/create-next-milestone.yml +2 -2
- data/.gitlab-ci.yml +18 -18
- data/.rubocop.yml +269 -7
- data/.rubocop_todo.yml +438 -0
- data/.simplecov +6 -0
- data/Appraisals +87 -9
- data/CHANGELOG.md +238 -1
- data/Gemfile +63 -3
- data/LICENSE-3rdparty.csv +2 -0
- data/README.md +1 -0
- data/Rakefile +65 -25
- data/bin/ddtracerb +15 -0
- data/ddtrace.gemspec +9 -36
- data/docker-compose.yml +75 -7
- data/docs/DevelopmentGuide.md +28 -0
- data/docs/GettingStarted.md +162 -68
- data/docs/ProfilingDevelopment.md +88 -0
- data/integration/README.md +67 -0
- data/integration/apps/rack/.dockerignore +1 -0
- data/integration/apps/rack/.envrc.sample +1 -0
- data/integration/apps/rack/.gitignore +4 -0
- data/integration/apps/rack/.rspec +1 -0
- data/integration/apps/rack/Dockerfile +28 -0
- data/integration/apps/rack/Dockerfile-ci +11 -0
- data/integration/apps/rack/Gemfile +24 -0
- data/integration/apps/rack/README.md +93 -0
- data/integration/apps/rack/app/acme.rb +80 -0
- data/integration/apps/rack/app/datadog.rb +17 -0
- data/integration/apps/rack/bin/run +22 -0
- data/integration/apps/rack/bin/setup +17 -0
- data/integration/apps/rack/bin/test +24 -0
- data/integration/apps/rack/config.ru +6 -0
- data/integration/apps/rack/config/puma.rb +14 -0
- data/integration/apps/rack/config/unicorn.rb +23 -0
- data/integration/apps/rack/docker-compose.ci.yml +62 -0
- data/integration/apps/rack/docker-compose.yml +78 -0
- data/integration/apps/rack/script/build-images +38 -0
- data/integration/apps/rack/script/ci +50 -0
- data/integration/apps/rack/spec/integration/basic_spec.rb +10 -0
- data/integration/apps/rack/spec/spec_helper.rb +16 -0
- data/integration/apps/rack/spec/support/integration_helper.rb +22 -0
- data/integration/apps/rails-five/.dockerignore +1 -0
- data/integration/apps/rails-five/.env +3 -0
- data/integration/apps/rails-five/.envrc.sample +1 -0
- data/integration/apps/rails-five/.gitignore +30 -0
- data/integration/apps/rails-five/Dockerfile +25 -0
- data/integration/apps/rails-five/Dockerfile-ci +11 -0
- data/integration/apps/rails-five/Gemfile +104 -0
- data/integration/apps/rails-five/README.md +94 -0
- data/integration/apps/rails-five/Rakefile +6 -0
- data/integration/apps/rails-five/app/channels/application_cable/channel.rb +4 -0
- data/integration/apps/rails-five/app/channels/application_cable/connection.rb +4 -0
- data/integration/apps/rails-five/app/controllers/application_controller.rb +2 -0
- data/integration/apps/rails-five/app/controllers/basic_controller.rb +36 -0
- data/integration/apps/rails-five/app/controllers/concerns/.keep +0 -0
- data/integration/apps/rails-five/app/controllers/health_controller.rb +9 -0
- data/integration/apps/rails-five/app/controllers/jobs_controller.rb +12 -0
- data/integration/apps/rails-five/app/jobs/application_job.rb +2 -0
- data/integration/apps/rails-five/app/jobs/test_job.rb +12 -0
- data/integration/apps/rails-five/app/mailers/application_mailer.rb +4 -0
- data/integration/apps/rails-five/app/models/application_record.rb +3 -0
- data/integration/apps/rails-five/app/models/concerns/.keep +0 -0
- data/integration/apps/rails-five/app/models/test.rb +2 -0
- data/integration/apps/rails-five/app/views/layouts/mailer.html.erb +13 -0
- data/integration/apps/rails-five/app/views/layouts/mailer.text.erb +1 -0
- data/integration/apps/rails-five/bin/bundle +3 -0
- data/integration/apps/rails-five/bin/rails +9 -0
- data/integration/apps/rails-five/bin/rake +9 -0
- data/integration/apps/rails-five/bin/run +24 -0
- data/integration/apps/rails-five/bin/setup +27 -0
- data/integration/apps/rails-five/bin/spring +17 -0
- data/integration/apps/rails-five/bin/test +21 -0
- data/integration/apps/rails-five/bin/update +28 -0
- data/integration/apps/rails-five/config.ru +5 -0
- data/integration/apps/rails-five/config/application.rb +97 -0
- data/integration/apps/rails-five/config/boot.rb +4 -0
- data/integration/apps/rails-five/config/cable.yml +10 -0
- data/integration/apps/rails-five/config/credentials.yml.enc +1 -0
- data/integration/apps/rails-five/config/database.yml +28 -0
- data/integration/apps/rails-five/config/environment.rb +5 -0
- data/integration/apps/rails-five/config/environments/development.rb +51 -0
- data/integration/apps/rails-five/config/environments/production.rb +82 -0
- data/integration/apps/rails-five/config/environments/test.rb +43 -0
- data/integration/apps/rails-five/config/initializers/datadog.rb +18 -0
- data/integration/apps/rails-five/config/initializers/filter_parameter_logging.rb +4 -0
- data/integration/apps/rails-five/config/initializers/resque.rb +4 -0
- data/integration/apps/rails-five/config/initializers/rollbar.rb +5 -0
- data/integration/apps/rails-five/config/initializers/wrap_parameters.rb +14 -0
- data/integration/apps/rails-five/config/locales/en.yml +33 -0
- data/integration/apps/rails-five/config/puma.rb +24 -0
- data/integration/apps/rails-five/config/routes.rb +11 -0
- data/integration/apps/rails-five/config/spring.rb +6 -0
- data/integration/apps/rails-five/config/unicorn.rb +29 -0
- data/integration/apps/rails-five/db/migrate/20190927215052_create_tests.rb +11 -0
- data/integration/apps/rails-five/db/schema.rb +23 -0
- data/integration/apps/rails-five/db/seeds.rb +7 -0
- data/integration/apps/rails-five/docker-compose.ci.yml +98 -0
- data/integration/apps/rails-five/docker-compose.yml +100 -0
- data/integration/apps/rails-five/lib/tasks/.keep +0 -0
- data/integration/apps/rails-five/log/.keep +0 -0
- data/integration/apps/rails-five/public/robots.txt +1 -0
- data/integration/apps/rails-five/script/build-images +35 -0
- data/integration/apps/rails-five/script/ci +50 -0
- data/integration/apps/rails-five/spec/integration/basic_spec.rb +10 -0
- data/integration/apps/rails-five/spec/spec_helper.rb +16 -0
- data/integration/apps/rails-five/spec/support/integration_helper.rb +22 -0
- data/integration/apps/rails-five/storage/.keep +0 -0
- data/integration/apps/rails-five/tmp/.keep +0 -0
- data/integration/apps/rails-five/vendor/.keep +0 -0
- data/integration/apps/ruby/.dockerignore +1 -0
- data/integration/apps/ruby/.envrc.sample +1 -0
- data/integration/apps/ruby/.gitignore +2 -0
- data/integration/apps/ruby/Dockerfile +25 -0
- data/integration/apps/ruby/Dockerfile-ci +11 -0
- data/integration/apps/ruby/Gemfile +11 -0
- data/integration/apps/ruby/README.md +70 -0
- data/integration/apps/ruby/agent.yaml +3 -0
- data/integration/apps/ruby/app/datadog.rb +13 -0
- data/integration/apps/ruby/app/fibonacci.rb +58 -0
- data/integration/apps/ruby/bin/run +20 -0
- data/integration/apps/ruby/bin/setup +17 -0
- data/integration/apps/ruby/bin/test +21 -0
- data/integration/apps/ruby/docker-compose.ci.yml +51 -0
- data/integration/apps/ruby/docker-compose.yml +63 -0
- data/integration/apps/ruby/script/build-images +38 -0
- data/integration/apps/ruby/script/ci +50 -0
- data/integration/images/agent/Dockerfile +2 -0
- data/integration/images/agent/agent.yaml +3 -0
- data/integration/images/include/datadog/analyzer.rb +71 -0
- data/integration/images/include/datadog/demo_env.rb +101 -0
- data/integration/images/include/http-health-check +33 -0
- data/integration/images/ruby/2.0/Dockerfile +54 -0
- data/integration/images/ruby/2.1/Dockerfile +54 -0
- data/integration/images/ruby/2.2/Dockerfile +54 -0
- data/integration/images/ruby/2.3/Dockerfile +70 -0
- data/integration/images/ruby/2.4/Dockerfile +54 -0
- data/integration/images/ruby/2.5/Dockerfile +54 -0
- data/integration/images/ruby/2.6/Dockerfile +54 -0
- data/integration/images/ruby/2.7/Dockerfile +54 -0
- data/integration/images/ruby/3.0/Dockerfile +54 -0
- data/integration/images/wrk/Dockerfile +33 -0
- data/integration/images/wrk/scripts/entrypoint.sh +17 -0
- data/integration/images/wrk/scripts/scenarios/basic/default.lua +1 -0
- data/integration/images/wrk/scripts/scenarios/basic/fibonacci.lua +1 -0
- data/integration/script/build-images +43 -0
- data/lib/ddtrace.rb +8 -5
- data/lib/ddtrace/analytics.rb +2 -0
- data/lib/ddtrace/auto_instrument.rb +3 -0
- data/lib/ddtrace/auto_instrument_base.rb +6 -0
- data/lib/ddtrace/buffer.rb +4 -4
- data/lib/ddtrace/configuration.rb +121 -26
- data/lib/ddtrace/configuration/base.rb +1 -1
- data/lib/ddtrace/configuration/components.rb +87 -5
- data/lib/ddtrace/configuration/option_definition.rb +1 -3
- data/lib/ddtrace/configuration/options.rb +4 -7
- data/lib/ddtrace/configuration/settings.rb +48 -3
- data/lib/ddtrace/context.rb +5 -6
- data/lib/ddtrace/context_provider.rb +0 -1
- data/lib/ddtrace/contrib/action_cable/event.rb +1 -0
- data/lib/ddtrace/contrib/action_cable/integration.rb +7 -0
- data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +1 -3
- data/lib/ddtrace/contrib/action_pack/integration.rb +7 -0
- data/lib/ddtrace/contrib/action_view/event.rb +1 -1
- data/lib/ddtrace/contrib/action_view/integration.rb +7 -0
- data/lib/ddtrace/contrib/action_view/utils.rb +1 -1
- data/lib/ddtrace/contrib/active_record/configuration/makara_resolver.rb +30 -0
- data/lib/ddtrace/contrib/active_record/configuration/resolver.rb +107 -18
- data/lib/ddtrace/contrib/active_record/integration.rb +7 -0
- data/lib/ddtrace/contrib/active_record/utils.rb +57 -20
- data/lib/ddtrace/contrib/active_support/integration.rb +7 -1
- data/lib/ddtrace/contrib/active_support/notifications/event.rb +2 -1
- data/lib/ddtrace/contrib/active_support/notifications/subscriber.rb +1 -0
- data/lib/ddtrace/contrib/active_support/notifications/subscription.rb +9 -5
- data/lib/ddtrace/contrib/auto_instrument.rb +49 -0
- data/lib/ddtrace/contrib/aws/patcher.rb +1 -0
- data/lib/ddtrace/contrib/aws/services.rb +2 -0
- data/lib/ddtrace/contrib/configurable.rb +63 -39
- data/lib/ddtrace/contrib/configuration/resolver.rb +70 -5
- data/lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb +19 -20
- data/lib/ddtrace/contrib/configuration/settings.rb +7 -6
- data/lib/ddtrace/contrib/cucumber/configuration/settings.rb +0 -10
- data/lib/ddtrace/contrib/cucumber/ext.rb +0 -2
- data/lib/ddtrace/contrib/cucumber/formatter.rb +5 -11
- data/lib/ddtrace/contrib/cucumber/integration.rb +5 -0
- data/lib/ddtrace/contrib/dalli/patcher.rb +0 -38
- data/lib/ddtrace/contrib/delayed_job/plugin.rb +0 -1
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +1 -0
- data/lib/ddtrace/contrib/elasticsearch/quantize.rb +3 -2
- data/lib/ddtrace/contrib/ethon/easy_patch.rb +10 -9
- data/lib/ddtrace/contrib/excon/middleware.rb +2 -6
- data/lib/ddtrace/contrib/extensions.rb +53 -3
- data/lib/ddtrace/contrib/faraday/middleware.rb +1 -3
- data/lib/ddtrace/contrib/faraday/patcher.rb +0 -36
- data/lib/ddtrace/contrib/grape/endpoint.rb +8 -15
- data/lib/ddtrace/contrib/grape/patcher.rb +0 -42
- data/lib/ddtrace/contrib/grpc/datadog_interceptor.rb +8 -8
- data/lib/ddtrace/contrib/grpc/datadog_interceptor/server.rb +1 -0
- data/lib/ddtrace/contrib/grpc/patcher.rb +0 -36
- data/lib/ddtrace/contrib/http/circuit_breaker.rb +1 -3
- data/lib/ddtrace/contrib/http/instrumentation.rb +5 -5
- data/lib/ddtrace/contrib/httpclient/configuration/settings.rb +32 -0
- data/lib/ddtrace/contrib/httpclient/ext.rb +17 -0
- data/lib/ddtrace/contrib/httpclient/instrumentation.rb +147 -0
- data/lib/ddtrace/contrib/httpclient/integration.rb +43 -0
- data/lib/ddtrace/contrib/httpclient/patcher.rb +38 -0
- data/lib/ddtrace/contrib/httprb/instrumentation.rb +14 -20
- data/lib/ddtrace/contrib/httprb/patcher.rb +5 -2
- data/lib/ddtrace/contrib/mongodb/instrumentation.rb +2 -0
- data/lib/ddtrace/contrib/mongodb/subscribers.rb +2 -3
- data/lib/ddtrace/contrib/patchable.rb +18 -7
- data/lib/ddtrace/contrib/patcher.rb +9 -6
- data/lib/ddtrace/contrib/presto/patcher.rb +5 -2
- data/lib/ddtrace/contrib/qless/qless_job.rb +1 -0
- data/lib/ddtrace/contrib/qless/tracer_cleaner.rb +1 -0
- data/lib/ddtrace/contrib/que/ext.rb +19 -19
- data/lib/ddtrace/contrib/que/tracer.rb +1 -1
- data/lib/ddtrace/contrib/racecar/event.rb +1 -0
- data/lib/ddtrace/contrib/rack/configuration/settings.rb +3 -3
- data/lib/ddtrace/contrib/rack/integration.rb +7 -0
- data/lib/ddtrace/contrib/rack/middlewares.rb +6 -11
- data/lib/ddtrace/contrib/rack/patcher.rb +1 -3
- data/lib/ddtrace/contrib/rack/request_queue.rb +6 -1
- data/lib/ddtrace/contrib/rails/auto_instrument_railtie.rb +10 -0
- data/lib/ddtrace/contrib/rails/patcher.rb +6 -2
- data/lib/ddtrace/contrib/rails/utils.rb +4 -0
- data/lib/ddtrace/contrib/rake/instrumentation.rb +4 -2
- data/lib/ddtrace/contrib/rake/integration.rb +1 -1
- data/lib/ddtrace/contrib/redis/configuration/resolver.rb +11 -4
- data/lib/ddtrace/contrib/redis/quantize.rb +1 -0
- data/lib/ddtrace/contrib/redis/vendor/LICENSE +20 -0
- data/lib/ddtrace/contrib/redis/vendor/resolver.rb +6 -7
- data/lib/ddtrace/contrib/registry.rb +2 -2
- data/lib/ddtrace/contrib/resque/configuration/settings.rb +17 -1
- data/lib/ddtrace/contrib/resque/integration.rb +1 -1
- data/lib/ddtrace/contrib/resque/patcher.rb +4 -4
- data/lib/ddtrace/contrib/resque/resque_job.rb +24 -1
- data/lib/ddtrace/contrib/rest_client/request_patch.rb +1 -3
- data/lib/ddtrace/contrib/rspec/configuration/settings.rb +0 -10
- data/lib/ddtrace/contrib/rspec/example.rb +24 -10
- data/lib/ddtrace/contrib/rspec/ext.rb +0 -3
- data/lib/ddtrace/contrib/rspec/integration.rb +6 -1
- data/lib/ddtrace/contrib/rspec/patcher.rb +0 -2
- data/lib/ddtrace/contrib/sequel/utils.rb +5 -6
- data/lib/ddtrace/contrib/shoryuken/configuration/settings.rb +1 -0
- data/lib/ddtrace/contrib/shoryuken/tracer.rb +7 -4
- data/lib/ddtrace/contrib/sidekiq/server_tracer.rb +2 -7
- data/lib/ddtrace/contrib/sidekiq/tracing.rb +0 -1
- data/lib/ddtrace/contrib/sinatra/env.rb +1 -3
- data/lib/ddtrace/contrib/sinatra/headers.rb +1 -3
- data/lib/ddtrace/contrib/sinatra/tracer.rb +1 -3
- data/lib/ddtrace/contrib/sinatra/tracer_middleware.rb +3 -3
- data/lib/ddtrace/contrib/sneakers/ext.rb +11 -11
- data/lib/ddtrace/contrib/sneakers/tracer.rb +2 -4
- data/lib/ddtrace/contrib/status_code_matcher.rb +5 -3
- data/lib/ddtrace/correlation.rb +1 -0
- data/lib/ddtrace/diagnostics/environment_logger.rb +3 -2
- data/lib/ddtrace/distributed_tracing/headers/headers.rb +1 -0
- data/lib/ddtrace/distributed_tracing/headers/helpers.rb +1 -3
- data/lib/ddtrace/error.rb +2 -0
- data/lib/ddtrace/ext/ci.rb +43 -10
- data/lib/ddtrace/ext/distributed.rb +1 -1
- data/lib/ddtrace/ext/git.rb +0 -1
- data/lib/ddtrace/ext/http.rb +1 -1
- data/lib/ddtrace/ext/profiling.rb +52 -0
- data/lib/ddtrace/ext/runtime.rb +3 -1
- data/lib/ddtrace/ext/transport.rb +1 -0
- data/lib/ddtrace/forced_tracing.rb +2 -0
- data/lib/ddtrace/logger.rb +1 -1
- data/lib/ddtrace/metrics.rb +14 -6
- data/lib/ddtrace/opentracer/distributed_headers.rb +3 -0
- data/lib/ddtrace/opentracer/span.rb +2 -6
- data/lib/ddtrace/opentracer/thread_local_scope.rb +1 -0
- data/lib/ddtrace/patcher.rb +25 -4
- data/lib/ddtrace/pin.rb +8 -61
- data/lib/ddtrace/pipeline/span_filter.rb +1 -1
- data/lib/ddtrace/profiling.rb +54 -0
- data/lib/ddtrace/profiling/backtrace_location.rb +32 -0
- data/lib/ddtrace/profiling/buffer.rb +41 -0
- data/lib/ddtrace/profiling/collectors/stack.rb +253 -0
- data/lib/ddtrace/profiling/encoding/profile.rb +31 -0
- data/lib/ddtrace/profiling/event.rb +13 -0
- data/lib/ddtrace/profiling/events/stack.rb +102 -0
- data/lib/ddtrace/profiling/exporter.rb +23 -0
- data/lib/ddtrace/profiling/ext/cpu.rb +54 -0
- data/lib/ddtrace/profiling/ext/cthread.rb +134 -0
- data/lib/ddtrace/profiling/ext/forking.rb +97 -0
- data/lib/ddtrace/profiling/flush.rb +41 -0
- data/lib/ddtrace/profiling/pprof/builder.rb +121 -0
- data/lib/ddtrace/profiling/pprof/converter.rb +85 -0
- data/lib/ddtrace/profiling/pprof/message_set.rb +12 -0
- data/lib/ddtrace/profiling/pprof/payload.rb +18 -0
- data/lib/ddtrace/profiling/pprof/pprof.proto +212 -0
- data/lib/ddtrace/profiling/pprof/pprof_pb.rb +81 -0
- data/lib/ddtrace/profiling/pprof/stack_sample.rb +90 -0
- data/lib/ddtrace/profiling/pprof/string_table.rb +10 -0
- data/lib/ddtrace/profiling/pprof/template.rb +114 -0
- data/lib/ddtrace/profiling/preload.rb +3 -0
- data/lib/ddtrace/profiling/profiler.rb +28 -0
- data/lib/ddtrace/profiling/recorder.rb +87 -0
- data/lib/ddtrace/profiling/scheduler.rb +84 -0
- data/lib/ddtrace/profiling/tasks/setup.rb +77 -0
- data/lib/ddtrace/profiling/transport/client.rb +12 -0
- data/lib/ddtrace/profiling/transport/http.rb +122 -0
- data/lib/ddtrace/profiling/transport/http/api.rb +43 -0
- data/lib/ddtrace/profiling/transport/http/api/endpoint.rb +90 -0
- data/lib/ddtrace/profiling/transport/http/api/instance.rb +36 -0
- data/lib/ddtrace/profiling/transport/http/api/spec.rb +40 -0
- data/lib/ddtrace/profiling/transport/http/builder.rb +28 -0
- data/lib/ddtrace/profiling/transport/http/client.rb +33 -0
- data/lib/ddtrace/profiling/transport/http/response.rb +21 -0
- data/lib/ddtrace/profiling/transport/io.rb +30 -0
- data/lib/ddtrace/profiling/transport/io/client.rb +27 -0
- data/lib/ddtrace/profiling/transport/io/response.rb +16 -0
- data/lib/ddtrace/profiling/transport/parcel.rb +17 -0
- data/lib/ddtrace/profiling/transport/request.rb +15 -0
- data/lib/ddtrace/profiling/transport/response.rb +8 -0
- data/lib/ddtrace/propagation/grpc_propagator.rb +1 -0
- data/lib/ddtrace/propagation/http_propagator.rb +17 -2
- data/lib/ddtrace/quantization/http.rb +1 -0
- data/lib/ddtrace/runtime/cgroup.rb +2 -2
- data/lib/ddtrace/runtime/container.rb +32 -26
- data/lib/ddtrace/runtime/identity.rb +8 -0
- data/lib/ddtrace/sampler.rb +1 -1
- data/lib/ddtrace/sampling/rule_sampler.rb +4 -9
- data/lib/ddtrace/span.rb +7 -7
- data/lib/ddtrace/sync_writer.rb +12 -12
- data/lib/ddtrace/tasks/exec.rb +48 -0
- data/lib/ddtrace/tasks/help.rb +14 -0
- data/lib/ddtrace/tracer.rb +28 -5
- data/lib/ddtrace/transport/http.rb +15 -8
- data/lib/ddtrace/transport/http/adapters/net.rb +27 -8
- data/lib/ddtrace/transport/http/adapters/registry.rb +1 -0
- data/lib/ddtrace/transport/http/adapters/unix_socket.rb +2 -4
- data/lib/ddtrace/transport/http/builder.rb +7 -1
- data/lib/ddtrace/transport/http/env.rb +8 -0
- data/lib/ddtrace/transport/http/traces.rb +2 -3
- data/lib/ddtrace/transport/io.rb +1 -1
- data/lib/ddtrace/transport/io/client.rb +15 -8
- data/lib/ddtrace/transport/io/response.rb +1 -3
- data/lib/ddtrace/transport/io/traces.rb +6 -0
- data/lib/ddtrace/transport/parcel.rb +4 -0
- data/lib/ddtrace/transport/traces.rb +18 -1
- data/lib/ddtrace/utils/compression.rb +27 -0
- data/lib/ddtrace/utils/object_set.rb +41 -0
- data/lib/ddtrace/utils/only_once.rb +40 -0
- data/lib/ddtrace/utils/sequence.rb +17 -0
- data/lib/ddtrace/utils/string_table.rb +45 -0
- data/lib/ddtrace/utils/time.rb +32 -1
- data/lib/ddtrace/vendor/active_record/MIT-LICENSE +20 -0
- data/lib/ddtrace/vendor/multipart-post/LICENSE +11 -0
- data/lib/ddtrace/vendor/multipart-post/multipart.rb +12 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post.rb +8 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/composite_read_io.rb +116 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/multipartable.rb +57 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/parts.rb +135 -0
- data/lib/ddtrace/vendor/multipart-post/multipart/post/version.rb +9 -0
- data/lib/ddtrace/vendor/multipart-post/net/http/post/multipart.rb +32 -0
- data/lib/ddtrace/version.rb +3 -1
- data/lib/ddtrace/workers.rb +5 -0
- data/lib/ddtrace/workers/async.rb +11 -3
- data/lib/ddtrace/workers/loop.rb +17 -3
- data/lib/ddtrace/workers/polling.rb +1 -0
- data/lib/ddtrace/workers/queue.rb +1 -0
- data/lib/ddtrace/workers/runtime_metrics.rb +14 -1
- data/lib/ddtrace/workers/trace_writer.rb +10 -10
- data/lib/ddtrace/writer.rb +7 -4
- metadata +213 -379
- data/lib/ddtrace/augmentation.rb +0 -13
- data/lib/ddtrace/augmentation/method_wrapper.rb +0 -20
- data/lib/ddtrace/augmentation/method_wrapping.rb +0 -38
- data/lib/ddtrace/augmentation/shim.rb +0 -102
- data/lib/ddtrace/contrib/rspec/example_group.rb +0 -61
- data/lib/ddtrace/monkey.rb +0 -58
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'ddtrace/buffer'
|
|
2
|
+
require 'ddtrace/utils/string_table'
|
|
3
|
+
require 'ddtrace/utils/object_set'
|
|
4
|
+
|
|
5
|
+
module Datadog
|
|
6
|
+
module Profiling
|
|
7
|
+
# Profiling buffer that stores profiling events. The buffer has a maximum size and when
|
|
8
|
+
# the buffer is full, a random event is discarded. This class is thread-safe.
|
|
9
|
+
class Buffer < Datadog::ThreadSafeBuffer
|
|
10
|
+
def initialize(*args)
|
|
11
|
+
super
|
|
12
|
+
@caches = {}
|
|
13
|
+
@string_table = Utils::StringTable.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def cache(cache_name)
|
|
17
|
+
synchronize do
|
|
18
|
+
@caches[cache_name] ||= Utils::ObjectSet.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def string_table
|
|
23
|
+
synchronize do
|
|
24
|
+
@string_table
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
protected
|
|
29
|
+
|
|
30
|
+
def drain!
|
|
31
|
+
items = super
|
|
32
|
+
|
|
33
|
+
# Clear caches
|
|
34
|
+
@caches = {}
|
|
35
|
+
@string_table = Utils::StringTable.new
|
|
36
|
+
|
|
37
|
+
items
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
require 'ddtrace/profiling/backtrace_location'
|
|
2
|
+
require 'ddtrace/profiling/events/stack'
|
|
3
|
+
require 'ddtrace/utils/only_once'
|
|
4
|
+
require 'ddtrace/utils/time'
|
|
5
|
+
require 'ddtrace/worker'
|
|
6
|
+
require 'ddtrace/workers/polling'
|
|
7
|
+
|
|
8
|
+
module Datadog
|
|
9
|
+
module Profiling
|
|
10
|
+
module Collectors
|
|
11
|
+
# Collects stack trace samples from Ruby threads for both CPU-time (if available) and wall-clock.
|
|
12
|
+
# Runs on its own background thread.
|
|
13
|
+
#
|
|
14
|
+
class Stack < Worker
|
|
15
|
+
include Workers::Polling
|
|
16
|
+
|
|
17
|
+
DEFAULT_MAX_TIME_USAGE_PCT = 2.0
|
|
18
|
+
MIN_INTERVAL = 0.01
|
|
19
|
+
THREAD_LAST_CPU_TIME_KEY = :datadog_profiler_last_cpu_time
|
|
20
|
+
|
|
21
|
+
attr_reader \
|
|
22
|
+
:recorder,
|
|
23
|
+
:max_frames,
|
|
24
|
+
:ignore_thread,
|
|
25
|
+
:max_time_usage_pct,
|
|
26
|
+
:thread_api
|
|
27
|
+
|
|
28
|
+
def initialize(
|
|
29
|
+
recorder,
|
|
30
|
+
max_frames: nil,
|
|
31
|
+
ignore_thread: nil,
|
|
32
|
+
max_time_usage_pct: DEFAULT_MAX_TIME_USAGE_PCT,
|
|
33
|
+
thread_api: Thread,
|
|
34
|
+
fork_policy: Workers::Async::Thread::FORK_POLICY_RESTART, # Restart in forks by default
|
|
35
|
+
interval: MIN_INTERVAL,
|
|
36
|
+
enabled: true
|
|
37
|
+
)
|
|
38
|
+
@recorder = recorder
|
|
39
|
+
# TODO: Make this a required named argument after we drop support for Ruby 2.0
|
|
40
|
+
@max_frames = max_frames || raise(ArgumentError, 'missing keyword :max_frames')
|
|
41
|
+
@ignore_thread = ignore_thread
|
|
42
|
+
@max_time_usage_pct = max_time_usage_pct
|
|
43
|
+
@thread_api = thread_api
|
|
44
|
+
|
|
45
|
+
# Workers::Async::Thread settings
|
|
46
|
+
self.fork_policy = fork_policy
|
|
47
|
+
|
|
48
|
+
# Workers::IntervalLoop settings
|
|
49
|
+
self.loop_base_interval = interval
|
|
50
|
+
|
|
51
|
+
# Workers::Polling settings
|
|
52
|
+
self.enabled = enabled
|
|
53
|
+
|
|
54
|
+
@warn_about_missing_cpu_time_instrumentation_only_once = Datadog::Utils::OnlyOnce.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def start
|
|
58
|
+
@last_wall_time = Datadog::Utils::Time.get_time
|
|
59
|
+
reset_cpu_time_tracking
|
|
60
|
+
perform
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def perform
|
|
64
|
+
collect_and_wait
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def loop_back_off?
|
|
68
|
+
false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def collect_and_wait
|
|
72
|
+
run_time = Datadog::Utils::Time.measure do
|
|
73
|
+
collect_events
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Update wait time to throttle profiling
|
|
77
|
+
self.loop_wait_time = compute_wait_time(run_time)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def collect_events
|
|
81
|
+
events = []
|
|
82
|
+
|
|
83
|
+
# Compute wall time interval
|
|
84
|
+
current_wall_time = Datadog::Utils::Time.get_time
|
|
85
|
+
last_wall_time = if instance_variable_defined?(:@last_wall_time)
|
|
86
|
+
@last_wall_time
|
|
87
|
+
else
|
|
88
|
+
current_wall_time
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
wall_time_interval_ns = ((current_wall_time - last_wall_time).round(9) * 1e9).to_i
|
|
92
|
+
@last_wall_time = current_wall_time
|
|
93
|
+
|
|
94
|
+
# Collect backtraces from each thread
|
|
95
|
+
thread_api.list.each do |thread|
|
|
96
|
+
next unless thread.alive?
|
|
97
|
+
next if ignore_thread.is_a?(Proc) && ignore_thread.call(thread)
|
|
98
|
+
|
|
99
|
+
event = collect_thread_event(thread, wall_time_interval_ns)
|
|
100
|
+
events << event unless event.nil?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Send events to recorder
|
|
104
|
+
recorder.push(events) unless events.empty?
|
|
105
|
+
|
|
106
|
+
events
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def collect_thread_event(thread, wall_time_interval_ns)
|
|
110
|
+
locations = thread.backtrace_locations
|
|
111
|
+
return if locations.nil?
|
|
112
|
+
|
|
113
|
+
# Get actual stack size then trim the stack
|
|
114
|
+
stack_size = locations.length
|
|
115
|
+
locations = locations[0..(max_frames - 1)]
|
|
116
|
+
|
|
117
|
+
# Convert backtrace locations into structs
|
|
118
|
+
locations = convert_backtrace_locations(locations)
|
|
119
|
+
|
|
120
|
+
thread_id = thread.respond_to?(:native_thread_id) ? thread.native_thread_id : thread.object_id
|
|
121
|
+
trace_id, span_id = get_trace_identifiers(thread)
|
|
122
|
+
cpu_time = get_cpu_time_interval!(thread)
|
|
123
|
+
|
|
124
|
+
Events::StackSample.new(
|
|
125
|
+
nil,
|
|
126
|
+
locations,
|
|
127
|
+
stack_size,
|
|
128
|
+
thread_id,
|
|
129
|
+
trace_id,
|
|
130
|
+
span_id,
|
|
131
|
+
cpu_time,
|
|
132
|
+
wall_time_interval_ns
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def get_cpu_time_interval!(thread)
|
|
137
|
+
# Return if we can't get the current CPU time
|
|
138
|
+
unless thread.respond_to?(:cpu_time_instrumentation_installed?) && thread.cpu_time_instrumentation_installed?
|
|
139
|
+
warn_about_missing_cpu_time_instrumentation(thread)
|
|
140
|
+
return
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
current_cpu_time_ns = thread.cpu_time(:nanosecond)
|
|
144
|
+
|
|
145
|
+
# NOTE: This can still be nil even when all of the checks above passed because of a race: there's a bit of
|
|
146
|
+
# initialization that needs to be done by the thread itself, and it's possible for us to try to sample
|
|
147
|
+
# *before* the thread had time to finish the initialization
|
|
148
|
+
return unless current_cpu_time_ns
|
|
149
|
+
|
|
150
|
+
last_cpu_time_ns = (thread[THREAD_LAST_CPU_TIME_KEY] || current_cpu_time_ns)
|
|
151
|
+
interval = current_cpu_time_ns - last_cpu_time_ns
|
|
152
|
+
|
|
153
|
+
# Update CPU time for thread
|
|
154
|
+
thread[THREAD_LAST_CPU_TIME_KEY] = current_cpu_time_ns
|
|
155
|
+
|
|
156
|
+
# Return interval
|
|
157
|
+
interval
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def get_trace_identifiers(thread)
|
|
161
|
+
return unless thread.is_a?(::Thread)
|
|
162
|
+
return unless Datadog.respond_to?(:tracer) && Datadog.tracer.respond_to?(:active_correlation)
|
|
163
|
+
|
|
164
|
+
identifier = Datadog.tracer.active_correlation(thread)
|
|
165
|
+
[identifier.trace_id, identifier.span_id]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def compute_wait_time(used_time)
|
|
169
|
+
# We took used_time to get the last sample.
|
|
170
|
+
#
|
|
171
|
+
# What we're computing here is -- if used_time corresponds to max_time_usage_pct of the time we should
|
|
172
|
+
# spend working, how much is (100% - max_time_usage_pct) of the time?
|
|
173
|
+
#
|
|
174
|
+
# For instance, if we took 10ms to sample, and max_time_usage_pct is 1%, then the other 99% is 990ms, which
|
|
175
|
+
# means we need to sleep for 990ms to guarantee that we don't spend more than 1% of the time working.
|
|
176
|
+
used_time_ns = used_time * 1e9
|
|
177
|
+
interval = (used_time_ns / (max_time_usage_pct / 100.0)) - used_time_ns
|
|
178
|
+
[interval / 1e9, MIN_INTERVAL].max
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Convert backtrace locations into structs
|
|
182
|
+
# Re-use old backtrace location objects if they already exist in the buffer
|
|
183
|
+
def convert_backtrace_locations(locations)
|
|
184
|
+
locations.collect do |location|
|
|
185
|
+
# Re-use existing BacktraceLocation if identical copy, otherwise build a new one.
|
|
186
|
+
recorder[Events::StackSample].cache(:backtrace_locations).fetch(
|
|
187
|
+
# Function name
|
|
188
|
+
location.base_label,
|
|
189
|
+
# Line number
|
|
190
|
+
location.lineno,
|
|
191
|
+
# Filename
|
|
192
|
+
location.path,
|
|
193
|
+
# Build function
|
|
194
|
+
&method(:build_backtrace_location)
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def build_backtrace_location(_id, base_label, lineno, path)
|
|
200
|
+
string_table = recorder[Events::StackSample].string_table
|
|
201
|
+
|
|
202
|
+
Profiling::BacktraceLocation.new(
|
|
203
|
+
string_table.fetch_string(base_label),
|
|
204
|
+
lineno,
|
|
205
|
+
string_table.fetch_string(path)
|
|
206
|
+
)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
def warn_about_missing_cpu_time_instrumentation(thread)
|
|
212
|
+
@warn_about_missing_cpu_time_instrumentation_only_once.run do
|
|
213
|
+
# Is the profiler thread instrumented? If it is, then we know instrumentation is available, but seems to be
|
|
214
|
+
# missing on this thread we just found.
|
|
215
|
+
#
|
|
216
|
+
# As far as we know, it can be missing due to one the following:
|
|
217
|
+
#
|
|
218
|
+
# a) The thread was started before we installed our instrumentation.
|
|
219
|
+
# In this case, the fix is to make sure ddtrace gets loaded before any other parts of the application.
|
|
220
|
+
#
|
|
221
|
+
# b) The thread was started using the Ruby native APIs (e.g. from a C extension such as ffi).
|
|
222
|
+
# We currently have no solution for this case; these threads will always be missing our CPU instrumentation.
|
|
223
|
+
#
|
|
224
|
+
# c) The thread was started with `Thread.start`/`Thread.fork` and hasn't yet enabled the instrumentation.
|
|
225
|
+
# When threads are started using these APIs, there's a small time window during which the thread has started
|
|
226
|
+
# but our code to apply the instrumentation hasn't run yet; in these cases it's just a matter of allowing
|
|
227
|
+
# it to run and our instrumentation to be applied.
|
|
228
|
+
#
|
|
229
|
+
if thread_api.current.respond_to?(:cpu_time) && thread_api.current.cpu_time
|
|
230
|
+
Datadog.logger.debug("Detected thread ('#{thread}') with missing CPU profiling instrumentation.")
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# If the profiler is started for a while, stopped and then restarted OR whenever the process forks, we need to
|
|
236
|
+
# clean up the per-thread cpu time counters we keep, so that the first sample after starting doesn't end up with:
|
|
237
|
+
#
|
|
238
|
+
# a) negative time: At least on my test docker container, and on the reliability environment, after the process
|
|
239
|
+
# forks, the clock reference changes and (old cpu time - new cpu time) can be < 0
|
|
240
|
+
#
|
|
241
|
+
# b) large amount of time: if the profiler was started, then stopped for some amount of time, and then
|
|
242
|
+
# restarted, we don't want the first sample to be "blamed" for multiple minutes of CPU time
|
|
243
|
+
#
|
|
244
|
+
# By resetting the last cpu time seen, we start with a clean slate every time we start the stack collector.
|
|
245
|
+
def reset_cpu_time_tracking
|
|
246
|
+
thread_api.list.each do |thread|
|
|
247
|
+
thread[THREAD_LAST_CPU_TIME_KEY] = nil if thread[THREAD_LAST_CPU_TIME_KEY]
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
require 'ddtrace/profiling/flush'
|
|
4
|
+
require 'ddtrace/profiling/pprof/template'
|
|
5
|
+
|
|
6
|
+
module Datadog
|
|
7
|
+
module Profiling
|
|
8
|
+
module Encoding
|
|
9
|
+
module Profile
|
|
10
|
+
# Encodes gathered data into the pprof format
|
|
11
|
+
module Protobuf
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
def encode(flush)
|
|
15
|
+
return unless flush
|
|
16
|
+
|
|
17
|
+
# Create a pprof template from the list of event types
|
|
18
|
+
event_classes = flush.event_groups.collect(&:event_class).uniq
|
|
19
|
+
template = Pprof::Template.for_event_classes(event_classes)
|
|
20
|
+
|
|
21
|
+
# Add all events to the pprof
|
|
22
|
+
flush.event_groups.each { |event_group| template.add_events!(event_group.event_class, event_group.events) }
|
|
23
|
+
|
|
24
|
+
# Build the profile and encode it
|
|
25
|
+
template.to_pprof
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'ddtrace/profiling/event'
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module Profiling
|
|
5
|
+
module Events
|
|
6
|
+
# Describes a stack profiling event
|
|
7
|
+
class Stack < Event
|
|
8
|
+
attr_reader \
|
|
9
|
+
:frames,
|
|
10
|
+
:hash,
|
|
11
|
+
:span_id,
|
|
12
|
+
:thread_id,
|
|
13
|
+
:total_frame_count,
|
|
14
|
+
:trace_id
|
|
15
|
+
|
|
16
|
+
def initialize(
|
|
17
|
+
timestamp,
|
|
18
|
+
frames,
|
|
19
|
+
total_frame_count,
|
|
20
|
+
thread_id,
|
|
21
|
+
trace_id,
|
|
22
|
+
span_id
|
|
23
|
+
)
|
|
24
|
+
super(timestamp)
|
|
25
|
+
|
|
26
|
+
@frames = frames
|
|
27
|
+
@total_frame_count = total_frame_count
|
|
28
|
+
@thread_id = thread_id
|
|
29
|
+
@trace_id = trace_id
|
|
30
|
+
@span_id = span_id
|
|
31
|
+
|
|
32
|
+
@hash = [
|
|
33
|
+
thread_id,
|
|
34
|
+
trace_id,
|
|
35
|
+
span_id,
|
|
36
|
+
[
|
|
37
|
+
frames.collect(&:hash),
|
|
38
|
+
total_frame_count
|
|
39
|
+
]
|
|
40
|
+
].hash
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Describes a stack sample
|
|
45
|
+
class StackSample < Stack
|
|
46
|
+
attr_reader \
|
|
47
|
+
:cpu_time_interval_ns,
|
|
48
|
+
:wall_time_interval_ns
|
|
49
|
+
|
|
50
|
+
def initialize(
|
|
51
|
+
timestamp,
|
|
52
|
+
frames,
|
|
53
|
+
total_frame_count,
|
|
54
|
+
thread_id,
|
|
55
|
+
trace_id,
|
|
56
|
+
span_id,
|
|
57
|
+
cpu_time_interval_ns,
|
|
58
|
+
wall_time_interval_ns
|
|
59
|
+
)
|
|
60
|
+
super(
|
|
61
|
+
timestamp,
|
|
62
|
+
frames,
|
|
63
|
+
total_frame_count,
|
|
64
|
+
thread_id,
|
|
65
|
+
trace_id,
|
|
66
|
+
span_id
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@cpu_time_interval_ns = cpu_time_interval_ns
|
|
70
|
+
@wall_time_interval_ns = wall_time_interval_ns
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Describes a stack sample with exception
|
|
75
|
+
class StackExceptionSample < Stack
|
|
76
|
+
attr_reader \
|
|
77
|
+
:exception
|
|
78
|
+
|
|
79
|
+
def initialize(
|
|
80
|
+
timestamp,
|
|
81
|
+
frames,
|
|
82
|
+
total_frame_count,
|
|
83
|
+
thread_id,
|
|
84
|
+
trace_id,
|
|
85
|
+
span_id,
|
|
86
|
+
exception
|
|
87
|
+
)
|
|
88
|
+
super(
|
|
89
|
+
timestamp,
|
|
90
|
+
frames,
|
|
91
|
+
total_frame_count,
|
|
92
|
+
thread_id,
|
|
93
|
+
trace_id,
|
|
94
|
+
span_id
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
@exception = exception
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'ddtrace/profiling/transport/io/client'
|
|
2
|
+
|
|
3
|
+
module Datadog
|
|
4
|
+
module Profiling
|
|
5
|
+
# Writes profiling data to a given transport
|
|
6
|
+
class Exporter
|
|
7
|
+
attr_reader \
|
|
8
|
+
:transport
|
|
9
|
+
|
|
10
|
+
def initialize(transport)
|
|
11
|
+
unless transport.is_a?(Profiling::Transport::Client)
|
|
12
|
+
raise ArgumentError, 'Unsupported transport for profiling exporter.'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@transport = transport
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def export(flush)
|
|
19
|
+
transport.send_profiling_flush(flush)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|