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,45 @@
|
|
1
|
+
module OneApm
|
2
|
+
module Agent
|
3
|
+
class Agent
|
4
|
+
module Helpers
|
5
|
+
|
6
|
+
def obfuscator
|
7
|
+
@obfuscator ||= lambda {|sql| OneApm::Agent::Database.default_sql_obfuscator(sql) }
|
8
|
+
end
|
9
|
+
# Sets a thread local variable as to whether we should or
|
10
|
+
# should not record sql in the current thread. Returns the
|
11
|
+
# previous value, if there is one
|
12
|
+
def set_record_sql(should_record) #THREAD_LOCAL_ACCESS
|
13
|
+
state = TransactionState.tl_get
|
14
|
+
prev = state.record_sql
|
15
|
+
state.record_sql = should_record
|
16
|
+
prev.nil? || prev
|
17
|
+
end
|
18
|
+
|
19
|
+
# Sets a thread local variable as to whether we should or
|
20
|
+
# should not record transaction traces in the current
|
21
|
+
# thread. Returns the previous value, if there is one
|
22
|
+
def set_record_tt(should_record) #THREAD_LOCAL_ACCESS
|
23
|
+
state = TransactionState.tl_get
|
24
|
+
prev = state.record_tt
|
25
|
+
state.record_tt = should_record
|
26
|
+
prev.nil? || prev
|
27
|
+
end
|
28
|
+
|
29
|
+
# Push flag indicating whether we should be tracing in this
|
30
|
+
# thread. This uses a stack which allows us to disable tracing
|
31
|
+
# children of a transaction without affecting the tracing of
|
32
|
+
# the whole transaction
|
33
|
+
def push_trace_execution_flag(should_trace=false) #THREAD_LOCAL_ACCESS
|
34
|
+
TransactionState.tl_get.push_traced(should_trace)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Pop the current trace execution status. Restore trace execution status
|
38
|
+
# to what it was before we pushed the current flag.
|
39
|
+
def pop_trace_execution_flag #THREAD_LOCAL_ACCESS
|
40
|
+
TransactionState.tl_get.pop_traced
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
module OneApm
|
2
|
+
module Agent
|
3
|
+
class Agent
|
4
|
+
# Herein lies the corpse of the former 'start' method. May
|
5
|
+
# its unmatched flog score rest in pieces.
|
6
|
+
module Start
|
7
|
+
|
8
|
+
# Sanity-check the agent configuration and start the agent,
|
9
|
+
# setting up the worker thread and the exit handler to shut
|
10
|
+
# down the agent
|
11
|
+
def check_config_and_start_agent
|
12
|
+
return unless monitoring? && has_correct_license_key?
|
13
|
+
return if using_forking_dispatcher?
|
14
|
+
setup_and_start_agent
|
15
|
+
end
|
16
|
+
|
17
|
+
# This is the shared method between the main agent startup and the
|
18
|
+
# after_fork call restarting the thread in deferred dispatchers.
|
19
|
+
#
|
20
|
+
# Treatment of @started and env report is important to get right.
|
21
|
+
def setup_and_start_agent(options={})
|
22
|
+
@started = true
|
23
|
+
@harvester.mark_started
|
24
|
+
|
25
|
+
unless in_resque_child_process?
|
26
|
+
generate_environment_report
|
27
|
+
install_exit_handler
|
28
|
+
@harvest_samplers.load_samplers unless Agent.config[:disable_samplers]
|
29
|
+
end
|
30
|
+
|
31
|
+
connect_in_foreground if Agent.config[:sync_startup]
|
32
|
+
start_worker_thread(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# True if we have initialized and completed 'start'
|
36
|
+
def started?
|
37
|
+
@started
|
38
|
+
end
|
39
|
+
|
40
|
+
# Check whether we have already started, which is an error condition
|
41
|
+
def already_started?
|
42
|
+
if started?
|
43
|
+
::OneApm::Agent.logger.error("Agent Started Already!")
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Installs our exit handler, which exploits the weird
|
49
|
+
# behavior of at_exit blocks to make sure it runs last, by
|
50
|
+
# doing an at_exit within an at_exit block.
|
51
|
+
def install_exit_handler
|
52
|
+
if Agent.config[:send_data_on_exit] && !weird_ruby?
|
53
|
+
at_exit do
|
54
|
+
# Workaround for MRI 1.9 bug that loses exit codes in at_exit blocks.
|
55
|
+
# This is necessary to get correct exit codes for the agent's
|
56
|
+
# test suites.
|
57
|
+
# http://bugs.ruby-lang.org/issues/5218
|
58
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
|
59
|
+
exit_status = $!.status if $!.is_a?(SystemExit)
|
60
|
+
shutdown
|
61
|
+
exit exit_status if exit_status
|
62
|
+
else
|
63
|
+
shutdown
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# The agent is disabled when it is not force enabled by the
|
70
|
+
# 'agent_enabled' option (e.g. in a manual start), or
|
71
|
+
# enabled normally through the configuration file
|
72
|
+
def disabled?
|
73
|
+
!Agent.config[:agent_enabled]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Logs the configured application names
|
77
|
+
def app_name_configured?
|
78
|
+
names = Agent.config.app_names
|
79
|
+
return names.respond_to?(:any?) && names.any?
|
80
|
+
end
|
81
|
+
|
82
|
+
# Connecting in the foreground blocks further startup of the
|
83
|
+
# agent until we have a connection - useful in cases where
|
84
|
+
# you're trying to log a very-short-running process and want
|
85
|
+
# to get statistics from before a server connection
|
86
|
+
# (typically 20 seconds) exists
|
87
|
+
def connect_in_foreground
|
88
|
+
OneApm::Agent.disable_all_tracing { connect(:keep_retrying => false) }
|
89
|
+
end
|
90
|
+
|
91
|
+
# If we're using sinatra, old versions run in an at_exit
|
92
|
+
# block so we should probably know that
|
93
|
+
def using_sinatra?
|
94
|
+
defined?(Sinatra::Application)
|
95
|
+
end
|
96
|
+
|
97
|
+
# we should not set an at_exit block if people are using
|
98
|
+
# these as they don't do standard at_exit behavior per MRI/YARV
|
99
|
+
def weird_ruby?
|
100
|
+
OneApm::LanguageSupport.using_engine?('rbx') ||
|
101
|
+
OneApm::LanguageSupport.using_engine?('jruby') ||
|
102
|
+
using_sinatra?
|
103
|
+
end
|
104
|
+
|
105
|
+
# Warn the user if they have configured their agent not to
|
106
|
+
# send data, that way we can see this clearly in the log file
|
107
|
+
def monitoring?
|
108
|
+
if Agent.config[:monitor_mode]
|
109
|
+
true
|
110
|
+
else
|
111
|
+
::OneApm::Agent.logger.warn('Agent configured not to send data in this environment.')
|
112
|
+
false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Tell the user when the license key is missing so they can
|
117
|
+
# fix it by adding it to the file
|
118
|
+
def has_license_key?
|
119
|
+
if Agent.config[:license_key] && Agent.config[:license_key].length > 0
|
120
|
+
true
|
121
|
+
else
|
122
|
+
::OneApm::Agent.logger.warn("No license key found. " +
|
123
|
+
"This often means your oneapm.yml file was not found, or it lacks a section for the running environment, '#{OneApm::Probe.instance.env}'. You may also want to try linting your oneapm.yml to ensure it is valid YML.")
|
124
|
+
false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# A correct license key exists and is of the proper length
|
129
|
+
def has_correct_license_key?
|
130
|
+
has_license_key?
|
131
|
+
end
|
132
|
+
|
133
|
+
# If we're using a dispatcher that forks before serving
|
134
|
+
# requests, we need to wait until the children are forked
|
135
|
+
# before connecting, otherwise the parent process sends useless data
|
136
|
+
def using_forking_dispatcher?
|
137
|
+
if [:puma, :passenger, :rainbows, :unicorn].include? Agent.config[:dispatcher]
|
138
|
+
::OneApm::Agent.logger.info "Deferring startup of agent reporting thread because #{Agent.config[:dispatcher]} may fork."
|
139
|
+
true
|
140
|
+
else
|
141
|
+
false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def defer_for_background_jobs?
|
146
|
+
if defer_for_delayed_job?
|
147
|
+
::OneApm::Agent.logger.debug "Deferring startup for DelayedJob"
|
148
|
+
return true
|
149
|
+
end
|
150
|
+
|
151
|
+
if defer_for_resque?
|
152
|
+
::OneApm::Agent.logger.debug "Deferring startup for Resque in case it daemonizes"
|
153
|
+
return true
|
154
|
+
end
|
155
|
+
|
156
|
+
false
|
157
|
+
end
|
158
|
+
|
159
|
+
require 'one_apm/inst/background_job/delayed_job_injection'
|
160
|
+
|
161
|
+
def defer_for_delayed_job?
|
162
|
+
OneApm::Agent.config[:dispatcher] == :delayed_job &&
|
163
|
+
!OneApm::DelayedJobInjection.worker_name
|
164
|
+
end
|
165
|
+
|
166
|
+
# Return true if we're using resque and it hasn't had a chance to (potentially)
|
167
|
+
# daemonize itself. This avoids hanging when there's a Thread started
|
168
|
+
# before Resque calls Process.daemon (Jira RUBY-857)
|
169
|
+
def defer_for_resque?
|
170
|
+
OneApm::Agent.config[:dispatcher] == :resque &&
|
171
|
+
OneApm::LanguageSupport.can_fork? &&
|
172
|
+
!OneApm::Agent::PipeChannelManager.listener.started?
|
173
|
+
end
|
174
|
+
|
175
|
+
def in_resque_child_process?
|
176
|
+
@service.is_a?(OneApm::Agent::PipeService)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Log startup information that we almost always want to know
|
180
|
+
def log_startup
|
181
|
+
log_environment
|
182
|
+
log_dispatcher
|
183
|
+
log_app_name
|
184
|
+
end
|
185
|
+
|
186
|
+
# Classy logging of the agent version and the current pid,
|
187
|
+
# so we can disambiguate processes in the log file and make
|
188
|
+
# sure they're running a reasonable version
|
189
|
+
def log_version_and_pid
|
190
|
+
::OneApm::Agent.logger.debug "OneApm Ruby Agent #{OneApm::VERSION::STRING} Initialized: pid = #{$$}"
|
191
|
+
end
|
192
|
+
|
193
|
+
# Log the environment the app thinks it's running in.
|
194
|
+
# Useful in debugging, as this is the key for config YAML lookups.
|
195
|
+
def log_environment
|
196
|
+
::OneApm::Agent.logger.info "Environment: #{OneApm::Probe.instance.env}"
|
197
|
+
end
|
198
|
+
|
199
|
+
# Logs the dispatcher to the log file to assist with
|
200
|
+
# debugging. When no debugger is present, logs this fact to
|
201
|
+
# assist with proper dispatcher detection
|
202
|
+
def log_dispatcher
|
203
|
+
dispatcher_name = Agent.config[:dispatcher].to_s
|
204
|
+
|
205
|
+
if dispatcher_name.empty?
|
206
|
+
::OneApm::Agent.logger.info 'No known dispatcher detected.'
|
207
|
+
else
|
208
|
+
::OneApm::Agent.logger.info "Dispatcher: #{dispatcher_name}"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def log_app_name
|
213
|
+
::OneApm::Agent.logger.info "Application: #{Agent.config.app_names.join(", ")}"
|
214
|
+
end
|
215
|
+
|
216
|
+
def log_ignore_url_regexes
|
217
|
+
regexes = OneApm::Agent.config[:'rules.ignore_url_regexes']
|
218
|
+
|
219
|
+
unless regexes.empty?
|
220
|
+
::OneApm::Agent.logger.info "Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}."
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module OneApm
|
2
|
+
module Agent
|
3
|
+
class Agent
|
4
|
+
# All of this module used to be contained in the
|
5
|
+
# start_worker_thread method - this is an artifact of
|
6
|
+
# refactoring and can be moved, renamed, etc at will
|
7
|
+
module StartWorkerThread
|
8
|
+
|
9
|
+
# Never allow any data type to be reported more frequently than once
|
10
|
+
# per second.
|
11
|
+
MIN_ALLOWED_REPORT_PERIOD = 1.0
|
12
|
+
UTILIZATION_REPORT_PERIOD = 30 * 60 # every half hour
|
13
|
+
LOG_ONCE_KEYS_RESET_PERIOD = 60.0
|
14
|
+
|
15
|
+
# Try to launch the worker thread and connect to the server.
|
16
|
+
#
|
17
|
+
# See #connect for a description of connection_options.
|
18
|
+
def start_worker_thread(connection_options = {})
|
19
|
+
if disable = OneApm::Agent.config[:disable_harvest_thread]
|
20
|
+
OneApm::Agent.logger.info "Not starting Ruby Agent worker thread because :disable_harvest_thread is #{disable}"
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
::OneApm::Agent.logger.info "Creating Ruby Agent worker thread."
|
25
|
+
@worker_thread = OneApm::Agent::Threading::AgentThread.create('Worker Loop') do
|
26
|
+
deferred_work!(connection_options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# This is the method that is run in a new thread in order to
|
31
|
+
# background the harvesting and sending of data during the
|
32
|
+
# normal operation of the agent.
|
33
|
+
#
|
34
|
+
# Takes connection options that determine how we should
|
35
|
+
# connect to the server, and loops endlessly - typically we
|
36
|
+
# never return from this method unless we're shutting down
|
37
|
+
# the agent
|
38
|
+
def deferred_work!(connection_options)
|
39
|
+
catch_errors do
|
40
|
+
OneApm::Agent.disable_all_tracing do
|
41
|
+
connect(connection_options)
|
42
|
+
if connected?
|
43
|
+
create_and_run_event_loop
|
44
|
+
# never reaches here unless there is a problem or
|
45
|
+
# the agent is exiting
|
46
|
+
else
|
47
|
+
::OneApm::Agent.logger.debug "No connection. Worker thread ending."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_and_run_event_loop
|
54
|
+
@event_loop = create_event_loop
|
55
|
+
|
56
|
+
@event_loop.on(:report_data) { transmit_data }
|
57
|
+
@event_loop.on(:report_event_data) { transmit_event_data }
|
58
|
+
@event_loop.on(:reset_log_once_keys) { OneApm::Agent.logger.clear_already_logged }
|
59
|
+
|
60
|
+
@event_loop.fire_every(Agent.config[:data_report_period], :report_data)
|
61
|
+
@event_loop.fire_every(report_period_for(:analytic_event_data), :report_event_data)
|
62
|
+
@event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
|
63
|
+
|
64
|
+
if Agent.config[:collect_utilization] && !in_resque_child_process?
|
65
|
+
@event_loop.on(:report_utilization_data) { transmit_utilization_data }
|
66
|
+
|
67
|
+
@event_loop.fire(:report_utilization_data)
|
68
|
+
@event_loop.fire_every(UTILIZATION_REPORT_PERIOD, :report_utilization_data)
|
69
|
+
end
|
70
|
+
|
71
|
+
@event_loop.run
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_event_loop
|
75
|
+
EventLoop.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def report_period_for(method)
|
79
|
+
config_key = "data_report_periods.#{method}".to_sym
|
80
|
+
period = Agent.config[config_key]
|
81
|
+
if !period
|
82
|
+
period = Agent.config[:data_report_period]
|
83
|
+
::OneApm::Agent.logger.warn("Could not find configured period for #{method}, falling back to data_report_period (#{period} s)")
|
84
|
+
end
|
85
|
+
if period < MIN_ALLOWED_REPORT_PERIOD
|
86
|
+
::OneApm::Agent.logger.warn("Configured #{config_key} was #{period}, but minimum allowed is #{MIN_ALLOWED_REPORT_PERIOD}, using #{MIN_ALLOWED_REPORT_PERIOD}.")
|
87
|
+
period = MIN_ALLOWED_REPORT_PERIOD
|
88
|
+
end
|
89
|
+
period
|
90
|
+
end
|
91
|
+
|
92
|
+
def stop_event_loop
|
93
|
+
if @event_loop
|
94
|
+
@event_loop.run_once(true) if Agent.config[:force_send]
|
95
|
+
@event_loop.stop
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# a wrapper method to handle all the errors that can happen
|
102
|
+
# in the connection and worker thread system. This
|
103
|
+
# guarantees a no-throw from the background thread.
|
104
|
+
def catch_errors
|
105
|
+
yield
|
106
|
+
rescue OneApm::ForceRestartException => e
|
107
|
+
handle_force_restart(e)
|
108
|
+
retry
|
109
|
+
rescue OneApm::ForceDisconnectException => e
|
110
|
+
handle_force_disconnect(e)
|
111
|
+
rescue => e
|
112
|
+
handle_other_error(e)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Handles the case where the server tells us to restart -
|
116
|
+
# this clears the data, clears connection attempts, and
|
117
|
+
# waits a while to reconnect.
|
118
|
+
def handle_force_restart(error)
|
119
|
+
::OneApm::Agent.logger.debug error.message
|
120
|
+
drop_buffered_data
|
121
|
+
@service.reset_metric_id_cache if @service
|
122
|
+
@connect_state = :pending
|
123
|
+
sleep 30
|
124
|
+
end
|
125
|
+
|
126
|
+
# when a disconnect is requested, stop the current thread, which
|
127
|
+
# is the worker thread that gathers data and talks to the
|
128
|
+
# server.
|
129
|
+
def handle_force_disconnect(error)
|
130
|
+
::OneApm::Agent.logger.warn "OneApm forced this agent to disconnect (#{error.message})"
|
131
|
+
disconnect
|
132
|
+
end
|
133
|
+
|
134
|
+
# Handles an unknown error in the worker thread by logging
|
135
|
+
# it and disconnecting the agent, since we are now in an
|
136
|
+
# unknown state.
|
137
|
+
def handle_other_error(error)
|
138
|
+
::OneApm::Agent.logger.error "Unhandled error in worker thread, disconnecting this agent process:"
|
139
|
+
# These errors are fatal (that is, they will prevent the agent from
|
140
|
+
# reporting entirely), so we really want backtraces when they happen
|
141
|
+
::OneApm::Agent.logger.log_exception(:error, error)
|
142
|
+
disconnect
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'one_apm/transaction/transaction_state'
|
4
|
+
|
5
|
+
module OneApm
|
6
|
+
module Agent
|
7
|
+
# This module supports calculation of actual time spent processing requests over the course of
|
8
|
+
# one harvest period. It's similar to what you would get if you just added up all the
|
9
|
+
# execution times of controller calls, however that will be inaccurate when requests
|
10
|
+
# span the minute boundaries. This module manages accounting of requests not yet
|
11
|
+
# completed.
|
12
|
+
#
|
13
|
+
# Calls are re-entrant. All start calls must be paired with finish
|
14
|
+
# calls, or a reset call.
|
15
|
+
module BusyCalculator
|
16
|
+
|
17
|
+
extend self
|
18
|
+
|
19
|
+
# For testability, add accessors:
|
20
|
+
attr_reader :harvest_start, :accumulator
|
21
|
+
|
22
|
+
# sets up busy calculations based on the start and end of
|
23
|
+
# transactions - used for a rough estimate of what percentage of
|
24
|
+
# wall clock time is spent processing requests
|
25
|
+
def dispatcher_start(time) #THREAD_LOCAL_ACCESS
|
26
|
+
state = TransactionState.tl_get
|
27
|
+
state.busy_entries ||= 0
|
28
|
+
callers = state.busy_entries += 1
|
29
|
+
return if callers > 1
|
30
|
+
@lock.synchronize do
|
31
|
+
@entrypoint_stack.push time
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# called when a transaction finishes, to add time to the
|
36
|
+
# instance variable accumulator. this is harvested when we send
|
37
|
+
# data to the server
|
38
|
+
def dispatcher_finish(end_time = nil) #THREAD_LOCAL_ACCESS
|
39
|
+
state = TransactionState.tl_get
|
40
|
+
# If #dispatcher_start hasn't been called at least once, abort early
|
41
|
+
return unless state.busy_entries
|
42
|
+
|
43
|
+
end_time ||= time_now
|
44
|
+
callers = state.busy_entries -= 1
|
45
|
+
|
46
|
+
# Ignore nested calls
|
47
|
+
return if callers > 0
|
48
|
+
|
49
|
+
@lock.synchronize do
|
50
|
+
if @entrypoint_stack.empty?
|
51
|
+
::OneApm::Agent.logger.warn("Stack underflow tracking dispatcher entry and exit!\n #{caller.join(" \n")}")
|
52
|
+
else
|
53
|
+
@accumulator += (end_time - @entrypoint_stack.pop).to_f
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# this returns the size of the entry point stack, which
|
59
|
+
# determines how many transactions are running
|
60
|
+
def busy_count
|
61
|
+
@entrypoint_stack.size
|
62
|
+
end
|
63
|
+
|
64
|
+
# Reset the state of the information accumulated by all threads,
|
65
|
+
# but only reset the recursion counter for this thread.
|
66
|
+
def reset #THREAD_LOCAL_ACCESS
|
67
|
+
@entrypoint_stack = []
|
68
|
+
TransactionState.tl_get.busy_entries = 0
|
69
|
+
@lock ||= Mutex.new
|
70
|
+
@accumulator = 0
|
71
|
+
@harvest_start = time_now
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# Called before uploading to to the server to collect current busy stats.
|
76
|
+
def harvest_busy
|
77
|
+
busy = 0
|
78
|
+
t0 = time_now
|
79
|
+
@lock.synchronize do
|
80
|
+
busy = accumulator
|
81
|
+
@accumulator = 0
|
82
|
+
|
83
|
+
# Walk through the stack and capture all times up to
|
84
|
+
# now for entrypoints
|
85
|
+
@entrypoint_stack.size.times do |frame|
|
86
|
+
busy += (t0 - @entrypoint_stack[frame]).to_f
|
87
|
+
@entrypoint_stack[frame] = t0
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
busy = 0.0 if busy < 0.0 # don't go below 0%
|
93
|
+
|
94
|
+
time_window = (t0 - harvest_start).to_f
|
95
|
+
time_window = 1.0 if time_window == 0.0 # protect against divide by zero
|
96
|
+
|
97
|
+
busy = busy / time_window
|
98
|
+
|
99
|
+
if Agent.config[:report_instance_busy]
|
100
|
+
OneApm::Agent.record_metric('Instance/Busy', busy)
|
101
|
+
end
|
102
|
+
@harvest_start = t0
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# so we can stub Time.now only for the BusyCalculator in tests
|
108
|
+
def time_now
|
109
|
+
Time.now
|
110
|
+
end
|
111
|
+
|
112
|
+
self.reset
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|