# encoding: utf-8 module OneApm module Agent class Agent module StartWorkerThread OA_MIN_ALLOWED_REPORT_PERIOD = 1.0 OA_UTILIZATION_REPORT_PERIOD = 30 * 60 OA_LOG_ONCE_KEYS_RESET_PERIOD = 60.0 def start_worker_thread(connection_options = {}) if disable = OneApm::Manager.config[:disable_harvest_thread] OneApm::Manager.logger.info "Not starting Ruby Agent worker thread because :disable_harvest_thread is #{disable}" return end OneApm::Manager.logger.debug "Creating Ruby Agent worker thread." @worker_thread = OneApm::Agent::Threading::AgentThread.create('Worker Loop') do deferred_work!(connection_options) end end def deferred_work!(connection_options) catch_errors do OneApm::Manager.disable_all_tracing do connect(connection_options) if connected? create_and_run_event_loop else OneApm::Manager.logger.debug "No connection. Worker thread ending." end end end end def create_and_run_event_loop @event_loop = create_event_loop @event_loop.on(:report_data) { transmit_data } @event_loop.on(:report_event_data) { transmit_event_data } @event_loop.on(:reset_log_once_keys) { OneApm::Manager.logger.clear_already_logged } @event_loop.on(:detect_config) { detect_config } @event_loop.on(:reset_counter) { reset_cross_app_sampler_counter } @event_loop.on(:update_rule) { update_rule } @event_loop.fire_every(Manager.config[:data_report_period], :report_data) @event_loop.fire_every(report_period_for(:analytic_event_data), :report_event_data) @event_loop.fire_every(OA_LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys) @event_loop.fire_every(Manager.config[:data_report_period], :detect_config) @event_loop.fire_every(Manager.config[:data_report_period], :reset_counter) @event_loop.fire_every(Manager.config[:update_rule_period], :update_rule) if OneApm::Manager.config[:collect_utilization] && !in_resque_child_process? @event_loop.on(:report_utilization_data) { transmit_utilization_data } @event_loop.fire(:report_utilization_data) @event_loop.fire_every(OA_UTILIZATION_REPORT_PERIOD, :report_utilization_data) end @event_loop.run end def create_event_loop OneApm::Support::EventLoop.new end def report_period_for(method) config_key = "data_report_periods.#{method}".to_sym period = OneApm::Manager.config[config_key] if !period period = OneApm::Manager.config[:data_report_period] OneApm::Manager.logger.warn("Could not find configured period for #{method}, falling back to data_report_period (#{period} s)") end if period < OA_MIN_ALLOWED_REPORT_PERIOD OneApm::Manager.logger.warn("Configured #{config_key} was #{period}, but minimum allowed is #{OA_MIN_ALLOWED_REPORT_PERIOD}, using #{OA_MIN_ALLOWED_REPORT_PERIOD}.") period = OA_MIN_ALLOWED_REPORT_PERIOD end period end def stop_event_loop if @event_loop @event_loop.run_once(true) if OneApm::Manager.config[:force_send] @event_loop.stop end end private def catch_errors yield rescue OneApm::ForceRestartException => e handle_force_restart(e) retry rescue OneApm::ForceDisconnectException => e handle_force_disconnect(e) rescue => e handle_other_error(e) end def handle_force_restart(error) OneApm::Manager.logger.debug error.message drop_buffered_data @service.reset_metric_id_cache if @service @connect_state = :pending sleep 30 end def handle_force_disconnect(error) OneApm::Manager.logger.warn "OneApm forced this agent to disconnect (#{error.message})" disconnect end def handle_other_error(error) OneApm::Manager.logger.error "Unhandled error in worker thread, disconnecting this agent process:" OneApm::Manager.logger.log_exception(:error, error) disconnect end end end end end