Class: WifiWand::EventLogger
- Inherits:
-
Object
- Object
- WifiWand::EventLogger
- Includes:
- Timing
- Defined in:
- lib/wifi_wand/services/event_logger.rb
Overview
EventLogger continuously monitors WiFi status and logs state changes. Each poll captures WiFi power and current SSID, then derives internet events from the explicit connectivity-state model. Internet reachability is checked via internet_connectivity_state on every poll so internet_on/internet_off always reflect the full TCP+DNS+captive-portal path. Internet reachability is checked independently of WiFi association so alternate uplinks such as Ethernet still produce accurate Internet events.
Threading model:
runis a blocking loop. If a caller wants to stop it programmatically,runshould usually execute in a background thread.- The calling thread, often the main thread, can then call
stopand wait for the logger thread to exit. - If
runandstopare both expected to happen on the same thread, thenstopcannot interrupt the loop while that thread is blocked waiting for the next poll. - Ctrl+C is different because it raises
Interrupt, which can break into the blocking wait without requiring another Ruby thread to callstop.
In other words, stop is intended for coordinated shutdown from another
thread, while Interrupt covers interactive termination from the console.
Constant Summary collapse
- SSID_UNAVAILABLE_LABEL =
NetworkIdentity::SSID_UNAVAILABLE_LABEL
- POLLING_BOUNDARY_ERROR =
StandardError excludes process-control and VM-level exceptions like Interrupt, SystemExit, and NoMemoryError.
StandardError
Instance Attribute Summary collapse
-
#interval ⇒ Object
readonly
Returns the value of attribute interval.
-
#log_file_manager ⇒ Object
readonly
Returns the value of attribute log_file_manager.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
Instance Method Summary collapse
- #cleanup ⇒ Object
-
#initialize(model, interval: 5, log_file_path: nil, log_file_manager: nil, internet_probe_timeout_in_secs: nil, runtime_config: nil, **kwargs) ⇒ EventLogger
constructor
A new instance of EventLogger.
- #log_initial_state(state) ⇒ Object
- #out_stream ⇒ Object
-
#run ⇒ Object
Start polling loop.
- #stop ⇒ Object
- #verbose? ⇒ Boolean
Methods included from Timing
monotonic_now, status_deadline, status_timeout_for
Constructor Details
#initialize(model, interval: 5, log_file_path: nil, log_file_manager: nil, internet_probe_timeout_in_secs: nil, runtime_config: nil, **kwargs) ⇒ EventLogger
Returns a new instance of EventLogger.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/wifi_wand/services/event_logger.rb', line 46 def initialize( model, interval: 5, log_file_path: nil, log_file_manager: nil, internet_probe_timeout_in_secs: nil, runtime_config: nil, **kwargs ) @model = model @interval = interval @internet_probe_timeout_in_secs = internet_probe_timeout_in_secs @runtime_config = runtime_config || RuntimeConfig.new(verbose: kwargs[:verbose], utc: kwargs[:utc]) @verbose_override = kwargs[:verbose] if kwargs.key?(:verbose) @utc_override = !!kwargs[:utc] if kwargs.key?(:utc) @out_stream_override = kwargs[:out_stream] if kwargs.key?(:out_stream) # Only create LogFileManager if file logging is requested @log_file_manager = if log_file_manager log_file_manager elsif log_file_path LogFileManager.new( log_file_path: log_file_path, out_stream: (@out_stream_override if kwargs.key?(:out_stream)), verbose: (@verbose_override if kwargs.key?(:verbose)), runtime_config: @runtime_config ) end @previous_state = nil @wait_mutex = Mutex.new @wait_condition = ConditionVariable.new @running = false @file_logging_warning_emitted = false @consecutive_state_fetch_failures = 0 @state_fetch_warning_emitted = false end |
Instance Attribute Details
#interval ⇒ Object (readonly)
Returns the value of attribute interval.
43 44 45 |
# File 'lib/wifi_wand/services/event_logger.rb', line 43 def interval @interval end |
#log_file_manager ⇒ Object (readonly)
Returns the value of attribute log_file_manager.
43 44 45 |
# File 'lib/wifi_wand/services/event_logger.rb', line 43 def log_file_manager @log_file_manager end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
43 44 45 |
# File 'lib/wifi_wand/services/event_logger.rb', line 43 def model @model end |
Instance Method Details
#cleanup ⇒ Object
155 156 157 158 159 160 |
# File 'lib/wifi_wand/services/event_logger.rb', line 155 def cleanup if @log_file_manager @log_file_manager.close @log_file_manager = nil end end |
#log_initial_state(state) ⇒ Object
145 146 147 148 149 150 151 152 153 |
# File 'lib/wifi_wand/services/event_logger.rb', line 145 def log_initial_state(state) (format_json_line( event: 'current_state', wifi: json_boolean_value(state[:wifi_on]), connection: json_connection_value(state[:connected]), network: json_network_value(state), internet: internet_state_label(state[:internet_state]) )) end |
#out_stream ⇒ Object
169 170 171 172 173 174 175 |
# File 'lib/wifi_wand/services/event_logger.rb', line 169 def out_stream if instance_variable_defined?(:@out_stream_override) @out_stream_override else runtime_config.out_stream end end |
#run ⇒ Object
Start polling loop. This method blocks until stop is called or Ctrl+C is pressed.
For programmatic shutdown, callers should usually run this in a background
thread so another thread can call stop.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/wifi_wand/services/event_logger.rb', line 85 def run start_running (format_json_line(event: 'logging_started', interval: @interval)) polling_error_raised = false begin while running? poll_started_at = monotonic_now current_state = fetch_current_state if @previous_state detect_and_emit_events(current_state) else log_initial_state(current_state) end @previous_state = current_state break unless running? sleep_until(poll_started_at + @interval) end rescue Interrupt stop rescue POLLING_BOUNDARY_ERROR => e polling_error_raised = true (e) raise ensure (format_json_line(event: 'logging_stopped')) unless polling_error_raised cleanup end end |
#stop ⇒ Object
162 163 164 165 166 167 |
# File 'lib/wifi_wand/services/event_logger.rb', line 162 def stop @wait_mutex.synchronize do @running = false @wait_condition.broadcast end end |
#verbose? ⇒ Boolean
521 522 523 524 525 526 527 |
# File 'lib/wifi_wand/services/event_logger.rb', line 521 def verbose? if instance_variable_defined?(:@verbose_override) @verbose_override else runtime_config.verbose end end |