├── .ci
├── .codecov.yml
├── .exclude.yml
├── .framework.yml
├── .main_framework.yml
├── .ruby.yml
├── docker
│ └── jruby
│ │ ├── 11-jdk
│ │ └── Dockerfile
│ │ ├── 12-jdk
│ │ └── Dockerfile
│ │ ├── 13-jdk
│ │ └── Dockerfile
│ │ ├── 7-jdk
│ │ └── Dockerfile
│ │ ├── 8-jdk
│ │ └── Dockerfile
│ │ ├── README.md
│ │ ├── run.sh
│ │ └── test.sh
├── scripts
│ ├── bench.sh
│ └── install-build-system.sh
└── updatecli
│ └── values.d
│ ├── apm-data-spec.yml
│ ├── apm-gherkin.yml
│ ├── apm-json-specs.yml
│ ├── scm.yml
│ └── update-compose.yml
├── .github
├── ISSUE_TEMPLATE
│ ├── Bug_report.md
│ └── Feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── labeler-config.yml
└── workflows
│ ├── README.md
│ ├── addToProject.yml
│ ├── ci-docs.yml
│ ├── ci.yml
│ ├── docs-build.yml
│ ├── docs-cleanup.yml
│ ├── github-commands-comment.yml
│ ├── labeler.yml
│ ├── microbenchmark.yml
│ ├── release.yml
│ ├── run-matrix.yml
│ ├── test-reporter.yml
│ └── updatecli.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .rspec
├── .rubocop.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── SECURITY.md
├── bench
├── .gitignore
├── app.rb
├── benchmark.rb
├── report.rb
├── rubyprof.rb
├── sql.rb
├── stackprof.rb
└── tmp
│ └── .gitkeep
├── bin
├── build_docs
├── console
├── dev
├── run-bdd
├── run-tests
├── setup
└── with_framework
├── docker-compose.yml
├── docs
├── docset.yml
├── reference
│ ├── advanced-topics.md
│ ├── api-reference.md
│ ├── configuration.md
│ ├── context.md
│ ├── custom-instrumentation.md
│ ├── getting-started-rack.md
│ ├── getting-started-rails.md
│ ├── graphql.md
│ ├── images
│ │ └── dynamic-config.svg
│ ├── index.md
│ ├── logs.md
│ ├── metrics.md
│ ├── opentracing-api.md
│ ├── performance-tuning.md
│ ├── set-up-apm-ruby-agent.md
│ ├── supported-technologies.md
│ ├── toc.yml
│ └── upgrading.md
└── release-notes
│ ├── index.md
│ ├── known-issues.md
│ └── toc.yml
├── elastic-apm.gemspec
├── features
├── api_key.feature
├── azure_app_service_metadata.feature
├── azure_functions_metadata.feature
├── otel_bridge.feature
├── outcome.feature
├── step_definitions
│ ├── api_key_steps.rb
│ ├── common_steps.rb
│ └── outcome_steps.rb
├── support
│ └── env.rb
└── user_agent.feature
├── lib
├── elastic-apm.rb
├── elastic_apm.rb
└── elastic_apm
│ ├── agent.rb
│ ├── central_config.rb
│ ├── central_config
│ └── cache_control.rb
│ ├── child_durations.rb
│ ├── config.rb
│ ├── config
│ ├── bytes.rb
│ ├── duration.rb
│ ├── log_level_map.rb
│ ├── options.rb
│ ├── regexp_list.rb
│ ├── round_float.rb
│ ├── round_float_hash_value.rb
│ ├── server_info.rb
│ └── wildcard_pattern_list.rb
│ ├── context.rb
│ ├── context
│ ├── request.rb
│ ├── request
│ │ ├── socket.rb
│ │ └── url.rb
│ ├── response.rb
│ └── user.rb
│ ├── context_builder.rb
│ ├── deprecations.rb
│ ├── error.rb
│ ├── error
│ ├── exception.rb
│ └── log.rb
│ ├── error_builder.rb
│ ├── fields.rb
│ ├── grape.rb
│ ├── graphql.rb
│ ├── grpc.rb
│ ├── instrumenter.rb
│ ├── internal_error.rb
│ ├── logging.rb
│ ├── metadata.rb
│ ├── metadata
│ ├── cloud_info.rb
│ ├── process_info.rb
│ ├── service_info.rb
│ ├── system_info.rb
│ └── system_info
│ │ └── container_info.rb
│ ├── metrics.rb
│ ├── metrics
│ ├── breakdown_set.rb
│ ├── cpu_mem_set.rb
│ ├── jvm_set.rb
│ ├── metric.rb
│ ├── set.rb
│ ├── span_scoped_set.rb
│ ├── transaction_set.rb
│ └── vm_set.rb
│ ├── metricset.rb
│ ├── middleware.rb
│ ├── naively_hashable.rb
│ ├── normalizers.rb
│ ├── normalizers
│ ├── grape.rb
│ ├── grape
│ │ └── endpoint_run.rb
│ ├── rails.rb
│ └── rails
│ │ ├── action_controller.rb
│ │ ├── action_mailer.rb
│ │ ├── action_view.rb
│ │ └── active_record.rb
│ ├── opentracing.rb
│ ├── rails.rb
│ ├── railtie.rb
│ ├── resque.rb
│ ├── sinatra.rb
│ ├── span.rb
│ ├── span
│ ├── context.rb
│ └── context
│ │ ├── db.rb
│ │ ├── destination.rb
│ │ ├── http.rb
│ │ ├── links.rb
│ │ ├── message.rb
│ │ └── service.rb
│ ├── span_helpers.rb
│ ├── spies.rb
│ ├── spies
│ ├── action_dispatch.rb
│ ├── azure_storage_table.rb
│ ├── delayed_job.rb
│ ├── dynamo_db.rb
│ ├── elasticsearch.rb
│ ├── faraday.rb
│ ├── http.rb
│ ├── json.rb
│ ├── mongo.rb
│ ├── net_http.rb
│ ├── racecar.rb
│ ├── rake.rb
│ ├── redis.rb
│ ├── resque.rb
│ ├── s3.rb
│ ├── sequel.rb
│ ├── shoryuken.rb
│ ├── sidekiq.rb
│ ├── sinatra.rb
│ ├── sneakers.rb
│ ├── sns.rb
│ ├── sqs.rb
│ ├── sucker_punch.rb
│ └── tilt.rb
│ ├── sql
│ ├── signature.rb
│ ├── tokenizer.rb
│ └── tokens.rb
│ ├── stacktrace.rb
│ ├── stacktrace
│ └── frame.rb
│ ├── stacktrace_builder.rb
│ ├── subscriber.rb
│ ├── trace_context.rb
│ ├── trace_context
│ ├── traceparent.rb
│ └── tracestate.rb
│ ├── transaction.rb
│ ├── transport
│ ├── base.rb
│ ├── connection.rb
│ ├── connection
│ │ ├── http.rb
│ │ └── proxy_pipe.rb
│ ├── filters.rb
│ ├── filters
│ │ ├── hash_sanitizer.rb
│ │ └── secrets_filter.rb
│ ├── headers.rb
│ ├── serializers.rb
│ ├── serializers
│ │ ├── context_serializer.rb
│ │ ├── error_serializer.rb
│ │ ├── metadata_serializer.rb
│ │ ├── metricset_serializer.rb
│ │ ├── span_serializer.rb
│ │ └── transaction_serializer.rb
│ ├── user_agent.rb
│ └── worker.rb
│ ├── util.rb
│ ├── util
│ ├── deep_dup.rb
│ ├── inflector.rb
│ ├── lru_cache.rb
│ ├── precision_validator.rb
│ └── throttle.rb
│ └── version.rb
├── spec
├── Dockerfile
├── build
│ ├── entrypoint.sh
│ ├── run-bdd.sh
│ ├── run-bench.sh
│ ├── run-tests.sh
│ └── update.sh
├── elastic_apm
│ ├── agent_spec.rb
│ ├── apm_spec.rb
│ ├── central_config
│ │ └── cache_control_spec.rb
│ ├── central_config_spec.rb
│ ├── config
│ │ ├── log_level_map_spec.rb
│ │ ├── server_info_spec.rb
│ │ └── wildcard_pattern_list_spec.rb
│ ├── config_spec.rb
│ ├── context
│ │ ├── request
│ │ │ ├── socket_spec.rb
│ │ │ └── url_spec.rb
│ │ ├── response_spec.rb
│ │ └── user_spec.rb
│ ├── context_builder_spec.rb
│ ├── context_spec.rb
│ ├── error
│ │ ├── exception_spec.rb
│ │ └── log_spec.rb
│ ├── error_builder_spec.rb
│ ├── error_spec.rb
│ ├── fields_spec.rb
│ ├── grape_spec.rb
│ ├── grpc_spec.rb
│ ├── instrumenter_spec.rb
│ ├── logging_spec.rb
│ ├── metadata
│ │ ├── cloud_info_spec.rb
│ │ ├── process_info_spec.rb
│ │ ├── service_info_spec.rb
│ │ ├── system_info
│ │ │ └── container_info_spec.rb
│ │ └── system_info_spec.rb
│ ├── metadata_spec.rb
│ ├── metrics
│ │ ├── cpu_mem_set_spec.rb
│ │ ├── jvm_set_spec.rb
│ │ ├── metric_spec.rb
│ │ ├── set_spec.rb
│ │ ├── span_scoped_set_spec.rb
│ │ └── vm_set_spec.rb
│ ├── metrics_spec.rb
│ ├── metricset_spec.rb
│ ├── middleware_spec.rb
│ ├── naively_hashable_spec.rb
│ ├── normalizers
│ │ ├── action_controller_spec.rb
│ │ ├── action_view_spec.rb
│ │ └── active_record_spec.rb
│ ├── normalizers_spec.rb
│ ├── rails_spec.rb
│ ├── sinatra_spec.rb
│ ├── span
│ │ ├── context
│ │ │ ├── destination_spec.rb
│ │ │ └── service_spec.rb
│ │ └── context_spec.rb
│ ├── span_helpers_spec.rb
│ ├── span_spec.rb
│ ├── spies
│ │ ├── azure_storage_table_spec.rb
│ │ ├── delayed_job_spec.rb
│ │ ├── dynamo_db_spec.rb
│ │ ├── elasticsearch_spec.rb
│ │ ├── faraday_spec.rb
│ │ ├── http_spec.rb
│ │ ├── mongo_spec.rb
│ │ ├── net_http_spec.rb
│ │ ├── racecar_spec.rb
│ │ ├── rake_spec.rb
│ │ ├── redis_spec.rb
│ │ ├── resque_spec.rb
│ │ ├── s3_spec.rb
│ │ ├── sequel_spec.rb
│ │ ├── shoryuken_spec.rb
│ │ ├── sidekiq_spec.rb
│ │ ├── sinatra_spec.rb
│ │ ├── sneakers_spec.rb
│ │ ├── sns_spec.rb
│ │ ├── sqs_spec.rb
│ │ ├── sucker_punch_spec.rb
│ │ └── tilt_spec.rb
│ ├── sql
│ │ ├── signature_spec.rb
│ │ └── tokenizer_spec.rb
│ ├── stacktrace_builder_spec.rb
│ ├── subscriber_spec.rb
│ ├── trace_context
│ │ ├── traceparent_spec.rb
│ │ └── tracestate_spec.rb
│ ├── trace_context_spec.rb
│ ├── transaction_spec.rb
│ ├── transport
│ │ ├── base_spec.rb
│ │ ├── connection
│ │ │ ├── http_spec.rb
│ │ │ └── proxy_pipe_spec.rb
│ │ ├── connection_spec.rb
│ │ ├── filters
│ │ │ ├── hash_sanitizer_spec.rb
│ │ │ └── secrets_filter_spec.rb
│ │ ├── filters_spec.rb
│ │ ├── headers_spec.rb
│ │ ├── serializers
│ │ │ ├── context_serializer_spec.rb
│ │ │ ├── error_serializer_spec.rb
│ │ │ ├── metadata_serializer_spec.rb
│ │ │ ├── metricset_serializer_spec.rb
│ │ │ ├── span_serializer_spec.rb
│ │ │ └── transaction_serializer_spec.rb
│ │ ├── serializers_spec.rb
│ │ ├── user_agent_spec.rb
│ │ └── worker_spec.rb
│ ├── util
│ │ ├── deep_dup_spec.rb
│ │ ├── lru_cache_spec.rb
│ │ ├── precision_validator_spec.rb
│ │ └── throttle_spec.rb
│ └── util_spec.rb
├── elastic_apm_spec.rb
├── entrypoint.sh
├── fixtures
│ ├── container_metadata_discovery.json
│ ├── elastic_apm.yml
│ ├── elastic_apm_erb.yml
│ ├── error.json
│ ├── log.json
│ ├── metadata.json
│ ├── metricset.json
│ ├── proc_meminfo
│ ├── proc_meminfo_wheezy
│ ├── proc_self_stat
│ ├── proc_stat_debian
│ ├── proc_stat_rhel
│ ├── service_resource_inference.json
│ ├── span.json
│ ├── span_types.json
│ ├── sql_signature_examples.json
│ ├── sql_token_examples.json
│ ├── transaction.json
│ ├── unknown_option.yml
│ ├── w3c_distributed_tracing.json
│ └── wildcard_matcher_tests.json
├── integration
│ ├── grape_spec.rb
│ ├── graphql_spec.rb
│ ├── json_spy_spec.rb
│ ├── mongo_spec.rb
│ ├── opentracing_spec.rb
│ ├── rails_console_spec.rb
│ ├── rails_grape_spec.rb
│ ├── rails_logger_ecs_spec.rb
│ ├── rails_logger_spec.rb
│ ├── rails_metrics_stress_spec.rb
│ ├── rails_paths_spec.rb
│ ├── rails_spec.rb
│ ├── sinatra_spec.rb
│ └── skip_require_patch_spec.rb
├── integration_helper.rb
├── scripts
│ ├── benchmarks.sh
│ ├── coverage_converge.sh
│ ├── coverage_entrypoint.sh
│ ├── features.sh
│ └── spec.sh
├── spec_helper.rb
└── support
│ ├── delegate_matcher.rb
│ ├── event_collector.rb
│ ├── exception_helpers.rb
│ ├── helloworld_pb.rb
│ ├── helloworld_services_pb.rb
│ ├── intercept.rb
│ ├── match_json_schema_matcher.rb
│ ├── mock_intake.rb
│ ├── mock_time.rb
│ ├── platform_helpers.rb
│ ├── rails_test_helpers.rb
│ ├── with_agent.rb
│ └── with_env.rb
└── updatecli-compose.yaml
/.ci/.codecov.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Tuple of ruby version and frameworks which are in charge to send data to codecov.
3 | # # is the separator between the ruby version and the framework.
4 | ENABLED:
5 | - ruby:2.7#rails-6.1
6 |
--------------------------------------------------------------------------------
/.ci/.framework.yml:
--------------------------------------------------------------------------------
1 | FRAMEWORK:
2 | - rails-7.2
3 | - rails-6.1
4 | - rails-5.2
5 | - rails-4.2
6 |
7 | - sinatra-2.2
8 | - sinatra-1.4
9 |
10 | - grape-1.6
11 |
--------------------------------------------------------------------------------
/.ci/.main_framework.yml:
--------------------------------------------------------------------------------
1 | FRAMEWORK:
2 | #- rails-main
3 | - sinatra-main
4 | - grape-master
5 |
--------------------------------------------------------------------------------
/.ci/.ruby.yml:
--------------------------------------------------------------------------------
1 | VERSION:
2 | - ruby:3.4
3 | - ruby:3.1
4 | - ruby:2.7
5 | - ruby:2.6
6 | - ruby:2.4
7 | - jruby:9.2
8 | - elasticobservability/jruby:9.2-13-jdk
9 | - elasticobservability/jruby:9.2-11-jdk
10 | - elasticobservability/jruby:9.2-8-jdk
11 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/11-jdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:11-jdk
2 |
3 | RUN apt-get update \
4 | && apt-get install -y libc6-dev --no-install-recommends \
5 | && apt-get install -y gcc \
6 | && rm -rf /var/lib/apt/lists/*
7 |
8 | ENV JRUBY_VERSION 9.2.16.0
9 |
10 | RUN mkdir -p /opt/jruby \
11 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz.sha256 -o /tmp/jruby.sha256 \
12 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz -o /tmp/jruby.tar.gz \
13 | && echo "$(cat /tmp/jruby.sha256) */tmp/jruby.tar.gz" | sha256sum -c - \
14 | && tar -zx --strip-components=1 -f /tmp/jruby.tar.gz -C /opt/jruby \
15 | && update-alternatives --install /usr/local/bin/ruby ruby /opt/jruby/bin/jruby 1
16 |
17 | # set the jruby binaries in the path
18 | ENV PATH /opt/jruby/bin:$PATH
19 |
20 | # skip installing gem documentation
21 | RUN mkdir -p /opt/jruby/etc \
22 | && { \
23 | echo 'install: --no-document'; \
24 | echo 'update: --no-document'; \
25 | } >> /opt/jruby/etc/gemrc
26 |
27 | # install bundler, gem requires bash to work
28 | # https://github.com/rubygems/rubygems/issues/2534#issuecomment-448843746
29 | RUN gem update --system --conservative || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems) \
30 | && gem install bundler:2.3.26 rake net-telnet xmlrpc tzinfo-data
31 |
32 | # install things globally, for great justice
33 | # and don't create ".bundle" in all our apps
34 | ENV GEM_HOME /usr/local/bundle
35 | ENV BUNDLE_PATH="$GEM_HOME" \
36 | BUNDLE_BIN="$GEM_HOME/bin" \
37 | BUNDLE_SILENCE_ROOT_WARNING=1 \
38 | BUNDLE_APP_CONFIG="$GEM_HOME"
39 | ENV PATH $BUNDLE_BIN:$PATH
40 | RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
41 | && chmod 777 "$GEM_HOME" "$BUNDLE_BIN"
42 |
43 | RUN useradd -rm -d /home/jruby -u 1001 jruby
44 | USER jruby
45 | WORKDIR /home/jruby
46 | CMD [ "irb" ]
47 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/12-jdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk:12-jdk-openj9
2 |
3 | RUN apt-get update \
4 | && apt-get install -y libc6-dev git tcc netbase --no-install-recommends \
5 | && apt-get install -y gcc \
6 | && rm -rf /var/lib/apt/lists/*
7 |
8 | ENV JRUBY_VERSION 9.3.1.0
9 |
10 | RUN mkdir -p /opt/jruby \
11 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz.sha256 -o /tmp/jruby.sha256 \
12 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz -o /tmp/jruby.tar.gz \
13 | && echo "$(cat /tmp/jruby.sha256) */tmp/jruby.tar.gz" | sha256sum -c - \
14 | && tar -zx --strip-components=1 -f /tmp/jruby.tar.gz -C /opt/jruby \
15 | && update-alternatives --install /usr/local/bin/ruby ruby /opt/jruby/bin/jruby 1
16 |
17 | # set the jruby binaries in the path
18 | ENV PATH /opt/jruby/bin:$PATH
19 |
20 | # skip installing gem documentation
21 | RUN mkdir -p /opt/jruby/etc \
22 | && { \
23 | echo 'install: --no-document'; \
24 | echo 'update: --no-document'; \
25 | } >> /opt/jruby/etc/gemrc
26 |
27 | # install bundler, gem requires bash to work
28 | RUN gem install bundler rake net-telnet xmlrpc tzinfo-data
29 |
30 | # install things globally, for great justice
31 | # and don't create ".bundle" in all our apps
32 | ENV GEM_HOME /usr/local/bundle
33 | ENV BUNDLE_PATH="$GEM_HOME" \
34 | BUNDLE_BIN="$GEM_HOME/bin" \
35 | BUNDLE_SILENCE_ROOT_WARNING=1 \
36 | BUNDLE_APP_CONFIG="$GEM_HOME"
37 | ENV PATH $BUNDLE_BIN:$PATH
38 | RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
39 | && chmod 777 "$GEM_HOME" "$BUNDLE_BIN"
40 |
41 | RUN useradd -rm -d /home/jruby -u 1001 jruby
42 | USER jruby
43 | WORKDIR /home/jruby
44 | CMD [ "irb" ]
45 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/13-jdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:13-jdk-slim
2 |
3 | RUN apt-get update \
4 | && apt-get install -y libc6-dev git tcc curl netbase --no-install-recommends \
5 | && apt-get install -y gcc \
6 | && rm -rf /var/lib/apt/lists/*
7 |
8 | ENV JRUBY_VERSION 9.3.1.0
9 |
10 | RUN mkdir -p /opt/jruby \
11 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz.sha256 -o /tmp/jruby.sha256 \
12 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz -o /tmp/jruby.tar.gz \
13 | && echo "$(cat /tmp/jruby.sha256) */tmp/jruby.tar.gz" | sha256sum -c - \
14 | && tar -zx --strip-components=1 -f /tmp/jruby.tar.gz -C /opt/jruby \
15 | && update-alternatives --install /usr/local/bin/ruby ruby /opt/jruby/bin/jruby 1
16 |
17 | # set the jruby binaries in the path
18 | ENV PATH /opt/jruby/bin:$PATH
19 |
20 | # skip installing gem documentation
21 | RUN mkdir -p /opt/jruby/etc \
22 | && { \
23 | echo 'install: --no-document'; \
24 | echo 'update: --no-document'; \
25 | } >> /opt/jruby/etc/gemrc
26 |
27 | # install bundler, gem requires bash to work
28 | RUN gem install bundler rake net-telnet xmlrpc tzinfo-data
29 |
30 | # install things globally, for great justice
31 | # and don't create ".bundle" in all our apps
32 | ENV GEM_HOME /usr/local/bundle
33 | ENV BUNDLE_PATH="$GEM_HOME" \
34 | BUNDLE_BIN="$GEM_HOME/bin" \
35 | BUNDLE_SILENCE_ROOT_WARNING=1 \
36 | BUNDLE_APP_CONFIG="$GEM_HOME"
37 | ENV PATH $BUNDLE_BIN:$PATH
38 | RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
39 | && chmod 777 "$GEM_HOME" "$BUNDLE_BIN"
40 |
41 | RUN useradd -rm -d /home/jruby -u 1001 jruby
42 | USER jruby
43 | WORKDIR /home/jruby
44 | CMD [ "irb" ]
45 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/7-jdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:7-jdk
2 |
3 | RUN apt-get update \
4 | && apt-get install -y libc6-dev --no-install-recommends \
5 | && apt-get install --force-yes -y gcc \
6 | && rm -rf /var/lib/apt/lists/*
7 |
8 | ENV JRUBY_VERSION 9.3.1.0
9 |
10 | RUN mkdir -p /opt/jruby \
11 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz.sha256 -o /tmp/jruby.sha256 \
12 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz -o /tmp/jruby.tar.gz \
13 | && echo "$(cat /tmp/jruby.sha256) */tmp/jruby.tar.gz" | sha256sum -c - \
14 | && tar -zx --strip-components=1 -f /tmp/jruby.tar.gz -C /opt/jruby \
15 | && update-alternatives --install /usr/local/bin/ruby ruby /opt/jruby/bin/jruby 1
16 |
17 | # set the jruby binaries in the path
18 | ENV PATH /opt/jruby/bin:$PATH
19 |
20 | # skip installing gem documentation
21 | RUN mkdir -p /opt/jruby/etc \
22 | && { \
23 | echo 'install: --no-document'; \
24 | echo 'update: --no-document'; \
25 | } >> /opt/jruby/etc/gemrc
26 |
27 | # install bundler, gem requires bash to work
28 | RUN gem install bundler rake net-telnet xmlrpc tzinfo-data
29 |
30 | # install things globally, for great justice
31 | # and don't create ".bundle" in all our apps
32 | ENV GEM_HOME /usr/local/bundle
33 | ENV BUNDLE_PATH="$GEM_HOME" \
34 | BUNDLE_BIN="$GEM_HOME/bin" \
35 | BUNDLE_SILENCE_ROOT_WARNING=1 \
36 | BUNDLE_APP_CONFIG="$GEM_HOME"
37 | ENV PATH $BUNDLE_BIN:$PATH
38 | RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
39 | && chmod 777 "$GEM_HOME" "$BUNDLE_BIN"
40 |
41 | RUN useradd -rm -d /home/jruby -u 1001 jruby
42 | USER jruby
43 | WORKDIR /home/jruby
44 | CMD [ "irb" ]
45 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/8-jdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk
2 |
3 | RUN apt-get update \
4 | && apt-get install -y libc6-dev --no-install-recommends \
5 | && apt-get install -y gcc \
6 | && rm -rf /var/lib/apt/lists/*
7 |
8 | ENV JRUBY_VERSION 9.2.14.0
9 |
10 | RUN mkdir -p /opt/jruby \
11 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz.sha256 -o /tmp/jruby.sha256 \
12 | && curl -fSL https://repo1.maven.org/maven2/org/jruby/jruby-dist/${JRUBY_VERSION}/jruby-dist-${JRUBY_VERSION}-bin.tar.gz -o /tmp/jruby.tar.gz \
13 | && echo "$(cat /tmp/jruby.sha256) */tmp/jruby.tar.gz" | sha256sum -c - \
14 | && tar -zx --strip-components=1 -f /tmp/jruby.tar.gz -C /opt/jruby \
15 | && update-alternatives --install /usr/local/bin/ruby ruby /opt/jruby/bin/jruby 1
16 |
17 | # set the jruby binaries in the path
18 | ENV PATH /opt/jruby/bin:$PATH
19 |
20 | # skip installing gem documentation
21 | RUN mkdir -p /opt/jruby/etc \
22 | && { \
23 | echo 'install: --no-document'; \
24 | echo 'update: --no-document'; \
25 | } >> /opt/jruby/etc/gemrc
26 |
27 | # install bundler, gem requires bash to work
28 | # https://github.com/rubygems/rubygems/issues/2534#issuecomment-448843746
29 | RUN gem update --system --conservative || (gem i "rubygems-update:~>2.7" --no-document && update_rubygems) \
30 | && gem install bundler:2.3.26 rake net-telnet xmlrpc tzinfo-data
31 |
32 | # install things globally, for great justice
33 | # and don't create ".bundle" in all our apps
34 | ENV GEM_HOME /usr/local/bundle
35 | ENV BUNDLE_PATH="$GEM_HOME" \
36 | BUNDLE_BIN="$GEM_HOME/bin" \
37 | BUNDLE_SILENCE_ROOT_WARNING=1 \
38 | BUNDLE_APP_CONFIG="$GEM_HOME"
39 | ENV PATH $BUNDLE_BIN:$PATH
40 | RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
41 | && chmod 777 "$GEM_HOME" "$BUNDLE_BIN"
42 |
43 | RUN useradd -rm -d /home/jruby -u 1001 jruby
44 | USER jruby
45 | WORKDIR /home/jruby
46 | CMD [ "irb" ]
47 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/README.md:
--------------------------------------------------------------------------------
1 | # JRuby docker images
2 |
3 | Builds jruby docker images.
4 |
5 | ## Build
6 |
7 | To build the images run
8 |
9 | ```bash
10 | ./run.sh --action build
11 | ```
12 |
13 | You can set your own docker registry with the flag `--registry x.y.z/org`
14 |
15 | You can exclude what images can be built with the flag `--exclude jdk-7`. Multiple usages of `--exclude` are accepted.
16 |
17 | ## Test
18 |
19 | To test the images run
20 |
21 | ```bash
22 | ./run.sh --action test
23 | ```
24 |
25 | ## Push
26 |
27 | To push the images run
28 |
29 | ```bash
30 | ./run.sh --action push
31 | ```
32 |
--------------------------------------------------------------------------------
/.ci/docker/jruby/test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | image=${1?image is required}
3 | version=${2}
4 |
5 | printf '\tTest %-30s %s\n' ${image}
6 |
7 | if [ -n "$version" ] ; then
8 | test_name="Test java -version '$version'"
9 | docker run -t --rm $image java -version | grep -q "openjdk version \"$version\|1.$version"
10 | TEST_JAVA_VERSION_RESULT=$?
11 | if [[ $TEST_JAVA_VERSION_RESULT -eq 0 ]]; then
12 | printf '\t\t%-40s %s\n' "${test_name}" "PASSED"
13 | else
14 | printf '\t\t%-40s %s\n' "${test_name}" "FAILED"
15 | fi
16 | fi
17 |
18 | test_name="Test Hello World"
19 | # random operation to verify that ruby evaluates the passed string correctly
20 | docker run -t --rm $image jruby -e "foo = 3 * 4; puts foo" | grep -q '12'
21 | TEST_HELLO_WORLD_RESULT=$?
22 | if [[ $TEST_HELLO_WORLD_RESULT -eq 0 ]]; then
23 | printf '\t\t%-40s %s\n' "${test_name}" "PASSED"
24 | else
25 | printf '\t\t%-40s %s\n' "${test_name}" "FAILED"
26 | fi
27 |
28 | ! (( $TEST_JAVA_VERSION_RESULT || $TEST_HELLO_WORLD_RESULT ))
29 |
--------------------------------------------------------------------------------
/.ci/scripts/bench.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Bash strict mode
4 | set -eo pipefail
5 |
6 | # Found current script directory
7 | RELATIVE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
8 |
9 | # Found project directory
10 | BASE_PROJECT="$(dirname "$(dirname "${RELATIVE_DIR}")")"
11 |
12 | ## Buildkite specific configuration
13 | if [ "$CI" == "true" ] ; then
14 | # If HOME is not set then use the Buildkite workspace
15 | # that's normally happening when running in the CI
16 | # owned by Elastic.
17 | if [ -z "$HOME" ] ; then
18 | HOME=$BUILDKITE_BUILD_CHECKOUT_PATH
19 | export HOME
20 | fi
21 |
22 | # required when running the benchmark
23 | PATH=$PATH:$HOME/.local/bin
24 | export PATH
25 |
26 | echo 'Docker login is done in the Buildkite hooks'
27 | fi
28 |
29 | # It does not fail so it runs for every single version and then we report the error at the end.
30 | set +e
31 | status=0
32 |
33 | for VERSION in "ruby:3.1" "ruby:3.0" "ruby:2.7" "ruby:2.6" "jruby:9.2" ; do
34 | ## Transform the versions like:
35 | ## jruby:9.1 to jruby-9.1
36 | echo "--- Benchmark for :ruby: ${VERSION}"
37 | OUTPUT_NAME=benchmark-$(echo "${VERSION//:/-}")
38 |
39 | # TBC, maybe a timeout could help so it can run the other versions?
40 | ${BASE_PROJECT}/spec/scripts/benchmarks.sh "${VERSION}" "${OUTPUT_NAME}"
41 |
42 | # Gather error if any
43 | if [ $? -gt 0 ] ; then
44 | status=1
45 | fi
46 |
47 | # Then we ship the data using the helper
48 | sendBenchmark "${ES_USER_SECRET}" "${ES_PASS_SECRET}" "${ES_URL_SECRET}" "${BASE_PROJECT}/spec/${OUTPUT_NAME}.bulk"
49 | done
50 |
51 | # Report status
52 | exit $status
53 |
--------------------------------------------------------------------------------
/.ci/scripts/install-build-system.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euxo pipefail
4 |
5 | gem install rake yard rspec
6 |
--------------------------------------------------------------------------------
/.ci/updatecli/values.d/apm-data-spec.yml:
--------------------------------------------------------------------------------
1 | apm_schema_specs_path: spec/fixtures
2 |
--------------------------------------------------------------------------------
/.ci/updatecli/values.d/apm-gherkin.yml:
--------------------------------------------------------------------------------
1 | apm_gherkin_specs_path: features
--------------------------------------------------------------------------------
/.ci/updatecli/values.d/apm-json-specs.yml:
--------------------------------------------------------------------------------
1 | apm_json_specs_path: spec/fixtures
2 |
--------------------------------------------------------------------------------
/.ci/updatecli/values.d/scm.yml:
--------------------------------------------------------------------------------
1 | scm:
2 | enabled: true
3 | owner: elastic
4 | repository: apm-agent-ruby
5 | branch: main
6 | commitusingapi: true
7 | # begin update-compose policy values
8 | user: obltmachine
9 | email: obltmachine@users.noreply.github.com
10 | # end update-compose policy values
11 |
--------------------------------------------------------------------------------
/.ci/updatecli/values.d/update-compose.yml:
--------------------------------------------------------------------------------
1 | spec:
2 | files:
3 | - "updatecli-compose.yaml"
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | ## Describe the bug
8 |
9 | ## Steps to reproduce
10 |
16 |
17 | ## Expected behavior
18 |
19 | ## Environment
20 |
21 | - **OS**:
22 | - **Ruby version**:
23 | - **Framework and version**:
24 | - **APM Server version**:
25 | - **Agent version**:
26 |
27 |
28 | ## Additional context
29 |
30 | Add any other context about the problem here.
31 |
32 | - Agent config options
33 |
34 | Click to expand
35 |
36 | ```
37 | replace this line with your agent config options
38 | remember to mask any sensitive fields like tokens
39 | ```
40 |
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | ## Is your feature request related to a problem? Please describe.
8 |
9 |
10 | ## Describe the solution you'd like
11 |
12 |
13 | ## Describe alternatives you've considered
14 |
15 |
16 | ## Additional context
17 |
18 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: 2
3 | updates:
4 |
5 | - package-ecosystem: bundler
6 | directory: "/"
7 | schedule:
8 | interval: "weekly"
9 | day: "sunday"
10 | time: "22:00"
11 | open-pull-requests-limit: 5
12 | ignore:
13 | - dependency-name: sucker_punch
14 | versions:
15 | - "> 2.0"
16 | - dependency-name: i18n
17 | versions:
18 | - 1.8.10
19 | - 1.8.8
20 | - 1.8.9
21 |
22 | # Maintain dependencies for GitHub Actions (/.github/workflows)
23 | - package-ecosystem: "github-actions"
24 | directory: "/"
25 | schedule:
26 | interval: "weekly"
27 | day: "sunday"
28 | time: "22:00"
29 | open-pull-requests-limit: 5
30 | reviewers:
31 | - "elastic/observablt-ci"
32 | labels:
33 | - dependencies
34 | groups:
35 | github-actions:
36 | patterns:
37 | - "*"
38 |
--------------------------------------------------------------------------------
/.github/labeler-config.yml:
--------------------------------------------------------------------------------
1 | # add 'agent-ruby' label to all new issues
2 | agent-ruby:
3 | - '.*'
4 |
--------------------------------------------------------------------------------
/.github/workflows/addToProject.yml:
--------------------------------------------------------------------------------
1 | name: Auto Assign to Project(s)
2 |
3 | on:
4 | issues:
5 | types: [opened, edited, milestoned]
6 | pull_request_target:
7 | types: [opened, edited, milestoned]
8 |
9 | permissions:
10 | contents: read
11 |
12 | jobs:
13 | assign_one_project:
14 | runs-on: ubuntu-latest
15 | name: Assign milestoned to Project
16 | steps:
17 | - name: Get token
18 | id: get_token
19 | uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0
20 | with:
21 | app_id: ${{ secrets.OBS_AUTOMATION_APP_ID }}
22 | private_key: ${{ secrets.OBS_AUTOMATION_APP_PEM }}
23 | permissions: >-
24 | {
25 | "issues": "read",
26 | "organization_projects": "write",
27 | "pull_requests": "read"
28 | }
29 | - name: Assign issues with milestones to project
30 | uses: elastic/assign-one-project-github-action@1.2.2
31 | if: github.event.issue && github.event.issue.milestone
32 | with:
33 | project: 'https://github.com/orgs/elastic/projects/454'
34 | project_id: '5882982'
35 | column_name: 'Planned'
36 | env:
37 | MY_GITHUB_TOKEN: ${{ steps.get_token.outputs.token }}
38 | - name: Assign new pull requests to project
39 | uses: elastic/assign-one-project-github-action@1.2.2
40 | if: github.event.action == 'opened' && github.event.pull_request
41 | with:
42 | project: 'https://github.com/orgs/elastic/projects/454'
43 | project_id: '5882982'
44 | column_name: 'In Progress'
45 | env:
46 | MY_GITHUB_TOKEN: ${{ steps.get_token.outputs.token }}
47 |
--------------------------------------------------------------------------------
/.github/workflows/ci-docs.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # This workflow sets the test / all status check to success in case it's a docs only PR and ci.yml is not triggered
3 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks
4 | name: ci # The name must be the same as in ci.yml
5 |
6 | on:
7 | pull_request:
8 | paths-ignore: # This expression needs to match the paths ignored on ci.yml.
9 | - '**'
10 | - '!**/*.md'
11 | - '!**/*.asciidoc'
12 |
13 | permissions:
14 | contents: read
15 |
16 | jobs:
17 | all:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - run: 'echo "No build required"'
21 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | pull_request:
5 | paths-ignore:
6 | - "**/*.asciidoc"
7 | - "**/*.md"
8 | push:
9 | branches:
10 | - main
11 | paths-ignore:
12 | - "**/*.asciidoc"
13 | - "**/*.md"
14 |
15 | permissions:
16 | contents: read
17 |
18 | jobs:
19 | sanity-checks:
20 | runs-on: ubuntu-latest
21 | steps:
22 | - uses: elastic/oblt-actions/pre-commit@v1
23 |
24 | # Invokes the actual matrix workflow with the provided files.
25 | matrix:
26 | uses: ./.github/workflows/run-matrix.yml
27 | with:
28 | versionsFile: .ci/.ruby.yml
29 | frameworksFile: .ci/.framework.yml
30 | excludedFile: .ci/.exclude.yml
31 |
32 | # Invokes the actual matrix workflow with the provided files.
33 | # In this case it's for the main frameworks.
34 | matrix-main-frameworks:
35 | uses: ./.github/workflows/run-matrix.yml
36 | with:
37 | versionsFile: .ci/.ruby.yml
38 | frameworksFile: .ci/.main_framework.yml
39 | excludedFile: .ci/.exclude.yml
40 |
41 | package:
42 | runs-on: ubuntu-latest
43 | steps:
44 | - uses: actions/checkout@v4
45 | - uses: ruby/setup-ruby@v1
46 | with:
47 | ruby-version: 2.6
48 | - name: Install build system
49 | run: .ci/scripts/install-build-system.sh
50 | - name: Create gem
51 | run: rake build
52 | - uses: actions/upload-artifact@v4
53 | with:
54 | name: package
55 | path: ./pkg/**/*
56 |
57 | all:
58 | if: always()
59 | runs-on: ubuntu-latest
60 | needs:
61 | - sanity-checks
62 | - matrix
63 | - matrix-main-frameworks
64 | - package
65 | steps:
66 | - id: check
67 | uses: elastic/oblt-actions/check-dependent-jobs@v1
68 | with:
69 | jobs: ${{ toJSON(needs) }}
70 | - run: ${{ steps.check.outputs.is-success }}
71 |
--------------------------------------------------------------------------------
/.github/workflows/docs-build.yml:
--------------------------------------------------------------------------------
1 | name: docs-build
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request_target: ~
8 | merge_group: ~
9 |
10 | jobs:
11 | docs-preview:
12 | uses: elastic/docs-builder/.github/workflows/preview-build.yml@main
13 | with:
14 | path-pattern: docs/**
15 | permissions:
16 | deployments: write
17 | id-token: write
18 | contents: read
19 | pull-requests: read
20 |
--------------------------------------------------------------------------------
/.github/workflows/docs-cleanup.yml:
--------------------------------------------------------------------------------
1 | name: docs-cleanup
2 |
3 | on:
4 | pull_request_target:
5 | types:
6 | - closed
7 |
8 | jobs:
9 | docs-preview:
10 | uses: elastic/docs-builder/.github/workflows/preview-cleanup.yml@main
11 | permissions:
12 | contents: none
13 | id-token: write
14 | deployments: write
15 |
--------------------------------------------------------------------------------
/.github/workflows/github-commands-comment.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: github-commands-comment
3 |
4 | on:
5 | pull_request_target:
6 | types:
7 | - opened
8 |
9 | permissions:
10 | contents: read
11 |
12 | jobs:
13 | comment:
14 | runs-on: ubuntu-latest
15 | permissions:
16 | pull-requests: write
17 | steps:
18 | - uses: elastic/oblt-actions/elastic/github-commands@v1
19 |
--------------------------------------------------------------------------------
/.github/workflows/labeler.yml:
--------------------------------------------------------------------------------
1 | name: "Issue Labeler"
2 | on:
3 | issues:
4 | types: [opened]
5 | pull_request_target:
6 | types: [opened]
7 |
8 | permissions:
9 | contents: read
10 | issues: write
11 | pull-requests: write
12 |
13 | jobs:
14 | triage:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: AlexanderWert/issue-labeler@v2.3
18 | with:
19 | repo-token: "${{ secrets.GITHUB_TOKEN }}"
20 | configuration-path: .github/labeler-config.yml
21 | enable-versioned-regex: 0
22 |
--------------------------------------------------------------------------------
/.github/workflows/microbenchmark.yml:
--------------------------------------------------------------------------------
1 | name: microbenchmark
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - main
8 | paths-ignore:
9 | - '**.md'
10 | - '**.asciidoc'
11 |
12 | # limit the access of the generated GITHUB_TOKEN
13 | permissions:
14 | contents: read
15 |
16 | jobs:
17 | microbenchmark:
18 | runs-on: ubuntu-latest
19 | timeout-minutes: 5
20 | steps:
21 | - name: Run microbenchmark
22 | uses: elastic/oblt-actions/buildkite/run@v1
23 | with:
24 | pipeline: "apm-agent-microbenchmark"
25 | token: ${{ secrets.BUILDKITE_TOKEN }}
26 | wait-for: false
27 | env-vars: |
28 | script=.ci/scripts/bench.sh
29 | repo=apm-agent-ruby
30 | sha=${{ github.sha }}
31 | BRANCH_NAME=${{ github.ref_name }}
32 |
--------------------------------------------------------------------------------
/.github/workflows/test-reporter.yml:
--------------------------------------------------------------------------------
1 | ---
2 | ## Workflow to process the JUnit test results and add a report to the checks.
3 | name: test-reporter
4 | on:
5 | workflow_run:
6 | workflows:
7 | - ci
8 | types:
9 | - completed
10 |
11 | permissions:
12 | contents: read
13 | actions: read
14 | checks: write
15 |
16 | jobs:
17 | report:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - uses: elastic/oblt-actions/test-report@v1
21 | with:
22 | artifact: /test-results(.*)/
23 | name: 'Test Report $1'
24 | path: "**/*ruby-agent-junit.xml"
25 | reporter: java-junit
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /.yardoc
3 | /_yardoc/
4 | /coverage/
5 | /doc/
6 | /pkg/
7 | /spec/reports/
8 | /tmp/
9 |
10 | # rspec failure tracking
11 | .rspec_status
12 |
13 | Gemfile.lock
14 | /html_docs/
15 | spec/elastic_apm.log
16 | spec/junit-reports
17 | .gem
18 | *.bulk
19 | vendor/
20 |
21 | .idea/
22 | log/
23 |
24 | benchmark-*.error
25 | benchmark-*.raw
26 |
27 | .ci/docker/jruby/output.log
28 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v2.2.3
4 | hooks:
5 | - id: check-case-conflict
6 | - id: check-executables-have-shebangs
7 | - id: check-json
8 | - id: check-merge-conflict
9 | - id: check-yaml
10 | - id: check-xml
11 |
12 | - repo: https://github.com/elastic/apm-pipeline-library
13 | rev: current
14 | hooks:
15 | - id: check-bash-syntax
16 | - id: check-unicode-non-breaking-spaces
17 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --exclude-pattern spec/integration/**/*_spec.rb
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG RUBY_IMAGE
2 | FROM ${RUBY_IMAGE}
3 |
4 | ARG USER_ID_GROUP
5 | ARG FRAMEWORKS
6 | ARG VENDOR_PATH
7 | ARG BUNDLER_VERSION
8 |
9 | # For tzdata
10 | # ENV DEBIAN_FRONTEND=noninteractive
11 |
12 | RUN apt-get update -qq \
13 | && apt-get install -qq -y --no-install-recommends \
14 | build-essential libpq-dev git \
15 | && rm -rf /var/lib/apt/lists/*
16 |
17 | # Configure bundler and PATH
18 | ENV LANG=C.UTF-8
19 |
20 | ENV GEM_HOME=$VENDOR_PATH
21 | ENV BUNDLE_PATH=$GEM_HOME \
22 | BUNDLE_JOBS=4 BUNDLE_RETRY=3
23 | ENV BUNDLE_APP_CONFIG=$BUNDLE_PATH \
24 | BUNDLE_BIN=$BUNDLE_PATH/bin
25 | ENV PATH=/app/bin:$BUNDLE_BIN:$PATH
26 |
27 | ENV FRAMEWORKS $FRAMEWORKS
28 |
29 | RUN mkdir -p $VENDOR_PATH \
30 | && chown -R $USER_ID_GROUP $VENDOR_PATH
31 |
32 | USER $USER_ID_GROUP
33 |
34 | # Upgrade RubyGems and install required Bundler version
35 | RUN gem update --system && \
36 | gem install bundler:$BUNDLER_VERSION
37 |
38 | # Use unpatched, system version for more speed over less security
39 | RUN gem install nokogiri -- --use-system-libraries
40 | # Rake is required to build http-parser on some jruby images
41 | RUN gem install rake
42 |
43 | WORKDIR /app
44 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'bundler/gem_tasks'
21 |
22 | desc 'Post release action:'\
23 | 'Update `3.x` branch to be at released commit and push it to GitHub.'
24 |
25 | namespace :release do
26 | task :update_branch do
27 | `git checkout 4.x &&
28 | git rebase main &&
29 | git push origin 4.x &&
30 | git checkout main`
31 | end
32 | end
33 |
34 | require 'rspec/core/rake_task'
35 | RSpec::Core::RakeTask.new(:spec)
36 |
37 | require 'yard'
38 | YARD::Rake::YardocTask.new
39 | task docs: :yard
40 |
41 | task default: :spec
42 |
43 | namespace :coverage do
44 | desc "Collates all result sets generated by the different test runners"
45 | task :report do
46 | require 'simplecov'
47 | require 'simplecov-cobertura'
48 | SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
49 | SimpleCov.collate Dir["coverage/matrix_results/**/.resultset.json"]
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | Thanks for your interest in the security of our products.
4 | Our security policy can be found at [https://www.elastic.co/community/security](https://www.elastic.co/community/security).
5 |
6 | ## Reporting a Vulnerability
7 | Please send security vulnerability reports to security@elastic.co.
8 |
--------------------------------------------------------------------------------
/bench/.gitignore:
--------------------------------------------------------------------------------
1 | tmp/*
2 | db/*
3 |
--------------------------------------------------------------------------------
/bench/app.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5 | require 'active_record'
6 | require 'action_controller/railtie'
7 | require 'elastic-apm'
8 | require 'elastic_apm/railtie'
9 |
10 | $log = Logger.new('/tmp/bench.log')
11 |
12 | ActiveRecord::Base.logger = $log
13 |
14 | ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: '/tmp/bench.sqlite3')
15 |
16 | ActiveRecord::Schema.define do
17 | create_table :posts, force: true do |t|
18 | t.string :title
19 | t.timestamps
20 | end
21 | end
22 |
23 | class Post < ActiveRecord::Base
24 | end
25 |
26 | 10.times { |i| Post.create! title: "Post #{i}" }
27 |
28 | class ApplicationController < ActionController::Base
29 | def index
30 | render inline: '<%= Post.pluck(:title).join(", ") %>'
31 | end
32 |
33 | def favicon
34 | render nothing: true
35 | end
36 | end
37 |
38 | class App < Rails::Application
39 | config.secret_key_base = '__secret'
40 | config.logger = $log
41 | config.eager_load = false
42 |
43 | config.elastic_apm.disable_send = true
44 | config.elastic_apm.logger = $log
45 | config.elastic_apm.log_level = Logger::DEBUG
46 | end
47 |
48 | App.initialize!
49 |
50 | App.routes.draw do
51 | get '/favicon.ico', to: 'application#favicon'
52 | root to: 'application#index'
53 | end
54 |
--------------------------------------------------------------------------------
/bench/benchmark.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | ENV['RAILS_ENV'] = 'production'
5 |
6 | require 'bundler'
7 | require 'bundler/setup'
8 |
9 | require 'benchmark'
10 | include Benchmark
11 | require 'rack/test'
12 |
13 | require './bench/app'
14 |
15 | def app
16 | App
17 | end
18 |
19 | include Rack::Test::Methods
20 |
21 | def perform
22 | 10_000.times do
23 | get '/'
24 | end
25 | end
26 |
27 | bench = Benchmark.benchmark(CAPTION, 15, FORMAT) do |b|
28 | perform # warm up
29 |
30 | b.report('with agent:') { perform }
31 |
32 | ElasticAPM.stop
33 | perform # warm up
34 |
35 | b.report('without agent:') { perform }
36 | end
37 |
--------------------------------------------------------------------------------
/bench/report.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require 'time'
5 | require 'json'
6 |
7 | input = STDIN.read.split("\n")
8 |
9 | git_sha, git_msg = `git log -n 1 --pretty="format:%H|||%s"`.split('|||')
10 | git_date = `git log -n 1 --pretty="format:%ai"`
11 | platform = Gem::Platform.local
12 |
13 | def doc(payload)
14 | puts({ index: { _index: "benchmark-ruby" } }.to_json)
15 | puts(payload.to_json)
16 | end
17 |
18 | meta = {
19 | executed_at: Time.new.iso8601,
20 | 'git.commit' => git_sha,
21 | 'git.date' => (String(git_date).strip != '' && Time.parse(git_date).iso8601) || Time.now.iso8601,
22 | 'git.subject' => git_msg,
23 | hostname: `hostname`.chomp,
24 | engine: RUBY_ENGINE,
25 | arch: platform.cpu,
26 | os: platform.os,
27 | ruby_version: "#{RUBY_ENGINE == 'jruby' ? 'j' : ''}#{RUBY_VERSION}"
28 | }
29 |
30 | results =
31 | input
32 | .grep(/^with/)
33 | .map do |line|
34 | title = line.match(/^(.*):/) { |m| m[1] }
35 | user, system, total, real = line.scan(/[0-9\.]+/).map(&:to_f)
36 | meta.merge(
37 | title: title,
38 | user: user,
39 | system: system,
40 | total: total,
41 | real: real,
42 | )
43 | end
44 |
45 | results.each { |result| doc result }
46 |
47 | overhead =
48 | (results[0][:total] - results[1][:total]) *
49 | 1000 / # milliseconds
50 | 10_000 # transactions
51 |
52 | doc meta.merge(
53 | title: 'overhead',
54 | overhead: overhead
55 | )
56 |
--------------------------------------------------------------------------------
/bench/rubyprof.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require 'ruby-prof'
5 | require 'rack/test'
6 |
7 | $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
8 | require 'elastic-apm'
9 |
10 | require './bench/app'
11 | include App::Helpers
12 |
13 | def perform(app, count: 1000)
14 | app.start
15 |
16 | transactions = count.times.map do |i|
17 | ElasticAPM.transaction "Transaction##{i}",
18 | context: ElasticAPM.build_context(app.mock_env) do
19 | ElasticAPM.span('Number one') { 'ok 1' }
20 | ElasticAPM.span('Number two') { 'ok 2' }
21 | ElasticAPM.span('Number three') { 'ok 3' }
22 | end
23 | end
24 |
25 | app.stop
26 | end
27 |
28 | def do_bench(transaction_count: 1000, **config)
29 | with_app(config) do |app|
30 | profile = RubyProf::Profile.new
31 | profile.exclude_common_methods!
32 | profile.start
33 | perform(app, count: transaction_count)
34 | profile.stop
35 | printer = RubyProf::GraphHtmlPrinter.new(profile)
36 | printer.print(File.open('bench/tmp/out.html', 'w'))
37 | end
38 | end
39 |
40 | do_bench(transaction_count: 10_000)
41 |
--------------------------------------------------------------------------------
/bench/sql.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5 |
6 | require 'json'
7 | require 'benchmark'
8 | include Benchmark # rubocop:disable Style/MixinUsage
9 |
10 | require 'elastic_apm/sql_summarizer'
11 | require 'elastic_apm/sql/signature'
12 |
13 | examples =
14 | JSON
15 | .parse(File.read('../apm/tests/random_sql_query_set.json'))
16 | .map { |ex| ex['input'] }
17 |
18 | puts "#{'=' * 14} Parsing #{examples.length} examples #{'=' * 14}"
19 |
20 | summarizer = ElasticAPM::SqlSummarizer.new
21 |
22 | result_old = nil
23 | result_new = nil
24 |
25 | benchmark(CAPTION, 7, FORMAT, 'avg/ex:') do |bm|
26 | old = bm.report('old:') do
27 | result_old = examples.map { |i| summarizer.summarize(i) }
28 | end
29 | new = bm.report('new:') do
30 | result_new = examples.map { |i| ElasticAPM::Sql::Signature.parse(i) }
31 | end
32 |
33 | [(new - old) / examples.length]
34 | end
35 |
36 | pp(result_old.count { |res| res == 'SQL' })
37 | pp(result_new.count { |res| res =~ /(--|\/\*\*)/ })
38 |
39 | ## Stackprof
40 |
41 | require 'stackprof'
42 |
43 | puts 'Running stackprof'
44 | profile = StackProf.run(mode: :wall, interval: 1) do
45 | examples.each { |i| ElasticAPM::Sql::Signature.parse(i) }
46 | end
47 | puts ''
48 |
49 | StackProf::Report.new(profile).print_text
50 |
--------------------------------------------------------------------------------
/bench/stackprof.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require 'stackprof'
5 | require 'rack/test'
6 |
7 | require './bench/app'
8 |
9 | def app
10 | App
11 | end
12 |
13 | include Rack::Test::Methods
14 |
15 | puts 'Running '
16 | profile = StackProf.run(mode: :cpu) do
17 | 10_000.times do
18 | get '/'
19 | end
20 | end
21 | puts ''
22 |
23 | StackProf::Report.new(profile).print_text
24 |
--------------------------------------------------------------------------------
/bench/tmp/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elastic/apm-agent-ruby/a87a9321b9e1e7f0a3e6a96e413c593af517369f/bench/tmp/.gitkeep
--------------------------------------------------------------------------------
/bin/build_docs:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -ex
3 |
4 | # Requires elastic/docs to be checked out at ../docs
5 | ../docs/build_docs --doc docs/index.asciidoc --chunk 1
6 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require 'bundler/setup'
5 | require 'elastic_apm'
6 |
7 | # You can add fixtures and/or initialization code here to make experimenting
8 | # with your gem easier. You can also use a different console, if you like.
9 |
10 | # (If you use this, don't forget to add pry to your Gemfile!)
11 | # require "pry"
12 | # Pry.start
13 |
14 | require 'irb'
15 | IRB.start(__FILE__)
16 |
--------------------------------------------------------------------------------
/bin/dev:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require 'optparse'
5 |
6 | options = {}
7 | OptionParser.new do |opts|
8 | opts.banner = 'Usage: bin/dev [options] [command]'
9 |
10 | opts.on(
11 | '-iIMAGE', '--image=IMAGE',
12 | 'Specify Docker image (eg. ruby:latest)'
13 | ) { |val| options[:image] = val }
14 |
15 | opts.on(
16 | '-fFRAMEWORKS', '--frameworks=FRAMEWORKS',
17 | 'Specify frameworks to test (eg. rails:master,sinatra)'
18 | ) { |val| options[:frameworks] = val }
19 |
20 | opts.on(
21 | '-s', '--skip-build',
22 | 'Skip building image'
23 | ) { |val| options[:skip_build] = val }
24 | end.parse!
25 |
26 | USER_ID_GROUP = %w[u g].map { |f| `id -#{f}`.chomp }.join(':')
27 |
28 | RUBY_IMAGE = options.fetch(:image, 'ruby:latest')
29 | FRAMEWORKS = options.fetch(:frameworks, 'rails,sinatra,grape')
30 |
31 | IMAGE_PATH_SAFE = RUBY_IMAGE.tr(':', '_')
32 | IMAGE_NAME = "apm-agent-ruby:#{IMAGE_PATH_SAFE}"
33 | VENDOR_PATH = "/vendor/#{IMAGE_PATH_SAFE}"
34 |
35 | def run(cmd)
36 | "IMAGE_NAME=#{IMAGE_NAME} #{cmd}".tap do |str|
37 | puts str
38 | system str
39 | end
40 | end
41 |
42 | unless options[:skip_build]
43 | run 'docker compose build ' \
44 | " --build-arg RUBY_IMAGE=#{RUBY_IMAGE}" \
45 | " --build-arg USER_ID_GROUP=#{USER_ID_GROUP}" \
46 | " --build-arg FRAMEWORKS=#{FRAMEWORKS}" \
47 | " --build-arg VENDOR_PATH=#{VENDOR_PATH}"
48 | exit $?.exitstatus unless $?.success?
49 | end
50 |
51 | run 'docker compose run' \
52 | " -u #{USER_ID_GROUP}" \
53 | ' --rm' \
54 | " specs #{ARGV.join}"
55 |
--------------------------------------------------------------------------------
/bin/run-bdd:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | specific_feature=$1
5 |
6 | export CUCUMBER_PUBLISH_QUIET=true
7 |
8 | if [[ $specific_feature = '' ]]; then
9 | echo 'Running all features'
10 |
11 | echo "========================================"
12 | cucumber
13 | else
14 | echo "Running only $specific_feature"
15 |
16 | cucumber $specific_feature
17 | fi
18 |
--------------------------------------------------------------------------------
/bin/run-tests:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | JUNIT_PREFIX=${JUNIT_PREFIX:-""}
5 |
6 | runRspec(){
7 | local case=${1:-""}
8 | local bn=${case}
9 |
10 | if [ -n "${case}" ]; then
11 | bn="$(basename ${case} _spec.rb)/"
12 | fi
13 | # If working on an isolated environment then copy the file to
14 | # the original location
15 | TEST_REPORT_DIR=spec/junit-reports/${JUNIT_PREFIX}${bn}
16 | if [ -n "$APP_PATH" ] ; then
17 | TEST_REPORT_DIR=$APP_PATH/$TEST_REPORT_DIR
18 | mkdir -p $TEST_REPORT_DIR
19 | fi
20 | bundle exec rspec \
21 | -f progress \
22 | -r yarjuf -f JUnit -o ${TEST_REPORT_DIR}ruby-agent-junit.xml \
23 | ${case}
24 | }
25 | specific_spec=$1
26 |
27 | if [[ $specific_spec = '' ]]; then
28 | echo 'Running all specs, including integration'
29 |
30 | runRspec
31 | for i in $(find spec/integration -name '*_spec.rb')
32 | do
33 | echo "========================================"
34 | echo $i
35 | echo "========================================"
36 | runRspec "$i"
37 | done
38 | else
39 | echo "Running only $specific_spec"
40 |
41 | runRspec $specific_spec
42 | fi
43 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 | IFS=$'\n\t'
4 | set -vx
5 |
6 | bundle install
7 |
8 | # Do any other automated setup that you need to do here
9 |
--------------------------------------------------------------------------------
/bin/with_framework:
--------------------------------------------------------------------------------
1 | #!/bin/bash -x
2 | set -e
3 |
4 | framework=$1
5 |
6 | FRAMEWORK=$framework bundle update
7 | FRAMEWORK=$framework ${@:2}
8 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: '3.4'
3 |
4 | services:
5 | mongodb:
6 | image: mongo:latest
7 | volumes: ['mongodata:/data/db']
8 | ports: ['27017:27017']
9 | security_opt:
10 | - no-new-privileges
11 |
12 | specs:
13 | build:
14 | context: .
15 | args:
16 | BUNDLER_VERSION: '2.2.21'
17 | image: '$IMAGE_NAME'
18 | environment:
19 | HOME: '/tmp'
20 | MONGODB_URL: 'mongodb:27017'
21 | entrypoint:
22 | 'spec/entrypoint.sh'
23 | tty: true
24 | volumes:
25 | - .:/app:cached
26 | - ./vendor:/vendor
27 | tmpfs:
28 | - /tmp:exec,mode=1777
29 | depends_on:
30 | - mongodb
31 | user: ${USER_ID}
32 | security_opt:
33 | - no-new-privileges
34 |
35 | ruby_rspec:
36 | image: apm-agent-ruby:${RUBY_VERSION}
37 | environment:
38 | APP_PATH: /opt/app
39 | FRAMEWORK: rails
40 | LOCAL_USER_ID: ${LOCAL_USER_ID}
41 | LOCAL_GROUP_ID: ${LOCAL_GROUP_ID}
42 | MONGODB_URL: 'mongodb:27017'
43 | security_opt:
44 | - no-new-privileges
45 |
46 | volumes:
47 | vendor:
48 | mongodata:
49 |
--------------------------------------------------------------------------------
/docs/docset.yml:
--------------------------------------------------------------------------------
1 | project: 'APM Ruby agent docs'
2 | products:
3 | - id: apm-agent
4 | cross_links:
5 | - apm-agent-rum-js
6 | - docs-content
7 | - ecs-logging
8 | - ecs-logging-ruby
9 | toc:
10 | - toc: reference
11 | - toc: release-notes
12 |
--------------------------------------------------------------------------------
/docs/reference/advanced-topics.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/advanced.html
4 | ---
5 |
6 | # Advanced topics [advanced]
7 |
8 | * [Adding additional context](/reference/context.md)
9 | * [Custom instrumentation](/reference/custom-instrumentation.md)
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/reference/context.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/context.html
4 | ---
5 |
6 | # Adding additional context [context]
7 |
8 |
9 | ## Adding custom context [_adding_custom_context]
10 |
11 | You can add your own custom, nested JSON-compatible data to the current transaction using `ElasticAPM.set_custom_context(hash)` eg.:
12 |
13 | ```ruby
14 | class ThingsController < ApplicationController
15 | before_action do
16 | ElasticAPM.set_custom_context(company: current_user.company)
17 | end
18 |
19 | # ...
20 | end
21 | ```
22 |
23 |
24 | ## Adding labels [_adding_labels]
25 |
26 | Labels are special in that they are indexed in your Elasticsearch database and therefore queryable.
27 |
28 | ```ruby
29 | ElasticAPM.set_label(:company_name, 'Acme, Inc.')
30 | ```
31 |
32 | Note that `.`, `*` and `"` in keys are converted to `_`.
33 |
34 |
35 | ## Providing info about the user [_providing_info_about_the_user]
36 |
37 | You can provide ElasticAPM with info about the current user.
38 |
39 | ```ruby
40 | class ApplicationController < ActionController::Base
41 | before_action do
42 | current_user && ElasticAPM.set_user(current_user)
43 | end
44 | end
45 | ```
46 |
47 |
--------------------------------------------------------------------------------
/docs/reference/getting-started-rack.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/getting-started-rack.html
4 | ---
5 |
6 | # Getting started with Rack [getting-started-rack]
7 |
8 | Add the gem to your `Gemfile`:
9 |
10 | ```ruby
11 | gem 'elastic-apm'
12 | ```
13 |
14 | Create a file `config/elastic_apm.yml`:
15 |
16 | ```yaml
17 | server_url: http://localhost:8200
18 | secret_token: ''
19 | ```
20 |
21 | Include the middleware, start (and stop) Elastic APM when booting your app:
22 |
23 | ```ruby
24 | # config.ru
25 |
26 | app = lambda do |env|
27 | [200, {'Content-Type' => 'text/plain'}, ['ok']]
28 | end
29 |
30 | # Wraps all requests in transactions and reports exceptions
31 | use ElasticAPM::Middleware
32 |
33 | # Start an instance of the Agent
34 | ElasticAPM.start(service_name: 'NothingButRack')
35 |
36 | run app
37 |
38 | # Gracefully stop the agent when process exits.
39 | # Makes sure any pending transactions are sent.
40 | at_exit { ElasticAPM.stop }
41 | ```
42 |
43 |
44 | ## Sinatra example [getting-started-sinatra]
45 |
46 | ```ruby
47 | # Example config.ru
48 |
49 | require 'sinatra/base'
50 |
51 | class MySinatraApp < Sinatra::Base
52 | use ElasticAPM::Middleware
53 |
54 | # ...
55 | end
56 |
57 | # Takes optional ElasticAPM::Config values
58 | ElasticAPM.start(app: MySinatraApp, ...)
59 |
60 | # You can also do the following, which is equivalent to the above:
61 | # ElasticAPM::Sinatra.start(MySinatraApp, ...)
62 |
63 | run MySinatraApp
64 |
65 | at_exit { ElasticAPM.stop }
66 | ```
67 |
68 |
69 | ## Grape example [getting-started-grape]
70 |
71 | ```ruby
72 | # Example config.ru
73 |
74 | require 'grape'
75 |
76 | module Twitter
77 | class API < Grape::API
78 | use ElasticAPM::Middleware
79 |
80 | # ...
81 | end
82 | end
83 |
84 | # Start the agent and hook in your app
85 | ElasticAPM::Grape.start(Twitter::API, config)
86 |
87 | run Twitter::API
88 | ```
89 |
90 |
--------------------------------------------------------------------------------
/docs/reference/getting-started-rails.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/getting-started-rails.html
4 | ---
5 |
6 | # Getting started with Rails [getting-started-rails]
7 |
8 |
9 | ## Setup [_setup]
10 |
11 | Add the gem to your `Gemfile`:
12 |
13 | ```ruby
14 | gem 'elastic-apm'
15 | ```
16 |
17 | Create a file `config/elastic_apm.yml`:
18 |
19 | ```yaml
20 | server_url: http://localhost:8200
21 | secret_token: ''
22 | ```
23 |
24 | Or if you prefer environment variables, skip the file and set `ELASTIC_APM_SERVER_URL` and `ELASTIC_APM_SECRET_TOKEN` in your local or server environment.
25 |
26 | This automatically sets up error logging and performance tracking but of course there are knobs to turn if you’d like to. See [*Configuration*](/reference/configuration.md).
27 |
28 |
--------------------------------------------------------------------------------
/docs/reference/graphql.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/graphql.html
4 | ---
5 |
6 | # GraphQL [graphql]
7 |
8 | The agent comes with support for GraphQL based APIs.
9 |
10 | This slightly alters how transactions are named when they relate to GraphQL queries, so they are easier to tell apart and debug.
11 |
12 | To enable GraphQL support, add the included Tracer to your schema:
13 |
14 | ```ruby
15 | class MySchema < GraphQL::Schema
16 | # ...
17 |
18 | tracer ElasticAPM::GraphQL # <-- include this
19 | end
20 | ```
21 |
22 |
--------------------------------------------------------------------------------
/docs/reference/images/dynamic-config.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/reference/set-up-apm-ruby-agent.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/set-up.html
4 | ---
5 |
6 | # Set up the APM Ruby agent [set-up]
7 |
8 | To get you off the ground, we’ve prepared guides for setting up the Agent with different frameworks:
9 |
10 | * [Rails](/reference/getting-started-rails.md)
11 | * [Rack](/reference/getting-started-rack.md)
12 |
13 | For custom instrumentation, see the [*API reference*](/reference/api-reference.md).
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docs/reference/toc.yml:
--------------------------------------------------------------------------------
1 | project: 'APM Ruby agent reference'
2 | toc:
3 | - file: index.md
4 | - file: set-up-apm-ruby-agent.md
5 | children:
6 | - file: getting-started-rails.md
7 | - file: getting-started-rack.md
8 | - file: supported-technologies.md
9 | - file: configuration.md
10 | - file: advanced-topics.md
11 | children:
12 | - file: context.md
13 | - file: custom-instrumentation.md
14 | - file: api-reference.md
15 | - file: metrics.md
16 | - file: logs.md
17 | - file: opentracing-api.md
18 | - file: graphql.md
19 | # TO DO: Not available on master
20 | # - file: log-correlation.md
21 | - file: performance-tuning.md
22 | - file: upgrading.md
--------------------------------------------------------------------------------
/docs/reference/upgrading.md:
--------------------------------------------------------------------------------
1 | ---
2 | mapped_pages:
3 | - https://www.elastic.co/guide/en/apm/agent/ruby/current/upgrading.html
4 | ---
5 |
6 | # Upgrading [upgrading]
7 |
8 | Upgrades between minor versions of the agent, like from 2.1 to 2.2 are always backwards compatible. Upgrades that involve a major version bump often come with some backwards incompatible changes.
9 |
10 | Before upgrading the agent, be sure to review the:
11 |
12 | * [Agent release notes](/release-notes/index.md)
13 | * [Agent and Server compatibility chart](docs-content://solutions/observability/apps/apm-agent-compatibility.md)
14 |
15 |
16 | ## End of life dates [end-of-life-dates]
17 |
18 | We love all our products, but sometimes we must say goodbye to a release so that we can continue moving forward on future development and innovation. Our [End of life policy](https://www.elastic.co/support/eol) defines how long a given release is considered supported, as well as how long a release is considered still in active development or maintenance.
19 |
20 |
--------------------------------------------------------------------------------
/docs/release-notes/known-issues.md:
--------------------------------------------------------------------------------
1 | ---
2 | navigation_title: "Known issues"
3 |
4 | ---
5 |
6 | # Elastic APM Ruby Agent known issues [elastic-apm-ruby-agent-known-issues]
7 |
8 | Known issues are significant defects or limitations that may impact your implementation. These issues are actively being worked on and will be addressed in a future release. Review the Elastic APM Ruby Agent known issues to help you make informed decisions, such as upgrading to a new version.
9 |
10 | % Use the following template to add entries to this page.
11 |
12 | % :::{dropdown} Title of known issue
13 | % **Details**
14 | % On [Month/Day/Year], a known issue was discovered that [description of known issue].
15 |
16 | % **Workaround**
17 | % Workaround description.
18 |
19 | % **Resolved**
20 | % On [Month/Day/Year], this issue was resolved.
21 |
22 | :::
23 |
24 | _No known issues_
--------------------------------------------------------------------------------
/docs/release-notes/toc.yml:
--------------------------------------------------------------------------------
1 | toc:
2 | - file: index.md
3 | - file: known-issues.md
--------------------------------------------------------------------------------
/elastic-apm.gemspec:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | lib = File.expand_path('../lib', __FILE__)
19 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
20 | require 'elastic_apm/version'
21 |
22 | Gem::Specification.new do |spec|
23 | spec.name = 'elastic-apm'
24 | spec.version = ElasticAPM::VERSION
25 | spec.authors = ['Mikkel Malmberg', 'Emily Stolfo']
26 | spec.email = ['info@elastic.co']
27 |
28 | spec.summary = 'The official Elastic APM agent for Ruby'
29 | spec.homepage = 'https://github.com/elastic/apm-agent-ruby'
30 | spec.metadata = { 'source_code_uri' => 'https://github.com/elastic/apm-agent-ruby' }
31 | spec.license = 'Apache-2.0'
32 | spec.required_ruby_version = ">= 2.3.0"
33 |
34 | spec.files = `git ls-files -z`.split("\x0").reject do |f|
35 | f.match(%r{^(test|spec|features)/})
36 | end
37 |
38 | spec.add_dependency('concurrent-ruby', '~> 1.0')
39 | spec.add_dependency('http', '>= 3.0')
40 | spec.add_runtime_dependency('ruby2_keywords')
41 |
42 | spec.require_paths = ['lib']
43 | end
44 |
--------------------------------------------------------------------------------
/features/api_key.feature:
--------------------------------------------------------------------------------
1 | Feature: APM server authentication with API key and secret token
2 |
3 | Scenario: A configured API key is sent in the Authorization header
4 | Given an agent configured with
5 | | setting | value |
6 | | api_key | RTNxMjlXNEJt |
7 | When the agent sends a request to APM server
8 | Then the Authorization header of the request is 'ApiKey RTNxMjlXNEJt'
9 |
10 | Scenario: A configured secret token is sent in the Authorization header
11 | Given an agent configured with
12 | | setting | value |
13 | | secret_token | secr3tT0ken |
14 | When the agent sends a request to APM server
15 | Then the Authorization header of the request is 'Bearer secr3tT0ken'
16 |
17 | Scenario: A configured API key takes precedence over a secret token
18 | Given an agent configured with
19 | | setting | value |
20 | | api_key | MjlXNEJasdfDt |
21 | | secret_token | secr3tT0ken |
22 | When the agent sends a request to APM server
23 | Then the Authorization header of the request is 'ApiKey MjlXNEJasdfDt'
24 |
25 |
--------------------------------------------------------------------------------
/features/step_definitions/api_key_steps.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # @api private
4 | module Helpers
5 | def config
6 | @agent.config
7 | end
8 | end
9 |
10 | World(Helpers)
11 |
12 | When('an api key is set to {string} in the config') do |api_key|
13 | config.api_key = api_key
14 | end
15 |
16 | Then('the Authorization header is {string}') do |auth_header|
17 | headers = ElasticAPM::Transport::Headers.new(config).to_h
18 | headers[:Authorization] == auth_header
19 | end
20 |
21 | When('an api key is set in the config') do
22 | config.api_key = '123:456'
23 | end
24 |
25 | Then('the api key is sent in the Authorization header') do
26 | headers = ElasticAPM::Transport::Headers.new(config).to_h
27 | headers[:Authorization].include?(config.api_key)
28 | end
29 |
30 | When('a secret_token is set to {string} in the config') do |api_key|
31 | config.secret_token = api_key
32 | end
33 |
34 | When('an api key is not set in the config') do
35 | end
36 |
37 | Then('the secret token is sent in the Authorization header') do
38 | headers = ElasticAPM::Transport::Headers.new(config).to_h
39 | headers[:Authorization].include?(config.secret_token)
40 | end
41 |
--------------------------------------------------------------------------------
/features/step_definitions/common_steps.rb:
--------------------------------------------------------------------------------
1 | After do
2 | @agent&.stop
3 | end
4 |
5 | Given('an agent') do
6 | @agent = ElasticAPM.start
7 | end
8 |
--------------------------------------------------------------------------------
/features/support/env.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'cucumber/rspec/doubles'
4 | require 'elastic-apm'
5 |
--------------------------------------------------------------------------------
/features/user_agent.feature:
--------------------------------------------------------------------------------
1 | Feature: Agent Transport User agent Header
2 |
3 | Scenario: Default user-agent
4 | Given an agent
5 | When the agent sends a request to APM server
6 | Then the User-Agent header of the request matches regex '^apm-agent-[a-z]+/[^ ]* \(.*\)'
7 |
8 | Scenario: Default user-agent when setting invalid service
9 | Given an agent configured with
10 | | setting | value |
11 | | service_name | myService/()<>@ |
12 | When the agent sends a request to APM server
13 | Then the User-Agent header of the request matches regex '^apm-agent-[a-z]+/[^ ]* \(.*\)'
14 |
15 | Scenario: User-agent with service name only
16 | Given an agent configured with
17 | | setting | value |
18 | | service_name | myService |
19 | When the agent sends a request to APM server
20 | Then the User-Agent header of the request matches regex '^apm-agent-[a-z]+/[^ ]* \(myService\)'
21 |
22 | Scenario Outline: User-agent with service name and service version
23 | Given an agent configured with
24 | | setting | value |
25 | | service_name | |
26 | | service_version | |
27 | When the agent sends a request to APM server
28 | Then the User-Agent header of the request matches regex '^apm-agent-[a-z]+/[^ ]* \(\)'
29 | Examples:
30 | | SERVICE_NAME | ESCAPED_SERVICE_NAME | SERVICE_VERSION | ESCAPED_SERVICE_VERSION |
31 | | myService | myService | v42 | v42 |
32 | | myService | myService | 123(:\;)456 | 123_:_;_456 |
33 |
--------------------------------------------------------------------------------
/lib/elastic-apm.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | # Make bundler auto-require work
21 | require 'elastic_apm'
22 |
--------------------------------------------------------------------------------
/lib/elastic_apm/central_config/cache_control.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class CentralConfig
22 | # @api private
23 | class CacheControl
24 | def initialize(value)
25 | @header = value
26 | parse!(value)
27 | end
28 |
29 | attr_reader(
30 | :must_revalidate,
31 | :no_cache,
32 | :no_store,
33 | :no_transform,
34 | :public,
35 | :private,
36 | :proxy_revalidate,
37 | :max_age,
38 | :s_maxage
39 | )
40 |
41 | private
42 |
43 | def parse!(value)
44 | value.split(',').each do |token|
45 | k, v = token.split('=').map(&:strip)
46 | instance_variable_set(:"@#{k.tr('-', '_')}", v ? v.to_i : true)
47 | end
48 | end
49 | end
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/lib/elastic_apm/child_durations.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module ChildDurations
23 | # @api private
24 | module Methods
25 | def child_durations
26 | @child_durations ||= Durations.new
27 | end
28 |
29 | def child_started
30 | child_durations.start
31 | end
32 |
33 | def child_stopped
34 | child_durations.stop
35 | end
36 | end
37 |
38 | # @api private
39 | class Durations
40 | def initialize
41 | @nesting_level = 0
42 | @start = nil
43 | @duration = 0
44 | @mutex = Mutex.new
45 | end
46 |
47 | attr_reader :duration
48 |
49 | def start
50 | @mutex.synchronize do
51 | @nesting_level += 1
52 | @start = Util.micros if @nesting_level == 1
53 | end
54 | end
55 |
56 | def stop
57 | @mutex.synchronize do
58 | @nesting_level -= 1
59 | @duration = (Util.micros - @start) if @nesting_level == 0
60 | end
61 | end
62 | end
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/bytes.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Config
22 | # @api private
23 | class Bytes
24 | MULTIPLIERS = {
25 | 'kb' => 1024,
26 | 'mb' => 1024 * 1_000,
27 | 'gb' => 1024 * 100_000
28 | }.freeze
29 | REGEX = /^(\d+)(b|kb|mb|gb)?$/i.freeze
30 |
31 | def initialize(default_unit: 'kb')
32 | @default_unit = default_unit
33 | end
34 |
35 | def call(value)
36 | _, amount, unit = REGEX.match(String(value)).to_a
37 | unit ||= @default_unit
38 | MULTIPLIERS.fetch(unit.downcase, 1) * amount.to_i
39 | end
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/duration.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Config
22 | # @api private
23 | class Duration
24 | MULTIPLIERS = { 'ms' => 0.001, 'm' => 60 }.freeze
25 | REGEX = /^(-)?(\d+)(m|ms|s)?$/i.freeze
26 |
27 | def initialize(default_unit: 's')
28 | @default_unit = default_unit
29 | end
30 |
31 | def call(str)
32 | _, negative, amount, unit = REGEX.match(String(str)).to_a
33 | unit ||= @default_unit
34 | seconds = MULTIPLIERS.fetch(unit.downcase, 1) * amount.to_i
35 | seconds = 0 - seconds if negative
36 | seconds
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/log_level_map.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Config
22 | # @api private
23 | class LogLevelMap
24 | LEVELS = {
25 | debug: Logger::DEBUG,
26 | info: Logger::INFO,
27 | warn: Logger::WARN,
28 | error: Logger::ERROR,
29 | fatal: Logger::FATAL,
30 | trace: Logger::DEBUG,
31 | warning: Logger::WARN,
32 | critical: Logger::FATAL,
33 | off: Logger::FATAL
34 | }.freeze
35 |
36 | DEFAULT = Logger::INFO
37 |
38 | def call(value)
39 | if value.is_a?(Integer)
40 | LEVELS.value?(value) ? value : DEFAULT
41 | else
42 | LEVELS.fetch(value.to_sym, DEFAULT)
43 | end
44 | end
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/regexp_list.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Config
22 | # @api private
23 | class RegexpList
24 | def call(value)
25 | value = value.is_a?(String) ? value.split(',') : Array(value)
26 | value.map { |p| Regexp.new(p) }
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/round_float.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'elastic_apm/util/precision_validator'
21 |
22 | module ElasticAPM
23 | class Config
24 | # @api private
25 | class RoundFloat
26 | def call(value)
27 | Util::PrecisionValidator.validate(value, precision: 4, minimum: 0.0001)
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/round_float_hash_value.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Config
22 | # @api private
23 | class RoundFloatHashValue
24 | def initialize
25 | @float_converter = RoundFloat.new
26 | end
27 |
28 | def call(hash)
29 | return {} unless hash
30 |
31 | hash.transform_values { |value| @float_converter.call(value) }
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/elastic_apm/config/server_info.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Config
22 | # @api private
23 | class ServerInfo
24 | attr_reader :payload, :config, :http
25 |
26 | VERSION_8_0 = '8.0'
27 | VERSION_0 = '0'
28 |
29 | def initialize(config)
30 | @config = config
31 | @http = Transport::Connection::Http.new(config)
32 | end
33 |
34 | def execute
35 | resp = http.get(config.server_url)
36 | @payload = JSON.parse(resp.body)
37 | rescue
38 | @payload = { "version" => VERSION_0 }
39 | end
40 |
41 | def version
42 | @version ||= begin
43 | execute
44 | payload["version"] ? payload["version"].to_s : VERSION_0
45 | end
46 | end
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/lib/elastic_apm/context/request.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Context
22 | # @api private
23 | class Request
24 | attr_accessor :body, :cookies, :env, :headers, :http_version, :method,
25 | :socket, :url
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/lib/elastic_apm/context/request/socket.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | class Context
23 | # @api private
24 | class Request
25 | # @api private
26 | class Socket
27 | def initialize(req)
28 | @remote_addr = req.env['REMOTE_ADDR']
29 | end
30 |
31 | attr_reader :remote_addr
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/elastic_apm/context/request/url.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | class Context
23 | # @api private
24 | class Request
25 | # @api private
26 | class Url
27 | SKIPPED_PORTS = {
28 | 'http' => 80,
29 | 'https' => 443
30 | }.freeze
31 |
32 | def initialize(req)
33 | @protocol = req.scheme
34 | @hostname = req.host
35 | @port = req.port.to_s
36 | @pathname = req.path
37 | @search = req.query_string
38 | @hash = nil
39 | @full = build_full_url req
40 | end
41 |
42 | attr_reader :protocol, :hostname, :port, :pathname, :search, :hash,
43 | :full
44 |
45 | private
46 |
47 | def build_full_url(req)
48 | url = "#{req.scheme}://#{req.host}"
49 |
50 | if req.port != SKIPPED_PORTS[req.scheme]
51 | url += ":#{req.port}"
52 | end
53 |
54 | url + req.fullpath
55 | end
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/lib/elastic_apm/context/response.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Context
22 | # @api private
23 | class Response
24 | def initialize(
25 | status_code,
26 | headers: {},
27 | headers_sent: true,
28 | finished: true
29 | )
30 | @status_code = status_code
31 | @headers_sent = headers_sent
32 | @finished = finished
33 |
34 | self.headers = headers
35 | end
36 |
37 | attr_accessor :status_code, :headers_sent, :finished
38 | attr_reader :headers
39 |
40 | def headers=(headers)
41 | @headers = headers&.transform_values { |v| v.to_s }
42 | end
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/elastic_apm/context/user.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Context
22 | # @api private
23 | class User
24 | def initialize(id: nil, email: nil, username: nil)
25 | @id = id
26 | @email = email
27 | @username = username
28 | end
29 |
30 | def self.infer(config, record)
31 | return unless record
32 |
33 | new(
34 | id: safe_get(record, config.current_user_id_method)&.to_s,
35 | email: safe_get(record, config.current_user_email_method),
36 | username: safe_get(record, config.current_user_username_method)
37 | )
38 | end
39 |
40 | attr_accessor :id, :email, :username
41 |
42 | def empty?
43 | !id && !email && !username
44 | end
45 |
46 | def any?
47 | !empty?
48 | end
49 |
50 | class << self
51 | private
52 |
53 | def safe_get(record, method_name)
54 | record.respond_to?(method_name) ? record.send(method_name) : nil
55 | end
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/lib/elastic_apm/deprecations.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Deprecations
23 | def deprecate(name, replacement = nil)
24 | alias_name = "#{name.to_s.chomp('=')}__deprecated_"
25 | alias_name += '=' if name.to_s.end_with?('=')
26 |
27 | class_eval <<-RUBY, __FILE__, __LINE__ + 1
28 | alias :"#{alias_name}" :"#{name}"
29 |
30 | def #{name}(*args, &block)
31 | warn "[ElasticAPM] [DEPRECATED] `#{name}' is being removed. " \
32 | "#{replacement && "See `#{replacement}'."}" \
33 | "\nCalled from \#{caller.first}"
34 | send("#{alias_name}", *args, &block)
35 | end
36 | RUBY
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/elastic_apm/error.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'elastic_apm/stacktrace'
21 | require 'elastic_apm/context'
22 | require 'elastic_apm/error/exception'
23 | require 'elastic_apm/error/log'
24 |
25 | module ElasticAPM
26 | # @api private
27 | class Error
28 | def initialize(culprit: nil, context: nil)
29 | @id = SecureRandom.hex(16)
30 | @culprit = culprit
31 | @timestamp = Util.micros
32 | @context = context
33 | end
34 |
35 | attr_accessor :id, :culprit, :exception, :log, :transaction_id,
36 | :transaction_name, :transaction, :context, :parent_id, :trace_id
37 | attr_reader :timestamp
38 |
39 | def inspect
40 | "'
48 | end
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/lib/elastic_apm/error/log.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Error
22 | # @api private
23 | class Log
24 | def initialize(message, attrs = {})
25 | @message = message
26 |
27 | attrs.each do |key, val|
28 | send(:"#{key}=", val)
29 | end
30 | end
31 |
32 | attr_accessor(
33 | :level,
34 | :logger_name,
35 | :message,
36 | :param_message,
37 | :stacktrace
38 | )
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/elastic_apm/internal_error.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class InternalError < StandardError; end
22 | class ExistingTransactionError < InternalError; end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/elastic_apm/metadata.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | class Metadata
23 | def initialize(config)
24 | @service = ServiceInfo.new(config)
25 | @process = ProcessInfo.new(config)
26 | @system = SystemInfo.new(config)
27 | @labels = config.global_labels
28 | @cloud = CloudInfo.new(config).fetch!
29 | end
30 |
31 | attr_reader :service, :process, :system, :cloud, :labels
32 | end
33 | end
34 |
35 | require 'elastic_apm/metadata/service_info'
36 | require 'elastic_apm/metadata/system_info'
37 | require 'elastic_apm/metadata/process_info'
38 | require 'elastic_apm/metadata/cloud_info'
39 |
--------------------------------------------------------------------------------
/lib/elastic_apm/metadata/process_info.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Metadata
22 | # @api private
23 | class ProcessInfo
24 | def initialize(config)
25 | @config = config
26 |
27 | @argv = ARGV
28 | @pid = $PID || Process.pid
29 | @title = $PROGRAM_NAME
30 | end
31 |
32 | attr_reader :argv, :pid, :title
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/elastic_apm/metrics/breakdown_set.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Metrics
22 | # @api private
23 | class BreakdownSet < SpanScopedSet
24 | def initialize(config)
25 | super
26 |
27 | disable! unless config.breakdown_metrics?
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/elastic_apm/metrics/span_scoped_set.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Metrics
22 | # @api private
23 | class SpanScopedSet < Set
24 | def collect
25 | super.tap do |sets|
26 | next unless sets
27 |
28 | sets.each do |set|
29 | move_transaction(set)
30 | move_span(set)
31 | end
32 | end
33 | end
34 |
35 | private
36 |
37 | def move_transaction(set)
38 | name = set.tags&.delete(:'transaction.name')
39 | type = set.tags&.delete(:'transaction.type')
40 | return unless name || type
41 |
42 | set.transaction = { name: name, type: type }
43 | set.tags = nil if set.tags.empty?
44 | end
45 |
46 | def move_span(set)
47 | type = set.tags&.delete(:'span.type')
48 | subtype = set.tags&.delete(:'span.subtype')
49 | return unless type
50 |
51 | set.span = { type: type, subtype: subtype }
52 | set.tags = nil if set.tags.empty?
53 | end
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/elastic_apm/metrics/transaction_set.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Metrics
22 | # @api private
23 | class TransactionSet < SpanScopedSet
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/elastic_apm/metricset.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | class Metricset
23 | def initialize(
24 | timestamp: Util.micros,
25 | tags: nil,
26 | transaction: nil,
27 | span: nil,
28 | **samples
29 | )
30 | @timestamp = timestamp
31 | @tags = tags
32 | @transaction = transaction
33 | @span = span
34 | @samples = samples
35 | end
36 |
37 | attr_accessor :timestamp, :transaction, :span, :tags
38 | attr_reader :samples
39 |
40 | def merge_tags!(tags)
41 | return unless tags
42 |
43 | @tags ||= {}
44 | @tags.merge! tags
45 | end
46 |
47 | def tags?
48 | tags&.any?
49 | end
50 |
51 | def empty?
52 | samples.empty?
53 | end
54 |
55 | def inspect
56 | ""
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/lib/elastic_apm/naively_hashable.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # TODO: Remove this?
22 | # @api private
23 | module NaivelyHashable
24 | def naively_hashable?
25 | true
26 | end
27 |
28 | def to_h
29 | instance_variables.each_with_object({}) do |name, h|
30 | key = name.to_s.delete('@').to_sym
31 | value = instance_variable_get(name)
32 | is_hashable =
33 | value.respond_to?(:naively_hashable?) && value.naively_hashable?
34 |
35 | h[key] = is_hashable ? value.to_h : value
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/elastic_apm/normalizers/grape.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | %w[endpoint_run].each do |lib|
21 | require "elastic_apm/normalizers/grape/#{lib}"
22 | end
23 |
--------------------------------------------------------------------------------
/lib/elastic_apm/normalizers/rails.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | %w[
21 | action_controller
22 | action_mailer
23 | action_view
24 | active_record
25 | ].each do |lib|
26 | require "elastic_apm/normalizers/rails/#{lib}"
27 | end
28 |
--------------------------------------------------------------------------------
/lib/elastic_apm/normalizers/rails/action_controller.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Normalizers
22 | module ActionController
23 | # @api private
24 | class ProcessActionNormalizer < Normalizer
25 | register 'process_action.action_controller'
26 |
27 | TYPE = 'app'
28 | SUBTYPE = 'controller'
29 | ACTION = 'action'
30 |
31 | def normalize(transaction, _name, payload)
32 | transaction.name = endpoint(payload)
33 | [transaction.name, TYPE, SUBTYPE, ACTION, nil]
34 | end
35 |
36 | private
37 |
38 | def endpoint(payload)
39 | "#{payload[:controller]}##{payload[:action]}"
40 | end
41 | end
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/lib/elastic_apm/normalizers/rails/action_mailer.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Normalizers
22 | module ActionMailer
23 | # @api private
24 | class ProcessActionNormalizer < Normalizer
25 | register 'process.action_mailer'
26 |
27 | TYPE = 'app'
28 | SUBTYPE = 'mailer'
29 | ACTION = 'action'
30 |
31 | def normalize(_transaction, _name, payload)
32 | [endpoint(payload), TYPE, SUBTYPE, ACTION, nil]
33 | end
34 |
35 | private
36 |
37 | def endpoint(payload)
38 | "#{payload[:mailer]}##{payload[:action]}"
39 | end
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/elastic_apm/railtie.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | class Railtie < ::Rails::Railtie
23 | config.elastic_apm = ActiveSupport::OrderedOptions.new
24 |
25 | Config.schema.each do |key, args|
26 | next unless args.length > 1
27 | config.elastic_apm[key] = args[:default]
28 | end
29 |
30 | initializer 'elastic_apm.initialize' do |app|
31 | config = Config.new(app.config.elastic_apm.merge(app: app)).tap do |c|
32 | # Prepend Rails.root to log_path if present
33 | if c.log_path && !c.log_path.start_with?('/')
34 | c.log_path = ::Rails.root.join(c.log_path)
35 | end
36 | end
37 |
38 | if Rails.start(config)
39 | app.middleware.insert 0, Middleware
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/elastic_apm/resque.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # Defines a before_first_fork hook for starting the ElasticAPM agent
22 | # with Resque.
23 | module Resque
24 | ::Resque.before_first_fork do
25 | ::Resque.logger.debug('Starting ElasticAPM agent')
26 | ElasticAPM.start
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/elastic_apm/span/context/db.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Span
22 | class Context
23 | # @api private
24 | class Db
25 | def initialize(
26 | instance: nil,
27 | statement: nil,
28 | type: nil,
29 | user: nil,
30 | rows_affected: nil
31 | )
32 | @instance = instance
33 | @statement = statement&.encode('utf-8', invalid: :replace, undef: :replace)
34 | @type = type
35 | @user = user
36 | @rows_affected = rows_affected
37 | end
38 |
39 | attr_accessor :instance, :statement, :type, :user, :rows_affected
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/elastic_apm/span/context/http.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Span
22 | class Context
23 | # @api private
24 | class Http
25 | def initialize(url: nil, status_code: nil, method: nil)
26 | @url = sanitize_url(url)
27 | @status_code = status_code
28 | @method = method
29 | end
30 |
31 | attr_accessor :url, :status_code, :method
32 |
33 | private
34 |
35 | def sanitize_url(uri_or_str)
36 | return unless uri_or_str
37 |
38 | uri = uri_or_str.is_a?(URI) ? uri_or_str.dup : URI(uri_or_str)
39 | uri.password = nil
40 | uri.to_s
41 | end
42 | end
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/elastic_apm/span/context/links.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Span
22 | class Context
23 | # @api private
24 | class Links < Array
25 | # @api private
26 | class Link < Struct.new(:trace_id, :span_id)
27 | end
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/elastic_apm/span/context/message.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Span
22 | class Context
23 | # @api private
24 | class Message
25 | def initialize(
26 | queue_name: nil,
27 | age_ms: nil
28 | )
29 | @queue_name = queue_name
30 | @age_ms = age_ms
31 | end
32 |
33 | attr_reader(
34 | :queue_name,
35 | :age_ms
36 | )
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/lib/elastic_apm/span/context/service.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | class Span
22 | class Context
23 | # @api private
24 | class Service
25 | include Fields
26 |
27 | field :target
28 |
29 | # @api private
30 | class Target
31 | include Fields
32 |
33 | field :name, default: ''
34 | field :type, default: ''
35 | end
36 |
37 | def initialize(target: nil, **attrs)
38 | super(**attrs)
39 |
40 | self.target = build_target(target)
41 | end
42 |
43 | private
44 |
45 | def build_target(target = nil)
46 | return Target.new unless target
47 | return target if target.is_a?(Target)
48 |
49 | Target.new(**target)
50 | end
51 | end
52 | end
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/lib/elastic_apm/spies/action_dispatch.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Spies
23 | # @api private
24 | class ActionDispatchSpy
25 | # @api private
26 | module Ext
27 | def render_exception(request, exception_or_wrapper)
28 | context = ElasticAPM.build_context(
29 | rack_env: request, for_type: :error
30 | )
31 | exception =
32 | if exception_or_wrapper.is_a?(ActionDispatch::ExceptionWrapper)
33 | exception_or_wrapper.exception
34 | else
35 | exception_or_wrapper
36 | end
37 | ElasticAPM.report(exception, context: context, handled: false)
38 |
39 | super(request, exception_or_wrapper)
40 | end
41 | end
42 |
43 | def install
44 | ::ActionDispatch::ShowExceptions.prepend(Ext)
45 | end
46 | end
47 |
48 | register(
49 | 'ActionDispatch::ShowExceptions',
50 | 'action_dispatch/show_exception',
51 | ActionDispatchSpy.new
52 | )
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/lib/elastic_apm/spies/json.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'elastic_apm/span_helpers'
21 |
22 | module ElasticAPM
23 | # @api private
24 | module Spies
25 | # @api private
26 | class JSONSpy
27 | def install
28 | ::JSON.class_eval do
29 | include SpanHelpers
30 | span_class_method :parse, 'JSON#parse', 'json.parse'
31 | span_class_method :parse!, 'JSON#parse!', 'json.parse'
32 | span_class_method :generate, 'JSON#generate', 'json.generate'
33 | end
34 | end
35 | end
36 |
37 | register 'JSON', 'json', JSONSpy.new
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/elastic_apm/spies/redis.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Spies
23 | # @api private
24 | class RedisSpy
25 | # @api private
26 | module Ext
27 | def call(command, &block)
28 | name = command[0].to_s.upcase
29 |
30 | return super(command, &block) if command[0] == :auth
31 |
32 | ElasticAPM.with_span(name.to_s, 'db.redis') do
33 | super(command, &block)
34 | end
35 | end
36 | end
37 |
38 | def install
39 | ::Redis::Client.prepend(Ext)
40 | end
41 | end
42 |
43 | register 'Redis', 'redis', RedisSpy.new
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/elastic_apm/spies/resque.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Spies
23 | # @api private
24 | class ResqueSpy
25 | TYPE = 'Resque'
26 |
27 | # @api private
28 | module Ext
29 | def perform
30 | name = @payload && @payload['class']&.to_s
31 | transaction = ElasticAPM.start_transaction(name, TYPE)
32 | super
33 | transaction&.done 'success'
34 | transaction&.outcome = Transaction::Outcome::SUCCESS
35 | rescue ::Exception => e
36 | ElasticAPM.report(e, handled: false)
37 | transaction&.done 'error'
38 | transaction&.outcome = Transaction::Outcome::FAILURE
39 | raise
40 | ensure
41 | ElasticAPM.end_transaction
42 | end
43 | end
44 |
45 | def install
46 | ::Resque::Job.prepend(Ext)
47 | end
48 | end
49 |
50 | register 'Resque', 'resque', ResqueSpy.new
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/lib/elastic_apm/spies/sinatra.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Spies
23 | # @api private
24 | class SinatraSpy
25 | # @api private
26 | module Ext
27 | def dispatch!(*args, &block)
28 | super(*args, &block).tap do
29 | next unless (transaction = ElasticAPM.current_transaction)
30 | next unless (route = env['sinatra.route'])
31 |
32 | transaction.name = route
33 | end
34 | end
35 |
36 | def compile_template(engine, data, opts, *args, &block)
37 | opts[:__elastic_apm_template_name] =
38 | case data
39 | when Symbol then data.to_s
40 | else format('Inline %s', engine)
41 | end
42 |
43 | super(engine, data, opts, *args, &block)
44 | end
45 | end
46 |
47 | def install
48 | ::Sinatra::Base.prepend(Ext)
49 | end
50 | end
51 |
52 | register 'Sinatra::Base', 'sinatra/base', SinatraSpy.new
53 | require 'elastic_apm/spies/tilt'
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/lib/elastic_apm/spies/tilt.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Spies
23 | # @api private
24 | class TiltSpy
25 | TYPE = 'template.tilt'
26 |
27 | # @api private
28 | module Ext
29 | def render(*args, &block)
30 | name = options[:__elastic_apm_template_name] || 'Unknown template'
31 |
32 | ElasticAPM.with_span name, TYPE do
33 | super(*args, &block)
34 | end
35 | end
36 | end
37 |
38 | def install
39 | ::Tilt::Template.prepend(Ext)
40 | end
41 | end
42 |
43 | register 'Tilt::Template', 'tilt/template', TiltSpy.new
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/elastic_apm/sql/tokens.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Sql
22 | # @api private
23 | module Tokens
24 | OTHER = :OTHER
25 | COMMENT = :COMMENT
26 | IDENT = :IDENT
27 | NUMBER = :NUMBER
28 | STRING = :STRING
29 |
30 | PERIOD = :PERIOD
31 | COMMA = :COMMA
32 | LPAREN = :LPAREN
33 | RPAREN = :RPAREN
34 |
35 | AS = :AS
36 | CALL = :CALL
37 | DELETE = :DELETE
38 | FROM = :FROM
39 | INSERT = :INSERT
40 | INTO = :INTO
41 | OR = :OR
42 | REPLACE = :REPLACE
43 | SELECT = :SELECT
44 | SET = :SET
45 | TABLE = :TABLE
46 | TRUNCATE = :TRUNCATE
47 | UPDATE = :UPDATE
48 |
49 | KEYWORDS = {
50 | 2 => [AS, OR],
51 | 3 => [SET],
52 | 4 => [CALL, FROM, INTO],
53 | 5 => [TABLE],
54 | 6 => [DELETE, INSERT, SELECT, UPDATE],
55 | 7 => [REPLACE],
56 | 8 => [TRUNCATE]
57 | }.freeze
58 |
59 | KEYWORD_MIN_LENGTH = KEYWORDS.keys.first
60 | KEYWORD_MAX_LENGTH = KEYWORDS.keys.last
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/lib/elastic_apm/stacktrace.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | class Stacktrace
23 | attr_accessor :frames
24 |
25 | def length
26 | frames.length
27 | end
28 |
29 | def to_a
30 | frames.map(&:to_h)
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/elastic_apm/transport/filters.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'elastic_apm/transport/filters/secrets_filter'
21 |
22 | module ElasticAPM
23 | module Transport
24 | # @api private
25 | module Filters
26 | SKIP = :skip
27 |
28 | def self.new(config)
29 | Container.new(config)
30 | end
31 |
32 | # @api private
33 | class Container
34 | def initialize(config)
35 | @filters = { secrets: SecretsFilter.new(config) }
36 | end
37 |
38 | def add(key, filter)
39 | @filters = @filters.merge(key => filter)
40 | end
41 |
42 | def remove(key)
43 | @filters.delete(key)
44 | end
45 |
46 | def apply!(payload)
47 | @filters.reduce(payload) do |result, (_key, filter)|
48 | result = filter.call(result)
49 | break SKIP if result.nil?
50 | result
51 | end
52 | end
53 |
54 | def length
55 | @filters.length
56 | end
57 | end
58 | end
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/lib/elastic_apm/transport/filters/hash_sanitizer.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'elastic_apm/util/deep_dup'
21 |
22 | module ElasticAPM
23 | module Transport
24 | module Filters
25 | # @api private
26 | class HashSanitizer
27 | FILTERED = '[FILTERED]'
28 |
29 | def initialize(key_patterns:)
30 | @key_patterns = key_patterns
31 | end
32 |
33 | attr_accessor :key_patterns
34 |
35 | def strip_from(obj)
36 | strip_from!(Util::DeepDup.dup(obj))
37 | end
38 |
39 | def strip_from!(obj)
40 | return unless obj.is_a?(Hash)
41 |
42 | obj.each_pair do |k, v|
43 | case v
44 | when Hash
45 | strip_from!(v)
46 | else
47 | next unless filter_key?(k)
48 | obj[k] = FILTERED
49 | end
50 | end
51 | end
52 |
53 | def filter_key?(key)
54 | @key_patterns.any? { |regex| regex.match(key) }
55 | end
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/lib/elastic_apm/transport/serializers/metricset_serializer.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Transport
22 | module Serializers
23 | # @api private
24 | class MetricsetSerializer < Serializer
25 | def build(metricset)
26 | payload = {
27 | timestamp: metricset.timestamp.to_i,
28 | samples: build_samples(metricset.samples)
29 | }
30 |
31 | if metricset.tags?
32 | payload[:tags] = mixed_object(metricset.tags)
33 | end
34 |
35 | if metricset.transaction
36 | payload[:transaction] = metricset.transaction
37 | end
38 |
39 | if metricset.span
40 | payload[:span] = metricset.span
41 | end
42 |
43 | { metricset: payload }
44 | end
45 |
46 | private
47 |
48 | def build_samples(samples)
49 | samples.transform_values do |value|
50 | { value: value }
51 | end
52 | end
53 | end
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/elastic_apm/transport/user_agent.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Transport
22 | # @api private
23 | class UserAgent
24 | def initialize(config, version: VERSION)
25 | @version = version
26 | @built = build(config)
27 | end
28 |
29 | def to_s
30 | @built
31 | end
32 |
33 | private
34 |
35 | def build(config)
36 | service = Metadata::ServiceInfo.new(config)
37 |
38 | [
39 | "elastic-apm-ruby/#{@version}",
40 | formatted_service_info(service)
41 | ].compact.join(' ')
42 | end
43 |
44 | def formatted_service_info(service)
45 | if service.name
46 | "(#{[
47 | service.name,
48 | service.version
49 | ].compact.join(' ')
50 | })"
51 | end
52 | end
53 | end
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/lib/elastic_apm/util.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | # @api private
22 | module Util
23 | def self.micros(target = Time.now)
24 | utc = target.utc
25 | utc.to_i * 1_000_000 + utc.usec
26 | end
27 |
28 | def self.monotonic_micros
29 | Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
30 | end
31 |
32 | def self.git_sha
33 | sha = `git rev-parse --verify HEAD 2>&1`.chomp
34 | $?&.success? ? sha : nil
35 | end
36 |
37 | def self.hex_to_bits(str)
38 | str.hex.to_s(2).rjust(str.size * 4, '0')
39 | end
40 |
41 | def self.reverse_merge!(first, *others)
42 | others.reduce(first) do |curr, other|
43 | curr.merge!(other) { |_, _, new| new }
44 | end
45 | end
46 |
47 | def self.truncate(value, max_length: 1024)
48 | return unless value
49 |
50 | value = String(value)
51 | return value if value.length <= max_length
52 |
53 | value[0...(max_length - 1)] + '…'
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/elastic_apm/util/deep_dup.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Util
22 | # @api private
23 | #
24 | # Makes a deep copy of an Array or Hash
25 | # NB: Not guaranteed to work well with complex objects, only simple Hash,
26 | # Array, String, Number, etc.
27 | class DeepDup
28 | def initialize(obj)
29 | @obj = obj
30 | end
31 |
32 | def dup
33 | deep_dup(@obj)
34 | end
35 |
36 | def self.dup(obj)
37 | new(obj).dup
38 | end
39 |
40 | private
41 |
42 | def deep_dup(obj)
43 | case obj
44 | when Hash then hash(obj)
45 | when Array then array(obj)
46 | else obj.dup
47 | end
48 | end
49 |
50 | def array(arr)
51 | arr.map { |obj| deep_dup(obj) }
52 | end
53 |
54 | def hash(hsh)
55 | result = hsh.dup
56 |
57 | hsh.each_pair do |key, value|
58 | result[key] = deep_dup(value)
59 | end
60 |
61 | result
62 | end
63 | end
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/lib/elastic_apm/util/lru_cache.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Util
22 | # @api private
23 | class LruCache
24 | def initialize(max_size = 512, &block)
25 | @max_size = max_size
26 | @data = Hash.new(&block)
27 | @mutex = Mutex.new
28 | end
29 |
30 | def [](key)
31 | @mutex.synchronize do
32 | val = @data[key]
33 | return unless val
34 | add(key, val)
35 | val
36 | end
37 | end
38 |
39 | def []=(key, val)
40 | @mutex.synchronize do
41 | add(key, val)
42 | end
43 | end
44 |
45 | def length
46 | @data.length
47 | end
48 |
49 | def to_a
50 | @data.to_a
51 | end
52 |
53 | private
54 |
55 | def add(key, val)
56 | @data.delete(key)
57 | @data[key] = val
58 |
59 | return unless @data.length > @max_size
60 |
61 | @data.delete(@data.first[0])
62 | end
63 | end
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/lib/elastic_apm/util/precision_validator.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Util
22 | # @api private
23 | # Rounds half away from zero.
24 | # If `minimum` is provided, and the value rounds to 0 (but was not zero to
25 | # begin with), use the minimum instead.
26 | module PrecisionValidator
27 | module_function
28 |
29 | def validate(value, precision: 0, minimum: nil)
30 | float = Float(value)
31 | return nil unless (0.0..1.0).cover?(float)
32 | return float if float == 0
33 |
34 | multiplier = Float(10**precision)
35 | rounded = (float * multiplier + 0.5).floor / multiplier
36 | if rounded == 0 && minimum
37 | minimum
38 | else
39 | rounded
40 | end
41 | rescue ArgumentError
42 | nil
43 | end
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/lib/elastic_apm/util/throttle.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | module Util
22 | # @api private
23 |
24 | # Usage example:
25 | # Throttle.new(5) { thing to only do once per 5 secs }
26 | class Throttle
27 | def initialize(buffer_secs, &block)
28 | @buffer_secs = buffer_secs
29 | @block = block
30 | end
31 |
32 | def call
33 | if @last_call && seconds_since_last_call < @buffer_secs
34 | return @last_result
35 | end
36 |
37 | @last_call = now
38 | @last_result = @block.call
39 | end
40 |
41 | private
42 |
43 | def now
44 | Process.clock_gettime(Process::CLOCK_MONOTONIC)
45 | end
46 |
47 | def seconds_since_last_call
48 | now - @last_call
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/lib/elastic_apm/version.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | VERSION = '4.8.0'
22 | end
23 |
--------------------------------------------------------------------------------
/spec/Dockerfile:
--------------------------------------------------------------------------------
1 | # Base image
2 | ARG RUBY_IMAGE
3 | FROM ${RUBY_IMAGE}
4 |
5 | # Env arguments
6 | ENV \
7 | APP_WORKDIR="/var/app" \
8 | CI="1" \
9 | DEBIAN_FRONTEND="noninteractive" \
10 | INCLUDE_COVERAGE="1" \
11 | LANG=C.UTF-8 \
12 | GOSU_VERSION="1.16"
13 |
14 | ENV \
15 | BUNDLE_BIN="$APP_WORKDIR/vendor/bin" \
16 | BUNDLE_CACHE_PATH="$APP_WORKDIR/cache" \
17 | BUNDLE_PATH="$APP_WORKDIR/vendor" \
18 | GEM_HOME="$APP_WORKDIR/vendor" \
19 | PATH="/opt/app/bin:$APP_WORKDIR/vendor/bin:$PATH"
20 |
21 | # Copy specific scripts
22 | COPY build/ /usr/local/bin/
23 |
24 | # Reset to root user
25 | USER root
26 |
27 | # Install dependencies and upgrade ruby system
28 | RUN \
29 | apt-get update > /dev/null \
30 | && apt-get install -qq -y build-essential libpq-dev git tzdata
31 |
32 | # Install gosu
33 | RUN \
34 | curl -o /usr/local/bin/gosu -sSL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-$(dpkg --print-architecture)" \
35 | && curl -o /usr/local/bin/gosu.asc -sSL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-$(dpkg --print-architecture).asc" \
36 | && gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
37 | && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
38 | && rm /usr/local/bin/gosu.asc \
39 | && chmod +x /usr/local/bin/gosu
40 |
41 | # Set workdir
42 | WORKDIR /app
43 |
44 | # Set specific entrypoint
45 | ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]
46 |
--------------------------------------------------------------------------------
/spec/build/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Bash strict mode
4 | set -eo pipefail
5 |
6 | # Remove jruby user if exists
7 | # The uid can collide with the one, we are trying to use
8 | if id "jruby" >/dev/null 2>&1; then
9 | userdel "jruby"
10 | fi
11 |
12 | # Create a new specific user
13 | USER_ID=${LOCAL_USER_ID:-1001}
14 | GROUP_ID=${LOCAL_GROUP_ID:-1001}
15 | echo "Starting with UID: ${USER_ID}, GID: ${GROUP_ID} and APP_WORKDIR: ${APP_WORKDIR}"
16 | [ $(getent group "${GROUP_ID}") ] || groupadd -g "${GROUP_ID}" user
17 | useradd -u "${USER_ID}" --gid "${GROUP_ID}" -s "/bin/false" -d "${APP_WORKDIR}" user
18 |
19 | # Create the app dir
20 | mkdir -p "${APP_WORKDIR}"
21 |
22 | # Install system dependencies
23 | update.sh
24 |
25 | # Fix permission for user
26 | chown -R "${USER_ID}:${GROUP_ID}" "${APP_WORKDIR}"
27 |
28 | # Run command with lower priviledge
29 | exec gosu ${USER_ID}:${GROUP_ID} "${@}"
30 |
--------------------------------------------------------------------------------
/spec/build/run-bdd.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Bash strict mode
4 | set -exo pipefail
5 |
6 | # Check env vars
7 | [ -z "${APP_PATH}" ] && echo "Environment variable 'APP_PATH' must be defined" && exit 1;
8 | [ -z "${APP_WORKDIR}" ] && echo "Environment variable 'APP_WORKDIR' must be defined" && exit 1;
9 |
10 | # Create an isolate bench folder
11 | cp -r ${APP_PATH}/. "${APP_WORKDIR}"
12 | cd "${APP_WORKDIR}"
13 |
14 | # Install project dependencies
15 | bundle update
16 |
17 | # Run tests
18 | timeout -s9 15m "${APP_WORKDIR}/bin/run-bdd" "${TEST:-}"
19 |
--------------------------------------------------------------------------------
/spec/build/run-bench.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Bash strict mode
4 | set -exo pipefail
5 |
6 | # Check env vars
7 | [ -z "${APP_PATH}" ] && echo "Environment variable 'APP_PATH' must be defined" && exit 1;
8 | [ -z "${APP_WORKDIR}" ] && echo "Environment variable 'APP_WORKDIR' must be defined" && exit 1;
9 | [ -z "${REPORT_OUTPUT_NAME}" ] && echo "Environment variable 'REPORT_OUTPUT_NAME' must be defined" && exit 1;
10 |
11 | # Create an isolate bench folder
12 | cp -r ${APP_PATH}/. "${APP_WORKDIR}"
13 | cd "${APP_WORKDIR}"
14 |
15 | # Install project dependencies
16 | bundle install
17 |
18 | # Run benchmark and generate report
19 | bench/benchmark.rb 2> "${APP_PATH}/spec/${REPORT_OUTPUT_NAME}.error" > "${APP_PATH}/spec/${REPORT_OUTPUT_NAME}.raw"
20 | bench/report.rb < "${APP_PATH}/spec/${REPORT_OUTPUT_NAME}.raw" > "${APP_PATH}/spec/${REPORT_OUTPUT_NAME}.bulk"
21 |
--------------------------------------------------------------------------------
/spec/build/run-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Bash strict mode
4 | set -exo pipefail
5 |
6 | # Check env vars
7 | [ -z "${APP_PATH}" ] && echo "Environment variable 'APP_PATH' must be defined" && exit 1;
8 | [ -z "${APP_WORKDIR}" ] && echo "Environment variable 'APP_WORKDIR' must be defined" && exit 1;
9 |
10 | # Create an isolate bench folder
11 | cp -r ${APP_PATH}/. "${APP_WORKDIR}"
12 | cd "${APP_WORKDIR}"
13 |
14 | # Install project dependencies
15 | bundle update
16 |
17 | # Run tests
18 | timeout -s9 15m "${APP_WORKDIR}/bin/run-tests" "${TEST:-}"
19 |
--------------------------------------------------------------------------------
/spec/build/update.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Bash strict mode
4 | set -eo pipefail
5 |
6 | # Extract ruby version
7 | RUBY_VERSION=$(ruby -e 'print "#{ RUBY_VERSION }\n"')
8 |
9 | # Install specific dependencies for rails 4.x versions
10 | if [[ "${FRAMEWORK}" =~ ^rails-4\.([0-9]) ]]; then
11 | gem i "rubygems-update:~>2.7" --no-document
12 | update_rubygems --no-document
13 | gem i "bundler:~>1.17.3" --no-document
14 | elif [[ "${RUBY_VERSION}" =~ ^2\.(6|7).+ ]]; then
15 | gem i "rubygems-update:~>3.4.0" --no-document
16 | update_rubygems --no-document
17 | gem i bundler --no-document
18 | # Install specific dependencies for 2.4.x and 2.5.x ruby versions
19 | elif [[ "${RUBY_VERSION}" =~ ^2\.(4|5).+ ]]; then
20 | gem i "rubygems-update:~>2.7" --no-document
21 | update_rubygems --no-document
22 | gem i "bundler:~>2.3.26" --no-document
23 | else
24 | gem update --system --no-document
25 | gem i bundler --no-document
26 | fi
27 |
28 | # Install rake
29 | gem i rake --no-document
30 |
--------------------------------------------------------------------------------
/spec/elastic_apm/apm_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | RSpec.describe ElasticAPM do
23 | it 'has a version number' do
24 | expect(ElasticAPM::VERSION).not_to be nil
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/elastic_apm/central_config/cache_control_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe CentralConfig::CacheControl do
24 | let(:header) { nil }
25 | subject { described_class.new(header) }
26 |
27 | context 'with max-age' do
28 | let(:header) { 'max-age=300' }
29 | its(:max_age) { should be 300 }
30 | its(:must_revalidate) { should be nil }
31 | end
32 |
33 | context 'with must-revalidate' do
34 | let(:header) { 'must-revalidate' }
35 | its(:max_age) { should be nil }
36 | its(:must_revalidate) { should be true }
37 | end
38 |
39 | context 'with multiple values' do
40 | let(:header) { 'must-revalidate, public, max-age=300' }
41 | its(:max_age) { should be 300 }
42 | its(:must_revalidate) { should be true }
43 | its(:public) { should be true }
44 | its(:private) { should be nil }
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/spec/elastic_apm/context/request/url_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | class Context
24 | class Request
25 | RSpec.describe Url do
26 | context 'from a rack req' do
27 | let(:url) { 'https://elastic.co:8080/nested/path?abc=123' }
28 | let(:req) { Rack::Request.new(Rack::MockRequest.env_for(url)) }
29 |
30 | subject { described_class.new(req) }
31 |
32 | its(:protocol) { is_expected.to eq 'https' }
33 | its(:hostname) { is_expected.to eq 'elastic.co' }
34 | its(:port) { is_expected.to eq '8080' }
35 | its(:pathname) { is_expected.to eq '/nested/path' }
36 | its(:search) { is_expected.to eq 'abc=123' }
37 | its(:hash) { is_expected.to eq nil }
38 | its(:full) { is_expected.to eq url }
39 | end
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/spec/elastic_apm/context/response_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Context::Response do
24 | let(:response) do
25 | described_class.new(
26 | nil,
27 | headers: headers
28 | )
29 | end
30 |
31 | let(:headers) do
32 | {
33 | a: 1,
34 | b: '2',
35 | c: [1, 2, 3]
36 | }
37 | end
38 |
39 | it 'converts header values to string' do
40 | expect(response.headers).to match(
41 | a: '1',
42 | b: '2',
43 | c: '[1, 2, 3]'
44 | )
45 | end
46 |
47 | context 'when headers are nil' do
48 | let(:headers) { nil }
49 | it 'sets headers to nil' do
50 | expect(response.headers).to eq(nil)
51 | end
52 | end
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/spec/elastic_apm/context/user_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Context::User do
24 | describe '.infer' do
25 | it 'sets values from passed object' do
26 | PossiblyUser = Struct.new(:id, :email, :username)
27 | record = PossiblyUser.new(1, 'a@a', 'abe')
28 |
29 | user = described_class.infer(Config.new, record)
30 | expect(user.id).to eq '1'
31 | expect(user.email).to eq 'a@a'
32 | expect(user.username).to eq 'abe'
33 | end
34 |
35 | it "doesn't explode with missing methods" do
36 | expect do
37 | user = described_class.infer(Config.new, Object.new)
38 | expect(user.id).to be_nil
39 | expect(user.email).to be_nil
40 | expect(user.username).to be_nil
41 | end.to_not raise_exception
42 | end
43 | end
44 |
45 | describe 'empty?' do
46 | it 'is when new' do
47 | expect(Context::User.new).to be_empty
48 | end
49 | end
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/spec/elastic_apm/error/log_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Error::Log do
24 | describe '#initialize' do
25 | it 'takes a message and optional attributes' do
26 | log = Error::Log.new 'Things', level: 'debug'
27 | expect(log.message).to eq 'Things'
28 | expect(log.level).to eq 'debug'
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/spec/elastic_apm/error_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Error do
24 | describe 'initialization' do
25 | subject { Error.new }
26 |
27 | its(:id) { should_not be nil }
28 | its(:timestamp) { should_not be nil }
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/spec/elastic_apm/metadata/process_info_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Metadata::ProcessInfo do
24 | describe '#initialize' do
25 | subject { described_class.new(Config.new) }
26 |
27 | it 'knows about the process' do
28 | expect(subject.argv).to be_a Array
29 | expect(subject.pid).to be_a Integer
30 | expect(subject.title).to match(/rspec/)
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/elastic_apm/metadata/service_info_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Metadata::ServiceInfo do
24 | describe '#initialize' do
25 | subject do
26 | described_class.new(
27 | Config.new(
28 | service_name: "my-service",
29 | service_node_name: "my-node"
30 | )
31 | )
32 | end
33 |
34 | its(:name) { is_expected.to eq "my-service" }
35 | its(:node_name) { is_expected.to eq "my-node" }
36 |
37 | it 'knows the runtime (mri)', unless: RSpec::Support::Ruby.jruby? do
38 | expect(subject.runtime.name).to eq 'ruby'
39 | expect(subject.runtime.version).to_not be_nil
40 | end
41 |
42 | it 'knows the runtime (JRuby)', if: RSpec::Support::Ruby.jruby? do
43 | expect(subject.runtime.name).to eq 'jruby'
44 | expect(subject.runtime.version).to_not be_nil
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/elastic_apm/metadata/system_info_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Metadata::SystemInfo do
24 | describe '#initialize' do
25 | subject { described_class.new(Config.new) }
26 |
27 | it 'has values' do
28 | %i[detected_hostname architecture platform].each do |key|
29 | expect(subject.send(key)).to_not be_nil
30 | end
31 | end
32 |
33 | context 'hostname' do
34 | it 'has no newline at the end' do
35 | expect(subject.detected_hostname).not_to match(/\n\z/)
36 | end
37 |
38 | context 'when there is an exception' do
39 | before do
40 | allow(Socket).to receive(:gethostname).and_raise(StandardError)
41 | end
42 |
43 | it 'returns nil' do
44 | expect(subject.detected_hostname).to eq(nil)
45 | end
46 | end
47 | end
48 | end
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/spec/elastic_apm/metadata_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Metadata do
24 | let(:config) { Config.new(global_labels: { apples: 'oranges' }) }
25 | subject { described_class.new(config) }
26 |
27 | describe '#labels' do
28 | it 'accesses the config\'s labels' do
29 | expect(subject.labels).to eq(apples: 'oranges')
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/elastic_apm/metricset_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Metricset do
24 | describe 'initialize' do
25 | subject { described_class.new(thing: 1) }
26 | its(:timestamp) { should_not be nil }
27 | its(:samples) { should match(thing: 1) }
28 | end
29 |
30 | describe 'empty?' do
31 | context 'with samples' do
32 | subject { described_class.new thing: 1 }
33 | it { should_not be_empty }
34 | end
35 |
36 | context 'with no samples' do
37 | subject { described_class.new }
38 | it { should be_empty }
39 | end
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/spec/elastic_apm/naively_hashable_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe NaivelyHashable do
24 | class Outer
25 | include NaivelyHashable
26 |
27 | def initialize(inner)
28 | @inner = inner
29 | end
30 | end
31 |
32 | class Inner
33 | include NaivelyHashable
34 |
35 | def initialize(name)
36 | @name = name
37 | end
38 | end
39 |
40 | it 'converts object into hash from ivars' do
41 | expect(Outer.new(Inner.new('Ron Burgundy')).to_h).to eq(
42 | inner: { name: 'Ron Burgundy' }
43 | )
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/spec/elastic_apm/normalizers_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | enable = false
23 | begin
24 | require 'active_support/notifications'
25 | enable = true
26 | rescue LoadError
27 | puts '[INFO] Skipping Normalizers spec'
28 | end
29 |
30 | if enable
31 | require 'elastic_apm/subscriber'
32 |
33 | module ElasticAPM
34 | RSpec.describe Normalizers do
35 | describe 'registration:' do
36 | it 'allows a normalizer to register itself' do
37 | class TestNormalizer < Normalizers::Normalizer
38 | register 'something'
39 | end
40 |
41 | built = Normalizers.build nil
42 | expect(built.for('something')).to be_a TestNormalizer
43 | expect(built.keys).to include 'something'
44 | end
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/elastic_apm/rails_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | if defined?(Rails)
23 | RSpec.describe Rails, :intercept do
24 | describe '.start' do
25 | it 'starts the agent' do
26 | begin
27 | ElasticAPM::Rails.start({})
28 | expect(ElasticAPM::Agent).to be_running
29 | ensure
30 | ElasticAPM.stop
31 | end
32 | end
33 | end
34 |
35 | describe 'Rails console' do
36 | before do
37 | module Rails
38 | class Console; end
39 | end
40 | end
41 |
42 | after { Rails.send(:remove_const, :Console) }
43 |
44 | it "doesn't start when console" do
45 | begin
46 | ElasticAPM::Rails.start({})
47 | expect(ElasticAPM.agent).to be nil
48 | expect(ElasticAPM).to_not be_running
49 | ensure
50 | ElasticAPM.stop
51 | end
52 | end
53 | end
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/spec/elastic_apm/span/context/service_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | #
18 | # frozen_string_literal: true
19 |
20 | require "spec_helper"
21 |
22 | module ElasticAPM
23 | class Span
24 | class Context
25 | RSpec.describe Service do
26 | context '.new' do
27 | it 'accepts a hash of arguments' do
28 | result = described_class.new(target: {name: 'name', type: 'sql'})
29 | expect(result.target).not_to be_nil
30 | expect(result.target.name).to eq('name')
31 | expect(result.target.type).to eq('sql')
32 | end
33 | end
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/spec/elastic_apm/spies/racecar_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | begin
23 | require 'active_support/notifications'
24 | require "active_support/subscriber"
25 | require 'racecar'
26 |
27 | module ElasticAPM
28 | RSpec.describe 'Spy: Racecar', :intercept do
29 | it 'captures the instrumentation' do
30 | with_agent do
31 | ActiveSupport::Notifications.instrument('start_process_message.racecar')
32 | ActiveSupport::Notifications.instrument('process_message.racecar') do
33 | # this is the body of the racecar consumer #process method
34 | end
35 | first_transaction = @intercepted.transactions.first
36 | expect(first_transaction).not_to be_nil
37 | expect(first_transaction.name).to eq('process_message')
38 | expect(first_transaction.type).to eq('kafka')
39 | end
40 | end
41 | end
42 | end
43 |
44 | rescue LoadError # in case we don't have ActiveSupport
45 | end
--------------------------------------------------------------------------------
/spec/elastic_apm/spies/redis_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | require 'fakeredis/rspec'
23 |
24 | module ElasticAPM
25 | RSpec.describe 'Spy: Redis' do
26 | it 'spans queries', :intercept do
27 | redis = ::Redis.new
28 |
29 | with_agent do
30 | ElasticAPM.with_transaction 'T' do
31 | redis.lrange('some:where', 0, -1)
32 | end
33 | end
34 |
35 | span, = @intercepted.spans
36 |
37 | expect(span.name).to eq 'LRANGE'
38 | expect(span.outcome).to eq 'success'
39 | end
40 |
41 | it 'sets span outcome to `failure` for failed operations', :intercept do
42 | redis = ::Redis.new
43 |
44 | with_agent do
45 | ElasticAPM.with_transaction 'Redis failure test' do
46 | begin
47 | redis.bitop("meh", "dest1", "key1")
48 | rescue Redis::CommandError
49 | end
50 | end
51 | end
52 |
53 | span, = @intercepted.spans
54 |
55 | expect(span.outcome).to eq 'failure'
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/spec/elastic_apm/spies/sinatra_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | RSpec.describe 'Spy: Sinatra' do
22 | # See Sinatra integration spec
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/spec/elastic_apm/spies/tilt_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ElasticAPM
21 | RSpec.describe 'Spy: Tilt' do
22 | # See Sinatra integration spec
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/spec/elastic_apm/util/deep_dup_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Util::DeepDup do
24 | context 'hashes' do
25 | it 'makes a copy' do
26 | obj1 = Object.new
27 | obj2 = Object.new
28 | orig = { a: obj1, nested: { b: obj2 } }
29 |
30 | expect(Util::DeepDup.dup(orig)[:a]).to_not be obj1
31 | expect(Util::DeepDup.dup(orig)[:nested][:b]).to_not be obj2
32 | end
33 | end
34 |
35 | context 'arrays' do
36 | it 'makes a copy' do
37 | obj = Object.new
38 | orig = [obj]
39 |
40 | expect(orig.dup.first).to be obj
41 | expect(Util::DeepDup.dup(orig).first).to_not be obj
42 | end
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/spec/elastic_apm/util/lru_cache_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | module ElasticAPM
23 | RSpec.describe Util::LruCache do
24 | it 'purges when filled' do
25 | subject = described_class.new(2)
26 |
27 | subject[:a] = 1
28 | subject[:b] = 2
29 | subject[:a]
30 | subject[:c] = 3
31 |
32 | expect(subject.length).to be 2
33 | expect(subject.to_a).to match([[:a, 1], [:c, 3]])
34 | end
35 |
36 | it 'taks a block' do
37 | subject = described_class.new do |cache, key|
38 | cache[key] = 'missing'
39 | end
40 |
41 | expect(subject['other key']).to eq 'missing'
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/spec/elastic_apm/util/throttle_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 |
22 | require 'elastic_apm/util/throttle'
23 |
24 | module ElasticAPM
25 | module Util
26 | RSpec.describe Throttle do
27 | let(:thing) { double call: 'ok' }
28 |
29 | subject { described_class.new(0.1) { thing.call } } # 100 milisecs
30 |
31 | it 'calls only once per 100 milisecs' do
32 | expect(thing).to receive(:call).once
33 | 5.times { subject.call }
34 |
35 | sleep 0.1
36 |
37 | expect(thing).to receive(:call).once
38 | 5.times { subject.call }
39 | end
40 |
41 | it 'returns result of last call' do
42 | subject = described_class.new(1) { 'here it is' }
43 | expect(subject.call).to eq('here it is')
44 | expect(subject.call).to eq('here it is')
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -x
3 |
4 | bundle check || (rm -f Gemfile.lock && bundle)
5 |
6 | # If first arg is a spec path, run spec(s)
7 | if [[ $1 == spec/* ]]; then
8 | bundle exec bin/run-tests $@
9 | exit $?
10 | fi
11 |
12 | # If no arguments, run all specs
13 | if [[ $# == 0 ]]; then
14 | bundle exec bin/run-tests
15 | exit $?
16 | fi
17 |
18 | # Otherwise, run args as command
19 | $@
20 |
--------------------------------------------------------------------------------
/spec/fixtures/elastic_apm.yml:
--------------------------------------------------------------------------------
1 | ---
2 | server_url: 'somewhere-config.com'
3 |
--------------------------------------------------------------------------------
/spec/fixtures/elastic_apm_erb.yml:
--------------------------------------------------------------------------------
1 | ---
2 | server_url: <%= 'somewhere-config.com' %>
3 |
--------------------------------------------------------------------------------
/spec/fixtures/proc_meminfo:
--------------------------------------------------------------------------------
1 | MemTotal: 3947960 kB
2 | MemFree: 704748 kB
3 | MemAvailable: 2685608 kB
4 | Buffers: 324060 kB
5 | Cached: 1357076 kB
6 | SwapCached: 9640 kB
7 | Active: 1524876 kB
8 | Inactive: 960344 kB
9 | Active(anon): 622160 kB
10 | Inactive(anon): 212836 kB
11 | Active(file): 902716 kB
12 | Inactive(file): 747508 kB
13 | Unevictable: 3652 kB
14 | Mlocked: 3652 kB
15 | SwapTotal: 1023996 kB
16 | SwapFree: 651900 kB
17 | Dirty: 468 kB
18 | Writeback: 0 kB
19 | AnonPages: 802664 kB
20 | Mapped: 86160 kB
21 | Shmem: 28488 kB
22 | Slab: 698796 kB
23 | SReclaimable: 619664 kB
24 | SUnreclaim: 79132 kB
25 | KernelStack: 6448 kB
26 | PageTables: 16156 kB
27 | NFS_Unstable: 0 kB
28 | Bounce: 0 kB
29 | WritebackTmp: 0 kB
30 | CommitLimit: 2997976 kB
31 | Committed_AS: 4322184 kB
32 | VmallocTotal: 34359738367 kB
33 | VmallocUsed: 0 kB
34 | VmallocChunk: 0 kB
35 | HardwareCorrupted: 0 kB
36 | AnonHugePages: 0 kB
37 | CmaTotal: 0 kB
38 | CmaFree: 0 kB
39 | HugePages_Total: 0
40 | HugePages_Free: 0
41 | HugePages_Rsvd: 0
42 | HugePages_Surp: 0
43 |
--------------------------------------------------------------------------------
/spec/fixtures/proc_meminfo_wheezy:
--------------------------------------------------------------------------------
1 | MemTotal: 3947960 kB
2 | MemFree: 704748 kB
3 | Buffers: 324060 kB
4 | Cached: 1357076 kB
5 | SwapCached: 9640 kB
6 | Active: 1524876 kB
7 | Inactive: 960344 kB
8 | Active(anon): 622160 kB
9 | Inactive(anon): 212836 kB
10 | Active(file): 902716 kB
11 | Inactive(file): 747508 kB
12 | Unevictable: 3652 kB
13 | Mlocked: 3652 kB
14 | SwapTotal: 1023996 kB
15 | SwapFree: 651900 kB
16 | Dirty: 468 kB
17 | Writeback: 0 kB
18 | AnonPages: 802664 kB
19 | Mapped: 86160 kB
20 | Shmem: 28488 kB
21 | Slab: 698796 kB
22 | SReclaimable: 619664 kB
23 | SUnreclaim: 79132 kB
24 | KernelStack: 6448 kB
25 | PageTables: 16156 kB
26 | NFS_Unstable: 0 kB
27 | Bounce: 0 kB
28 | WritebackTmp: 0 kB
29 | CommitLimit: 2997976 kB
30 | Committed_AS: 4322184 kB
31 | VmallocTotal: 34359738367 kB
32 | VmallocUsed: 0 kB
33 | VmallocChunk: 0 kB
34 | HardwareCorrupted: 0 kB
35 | AnonHugePages: 0 kB
36 | CmaTotal: 0 kB
37 | CmaFree: 0 kB
38 | HugePages_Total: 0
39 | HugePages_Free: 0
40 | HugePages_Rsvd: 0
41 | HugePages_Surp: 0
42 |
--------------------------------------------------------------------------------
/spec/fixtures/proc_self_stat:
--------------------------------------------------------------------------------
1 | 4861 (ruby) R 4441 4861 4441 34820 4861 4194304 2086 0 0 0 {utime} {stime} 0 0 20 0 2 0 170151991 53223424 3110 18446744073709551615 4194304 4197164 140726901561824 140726901547920 140610609386109 0 0 0 1107328591 0 0 0 17 1 0 0 0 0 0 6294976 6295568 36663296 140726901566581 140726901566611 140726901566611 140726901567467 0
2 |
--------------------------------------------------------------------------------
/spec/fixtures/proc_stat_debian:
--------------------------------------------------------------------------------
1 | cpu {user} 11619 2457910 {idle} 376284 0 185125 0 0 0
2 | cpu0 3178685 5678 1254045 164774549 230030 0 53036 0 0 0
3 | cpu1 3231872 5941 1203865 164660122 146253 0 132088 0 0 0
4 | intr 636734946 23 10 0 0 2880 0 3 0 1 0 0 36 15 0 0 1660876 0 0 0 0 0 0 0 0 0 22 0 7954532 141 0 0 1 33962710 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 | ctxt 1290513757
6 | btime 1543445836
7 | processes 3990587
8 | procs_running 1
9 | procs_blocked 0
10 | softirq 521577188 0 145989881 7936 42291435 32957532 0 140 130217236 0 170113028
11 |
--------------------------------------------------------------------------------
/spec/fixtures/proc_stat_rhel:
--------------------------------------------------------------------------------
1 | cpu {user} 2037 278561 {idle} 15536 0 178811
2 | cpu0 259246 7001 60190 34250993 137517 772 0
3 | intr 354133732 347209999 2272 0 4 4 0 0 3 1 1249247 0 0 80143 0 422626 5169433
4 | ctxt 12547729
5 | btime 1093631447
6 | processes 130523
7 | procs_running 1
8 | procs_blocked 0
9 |
--------------------------------------------------------------------------------
/spec/fixtures/unknown_option.yml:
--------------------------------------------------------------------------------
1 | ---
2 | unknown_option_in_config_file: 123
3 |
--------------------------------------------------------------------------------
/spec/integration/rails_console_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'integration_helper'
21 |
22 | if defined?(Rails)
23 | require 'action_controller/railtie'
24 |
25 | RSpec.describe 'Rails console', :spec_logger do
26 | before :all do
27 | class RailsConsoleTestApp < Rails::Application
28 | RailsTestHelpers.setup_rails_test_config(config)
29 |
30 | config.elastic_apm.disable_send = true
31 | config.logger = Logger.new(SpecLogger)
32 | end
33 |
34 | # rubocop:disable Style/ClassAndModuleChildren
35 | class ::ApplicationController < ActionController::Base; end
36 | class ::Rails::Console; end
37 | # rubocop:enable Style/ClassAndModuleChildren
38 |
39 | RailsConsoleTestApp.initialize!
40 | end
41 |
42 | after :all do
43 | ElasticAPM.stop
44 | end
45 |
46 | it "doesn't start when console" do
47 | expect(ElasticAPM.agent).to be nil
48 | end
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/spec/integration/rails_logger_ecs_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'integration_helper'
21 |
22 | if defined?(Rails)
23 | require 'action_controller/railtie'
24 |
25 | RSpec.describe 'Rails logger with Ecs logging option', :allow_running_agent do
26 | before :all do
27 | module RailsTestAppEcsLogger
28 | class Application < Rails::Application
29 | RailsTestHelpers.setup_rails_test_config(config)
30 |
31 | config.disable_send = true
32 |
33 | config.elastic_apm.log_ecs_reformatting = 'override'
34 | end
35 | end
36 |
37 | class ApplicationController < ActionController::Base
38 | end
39 |
40 | MockIntake.stub!
41 |
42 | RailsTestAppEcsLogger::Application.initialize!
43 | end
44 |
45 | it 'uses the Rails logger' do
46 | expect(Rails.logger).to be(ElasticAPM.agent.config.logger)
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/spec/integration/rails_logger_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'integration_helper'
21 |
22 | if defined?(Rails)
23 | require 'action_controller/railtie'
24 |
25 | RSpec.describe 'Rails logger', :allow_running_agent, :mock_intake do
26 | before :all do
27 | module RailsTestApp
28 | class Application < Rails::Application
29 | RailsTestHelpers.setup_rails_test_config(config)
30 |
31 | config.disable_send = true
32 |
33 | config.elastic_apm.logger = Logger.new(nil)
34 | config.logger = Logger.new(nil)
35 | end
36 | end
37 |
38 | class ApplicationController < ActionController::Base
39 | end
40 |
41 | MockIntake.stub!
42 |
43 | RailsTestApp::Application.initialize!
44 | end
45 |
46 | it 'sets the custom logger' do
47 | expect(Rails.logger).not_to be(ElasticAPM.agent.config.logger)
48 | end
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/spec/integration/skip_require_patch_spec.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | # Deliberately setting this before requiring spec_helper.rb so it's set
21 | # before we require the agent
22 | ENV['ELASTIC_APM_SKIP_REQUIRE_PATCH'] = '1'
23 | require 'integration_helper'
24 |
25 | RSpec.describe "Disabling the require hook" do
26 | it "doesn't add aliased original method" do
27 | expect { Kernel.method(:require_without_apm) }
28 | .to raise_error(NameError)
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/integration_helper.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.configure do |config|
4 | config.before(:each) do |example|
5 | if ElasticAPM.running? && !example.metadata[:allow_running_agent]
6 | raise "Previous example left an agent running"
7 | end
8 | end
9 |
10 | config.after(:each) do |example|
11 | if ElasticAPM.running? && !example.metadata[:allow_running_agent]
12 | raise "This example left an agent running"
13 | end
14 | end
15 |
16 | config.after(:each, spec_logger: true) do |example|
17 | SpecLogger.rewind
18 | next unless example.exception
19 |
20 | puts("Example failed, dumping log:")
21 | puts(SpecLogger.read)
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/scripts/benchmarks.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Perform benchmarks for the given docker ruby image.
4 | # NOTE: It's required to be launched inside the root of the project.
5 | #
6 | # Usage: ./spec/scripts/benchmarks.sh jruby:9.1
7 | #
8 |
9 | # Bash strict mode
10 | set -exo pipefail
11 |
12 | # Found current script directory
13 | RELATIVE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
14 |
15 | # Found project directory
16 | BASE_PROJECT="$(dirname "$(dirname "${RELATIVE_DIR}")")"
17 |
18 | # Arguments
19 | IMAGE_NAME=${1:?"missing RUBY IMAGE NAME"}
20 | VERSION=$(echo "${IMAGE_NAME}" | cut -d":" -f2)
21 | REPORT_OUTPUT_NAME=${2:?"missing THE REPORT OUTPUT NAME"}
22 |
23 | # Move in spec
24 | cd "${BASE_PROJECT}/spec"
25 |
26 | # Build custom container image
27 | docker build --pull --force-rm --build-arg "RUBY_IMAGE=${IMAGE_NAME}" -t "apm-agent-ruby:${VERSION}" .
28 |
29 | # Run bench
30 | IMAGE_NAME="${IMAGE_NAME}" \
31 | LOCAL_GROUP_ID="$(id -g)" \
32 | LOCAL_USER_ID="$(id -u)" \
33 | RUBY_VERSION="${VERSION}" \
34 | docker compose -f ../docker-compose.yml run \
35 | -e REPORT_OUTPUT_NAME="${REPORT_OUTPUT_NAME}" \
36 | -v "${BASE_PROJECT}:/opt/app" \
37 | --rm ruby_rspec \
38 | run-bench.sh
39 |
--------------------------------------------------------------------------------
/spec/scripts/coverage_converge.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker build --build-arg "RUBY_IMAGE=ruby:2.7" --build-arg "VENDOR_PATH=vendor/2.7" --build-arg "BUNDLER_VERSION=2.0.2" --build-arg "USER_ID_GROUP=$(id -u):$(id -u)" -t "apm-agent-ruby:coverage" .
4 | docker run -e "TEST_MATRIX=nil" --mount type=bind,source="$(pwd)",target=/app apm-agent-ruby:coverage spec/scripts/coverage_entrypoint.sh
--------------------------------------------------------------------------------
/spec/scripts/coverage_entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | bundle
3 | rake coverage:report
4 |
--------------------------------------------------------------------------------
/spec/support/delegate_matcher.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | RSpec::Matchers.define :delegate do |method, opts|
21 | to = opts[:to]
22 | args = opts[:args]
23 |
24 | match do |delegator|
25 | unless to.respond_to?(method)
26 | raise NoMethodError, "no method `#{method}` on #{to.inspect}"
27 | end
28 |
29 | if args
30 | expect(to).to receive(method).at_least(:once).with(*args) { true }
31 | else
32 | expect(to).to receive(method).at_least(:once).with(no_args) { true }
33 | end
34 |
35 | if args&.last.is_a?(Hash)
36 | kw = args.pop
37 | delegator.send method, *args, **kw
38 | else
39 | delegator.send method, *args
40 | end
41 | end
42 |
43 | description do
44 | "delegate :#{method} to #{to}"
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/spec/support/exception_helpers.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module ExceptionHelpers
21 | def actual_exception
22 | 1 / 0
23 | rescue => e
24 | e
25 | end
26 |
27 | class ChainedErrorOne < StandardError; end
28 | class ChainedErrorTwo < StandardError; end
29 | class ChainedErrorThree < StandardError; end
30 |
31 | def actual_chained_exception
32 | raise ChainedErrorThree
33 | rescue ChainedErrorThree
34 | begin
35 | raise ChainedErrorTwo
36 | rescue ChainedErrorTwo
37 | begin
38 | raise ChainedErrorOne
39 | rescue ChainedErrorOne => e
40 | e
41 | end
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/spec/support/match_json_schema_matcher.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | require 'spec_helper'
21 | require 'json-schema'
22 | require 'open-uri'
23 |
24 | base = 'https://raw.githubusercontent.com/elastic/apm-server/master/docs/spec/v2'
25 |
26 | SCHEMA_URLS = {
27 | metadatas: "#{base}/metadata.json",
28 | transactions: "#{base}/transaction.json",
29 | spans: "#{base}/span.json",
30 | errors: "#{base}/error.json",
31 | metricset: "#{base}/metricset.json"
32 | }.freeze
33 |
34 | RSpec::Matchers.define :match_json_schema do |schema|
35 | match do |json|
36 | begin
37 | WebMock.disable!
38 | url = SCHEMA_URLS.fetch(schema)
39 | schema = URI.send(:open, url).read
40 | JSON::Validator.validate!(schema, json)
41 | rescue JSON::ParserError, JSON::Schema::ValidationError # jruby sometimes weirds out
42 | puts json.inspect
43 | raise
44 | ensure
45 | WebMock.enable!
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/support/mock_time.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | RSpec.configure do |config|
21 | config.before :each, mock_time: true do
22 | @mocked_time = Time.utc(1992, 1, 1)
23 | @mocked_clock = 123_000
24 |
25 | def travel(us)
26 | Timecop.freeze(@mocked_time += (us / 1_000_000.0))
27 | @mocked_clock += us
28 | end
29 |
30 | allow(ElasticAPM::Util).to receive(:monotonic_micros) { @mocked_clock }
31 |
32 | travel 0
33 | end
34 |
35 | config.after :each, mock_time: true do
36 | Timecop.return
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/support/platform_helpers.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module PlatformHelpers
21 | def darwin?
22 | ElasticAPM::Metrics.platform == :darwin
23 | end
24 |
25 | def linux?
26 | ElasticAPM::Metrics.platform == :linux
27 | end
28 |
29 | def self.jruby_92?
30 | defined?(JRUBY_VERSION) && JRUBY_VERSION =~ /^9\.2/
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/spec/support/rails_test_helpers.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | SpecLogger = StringIO.new
21 |
22 | module RailsTestHelpers
23 | def self.setup_rails_test_config(config)
24 | config.secret_key_base = "__secret_key_base"
25 | config.consider_all_requests_local = false
26 | config.eager_load = false
27 |
28 | config.elastic_apm.api_request_time = "200ms"
29 | config.elastic_apm.disable_start_message = true
30 |
31 | if config.respond_to?(:action_mailer)
32 | config.action_mailer.perform_deliveries = false
33 | end
34 |
35 | config.logger = Logger.new(SpecLogger)
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/spec/support/with_agent.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module WithAgent
21 | def with_agent(klass: ElasticAPM, args: [], **config)
22 | unless @mock_intake || @intercepted
23 | raise 'Using with_agent but neither MockIntake nor Intercepted'
24 | end
25 |
26 | @central_config_stub ||=
27 | WebMock.stub_request(
28 | :get, %r{^http://localhost:8200/config/v1/agents/?$}
29 | ).to_return(body: '{}')
30 |
31 | @server_version_stub =
32 | WebMock.stub_request(:get, %r{^http://localhost:8200/$}).
33 | to_return(body: '{"version":"8.0"}')
34 |
35 | klass.start(*args, **config)
36 | yield
37 | ensure
38 | ElasticAPM.stop
39 |
40 | @central_config_stub = nil
41 | @server_version_stub = nil
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/spec/support/with_env.rb:
--------------------------------------------------------------------------------
1 | # Licensed to Elasticsearch B.V. under one or more contributor
2 | # license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright
4 | # ownership. Elasticsearch B.V. licenses this file to you under
5 | # the Apache License, Version 2.0 (the "License"); you may
6 | # not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 |
18 | # frozen_string_literal: true
19 |
20 | module WithEnv
21 | def with_env(env)
22 | current_values = env.keys.each_with_object({}) do |(key, value), current|
23 | current[key] = ENV.key?(key) ? ENV[value] : :__missing
24 | end
25 |
26 | env.each_key { |key| ENV[key] = env[key] }
27 |
28 | yield
29 | ensure
30 | current_values.each do |key, value|
31 | case value
32 | when :__missing
33 | ENV.delete(key)
34 | else
35 | ENV[key] = value
36 | end
37 | end
38 | end
39 | end
40 |
41 | RSpec.configure do |config|
42 | config.include WithEnv
43 | end
44 |
--------------------------------------------------------------------------------
/updatecli-compose.yaml:
--------------------------------------------------------------------------------
1 | # Config file for `updatecli compose ...`.
2 | # https://www.updatecli.io/docs/core/compose/
3 | policies:
4 | - name: Handle apm-data server specs
5 | policy: ghcr.io/elastic/oblt-updatecli-policies/apm/apm-data-spec:0.6.0@sha256:c0bbdec23541bed38df1342c95aeb601530a113db1ff11715c1c7616ed5e9e8b
6 | values:
7 | - .ci/updatecli/values.d/scm.yml
8 | - .ci/updatecli/values.d/apm-data-spec.yml
9 | - name: Handle apm gherkin specs
10 | policy: ghcr.io/elastic/oblt-updatecli-policies/apm/apm-gherkin:0.6.0@sha256:dbaf4d855c5c212c3b5a8d2cc98c243a2b769ac347198ae8814393a1a0576587
11 | values:
12 | - .ci/updatecli/values.d/scm.yml
13 | - .ci/updatecli/values.d/apm-gherkin.yml
14 | - name: Handle apm json specs
15 | policy: ghcr.io/elastic/oblt-updatecli-policies/apm/apm-json-specs:0.6.0@sha256:e5a74c159ceed02fd20515ea76fa25ff81e3ccf977e74e636f9973db86aa52a5
16 | values:
17 | - .ci/updatecli/values.d/scm.yml
18 | - .ci/updatecli/values.d/apm-json-specs.yml
19 | - name: Update Updatecli policies
20 | policy: ghcr.io/updatecli/policies/autodiscovery/updatecli:0.8.0@sha256:99e9e61b501575c2c176c39f2275998d198b590a3f6b1fe829f7315f8d457e7f
21 | values:
22 | - .ci/updatecli/values.d/scm.yml
23 | - .ci/updatecli/values.d/update-compose.yml
24 |
--------------------------------------------------------------------------------