Skip to content

Instantly share code, notes, and snippets.

@keithrbennett
Last active March 30, 2025 12:45
Show Gist options
  • Save keithrbennett/e37b7473e018b5cfa5d98ee37e8a0789 to your computer and use it in GitHub Desktop.
Save keithrbennett/e37b7473e018b5cfa5d98ee37e8a0789 to your computer and use it in GitHub Desktop.
Python script to monitor and output Internet connection state to console and log file.
#!/usr/bin/env python -u
# This script monitors the internet connection status and logs the changes to a file.
# It uses ping or http to check the connection and the platform module to determine the appropriate ping command for the operating system.
# The script writes both human-readable output to stdout and machine-readable JSON logs to the specified log file.
# Each log entry includes:
# - timestamp: ISO format timestamp
# - state: Current connection state ("On" or "Off")
# - duration: Duration in the previous state
# - event: Only present when monitoring stops (value: "monitor_stopped")
# The script supports command-line arguments to specify the check interval and log file.
# It also handles keyboard interrupts to gracefully stop the monitoring process.
# Sample console output:
# Internet connection monitor v3.0.1
# Use -h or --help for detailed usage information
# Internet connection monitoring started (checking every 1 seconds)
# Logging to: internet-monitor.log
# Press Ctrl+C to stop monitoring
# 2025-03-27 13:12:27 - Internet connection state: On: 00:00:01
# 2025-03-27 13:12:33 - Internet connection state: Off: 00:00:05
# 2025-03-27 13:12:36 - Internet connection state: On: 00:00:02^C
# 2025-03-27 13:12:37 - Monitoring stopped - Connection was On for 00:00:02
# Sample log file output:
{"timestamp": "2025-03-27T13:12:26.592210", "state": "On", "duration": 0, "event": "monitor_started"}
{"timestamp": "2025-03-27T13:12:29.750346", "state": "Off", "duration": 2.23}
{"timestamp": "2025-03-27T13:12:34.821500", "state": "On", "duration": 6.07}
{"timestamp": "2025-03-27T13:12:37.300495", "state": "On", "duration": 2.48, "event": "monitor_stopped"}
import time
import datetime
import sys
import argparse
import json
import urllib.request
import urllib.error
def check_internet_connection():
"""Check if there is an active internet connection."""
return check_internet_connection_with_http()
def check_internet_connection_with_http():
"""Check if there is an active internet connection using HTTP."""
try:
# Use Google's 204 endpoint for a quick connection test
urllib.request.urlopen('https://www.google.com/generate_204')
return True
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ConnectionResetError):
return False
def check_internet_connection_with_ping():
"""Check if there is an active internet connection using ping."""
try:
# Choose the appropriate ping command based on the operating system
if platform.system().lower() == 'windows':
ping_count_param = '-n'
else:
ping_count_param = '-c'
# Ping Google's DNS server with timeout
subprocess.check_output(['ping', ping_count_param, '1', '8.8.8.8'],
stderr=subprocess.STDOUT,
universal_newlines=True)
return True
except (subprocess.CalledProcessError, subprocess.SubprocessError):
return False
def format_duration(seconds):
"""Format duration in seconds to hours, minutes, and seconds."""
hours, remainder = divmod(seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}"
def internet_on_off_string(state, prev_state_change_time):
curr_time_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
clr_to_end_of_line = '\033[K'
const_str = f"\r{clr_to_end_of_line}{curr_time_str} - Internet connection state: "
elapsed_time = datetime.datetime.now() - prev_state_change_time
elapsed_time_str = format_duration(elapsed_time.total_seconds())
if state:
var_str = f"On: {elapsed_time_str}"
else:
var_str = f" Off: {elapsed_time_str}"
return const_str + var_str
def state_label(state):
return "On" if state else "Off"
def create_log_entry(current_state, duration=0, event=None):
"""Create a log entry dictionary with the given parameters."""
log_entry = {
'timestamp': datetime.datetime.now().isoformat(),
'state': state_label(current_state),
'duration': round(duration, 2)
}
if event is not None:
log_entry['event'] = event
return log_entry
def write_log_entry(log_file, log_entry):
"""Write a log entry to the specified file."""
with open(log_file, 'a') as f:
f.write(json.dumps(log_entry) + '\n')
def monitor_connection(check_interval=5, log_file='internet-monitor.log'):
"""
Monitor internet connection and log changes.
Args:
check_interval: Time in seconds between connection checks
log_file: Name of the file to write machine-readable logs
"""
# Initial check
previous_state = check_internet_connection()
state_change_time = datetime.datetime.now()
# Write initial state to both stdout and log file
write_log_entry(log_file, create_log_entry(previous_state, event='monitor_started'))
print(internet_on_off_string(previous_state, state_change_time), end='')
try:
while True:
time.sleep(check_interval)
current_time = datetime.datetime.now()
current_state = check_internet_connection()
# If the state has changed
if current_state != previous_state:
# Write machine-readable log entry
duration = (current_time - state_change_time).total_seconds()
log_entry = create_log_entry(
previous_state,
duration
)
write_log_entry(log_file, log_entry)
# Write human-readable output for state changes
print(f"\n{internet_on_off_string(current_state, current_time)}", end='')
# Update state tracking variables
previous_state = current_state
state_change_time = current_time
else:
print(internet_on_off_string(current_state, state_change_time), end='')
except KeyboardInterrupt:
# Calculate final duration when the program is interrupted
current_time = datetime.datetime.now()
duration = (current_time - state_change_time).total_seconds()
# Write final log entry
log_entry = create_log_entry(
previous_state,
duration=duration,
event='monitor_stopped'
)
write_log_entry(log_file, log_entry)
print(f"\n{current_time.strftime('%Y-%m-%d %H:%M:%S')} - "
f"Monitoring stopped - Connection was {state_label(current_state)} "
f"for {format_duration(duration)}")
sys.exit(0)
def main():
parser = argparse.ArgumentParser(
description='Monitor internet connection status',
epilog="""
Examples:
./internet_monitor.py -n 10 # Check every 10 seconds
./internet_monitor.py -l my-log.json # Use custom log file
./internet_monitor.py -n 5 -l log.txt # Combine options
The script writes both human-readable output to stdout and machine-readable
JSON logs to the specified log file. Each log entry includes:
- timestamp: ISO format timestamp
- state: Current connection state ("On" or "Off")
- duration: Duration in the previous state
- event: Only present when monitoring stops (value: "monitor_stopped")
""",
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-n', '--interval', type=float, default=5,
help='Check interval in seconds (default: 5)')
parser.add_argument('-l', '--log-file', default='internet-monitor.log',
help='Name of the log file (default: internet-monitor.log)')
args = parser.parse_args()
print("Internet connection monitor v3.0.1")
print("Use -h or --help for detailed usage information")
print(f"Internet connection monitoring started (checking every {args.interval} seconds)")
print(f"Logging to: {args.log_file}")
print("Press Ctrl+C to stop monitoring")
monitor_connection(args.interval, args.log_file)
if __name__ == "__main__":
main()
@keithrbennett
Copy link
Author

As a followup to the previous comment, I realized some clarifications to the program's output should be made, and asked the AI assistance to implement them. After about a dozen attempts at the first improvement that resulted in failure, I decided to do it myself, the old fashioned way. It turned out that all that was needed was a minor tweak to a single line of code. I wasted a lot of time expecting the AI to be brilliant, but it was an utter failure. I learned that a really important skill with AI assisted coding is just knowing when and when not to use it at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment