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,175 @@
|
|
1
|
+
module OneApm
|
2
|
+
module Agent
|
3
|
+
class Agent
|
4
|
+
# This module is an artifact of a refactoring of the connect
|
5
|
+
# method - all of its methods are used in that context, so it
|
6
|
+
# can be refactored at will. It should be fully tested
|
7
|
+
module Connect
|
8
|
+
# number of attempts we've made to contact the server
|
9
|
+
attr_accessor :connect_attempts
|
10
|
+
|
11
|
+
# Disconnect just sets connected to false, which prevents
|
12
|
+
# the agent from trying to connect again
|
13
|
+
def disconnect
|
14
|
+
@connect_state = :disconnected
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def connected?
|
19
|
+
@connect_state == :connected
|
20
|
+
end
|
21
|
+
|
22
|
+
def disconnected?
|
23
|
+
@connect_state == :disconnected
|
24
|
+
end
|
25
|
+
|
26
|
+
# Don't connect if we're already connected, or if we tried to connect
|
27
|
+
# and were rejected with prejudice because of a license issue, unless
|
28
|
+
# we're forced to by force_reconnect.
|
29
|
+
def should_connect?(force = false)
|
30
|
+
force || (!connected? && !disconnected?)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Retry period is a minute for each failed attempt that
|
34
|
+
# we've made. This should probably do some sort of sane TCP
|
35
|
+
# backoff to prevent hammering the server, but a minute for
|
36
|
+
# each attempt seems to work reasonably well.
|
37
|
+
def connect_retry_period
|
38
|
+
[600, connect_attempts * 60].min
|
39
|
+
end
|
40
|
+
|
41
|
+
def note_connect_failure
|
42
|
+
self.connect_attempts += 1
|
43
|
+
end
|
44
|
+
|
45
|
+
# When we have a problem connecting to the server, we need
|
46
|
+
# to tell the user what happened, since this is not an error
|
47
|
+
# we can handle gracefully.
|
48
|
+
def log_error(error)
|
49
|
+
::OneApm::Agent.logger.error "Error establishing connection with OneApm Service at #{@service.server}:", error
|
50
|
+
end
|
51
|
+
|
52
|
+
# When the server sends us an error with the license key, we
|
53
|
+
# want to tell the user that something went wrong, and let
|
54
|
+
# them know where to go to get a valid license key
|
55
|
+
#
|
56
|
+
# After this runs, it disconnects the agent so that it will
|
57
|
+
# no longer try to connect to the server, saving the
|
58
|
+
# application and the server load
|
59
|
+
def handle_license_error(error)
|
60
|
+
::OneApm::Agent.logger.error( \
|
61
|
+
error.message, \
|
62
|
+
"Visit oneapm.com to obtain a valid license key, or to upgrade your account.")
|
63
|
+
disconnect
|
64
|
+
end
|
65
|
+
|
66
|
+
def handle_unrecoverable_agent_error(error)
|
67
|
+
::OneApm::Agent.logger.error(error.message)
|
68
|
+
disconnect
|
69
|
+
shutdown
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate_environment_report
|
73
|
+
@environment_report = environment_for_connect
|
74
|
+
end
|
75
|
+
|
76
|
+
# Checks whether we should send environment info, and if so,
|
77
|
+
# returns the snapshot from the local environment.
|
78
|
+
# Generating the EnvironmentReport has the potential to trigger
|
79
|
+
# require calls in Rails environments, so this method should only
|
80
|
+
# be called synchronously from on the main thread.
|
81
|
+
def environment_for_connect
|
82
|
+
Agent.config[:send_environment_info] ? Array(EnvironmentReport.new) : []
|
83
|
+
end
|
84
|
+
|
85
|
+
# We've seen objects in the environment report (Rails.env in
|
86
|
+
# particular) that can't seralize to JSON. Cope with that here and
|
87
|
+
# clear out so downstream code doesn't have to check again.
|
88
|
+
def sanitize_environment_report
|
89
|
+
if !@service.valid_to_marshal?(@environment_report)
|
90
|
+
@environment_report = []
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Initializes the hash of settings that we send to the
|
95
|
+
# server. Returns a literal hash containing the options
|
96
|
+
def connect_settings
|
97
|
+
sanitize_environment_report
|
98
|
+
{
|
99
|
+
:pid => $$,
|
100
|
+
:host => local_host,
|
101
|
+
:app_name => Agent.config.app_names,
|
102
|
+
:language => 'ruby',
|
103
|
+
:labels => Agent.config.parsed_labels,
|
104
|
+
:agent_version => OneApm::VERSION::STRING,
|
105
|
+
:environment => @environment_report,
|
106
|
+
:settings => Agent.config.to_collector_hash,
|
107
|
+
:high_security => Agent.config[:high_security],
|
108
|
+
:identifier => "ruby:#{local_host}"
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
# apdex_f is always 4 times the apdex_t
|
113
|
+
def apdex_f
|
114
|
+
(4 * Agent.config[:apdex_t]).to_f
|
115
|
+
end
|
116
|
+
|
117
|
+
# Sets the collector host and connects to the server, then
|
118
|
+
# invokes the final configuration with the returned data
|
119
|
+
def query_server_for_configuration
|
120
|
+
finish_setup(connect_to_server)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns connect data passed back from the server
|
124
|
+
def connect_to_server
|
125
|
+
@service.connect(connect_settings)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Takes a hash of configuration data returned from the
|
129
|
+
# server and uses it to set local variables and to
|
130
|
+
# initialize various parts of the agent that are configured
|
131
|
+
# separately.
|
132
|
+
#
|
133
|
+
# Can accommodate most arbitrary data - anything extra is
|
134
|
+
# ignored unless we say to do something with it here.
|
135
|
+
def finish_setup(config_data)
|
136
|
+
return if config_data == nil
|
137
|
+
|
138
|
+
@service.agent_id = config_data['agent_run_id'] if @service
|
139
|
+
|
140
|
+
::OneApm::Agent.logger.debug "Server provided config: #{config_data.inspect}"
|
141
|
+
server_config = OneApm::Configuration::ServerSource.new(config_data, Agent.config)
|
142
|
+
Agent.config.replace_or_add_config(server_config)
|
143
|
+
log_connection!(config_data) if @service
|
144
|
+
|
145
|
+
@transaction_rules = OneApm::Support::RulesEngine.create_transaction_rules(config_data)
|
146
|
+
@stats_engine.metric_rules = OneApm::Support::RulesEngine.create_metric_rules(config_data)
|
147
|
+
|
148
|
+
# If you're adding something else here to respond to the server-side config,
|
149
|
+
# use Agent.instance.events.subscribe(:finished_configuring) callback instead!
|
150
|
+
end
|
151
|
+
|
152
|
+
def local_host
|
153
|
+
@local_host ||= OneApm::Agent::Hostname.get
|
154
|
+
end
|
155
|
+
|
156
|
+
# Logs when we connect to the server, for debugging purposes
|
157
|
+
# - makes sure we know if an agent has not connected
|
158
|
+
def log_connection!(config_data)
|
159
|
+
::OneApm::Agent.logger.debug "Connected to OneApm Service at #{@service.collector.name}"
|
160
|
+
::OneApm::Agent.logger.debug "Agent Run = #{@service.agent_id}."
|
161
|
+
::OneApm::Agent.logger.debug "Connection data = #{config_data.inspect}"
|
162
|
+
if config_data['messages'] && config_data['messages'].any?
|
163
|
+
log_collector_messages(config_data['messages'])
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def log_collector_messages(messages)
|
168
|
+
messages.each do |message|
|
169
|
+
::OneApm::Agent.logger.send(message['level'].downcase, message['message'])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module OneApm
|
2
|
+
module Agent
|
3
|
+
class Agent
|
4
|
+
module ContainerDataManager
|
5
|
+
|
6
|
+
# the statistics engine that holds all the timeslice data
|
7
|
+
attr_reader :stats_engine
|
8
|
+
# the transaction sampler that handles recording transactions
|
9
|
+
attr_reader :transaction_sampler
|
10
|
+
attr_reader :sql_sampler
|
11
|
+
# manages agent commands we receive from the collector, and the handlers
|
12
|
+
attr_reader :agent_command_router
|
13
|
+
# error collector is a simple collection of recorded errors
|
14
|
+
attr_reader :error_collector
|
15
|
+
attr_reader :custom_event_aggregator
|
16
|
+
|
17
|
+
def merge_data_for_endpoint(endpoint, data)
|
18
|
+
if data && !data.empty?
|
19
|
+
container_for_endpoint(endpoint).merge!(data)
|
20
|
+
end
|
21
|
+
rescue => e
|
22
|
+
OneApm::Agent.logger.error("Error while merging #{endpoint} data from child: ", e)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Clear out the metric data, errors, and transaction traces, etc.
|
26
|
+
def drop_buffered_data
|
27
|
+
@stats_engine.reset!
|
28
|
+
@error_collector.reset!
|
29
|
+
@transaction_sampler.reset!
|
30
|
+
@transaction_event_aggregator.reset!
|
31
|
+
@custom_event_aggregator.reset!
|
32
|
+
@sql_sampler.reset!
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def init_containers(events)
|
38
|
+
@stats_engine = OneApm::Collector::StatsEngine.new
|
39
|
+
@transaction_sampler = OneApm::Collector::TransactionSampler.new
|
40
|
+
@sql_sampler = OneApm::Collector::SqlSampler.new
|
41
|
+
@error_collector = OneApm::Collector::ErrorCollector.new
|
42
|
+
@custom_event_aggregator = OneApm::Collector::CustomEventAggregator.new
|
43
|
+
@transaction_event_aggregator = OneApm::Collector::TransactionEventAggregator.new(@events)
|
44
|
+
@utilization_data = OneApm::Collector::UtilizationData.new
|
45
|
+
@agent_command_router = OneApm::Collector::AgentCommandRouter.new(@events)
|
46
|
+
end
|
47
|
+
|
48
|
+
def container_for_endpoint(endpoint)
|
49
|
+
case endpoint
|
50
|
+
when :metric_data then @stats_engine
|
51
|
+
when :transaction_sample_data then @transaction_sampler
|
52
|
+
when :sql_trace_data then @sql_sampler
|
53
|
+
when :error_data then @error_collector
|
54
|
+
when :custom_event_data then @custom_event_aggregator
|
55
|
+
when :analytic_event_data then @transaction_event_aggregator
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Harvests data from the given container, sends it to the named endpoint
|
60
|
+
# on the service, and automatically merges back in upon a recoverable
|
61
|
+
# failure.
|
62
|
+
#
|
63
|
+
# The given container should respond to:
|
64
|
+
#
|
65
|
+
# #harvest!
|
66
|
+
# returns an enumerable collection of data items to be sent to the
|
67
|
+
# collector.
|
68
|
+
#
|
69
|
+
# #reset!
|
70
|
+
# drop any stored data and reset to a clean state.
|
71
|
+
#
|
72
|
+
# #merge!(items)
|
73
|
+
# merge the given items back into the internal buffer of the
|
74
|
+
# container, so that they may be harvested again later.
|
75
|
+
#
|
76
|
+
def harvest_and_send_from_container(container, endpoint)
|
77
|
+
items = harvest_from_container(container, endpoint)
|
78
|
+
send_data_to_endpoint(endpoint, items, container) unless items.empty?
|
79
|
+
end
|
80
|
+
|
81
|
+
def harvest_from_container(container, endpoint)
|
82
|
+
items = []
|
83
|
+
begin
|
84
|
+
items = container.harvest!
|
85
|
+
rescue => e
|
86
|
+
OneApm::Agent.logger.error("Failed to harvest #{endpoint} data, resetting. Error: ", e)
|
87
|
+
container.reset!
|
88
|
+
end
|
89
|
+
items
|
90
|
+
end
|
91
|
+
|
92
|
+
def send_data_to_endpoint(endpoint, items, container)
|
93
|
+
OneApm::Agent.logger.debug("Sending #{items.size} items to #{endpoint}")
|
94
|
+
begin
|
95
|
+
@service.send(endpoint, items)
|
96
|
+
rescue ForceRestartException, ForceDisconnectException
|
97
|
+
raise
|
98
|
+
rescue SerializationError => e
|
99
|
+
OneApm::Agent.logger.warn("Failed to serialize data for #{endpoint}, discarding. Error: ", e)
|
100
|
+
rescue UnrecoverableServerException => e
|
101
|
+
OneApm::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
|
102
|
+
rescue ServerConnectionException => e
|
103
|
+
log_remote_unavailable(endpoint, e)
|
104
|
+
container.merge!(items)
|
105
|
+
rescue => e
|
106
|
+
OneApm::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
|
107
|
+
container.merge!(items)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def harvest_and_send_timeslice_data
|
112
|
+
OneApm::Agent::BusyCalculator.harvest_busy
|
113
|
+
harvest_and_send_from_container(@stats_engine, :metric_data)
|
114
|
+
end
|
115
|
+
|
116
|
+
def harvest_and_send_slowest_sql
|
117
|
+
harvest_and_send_from_container(@sql_sampler, :sql_trace_data)
|
118
|
+
end
|
119
|
+
|
120
|
+
# This handles getting the transaction traces and then sending
|
121
|
+
# them across the wire. This includes gathering SQL
|
122
|
+
# explanations, stripping out stack traces, and normalizing
|
123
|
+
# SQL. note that we explain only the sql statements whose
|
124
|
+
# segments' execution times exceed our threshold.
|
125
|
+
def harvest_and_send_transaction_traces
|
126
|
+
harvest_and_send_from_container(@transaction_sampler, :transaction_sample_data)
|
127
|
+
end
|
128
|
+
|
129
|
+
def harvest_and_send_for_agent_commands
|
130
|
+
harvest_and_send_from_container(@agent_command_router, :profile_data)
|
131
|
+
end
|
132
|
+
|
133
|
+
def harvest_and_send_errors
|
134
|
+
harvest_and_send_from_container(@error_collector, :error_data)
|
135
|
+
end
|
136
|
+
|
137
|
+
def harvest_and_send_analytic_event_data
|
138
|
+
harvest_and_send_from_container(@transaction_event_aggregator, :analytic_event_data)
|
139
|
+
harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
|
140
|
+
end
|
141
|
+
|
142
|
+
def harvest_and_send_utilization_data
|
143
|
+
harvest_and_send_from_container(@utilization_data, :utilization_data)
|
144
|
+
end
|
145
|
+
|
146
|
+
def transmit_data
|
147
|
+
harvest_lock.synchronize do
|
148
|
+
transmit_data_already_locked
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def transmit_event_data
|
153
|
+
transmit_single_data_type(:harvest_and_send_analytic_event_data, "TransactionEvent")
|
154
|
+
end
|
155
|
+
|
156
|
+
def transmit_utilization_data
|
157
|
+
transmit_single_data_type(:harvest_and_send_utilization_data, "UtilizationData")
|
158
|
+
end
|
159
|
+
|
160
|
+
def transmit_single_data_type(harvest_method, supportability_name)
|
161
|
+
now = Time.now
|
162
|
+
|
163
|
+
msg = "Sending #{harvest_method.to_s.gsub("harvest_and_send_", "")} to OneApm Service"
|
164
|
+
::OneApm::Agent.logger.debug msg
|
165
|
+
|
166
|
+
harvest_lock.synchronize do
|
167
|
+
@service.session do # use http keep-alive
|
168
|
+
self.send(harvest_method)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
ensure
|
172
|
+
duration = (Time.now - now).to_f
|
173
|
+
OneApm::Agent.record_metric("Supportability/#{supportability_name}Harvest", duration)
|
174
|
+
end
|
175
|
+
|
176
|
+
# This method is expected to only be called with the harvest_lock already held
|
177
|
+
def transmit_data_already_locked
|
178
|
+
now = Time.now
|
179
|
+
::OneApm::Agent.logger.debug "Sending data to OneApm Service"
|
180
|
+
|
181
|
+
@events.notify(:before_harvest)
|
182
|
+
@service.session do
|
183
|
+
harvest_and_send_errors
|
184
|
+
harvest_and_send_transaction_traces
|
185
|
+
harvest_and_send_slowest_sql
|
186
|
+
harvest_and_send_timeslice_data
|
187
|
+
|
188
|
+
check_for_and_handle_agent_commands
|
189
|
+
harvest_and_send_for_agent_commands
|
190
|
+
end
|
191
|
+
ensure
|
192
|
+
OneApm::Agent::Database.close_connections
|
193
|
+
duration = (Time.now - now).to_f
|
194
|
+
OneApm::Agent.record_metric('Supportability/Harvest', duration)
|
195
|
+
end
|
196
|
+
|
197
|
+
def check_for_and_handle_agent_commands
|
198
|
+
begin
|
199
|
+
@agent_command_router.check_for_and_handle_agent_commands
|
200
|
+
rescue ForceRestartException, ForceDisconnectException
|
201
|
+
raise
|
202
|
+
rescue ServerConnectionException => e
|
203
|
+
log_remote_unavailable(:get_agent_commands, e)
|
204
|
+
rescue => e
|
205
|
+
OneApm::Agent.logger.info("Error during check_for_and_handle_agent_commands, will retry later: ", e)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def log_remote_unavailable(endpoint, e)
|
210
|
+
OneApm::Agent.logger.debug("Unable to send #{endpoint} data, will try again later. Error: ", e)
|
211
|
+
OneApm::Agent.record_metric("Supportability/remote_unavailable", 0.0)
|
212
|
+
OneApm::Agent.record_metric("Supportability/remote_unavailable/#{endpoint.to_s}", 0.0)
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module OneApm
|
2
|
+
module Agent
|
3
|
+
class Agent
|
4
|
+
module ForkableDispatcherFunctions
|
5
|
+
|
6
|
+
# This method should be called in a forked process after a fork.
|
7
|
+
# It assumes the parent process initialized the agent, but does
|
8
|
+
# not assume the agent started.
|
9
|
+
#
|
10
|
+
# The call is idempotent, but not re-entrant.
|
11
|
+
#
|
12
|
+
# * It clears any metrics carried over from the parent process
|
13
|
+
# * Restarts the sampler thread if necessary
|
14
|
+
# * Initiates a new agent run and worker loop unless that was done
|
15
|
+
# in the parent process and +:force_reconnect+ is not true
|
16
|
+
#
|
17
|
+
# Options:
|
18
|
+
# * <tt>:force_reconnect => true</tt> to force the spawned process to
|
19
|
+
# establish a new connection, such as when forking a long running process.
|
20
|
+
# The default is false--it will only connect to the server if the parent
|
21
|
+
# had not connected.
|
22
|
+
# * <tt>:keep_retrying => false</tt> if we try to initiate a new
|
23
|
+
# connection, this tells me to only try it once so this method returns
|
24
|
+
# quickly if there is some kind of latency with the server.
|
25
|
+
def after_fork(options={})
|
26
|
+
needs_restart = false
|
27
|
+
@after_fork_lock.synchronize do
|
28
|
+
needs_restart = @harvester.needs_restart?
|
29
|
+
@harvester.mark_started
|
30
|
+
end
|
31
|
+
|
32
|
+
return if !needs_restart ||
|
33
|
+
!Agent.config[:agent_enabled] ||
|
34
|
+
!Agent.config[:monitor_mode] ||
|
35
|
+
disconnected?
|
36
|
+
|
37
|
+
::OneApm::Agent.logger.debug "Starting the worker thread in #{Process.pid} (parent #{Process.ppid}) after forking."
|
38
|
+
|
39
|
+
channel_id = options[:report_to_channel]
|
40
|
+
install_pipe_service(channel_id) if channel_id
|
41
|
+
|
42
|
+
# Clear out locks and stats left over from parent process
|
43
|
+
reset_objects_with_locks
|
44
|
+
drop_buffered_data
|
45
|
+
|
46
|
+
setup_and_start_agent(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def install_pipe_service(channel_id)
|
50
|
+
@service = OneApm::Agent::PipeService.new(channel_id)
|
51
|
+
if connected?
|
52
|
+
@connected_pid = Process.pid
|
53
|
+
else
|
54
|
+
::OneApm::Agent.logger.debug("Child process #{Process.pid} not reporting to non-connected parent (process #{Process.ppid}).")
|
55
|
+
@service.shutdown(Time.now)
|
56
|
+
disconnect
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Synchronize with the harvest loop. If the harvest thread has taken
|
61
|
+
# a lock (DNS lookups, backticks, agent-owned locks, etc), and we
|
62
|
+
# fork while locked, this can deadlock child processes. For more
|
63
|
+
# details, see https://github.com/resque/resque/issues/1101
|
64
|
+
def synchronize_with_harvest
|
65
|
+
harvest_lock.synchronize do
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Clear out state for any objects that we know lock from our parents
|
71
|
+
# This is necessary for cases where we're in a forked child and Ruby
|
72
|
+
# might be holding locks for background thread that aren't there anymore.
|
73
|
+
def reset_objects_with_locks
|
74
|
+
@stats_engine = OneApm::Collector::StatsEngine.new
|
75
|
+
reset_harvest_locks
|
76
|
+
end
|
77
|
+
|
78
|
+
# Some forking cases (like Resque) end up with harvest lock from the
|
79
|
+
# parent process orphaned in the child. Let it go before we proceed.
|
80
|
+
def reset_harvest_locks
|
81
|
+
return if harvest_lock.nil?
|
82
|
+
|
83
|
+
harvest_lock.unlock if harvest_lock.locked?
|
84
|
+
end
|
85
|
+
|
86
|
+
def flush_pipe_data
|
87
|
+
if connected? && @service.is_a?(::OneApm::Agent::PipeService)
|
88
|
+
transmit_data
|
89
|
+
transmit_event_data
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|