oneapm_rpm 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +30 -0
- data/.rubocop.yml +725 -0
- data/Gemfile +3 -0
- data/Guardfile +7 -0
- data/LICENSE +1 -0
- data/README.md +3 -0
- data/config/cert/cacert.pem +1177 -0
- data/config/database.yml +5 -0
- data/lib/initializers/goliath.rb +11 -0
- data/lib/initializers/other.rb +1 -0
- data/lib/initializers/rails.rb +15 -0
- data/lib/one_apm/agent.rb +253 -0
- data/lib/one_apm/agent/agent.rb +283 -0
- data/lib/one_apm/agent/agent/connect.rb +175 -0
- data/lib/one_apm/agent/agent/container_data_manager.rb +218 -0
- data/lib/one_apm/agent/agent/forkable_dispatcher_functions.rb +96 -0
- data/lib/one_apm/agent/agent/helpers.rb +45 -0
- data/lib/one_apm/agent/agent/start.rb +226 -0
- data/lib/one_apm/agent/agent/start_worker_thread.rb +148 -0
- data/lib/one_apm/agent/busy_calculator.rb +115 -0
- data/lib/one_apm/agent/cross_app/cross_app_monitor.rb +181 -0
- data/lib/one_apm/agent/cross_app/cross_app_tracing.rb +336 -0
- data/lib/one_apm/agent/database.rb +308 -0
- data/lib/one_apm/agent/database/active_record_helper.rb +80 -0
- data/lib/one_apm/agent/database/obfuscation_helpers.rb +76 -0
- data/lib/one_apm/agent/database/obfuscator.rb +78 -0
- data/lib/one_apm/agent/database/postgres_explain_obfuscator.rb +45 -0
- data/lib/one_apm/agent/datastores.rb +175 -0
- data/lib/one_apm/agent/datastores/metric_helper.rb +83 -0
- data/lib/one_apm/agent/datastores/mongo.rb +27 -0
- data/lib/one_apm/agent/datastores/mongo/metric_translator.rb +189 -0
- data/lib/one_apm/agent/datastores/mongo/obfuscator.rb +37 -0
- data/lib/one_apm/agent/datastores/mongo/statement_formatter.rb +51 -0
- data/lib/one_apm/agent/event/event_listener.rb +40 -0
- data/lib/one_apm/agent/event/event_loop.rb +191 -0
- data/lib/one_apm/agent/event/worker_loop.rb +97 -0
- data/lib/one_apm/agent/harvester.rb +48 -0
- data/lib/one_apm/agent/inbound_request_monitor.rb +30 -0
- data/lib/one_apm/agent/javascript_instrumentor.rb +186 -0
- data/lib/one_apm/agent/pipe/pipe_channel_manager.rb +275 -0
- data/lib/one_apm/agent/pipe/pipe_service.rb +81 -0
- data/lib/one_apm/agent/sampler.rb +55 -0
- data/lib/one_apm/agent/sampler_collection.rb +65 -0
- data/lib/one_apm/agent/samplers/cpu_sampler.rb +49 -0
- data/lib/one_apm/agent/samplers/delayed_job_sampler.rb +109 -0
- data/lib/one_apm/agent/samplers/memory_sampler.rb +144 -0
- data/lib/one_apm/agent/samplers/object_sampler.rb +22 -0
- data/lib/one_apm/agent/samplers/vm_sampler.rb +124 -0
- data/lib/one_apm/agent/synthetics_monitor.rb +48 -0
- data/lib/one_apm/agent/threading/agent_thread.rb +74 -0
- data/lib/one_apm/agent/threading/backtrace_node.rb +133 -0
- data/lib/one_apm/agent/threading/backtrace_service.rb +259 -0
- data/lib/one_apm/agent/threading/thread_profile.rb +155 -0
- data/lib/one_apm/collector/collector/helper.rb +139 -0
- data/lib/one_apm/collector/collector/http_connection.rb +254 -0
- data/lib/one_apm/collector/collector/server_methods.rb +71 -0
- data/lib/one_apm/collector/collector_service.rb +123 -0
- data/lib/one_apm/collector/commands/agent_command.rb +17 -0
- data/lib/one_apm/collector/commands/thread_profiler_session.rb +108 -0
- data/lib/one_apm/collector/commands/xray_session.rb +53 -0
- data/lib/one_apm/collector/commands/xray_session_collection.rb +156 -0
- data/lib/one_apm/collector/containers/agent_command_router.rb +153 -0
- data/lib/one_apm/collector/containers/custom_event_aggregator.rb +94 -0
- data/lib/one_apm/collector/containers/error_collector.rb +349 -0
- data/lib/one_apm/collector/containers/sql_sampler.rb +331 -0
- data/lib/one_apm/collector/containers/stats_engine.rb +34 -0
- data/lib/one_apm/collector/containers/transaction_event_aggregator.rb +249 -0
- data/lib/one_apm/collector/containers/transaction_sampler.rb +352 -0
- data/lib/one_apm/collector/containers/utilization_data.rb +36 -0
- data/lib/one_apm/collector/stats_engine/gc_profiler.rb +106 -0
- data/lib/one_apm/collector/stats_engine/metric_stats.rb +243 -0
- data/lib/one_apm/collector/stats_engine/stats_hash.rb +105 -0
- data/lib/one_apm/configuration.rb +429 -0
- data/lib/one_apm/configuration/autostart.rb +41 -0
- data/lib/one_apm/configuration/default_source.rb +1026 -0
- data/lib/one_apm/configuration/environment_source.rb +113 -0
- data/lib/one_apm/configuration/high_security_source.rb +56 -0
- data/lib/one_apm/configuration/manual_source.rb +13 -0
- data/lib/one_apm/configuration/server_source.rb +60 -0
- data/lib/one_apm/configuration/yaml_source.rb +134 -0
- data/lib/one_apm/errors/agent_errors.rb +26 -0
- data/lib/one_apm/errors/internal_agent_error.rb +16 -0
- data/lib/one_apm/errors/noticed_error.rb +79 -0
- data/lib/one_apm/frameworks/external.rb +15 -0
- data/lib/one_apm/frameworks/rails.rb +103 -0
- data/lib/one_apm/frameworks/rails3.rb +37 -0
- data/lib/one_apm/frameworks/rails4.rb +21 -0
- data/lib/one_apm/frameworks/ruby.rb +21 -0
- data/lib/one_apm/frameworks/sinatra.rb +12 -0
- data/lib/one_apm/inst/3rd/active_merchant.rb +35 -0
- data/lib/one_apm/inst/3rd/acts_as_solr.rb +70 -0
- data/lib/one_apm/inst/3rd/authlogic.rb +23 -0
- data/lib/one_apm/inst/3rd/sunspot.rb +31 -0
- data/lib/one_apm/inst/background_job/active_job.rb +88 -0
- data/lib/one_apm/inst/background_job/delayed_job.rb +52 -0
- data/lib/one_apm/inst/background_job/delayed_job_injection.rb +8 -0
- data/lib/one_apm/inst/background_job/resque.rb +107 -0
- data/lib/one_apm/inst/background_job/sidekiq.rb +64 -0
- data/lib/one_apm/inst/dispatcher/passenger.rb +25 -0
- data/lib/one_apm/inst/dispatcher/rainbows.rb +23 -0
- data/lib/one_apm/inst/framework/grape.rb +94 -0
- data/lib/one_apm/inst/framework/padrino.rb +30 -0
- data/lib/one_apm/inst/framework/sinatra.rb +185 -0
- data/lib/one_apm/inst/framework/sinatra/ignorer.rb +50 -0
- data/lib/one_apm/inst/framework/sinatra/transaction_namer.rb +54 -0
- data/lib/one_apm/inst/http_clients/curb.rb +189 -0
- data/lib/one_apm/inst/http_clients/excon.rb +70 -0
- data/lib/one_apm/inst/http_clients/excon/connection.rb +31 -0
- data/lib/one_apm/inst/http_clients/excon/middleware.rb +55 -0
- data/lib/one_apm/inst/http_clients/httpclient.rb +44 -0
- data/lib/one_apm/inst/http_clients/net.rb +34 -0
- data/lib/one_apm/inst/http_clients/typhoeus.rb +76 -0
- data/lib/one_apm/inst/nosql/memcache.rb +134 -0
- data/lib/one_apm/inst/nosql/mongo.rb +126 -0
- data/lib/one_apm/inst/nosql/mongo_moped.rb +85 -0
- data/lib/one_apm/inst/nosql/redis.rb +83 -0
- data/lib/one_apm/inst/orm/active_record.rb +99 -0
- data/lib/one_apm/inst/orm/active_record_4.rb +28 -0
- data/lib/one_apm/inst/orm/data_mapper.rb +180 -0
- data/lib/one_apm/inst/orm/sequel.rb +47 -0
- data/lib/one_apm/inst/rack.rb +38 -0
- data/lib/one_apm/inst/rack/rack.rb +44 -0
- data/lib/one_apm/inst/rack/rack_builder.rb +51 -0
- data/lib/one_apm/inst/rails/action_controller.rb +118 -0
- data/lib/one_apm/inst/rails/action_web_service.rb +44 -0
- data/lib/one_apm/inst/rails/errors.rb +43 -0
- data/lib/one_apm/inst/rails3/action_controller.rb +172 -0
- data/lib/one_apm/inst/rails3/errors.rb +43 -0
- data/lib/one_apm/inst/rails4/action_controller.rb +27 -0
- data/lib/one_apm/inst/rails4/action_controller_subscriber.rb +121 -0
- data/lib/one_apm/inst/rails4/action_view.rb +23 -0
- data/lib/one_apm/inst/rails4/action_view_subscriber.rb +93 -0
- data/lib/one_apm/inst/rails4/active_record_subscriber.rb +96 -0
- data/lib/one_apm/inst/rails4/errors.rb +42 -0
- data/lib/one_apm/inst/rails_middleware.rb +40 -0
- data/lib/one_apm/inst/support/evented_subscriber.rb +98 -0
- data/lib/one_apm/inst/support/ignore_actions.rb +39 -0
- data/lib/one_apm/inst/support/queue_time.rb +76 -0
- data/lib/one_apm/inst/transaction_base.rb +405 -0
- data/lib/one_apm/logger/agent_logger.rb +206 -0
- data/lib/one_apm/logger/audit_logger.rb +78 -0
- data/lib/one_apm/logger/memory_logger.rb +50 -0
- data/lib/one_apm/logger/null_logger.rb +19 -0
- data/lib/one_apm/metrics/metric_data.rb +72 -0
- data/lib/one_apm/metrics/metric_spec.rb +82 -0
- data/lib/one_apm/metrics/stats.rb +173 -0
- data/lib/one_apm/probe.rb +16 -0
- data/lib/one_apm/probe/framework_loader.rb +53 -0
- data/lib/one_apm/probe/instance_methods.rb +105 -0
- data/lib/one_apm/probe/instrumentation.rb +60 -0
- data/lib/one_apm/rack/browser_monitoring.rb +144 -0
- data/lib/one_apm/rack/middleware_base.rb +27 -0
- data/lib/one_apm/rack/middleware_hooks.rb +17 -0
- data/lib/one_apm/rack/middleware_tracing.rb +81 -0
- data/lib/one_apm/rack/middleware_wrapper.rb +86 -0
- data/lib/one_apm/support/chained_call.rb +15 -0
- data/lib/one_apm/support/coerce.rb +81 -0
- data/lib/one_apm/support/collection_helper.rb +79 -0
- data/lib/one_apm/support/dotted_hash.rb +45 -0
- data/lib/one_apm/support/encoders.rb +34 -0
- data/lib/one_apm/support/environment_report.rb +127 -0
- data/lib/one_apm/support/event_buffer.rb +82 -0
- data/lib/one_apm/support/event_buffer/sampled_buffer.rb +45 -0
- data/lib/one_apm/support/event_buffer/sized_buffer.rb +21 -0
- data/lib/one_apm/support/event_buffer/synthetics_event_buffer.rb +40 -0
- data/lib/one_apm/support/helper.rb +49 -0
- data/lib/one_apm/support/hostname.rb +13 -0
- data/lib/one_apm/support/http_clients/curb_wrappers.rb +65 -0
- data/lib/one_apm/support/http_clients/excon_wrappers.rb +63 -0
- data/lib/one_apm/support/http_clients/httpclient_wrappers.rb +61 -0
- data/lib/one_apm/support/http_clients/net_http_wrappers.rb +48 -0
- data/lib/one_apm/support/http_clients/typhoeus_wrappers.rb +73 -0
- data/lib/one_apm/support/http_clients/uri_util.rb +39 -0
- data/lib/one_apm/support/json_marshaller.rb +68 -0
- data/lib/one_apm/support/json_wrapper.rb +130 -0
- data/lib/one_apm/support/language_support.rb +142 -0
- data/lib/one_apm/support/library_detection.rb +119 -0
- data/lib/one_apm/support/local_environment.rb +196 -0
- data/lib/one_apm/support/marshaller.rb +62 -0
- data/lib/one_apm/support/method_tracer.rb +334 -0
- data/lib/one_apm/support/method_tracer/helpers.rb +92 -0
- data/lib/one_apm/support/method_tracer/traced_method_stack.rb +103 -0
- data/lib/one_apm/support/obfuscator.rb +47 -0
- data/lib/one_apm/support/okjson.rb +601 -0
- data/lib/one_apm/support/parameter_filtering.rb +35 -0
- data/lib/one_apm/support/rules_engine.rb +56 -0
- data/lib/one_apm/support/rules_engine/replacement_rule.rb +80 -0
- data/lib/one_apm/support/rules_engine/segment_terms_rule.rb +46 -0
- data/lib/one_apm/support/server.rb +11 -0
- data/lib/one_apm/support/supported_versions.rb +257 -0
- data/lib/one_apm/support/system_info.rb +211 -0
- data/lib/one_apm/support/timer_lib.rb +29 -0
- data/lib/one_apm/support/version_number.rb +51 -0
- data/lib/one_apm/support/vm.rb +30 -0
- data/lib/one_apm/support/vm/jruby_vm.rb +38 -0
- data/lib/one_apm/support/vm/monotonic_gc_profiler.rb +43 -0
- data/lib/one_apm/support/vm/mri_vm.rb +85 -0
- data/lib/one_apm/support/vm/rubinius_vm.rb +129 -0
- data/lib/one_apm/support/vm/snapshot.rb +18 -0
- data/lib/one_apm/transaction.rb +336 -0
- data/lib/one_apm/transaction/class_methods.rb +132 -0
- data/lib/one_apm/transaction/instance_helpers.rb +82 -0
- data/lib/one_apm/transaction/metric_constants.rb +42 -0
- data/lib/one_apm/transaction/sample_buffer/force_persist_sample_buffer.rb +21 -0
- data/lib/one_apm/transaction/sample_buffer/slowest_sample_buffer.rb +21 -0
- data/lib/one_apm/transaction/sample_buffer/synthetics_sample_buffer.rb +21 -0
- data/lib/one_apm/transaction/sample_buffer/transaction_sample_buffer.rb +101 -0
- data/lib/one_apm/transaction/sample_buffer/xray_sample_buffer.rb +60 -0
- data/lib/one_apm/transaction/segment.rb +193 -0
- data/lib/one_apm/transaction/segment_summary.rb +51 -0
- data/lib/one_apm/transaction/thread_local_access.rb +73 -0
- data/lib/one_apm/transaction/transaction_analysis.rb +78 -0
- data/lib/one_apm/transaction/transaction_apdex.rb +20 -0
- data/lib/one_apm/transaction/transaction_cpu.rb +22 -0
- data/lib/one_apm/transaction/transaction_finish_append.rb +67 -0
- data/lib/one_apm/transaction/transaction_ignore.rb +33 -0
- data/lib/one_apm/transaction/transaction_jruby_functions.rb +40 -0
- data/lib/one_apm/transaction/transaction_metrics.rb +53 -0
- data/lib/one_apm/transaction/transaction_name.rb +90 -0
- data/lib/one_apm/transaction/transaction_namer.rb +49 -0
- data/lib/one_apm/transaction/transaction_sample.rb +204 -0
- data/lib/one_apm/transaction/transaction_sample_builder.rb +168 -0
- data/lib/one_apm/transaction/transaction_state.rb +149 -0
- data/lib/one_apm/transaction/transaction_summary.rb +28 -0
- data/lib/one_apm/transaction/transaction_synthetics.rb +40 -0
- data/lib/one_apm/transaction/transaction_timings.rb +54 -0
- data/lib/one_apm/version.rb +13 -0
- data/lib/oneapm_rpm.rb +16 -0
- data/lib/sequel/extensions/oneapm_instrumentation.rb +84 -0
- data/lib/sequel/plugins/oneapm_instrumentation.rb +66 -0
- data/oneapm.yml +135 -0
- data/oneapm_rpm.gemspec +58 -0
- metadata +474 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'resolv'
|
4
|
+
require 'one_apm/support/server'
|
5
|
+
|
6
|
+
module OneApm
|
7
|
+
module Collector
|
8
|
+
class CollectorService
|
9
|
+
module ServerMethods
|
10
|
+
|
11
|
+
def server
|
12
|
+
@remote_server ||= server_from_host
|
13
|
+
end
|
14
|
+
|
15
|
+
# a new instances of the proxy server - this passes through if
|
16
|
+
# there is no proxy, otherwise it has proxy configuration
|
17
|
+
# information pulled from the config file
|
18
|
+
def proxy_server
|
19
|
+
@proxy_server ||= OneApm::Support::ProxyServer.new(Agent.config[:proxy_host],
|
20
|
+
Agent.config[:proxy_port],
|
21
|
+
Agent.config[:proxy_user],
|
22
|
+
Agent.config[:proxy_pass])
|
23
|
+
end
|
24
|
+
|
25
|
+
# turns a hostname into an ip address and returns a
|
26
|
+
# OneApm::Support::Server that contains the configuration info
|
27
|
+
def server_from_host(hostname=nil)
|
28
|
+
host = hostname || Agent.config[:host]
|
29
|
+
|
30
|
+
# if the host is not an IP address, turn it into one
|
31
|
+
OneApm::Support::Server.new(host, Agent.config[:port], convert_to_ip_address(host))
|
32
|
+
end
|
33
|
+
|
34
|
+
# Check to see if we need to look up the IP address
|
35
|
+
# If it's an IP address already, we pass it through.
|
36
|
+
# If it's nil, or localhost, we don't bother.
|
37
|
+
# Otherwise, use `resolve_ip_address` to find one
|
38
|
+
def convert_to_ip_address(host)
|
39
|
+
# here we leave it as a host name since the cert verification
|
40
|
+
# needs it in host form
|
41
|
+
return host if Agent.config[:ssl]
|
42
|
+
# We won't talk directly to the host, so no need to resolve if proxy configured
|
43
|
+
return host if Agent.config[:proxy_host]
|
44
|
+
return nil if host.nil? || host.downcase == "localhost"
|
45
|
+
ip = resolve_ip_address(host)
|
46
|
+
|
47
|
+
OneApm::Agent.logger.debug "Resolved #{host} to #{ip}"
|
48
|
+
ip
|
49
|
+
end
|
50
|
+
|
51
|
+
# Look up the ip address of the host using the pure ruby lookup
|
52
|
+
# to prevent blocking. If that fails, fall back to the regular
|
53
|
+
# IPSocket library. Return nil if we can't find the host ip
|
54
|
+
# address and don't have a good default.
|
55
|
+
def resolve_ip_address(host)
|
56
|
+
Resolv.getaddress(host)
|
57
|
+
rescue => e
|
58
|
+
OneApm::Agent.logger.warn("DNS Error caching IP address:", e)
|
59
|
+
begin
|
60
|
+
OneApm::Agent.logger.debug("Trying native DNS lookup since Resolv failed")
|
61
|
+
IPSocket.getaddress(host)
|
62
|
+
rescue => e
|
63
|
+
OneApm::Agent.logger.error("Could not look up server address: #{e}")
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'zlib'
|
4
|
+
require 'one_apm/logger/audit_logger'
|
5
|
+
require 'one_apm/support/encoders'
|
6
|
+
require 'one_apm/support/marshaller'
|
7
|
+
require 'one_apm/support/json_marshaller'
|
8
|
+
require 'one_apm/collector/collector/server_methods'
|
9
|
+
require 'one_apm/collector/collector/http_connection'
|
10
|
+
require 'one_apm/collector/collector/helper'
|
11
|
+
|
12
|
+
module OneApm
|
13
|
+
module Collector
|
14
|
+
class CollectorService
|
15
|
+
include OneApm::Collector::CollectorService::Helper
|
16
|
+
include OneApm::Collector::CollectorService::ServerMethods
|
17
|
+
include OneApm::Collector::CollectorService::HttpConnection
|
18
|
+
|
19
|
+
PROTOCOL_VERSION = 1
|
20
|
+
|
21
|
+
attr_accessor :request_timeout, :agent_id
|
22
|
+
attr_reader :collector,:marshaller, :metric_id_cache
|
23
|
+
|
24
|
+
def initialize(license_key = nil, collector = nil)
|
25
|
+
@license_key = license_key || Agent.config[:license_key]
|
26
|
+
@collector = collector || server
|
27
|
+
@request_timeout = Agent.config[:timeout]
|
28
|
+
@metric_id_cache = {}
|
29
|
+
@audit_logger = ::OneApm::Agent::AuditLogger.new
|
30
|
+
|
31
|
+
Agent.config.register_callback(:'audit_log.enabled') do |enabled|
|
32
|
+
@audit_logger.enabled = enabled
|
33
|
+
end
|
34
|
+
|
35
|
+
Agent.config.register_callback(:ssl) do |ssl|
|
36
|
+
if !ssl
|
37
|
+
OneApm::Agent.logger.warn("Agent is configured not to use SSL when communicating with OneApm's servers")
|
38
|
+
else
|
39
|
+
OneApm::Agent.logger.debug("Agent is configured to use SSL")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Agent.config.register_callback(:marshaller) do |marshaller|
|
44
|
+
@marshaller = OneApm::Support::JsonMarshaller.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_redirect_host
|
49
|
+
invoke_remote(:get_redirect_host)
|
50
|
+
end
|
51
|
+
|
52
|
+
def connect(settings={})
|
53
|
+
if host = get_redirect_host
|
54
|
+
@collector = server_from_host(host)
|
55
|
+
end
|
56
|
+
response = invoke_remote(:connect, [settings])
|
57
|
+
@agent_id = response['agent_run_id']
|
58
|
+
response
|
59
|
+
end
|
60
|
+
|
61
|
+
def shutdown(time)
|
62
|
+
invoke_remote(:shutdown, [@agent_id, time.to_i]) if @agent_id
|
63
|
+
end
|
64
|
+
|
65
|
+
def metric_data(stats_hash)
|
66
|
+
timeslice_start = stats_hash.started_at
|
67
|
+
timeslice_end = stats_hash.harvested_at || Time.now
|
68
|
+
|
69
|
+
metric_data_array = build_metric_data_array(stats_hash)
|
70
|
+
|
71
|
+
result = invoke_remote(
|
72
|
+
:metric_data,
|
73
|
+
[@agent_id, timeslice_start.to_f, timeslice_end.to_f, metric_data_array],
|
74
|
+
:item_count => metric_data_array.size
|
75
|
+
)
|
76
|
+
|
77
|
+
fill_metric_id_cache(result)
|
78
|
+
result
|
79
|
+
end
|
80
|
+
|
81
|
+
def error_data(unsent_errors)
|
82
|
+
invoke_remote(:error_data, [@agent_id, unsent_errors], :item_count => unsent_errors.size)
|
83
|
+
end
|
84
|
+
|
85
|
+
def transaction_sample_data(traces)
|
86
|
+
invoke_remote(:transaction_sample_data, [@agent_id, traces], :item_count => traces.size)
|
87
|
+
end
|
88
|
+
|
89
|
+
def sql_trace_data(sql_traces)
|
90
|
+
invoke_remote(:sql_trace_data, [sql_traces], :item_count => sql_traces.size)
|
91
|
+
end
|
92
|
+
|
93
|
+
def profile_data(profile)
|
94
|
+
invoke_remote(:profile_data, [@agent_id, profile], :skip_normalization => true) || ''
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_agent_commands
|
98
|
+
invoke_remote(:get_agent_commands, [@agent_id])
|
99
|
+
end
|
100
|
+
|
101
|
+
def agent_command_results(results)
|
102
|
+
invoke_remote(:agent_command_results, [@agent_id, results])
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_xray_metadata(xray_ids)
|
106
|
+
invoke_remote(:get_xray_metadata, [@agent_id, *xray_ids])
|
107
|
+
end
|
108
|
+
|
109
|
+
def analytic_event_data(data)
|
110
|
+
invoke_remote(:analytic_event_data, [@agent_id, data], :item_count => data.size)
|
111
|
+
end
|
112
|
+
|
113
|
+
def custom_event_data(data)
|
114
|
+
invoke_remote(:custom_event_data, [@agent_id, data], :item_count => data.size)
|
115
|
+
end
|
116
|
+
|
117
|
+
def utilization_data(data)
|
118
|
+
invoke_remote(:utilization_data, data)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module OneApm
|
4
|
+
module Collector
|
5
|
+
module Commands
|
6
|
+
class AgentCommand
|
7
|
+
attr_reader :id, :name, :arguments
|
8
|
+
|
9
|
+
def initialize(raw_collector_command)
|
10
|
+
@id = raw_collector_command[0]
|
11
|
+
@name = raw_collector_command[1]["name"]
|
12
|
+
@arguments = raw_collector_command[1]["arguments"]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'one_apm/agent/threading/agent_thread'
|
4
|
+
require 'one_apm/agent/threading/backtrace_service'
|
5
|
+
require 'one_apm/agent/threading/thread_profile'
|
6
|
+
|
7
|
+
module OneApm
|
8
|
+
module Collector
|
9
|
+
module Commands
|
10
|
+
|
11
|
+
class ThreadProfilerSession
|
12
|
+
|
13
|
+
def initialize(backtrace_service)
|
14
|
+
@backtrace_service = backtrace_service
|
15
|
+
end
|
16
|
+
|
17
|
+
def handle_start_command(agent_command)
|
18
|
+
raise_unsupported_error unless OneApm::Agent::Threading::BacktraceService.is_supported?
|
19
|
+
raise_thread_profiler_disabled unless enabled?
|
20
|
+
raise_already_started_error if running?
|
21
|
+
start(agent_command)
|
22
|
+
end
|
23
|
+
|
24
|
+
def handle_stop_command(agent_command)
|
25
|
+
report_data = agent_command.arguments.fetch("report_data", true)
|
26
|
+
stop(report_data)
|
27
|
+
end
|
28
|
+
|
29
|
+
def start(agent_command)
|
30
|
+
OneApm::Agent.logger.debug("Starting Thread Profiler.")
|
31
|
+
profile = @backtrace_service.subscribe(
|
32
|
+
OneApm::Agent::Threading::BacktraceService::ALL_TRANSACTIONS,
|
33
|
+
agent_command.arguments
|
34
|
+
)
|
35
|
+
|
36
|
+
@started_at = Time.now
|
37
|
+
@duration = profile.duration if profile
|
38
|
+
end
|
39
|
+
|
40
|
+
def stop(report_data)
|
41
|
+
return unless running?
|
42
|
+
OneApm::Agent.logger.debug("Stopping Thread Profiler.")
|
43
|
+
@finished_profile = @backtrace_service.harvest(OneApm::Agent::Threading::BacktraceService::ALL_TRANSACTIONS)
|
44
|
+
@backtrace_service.unsubscribe(OneApm::Agent::Threading::BacktraceService::ALL_TRANSACTIONS)
|
45
|
+
@finished_profile = nil if !report_data
|
46
|
+
end
|
47
|
+
|
48
|
+
def harvest
|
49
|
+
OneApm::Agent.logger.debug("Harvesting from Thread Profiler #{@finished_profile.to_log_description unless @finished_profile.nil?}")
|
50
|
+
profile = @finished_profile
|
51
|
+
@backtrace_service.profile_agent_code = false
|
52
|
+
@finished_profile = nil
|
53
|
+
@started_at = nil
|
54
|
+
profile
|
55
|
+
end
|
56
|
+
|
57
|
+
def enabled?
|
58
|
+
OneApm::Agent.config[:'thread_profiler.enabled']
|
59
|
+
end
|
60
|
+
|
61
|
+
def running?
|
62
|
+
@backtrace_service.subscribed?(OneApm::Agent::Threading::BacktraceService::ALL_TRANSACTIONS)
|
63
|
+
end
|
64
|
+
|
65
|
+
def ready_to_harvest?
|
66
|
+
past_time? || stopped?
|
67
|
+
end
|
68
|
+
|
69
|
+
def past_time?
|
70
|
+
@started_at && (Time.now > @started_at + @duration)
|
71
|
+
end
|
72
|
+
|
73
|
+
def stopped?
|
74
|
+
!!@finished_profile
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def raise_command_error(msg)
|
80
|
+
raise OneApm::Collector::AgentCommandRouter::AgentCommandError.new(msg)
|
81
|
+
end
|
82
|
+
|
83
|
+
def raise_unsupported_error
|
84
|
+
msg = <<-EOF
|
85
|
+
Thread profiling is only supported on 1.9.2 and greater versions of Ruby.
|
86
|
+
We detected running agents capable of profiling, but the profile started with
|
87
|
+
an agent running Ruby #{RUBY_VERSION}.
|
88
|
+
|
89
|
+
Profiling again might select an appropriate agent, but we recommend running a
|
90
|
+
consistent version of Ruby across your application for better results.
|
91
|
+
EOF
|
92
|
+
raise_command_error(msg)
|
93
|
+
end
|
94
|
+
|
95
|
+
def raise_thread_profiler_disabled
|
96
|
+
msg = "Not starting Thread Profiler because of config 'thread_profiler.enabled' = #{enabled?}"
|
97
|
+
raise_command_error(msg)
|
98
|
+
end
|
99
|
+
|
100
|
+
def raise_already_started_error
|
101
|
+
msg = "Profile already in progress. Ignoring agent command to start another."
|
102
|
+
raise_command_error(msg)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module OneApm
|
6
|
+
module Collector
|
7
|
+
module Commands
|
8
|
+
class XraySession
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
attr_reader :id, :command_arguments
|
12
|
+
attr_reader :xray_session_name, :key_transaction_name,
|
13
|
+
:requested_trace_count, :duration, :sample_period
|
14
|
+
|
15
|
+
def initialize(command_arguments)
|
16
|
+
@command_arguments = command_arguments
|
17
|
+
@id = command_arguments.fetch("x_ray_id", nil)
|
18
|
+
@xray_session_name = command_arguments.fetch("xray_session_name", "")
|
19
|
+
@key_transaction_name = command_arguments.fetch("key_transaction_name", "")
|
20
|
+
@requested_trace_count = command_arguments.fetch("requested_trace_count", 100)
|
21
|
+
@duration = command_arguments.fetch("duration", 86400)
|
22
|
+
@sample_period = command_arguments.fetch("sample_period", 0.1)
|
23
|
+
@run_profiler = command_arguments.fetch("run_profiler", true)
|
24
|
+
end
|
25
|
+
|
26
|
+
def active?
|
27
|
+
@active
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_profiler?
|
31
|
+
@run_profiler && OneApm::Agent.config[:'xray_session.allow_profiles']
|
32
|
+
end
|
33
|
+
|
34
|
+
def activate
|
35
|
+
@active = true
|
36
|
+
@start_time = Time.now
|
37
|
+
end
|
38
|
+
|
39
|
+
def deactivate
|
40
|
+
@active = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def requested_period
|
44
|
+
@sample_period
|
45
|
+
end
|
46
|
+
|
47
|
+
def finished?
|
48
|
+
@start_time + @duration < Time.now
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
require 'thread'
|
5
|
+
require 'one_apm/collector/commands/xray_session'
|
6
|
+
|
7
|
+
module OneApm
|
8
|
+
module Collector
|
9
|
+
module Commands
|
10
|
+
class XraySessionCollection
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
def initialize(backtrace_service, event_listener)
|
14
|
+
@backtrace_service = backtrace_service
|
15
|
+
|
16
|
+
# This lock protects access to the sessions hash, but it's expected
|
17
|
+
# that individual session objects within the hash will be manipulated
|
18
|
+
# outside the lock. This is safe because manipulation of the session
|
19
|
+
# objects is expected from only a single thread (the harvest thread)
|
20
|
+
@sessions_lock = Mutex.new
|
21
|
+
@sessions = {}
|
22
|
+
|
23
|
+
if event_listener
|
24
|
+
event_listener.subscribe(:before_harvest, &method(:cleanup_finished_sessions))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_active_xray_sessions(agent_command)
|
29
|
+
# If X-Rays are disabled, just be quiet about it and don't start the
|
30
|
+
# command. Other hosts might be running the X-Ray, so we don't need
|
31
|
+
# to bark on every get_agent_commands.
|
32
|
+
if !OneApm::Agent.config[:'xray_session.enabled']
|
33
|
+
OneApm::Agent.logger.debug("Not responding to X-Ray command because of config 'xray_session.enabled' = #{OneApm::Agent.config[:'xray_session.enabled']}")
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
incoming_ids = agent_command.arguments["xray_ids"]
|
38
|
+
deactivate_for_incoming_sessions(incoming_ids)
|
39
|
+
activate_sessions(incoming_ids)
|
40
|
+
end
|
41
|
+
|
42
|
+
def session_id_for_transaction_name(name)
|
43
|
+
@sessions_lock.synchronize do
|
44
|
+
@sessions.keys.find { |id| @sessions[id].key_transaction_name == name }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
NO_PROFILES = [].freeze
|
49
|
+
|
50
|
+
def harvest_thread_profiles
|
51
|
+
return NO_PROFILES unless OneApm::Agent::Threading::BacktraceService.is_supported?
|
52
|
+
|
53
|
+
profiles = active_thread_profiling_sessions.map do |session|
|
54
|
+
OneApm::Agent.logger.debug("Harvesting profile for X-Ray session #{session.inspect}")
|
55
|
+
@backtrace_service.harvest(session.key_transaction_name)
|
56
|
+
end
|
57
|
+
profiles.reject! {|p| p.empty?}
|
58
|
+
profiles.compact
|
59
|
+
end
|
60
|
+
|
61
|
+
def stop_all_sessions
|
62
|
+
deactivate_for_incoming_sessions([])
|
63
|
+
end
|
64
|
+
|
65
|
+
def cleanup_finished_sessions
|
66
|
+
finished_session_ids.each do |id|
|
67
|
+
OneApm::Agent.logger.debug("Finished X-Ray session #{id} by duration. Removing it from active sessions.")
|
68
|
+
remove_session_by_id(id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
### Internals
|
74
|
+
|
75
|
+
def one_apm_service
|
76
|
+
OneApm::Agent.instance.service
|
77
|
+
end
|
78
|
+
|
79
|
+
# These are unsynchonized and should only be used for testing
|
80
|
+
def_delegators :@sessions, :[], :include?
|
81
|
+
|
82
|
+
def active_thread_profiling_sessions
|
83
|
+
@sessions_lock.synchronize do
|
84
|
+
@sessions.values.select { |s| s.active? && s.run_profiler? }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
### Session activation
|
89
|
+
|
90
|
+
def activate_sessions(incoming_ids)
|
91
|
+
lookup_metadata_for(ids_to_activate(incoming_ids)).each do |raw|
|
92
|
+
add_session(XraySession.new(raw))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def ids_to_activate(incoming_ids)
|
97
|
+
@sessions_lock.synchronize { incoming_ids - @sessions.keys }
|
98
|
+
end
|
99
|
+
|
100
|
+
# Please don't hold the @sessions_lock across me! Calling the service
|
101
|
+
# is time-consuming, and will block request threads. Which is rude.
|
102
|
+
def lookup_metadata_for(ids_to_activate)
|
103
|
+
return [] if ids_to_activate.empty?
|
104
|
+
|
105
|
+
OneApm::Agent.logger.debug("Retrieving metadata for X-Ray sessions #{ids_to_activate.inspect}")
|
106
|
+
one_apm_service.get_xray_metadata(ids_to_activate)
|
107
|
+
end
|
108
|
+
|
109
|
+
def add_session(session)
|
110
|
+
OneApm::Agent.logger.debug("Adding X-Ray session #{session.inspect}")
|
111
|
+
OneApm::Agent.increment_metric("Supportability/XraySessions/Starts")
|
112
|
+
|
113
|
+
@sessions_lock.synchronize { @sessions[session.id] = session }
|
114
|
+
|
115
|
+
session.activate
|
116
|
+
if session.run_profiler?
|
117
|
+
@backtrace_service.subscribe(session.key_transaction_name, session.command_arguments)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
### Session deactivation
|
122
|
+
|
123
|
+
def deactivate_for_incoming_sessions(incoming_ids)
|
124
|
+
ids_to_remove(incoming_ids).each do |session_id|
|
125
|
+
remove_session_by_id(session_id)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def ids_to_remove(incoming_ids)
|
130
|
+
@sessions_lock.synchronize { @sessions.keys - incoming_ids }
|
131
|
+
end
|
132
|
+
|
133
|
+
def remove_session_by_id(id)
|
134
|
+
session = @sessions_lock.synchronize { @sessions.delete(id) }
|
135
|
+
|
136
|
+
if session
|
137
|
+
OneApm::Agent.logger.debug("Removing X-Ray session #{session.inspect}")
|
138
|
+
OneApm::Agent.increment_metric("Supportability/XraySessions/Stops")
|
139
|
+
|
140
|
+
if session.run_profiler?
|
141
|
+
@backtrace_service.unsubscribe(session.key_transaction_name)
|
142
|
+
end
|
143
|
+
session.deactivate
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def finished_session_ids
|
148
|
+
@sessions_lock.synchronize do
|
149
|
+
@sessions.map{|k, s| k if s.finished?}.compact
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|