system-admin intermediate

How to send system metrics to a log file in Perl?

Question

How to send system metrics to a log file in Perl?

How to Send System Metrics to a Log File in Perl

Collecting system metrics and logging them to a file is a common task for system administrators and developers monitoring server health or debugging performance issues. In Perl, you can easily gather key system statistics and output them in a structured, readable form to a log file.

This answer covers:

  • How to extract basic system information like CPU load, memory usage, and uptime
  • Best practices for logging data with timestamps
  • Perl-specific tips such as file handling, TMTOWTDI ("There's more than one way to do it"), and context considerations
  • A runnable code example for Unix-like systems using /proc and standard command output

Gathering System Metrics in Perl

On Unix and Linux systems, some of the easiest sources for metrics are:

  • /proc/loadavg for load averages
  • /proc/meminfo for memory statistics
  • the uptime command for system uptime
  • date or localtime for timestamps

Perl’s ability to open and read text files line-by-line makes it straightforward to parse these resources. Using backticks or qx(), you can capture command output, but reading files directly is often faster and cleaner.

Logging with Timestamps

It is important to prefix each log entry with a timestamp, ideally in ISO 8601 format (e.g., 2024-04-27T13:45:00) for easy sorting and parsing by log monitoring tools.

Key Perl Concepts Relevant Here

  • Sigils: Scalars like $loadavg hold string or numeric data. Arrays @data hold multiple lines or elements.
  • Context: When reading from files or running commands, context (scalar vs list) affects behavior. e.g., my @lines = <FILE>; reads all lines into an array.
  • TMTOWTDI: Perl permits multiple ways to read system metrics—by external commands, modules, or file parsing.

Common Pitfalls

  • Be careful to open files with proper error checking to avoid silent failures.
  • File formats like /proc/meminfo can change slightly between kernel versions, so code may need adjustments.
  • Running external commands like uptime assumes they exist in PATH.
  • Ensure filehandles are closed properly or use lexical filehandles for automatic scope closing.

Runnable Example: Logging Basic System Metrics

This script reads system load averages, memory usage, and uptime, then appends a timestamped log entry to system_metrics.log in the current directory. It demonstrates Perl file IO, parsing, and basic formatting.


#!/usr/bin/perl
use strict;
use warnings;

# Log file path
my $log_file = "system_metrics.log";

# Get timestamp in ISO 8601 format
my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
$year += 1900;
$mon  += 1;
my $timestamp = sprintf("%04d-%02d-%02dT%02d:%02d:%02d",
                        $year, $mon, $mday, $hour, $min, $sec);

# Read load averages from /proc/loadavg
my $loadavg = "";
if (open my $fh, '<', '/proc/loadavg') {
    $loadavg = <$fh>;
    chomp $loadavg;
    close $fh;
} else {
    $loadavg = "N/A";
}

# Read total and free memory from /proc/meminfo
my ($mem_total, $mem_free) = ("N/A", "N/A");
if (open my $meminfo, '<', '/proc/meminfo') {
    while (<$meminfo>) {
        if (/^MemTotal:\s+(\d+)\skB/) { $mem_total = $1; }
        if (/^MemFree:\s+(\d+)\skB/)  { $mem_free  = $1; }
        last if $mem_total ne "N/A" && $mem_free ne "N/A";
    }
    close $meminfo;
}

# Get uptime from `uptime` command (fallback if needed)
my $uptime = "";
my $uptime_out = qx{uptime};
if ($? == 0) {
    $uptime = $uptime_out;
    $uptime =~ s/^\s+|\s+$//g;  # trim whitespace
} else {
    $uptime = "N/A";
}

# Format log entry
my $log_entry = sprintf(
    "[%s] LoadAverage: %s | MemTotal: %s kB | MemFree: %s kB | Uptime: %s\n",
    $timestamp, $loadavg, $mem_total, $mem_free, $uptime
);

# Append to log file
open my $logfh, '>>', $log_file or die "Cannot open $log_file: $!";
print $logfh $log_entry;
close $logfh;

# Print confirmation to STDOUT
print "Logged system metrics at $timestamp\n";

Explanation

  • The script uses localtime() to get the current datetime and formats it as ISO 8601.
  • /proc/loadavg returns the system load average; reading the first line suffices.
  • /proc/meminfo is parsed for total and free memory in kilobytes.
  • The output of uptime provides a human-readable system uptime and load info.
  • The log entry gets appended to a file with a newline termination.
  • Finally, a confirmation message prints out the timestamp that was logged.

Extending and Customizing

You can extend this basic approach by:

  • Collecting additional metrics like disk usage (df), network stats, or process counts.
  • Using modules like Sys::Hostname or Time::HiRes (core modules on modern Perl) for enhanced logging.
  • Scheduling the script periodically using cron for continuous monitoring.
  • Implementing JSON or CSV output for easier integration into monitoring dashboards.

This approach works on Perl 5.10+ and does not require any external modules beyond core. It showcases Perl’s strength in text parsing and file handling, perfectly suited for sysadmin tasks.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 21ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Logged system metrics at 2025-12-30T13:02:25
STDERR
(empty)

Was this helpful?

Related Questions