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,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module OneApm
|
4
|
+
module Agent
|
5
|
+
module Datastores
|
6
|
+
module Mongo
|
7
|
+
module Obfuscator
|
8
|
+
|
9
|
+
WHITELIST = [:operation].freeze
|
10
|
+
|
11
|
+
def self.obfuscate_statement(source, whitelist=WHITELIST)
|
12
|
+
obfuscated = {}
|
13
|
+
source.each do |key, value|
|
14
|
+
if whitelist.include?(key)
|
15
|
+
obfuscated[key] = value
|
16
|
+
else
|
17
|
+
obfuscated[key] = obfuscate_value(value, whitelist)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
obfuscated
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.obfuscate_value(value, whitelist)
|
25
|
+
if value.is_a?(Hash)
|
26
|
+
obfuscate_statement(value, whitelist)
|
27
|
+
elsif value.is_a?(Array)
|
28
|
+
value.map {|v| obfuscate_value(v, whitelist)}
|
29
|
+
else
|
30
|
+
'?'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'one_apm/agent/datastores/mongo/obfuscator'
|
4
|
+
|
5
|
+
module OneApm
|
6
|
+
module Agent
|
7
|
+
module Datastores
|
8
|
+
module Mongo
|
9
|
+
module StatementFormatter
|
10
|
+
|
11
|
+
PLAINTEXT_KEYS = [
|
12
|
+
:database,
|
13
|
+
:collection,
|
14
|
+
:operation,
|
15
|
+
:fields,
|
16
|
+
:skip,
|
17
|
+
:limit,
|
18
|
+
:order
|
19
|
+
]
|
20
|
+
|
21
|
+
OBFUSCATE_KEYS = [
|
22
|
+
:selector
|
23
|
+
]
|
24
|
+
|
25
|
+
def self.format(statement, operation)
|
26
|
+
return nil unless OneApm::Agent.config[:'mongo.capture_queries']
|
27
|
+
|
28
|
+
result = { :operation => operation }
|
29
|
+
|
30
|
+
PLAINTEXT_KEYS.each do |key|
|
31
|
+
result[key] = statement[key] if statement.key?(key)
|
32
|
+
end
|
33
|
+
|
34
|
+
OBFUSCATE_KEYS.each do |key|
|
35
|
+
if statement.key?(key) && statement[key]
|
36
|
+
obfuscated = obfuscate(statement[key])
|
37
|
+
result[key] = obfuscated if obfuscated
|
38
|
+
end
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.obfuscate(statement)
|
44
|
+
statement = Obfuscator.obfuscate_statement(statement) if OneApm::Agent.config[:'mongo.obfuscate_queries']
|
45
|
+
statement
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module OneApm::Agent
|
4
|
+
class EventListener
|
5
|
+
|
6
|
+
attr_accessor :runaway_threshold
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@events = {}
|
10
|
+
@runaway_threshold = 100
|
11
|
+
end
|
12
|
+
|
13
|
+
def subscribe(event, &handler)
|
14
|
+
@events[event] ||= []
|
15
|
+
@events[event] << handler
|
16
|
+
check_for_runaway_subscriptions(event)
|
17
|
+
end
|
18
|
+
|
19
|
+
def check_for_runaway_subscriptions(event)
|
20
|
+
count = @events[event].size
|
21
|
+
OneApm::Agent.logger.debug("Run-away event subscription on #{event}? Subscribed #{count}") if count > @runaway_threshold
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear
|
25
|
+
@events.clear
|
26
|
+
end
|
27
|
+
|
28
|
+
def notify(event, *args)
|
29
|
+
return unless @events.has_key?(event)
|
30
|
+
|
31
|
+
@events[event].each do |handler|
|
32
|
+
begin
|
33
|
+
handler.call(*args)
|
34
|
+
rescue => err
|
35
|
+
OneApm::Agent.logger.debug("Failure during notify for #{event}", err)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
module OneApm
|
6
|
+
module Agent
|
7
|
+
class EventLoop
|
8
|
+
class Timer
|
9
|
+
|
10
|
+
attr_reader :next_fire_time, :event, :interval, :last_fired_at
|
11
|
+
|
12
|
+
def initialize(interval, event, repeat=false)
|
13
|
+
@interval = interval
|
14
|
+
@event = event
|
15
|
+
@repeat = repeat
|
16
|
+
@started_at = Time.now
|
17
|
+
@last_fired_at = nil
|
18
|
+
reschedule
|
19
|
+
end
|
20
|
+
|
21
|
+
def reschedule
|
22
|
+
@next_fire_time = calculate_next_fire_time
|
23
|
+
end
|
24
|
+
|
25
|
+
def advance(amount)
|
26
|
+
@next_fire_time -= amount
|
27
|
+
end
|
28
|
+
|
29
|
+
def last_interval_start
|
30
|
+
@last_fired_at || @started_at
|
31
|
+
end
|
32
|
+
|
33
|
+
def calculate_next_fire_time
|
34
|
+
now = Time.now
|
35
|
+
return now if @interval == 0
|
36
|
+
fire_time = @last_fired_at || now
|
37
|
+
while fire_time <= now
|
38
|
+
fire_time += @interval
|
39
|
+
end
|
40
|
+
fire_time
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_fired_time
|
44
|
+
@last_fired_at = Time.now
|
45
|
+
end
|
46
|
+
|
47
|
+
def due?(now=Time.now)
|
48
|
+
now >= @next_fire_time
|
49
|
+
end
|
50
|
+
|
51
|
+
def finished?
|
52
|
+
!@repeat && @last_fired_at
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@self_pipe_rd, @self_pipe_wr = IO.pipe
|
59
|
+
@event_queue = Queue.new
|
60
|
+
@stopped = false
|
61
|
+
@timers = {}
|
62
|
+
|
63
|
+
@subscriptions = Hash.new { |h,k| h[k] = [] }
|
64
|
+
@subscriptions[:__add_timer] << Proc.new { |t| set_timer(t) }
|
65
|
+
@subscriptions[:__add_event] << Proc.new { |e, blk| @subscriptions[e] << blk }
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_timer(timer)
|
69
|
+
existing_timer = @timers[timer.event]
|
70
|
+
|
71
|
+
if existing_timer
|
72
|
+
elapsed_interval = Time.now - existing_timer.last_interval_start
|
73
|
+
timer.advance(elapsed_interval)
|
74
|
+
end
|
75
|
+
|
76
|
+
@timers[timer.event] = timer
|
77
|
+
|
78
|
+
fire_timer(timer)
|
79
|
+
end
|
80
|
+
|
81
|
+
def next_timeout
|
82
|
+
return nil if @timers.empty?
|
83
|
+
timeout = @timers.values.map(&:next_fire_time).min - Time.now
|
84
|
+
timeout < 0 ? 0 : timeout
|
85
|
+
end
|
86
|
+
|
87
|
+
def stopped?
|
88
|
+
@stopped
|
89
|
+
end
|
90
|
+
|
91
|
+
def stop
|
92
|
+
@stopped = true
|
93
|
+
wakeup
|
94
|
+
end
|
95
|
+
|
96
|
+
def run
|
97
|
+
OneApm::Agent.logger.debug "Running event loop"
|
98
|
+
while !stopped?
|
99
|
+
run_once
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_once(nonblock=false)
|
104
|
+
wait_to_run(nonblock)
|
105
|
+
|
106
|
+
prune_timers
|
107
|
+
fire_timers
|
108
|
+
|
109
|
+
until @event_queue.empty?
|
110
|
+
evt, args = @event_queue.pop
|
111
|
+
dispatch_event(evt, args)
|
112
|
+
reschedule_timer_for_event(evt)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def wait_to_run(nonblock)
|
117
|
+
timeout = nonblock ? 0 : next_timeout
|
118
|
+
ready = IO.select([@self_pipe_rd], nil, nil, timeout)
|
119
|
+
|
120
|
+
if ready && ready[0] && ready[0][0] && ready[0][0] == @self_pipe_rd
|
121
|
+
@self_pipe_rd.read(1)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def fire_timers
|
126
|
+
@timers.each do |event, timer|
|
127
|
+
fire_timer(timer)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def fire_timer(timer)
|
132
|
+
if timer.due?
|
133
|
+
@event_queue << [timer.event]
|
134
|
+
timer.set_fired_time
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def prune_timers
|
139
|
+
@timers.delete_if { |e, t| t.finished? }
|
140
|
+
end
|
141
|
+
|
142
|
+
def dispatch_event(event, args)
|
143
|
+
OneApm::Agent.logger.debug("EventLoop: Dispatching event '#{event}' with #{@subscriptions[event].size} callback(s).")
|
144
|
+
|
145
|
+
errors = []
|
146
|
+
@subscriptions[event].each do |s|
|
147
|
+
begin
|
148
|
+
s.call(*args)
|
149
|
+
rescue OneApm::ForceRestartException, OneApm::ForceDisconnectException
|
150
|
+
raise
|
151
|
+
rescue => e
|
152
|
+
errors << e
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if !errors.empty?
|
157
|
+
OneApm::Agent.logger.error "#{errors.size} error(s) running task for event '#{event}' in Agent Event Loop:", *errors
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def reschedule_timer_for_event(e)
|
162
|
+
@timers[e].reschedule if @timers[e]
|
163
|
+
end
|
164
|
+
|
165
|
+
def on(event, &blk)
|
166
|
+
fire(:__add_event, event, blk)
|
167
|
+
end
|
168
|
+
|
169
|
+
def fire(event, *args)
|
170
|
+
@event_queue << [event, args]
|
171
|
+
wakeup
|
172
|
+
end
|
173
|
+
|
174
|
+
def fire_every(interval, event)
|
175
|
+
OneApm::Agent.logger.debug "Firing event #{event} every #{interval} seconds."
|
176
|
+
fire(:__add_timer, Timer.new(interval, event, true))
|
177
|
+
end
|
178
|
+
|
179
|
+
def fire_after(interval, event)
|
180
|
+
OneApm::Agent.logger.debug "Firing event #{event} after #{interval} seconds."
|
181
|
+
fire(:__add_timer, Timer.new(interval, event, false))
|
182
|
+
end
|
183
|
+
|
184
|
+
def wakeup
|
185
|
+
@self_pipe_wr.write_nonblock '.'
|
186
|
+
rescue Errno::EAGAIN
|
187
|
+
OneApm::Agent.logger.debug "Failed to wakeup event loop"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
module OneApm
|
5
|
+
module Agent
|
6
|
+
|
7
|
+
# A worker loop executes a set of registered tasks on a single thread.
|
8
|
+
# A task is a proc or block with a specified call period in seconds.
|
9
|
+
class WorkerLoop
|
10
|
+
|
11
|
+
attr_accessor :period, :propagate_errors
|
12
|
+
attr_reader :iterations
|
13
|
+
|
14
|
+
# Optional argument :duration (in seconds) for how long the worker loop runs
|
15
|
+
# or :limit (integer) for max number of iterations
|
16
|
+
def initialize(opts={})
|
17
|
+
@should_run = true
|
18
|
+
@next_invocation_time = Time.now
|
19
|
+
@period = 60.0
|
20
|
+
@duration = opts[:duration] if opts[:duration]
|
21
|
+
@limit = opts[:limit] if opts[:limit]
|
22
|
+
@iterations = 0
|
23
|
+
@propagate_errors = opts.fetch(:propagate_errors, false)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Reset state that is changed by running the worker loop
|
27
|
+
def setup(period, task)
|
28
|
+
@task = task
|
29
|
+
@period = period if period
|
30
|
+
@should_run = true
|
31
|
+
@iterations = 0
|
32
|
+
|
33
|
+
now = Time.now
|
34
|
+
@deadline = now + @duration if @duration
|
35
|
+
@next_invocation_time = (now + @period)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Run infinitely, calling the registered tasks at their specified
|
39
|
+
# call periods. The caller is responsible for creating the thread
|
40
|
+
# that runs this worker loop. This will run the task immediately.
|
41
|
+
def run(period=nil, &block)
|
42
|
+
setup(period, block)
|
43
|
+
while keep_running? do
|
44
|
+
sleep_time = schedule_next_invocation
|
45
|
+
sleep(sleep_time) if sleep_time > 0
|
46
|
+
run_task if keep_running?
|
47
|
+
@iterations += 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def schedule_next_invocation
|
52
|
+
now = Time.now
|
53
|
+
while @next_invocation_time <= now && @period > 0
|
54
|
+
@next_invocation_time += @period
|
55
|
+
end
|
56
|
+
@next_invocation_time - Time.now
|
57
|
+
end
|
58
|
+
|
59
|
+
# a simple accessor for @should_run
|
60
|
+
def keep_running?
|
61
|
+
@should_run && under_duration? && under_limit?
|
62
|
+
end
|
63
|
+
|
64
|
+
def under_duration?
|
65
|
+
!@deadline || Time.now < @deadline
|
66
|
+
end
|
67
|
+
|
68
|
+
def under_limit?
|
69
|
+
@limit.nil? || @iterations < @limit
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sets @should_run to false. Returns false
|
73
|
+
def stop
|
74
|
+
@should_run = false
|
75
|
+
end
|
76
|
+
|
77
|
+
# Executes the block given to the worker loop, and handles many
|
78
|
+
# possible errors. Also updates the execution time so that the
|
79
|
+
# next run occurs on schedule, even if we execute at some odd time
|
80
|
+
def run_task
|
81
|
+
if @propagate_errors
|
82
|
+
@task.call
|
83
|
+
else
|
84
|
+
begin
|
85
|
+
@task.call
|
86
|
+
rescue OneApm::ForceRestartException, OneApm::ForceDisconnectException
|
87
|
+
# blow out the loop
|
88
|
+
raise
|
89
|
+
rescue => e
|
90
|
+
# Don't blow out the stack for anything that hasn't already propagated
|
91
|
+
::OneApm::Agent.logger.error "Error running task in Agent Worker Loop:", e
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module OneApm
|
4
|
+
module Agent
|
5
|
+
class Harvester
|
6
|
+
|
7
|
+
attr_accessor :starting_pid
|
8
|
+
|
9
|
+
# Inject target for after_fork call to avoid spawning thread in tests
|
10
|
+
def initialize(events, after_forker = OneApm::Agent)
|
11
|
+
# We intentionally don't set our pid as started at this point.
|
12
|
+
# Startup routines must call mark_started when they consider us set!
|
13
|
+
@starting_pid = nil
|
14
|
+
@after_forker = after_forker
|
15
|
+
|
16
|
+
if events
|
17
|
+
events.subscribe(:start_transaction, &method(:on_transaction))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_transaction(*_)
|
22
|
+
return unless restart_in_children_enabled? && needs_restart? && harvest_thread_enabled?
|
23
|
+
|
24
|
+
restart_harvest_thread
|
25
|
+
end
|
26
|
+
|
27
|
+
def mark_started(pid = Process.pid)
|
28
|
+
@starting_pid = pid
|
29
|
+
end
|
30
|
+
|
31
|
+
def needs_restart?(pid = Process.pid)
|
32
|
+
@starting_pid != pid
|
33
|
+
end
|
34
|
+
|
35
|
+
def restart_in_children_enabled?
|
36
|
+
OneApm::Agent.config[:restart_thread_in_children]
|
37
|
+
end
|
38
|
+
|
39
|
+
def harvest_thread_enabled?
|
40
|
+
!OneApm::Agent.config[:disable_harvest_thread]
|
41
|
+
end
|
42
|
+
|
43
|
+
def restart_harvest_thread
|
44
|
+
@after_forker.after_fork(:force_reconnect => true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|