Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Monitoring macOS Updates Remotely - Part 2 : Dashboard Generation


In Part 1 - we created a system for collecting automated update logs from remote macOS systems. Now I need to transform this raw log data into something meaningful - a visual dashboard that provides instant insight into the health and status of all monitored systems.

Making Sense of Raw Log Data

After implementing the log collection system from Part 1, we ended up with a folder full of time stamped log files. Each file contained valuable information, but manually parsing dozens of logs to understand system status was impractical. I needed an automated solution that could:

  • Parse multiple log files dynamically
  • Extract meaningful metrics from unstructured log data
  • Present information in an easily digestible format
  • Provide health status at a glance
  • Handle various timestamp formats and edge cases

Log Structure

Before building the dashboard generator, I analyzed the log file naming convention established in Part One:

YYYY-MM-DD-SiteName-automated_updates.log

This naming scheme allows the script to automatically extract both the date and site name without additional configuration files or manual input.

Building the Script engine

The core challenge was parsing timestamps and determining the most recent events. The logs contained various timestamp formats:

Mon Aug 25 10:14:16 BST 2025: Automated update check started
Wed Jul 30 20:08:00 BST 2025: Updates completed successfully

Pitfall #1: Timestamp Comparison Logic

My first approach used simple string comparison:

if ($timestamp -gt $currentSite.LastSuccessfulUpdate) {
    $currentSite.LastSuccessfulUpdate = $timestamp
}

The Problem: String comparison doesn't work for dates. "Wed Jul 30" appears "greater than" "Mon Aug 25" alphabetically, causing older dates to overwrite newer ones.

The Solution: Implement proper DateTime parsing with multiple format support:

$dateFormats = @(
    'ddd MMM dd HH:mm:ss BST yyyy',
    'ddd MMM  d HH:mm:ss BST yyyy',
    'MMM dd HH:mm:ss BST yyyy',
    'MMM  d HH:mm:ss BST yyyy'
)

foreach ($format in $dateFormats) {
    try {
        $currentDateTime = [DateTime]::ParseExact($timestampPart, $format, [System.Globalization.CultureInfo]::InvariantCulture)
        break
    } catch { continue }
}

Pitfall #2: Inconsistent Timestamp Formats

Different log entries used varying spacing for single-digit days:

  • Mon Aug 5 (two spaces)
  • Mon Aug 25 (one space)

The Solution: Create multiple format patterns to handle spacing variations and implement fallback parsing using the general [DateTime]::Parse() method.

The Health Status System

I implemented a color-coded health system that provides instant visual feedback based on when update checks are performed, not actual installations:

  • Healthy: System checked for updates within 7 days
  • Warning: Last update check performed 7-30 days ago
  • Critical: Last update check performed more than 30 days ago
  • No Updates: No update checks recorded
  • Unknown: Unable to determine check status

This approach makes sense because systems should be regularly checking for updates (daily or weekly)

The health status indicates whether the automated update checking mechanism is working properly, not whether new macOS versions are being installed constantly.

Dynamic HTML Generation

Rather than using static templates, I built a completely dynamic HTML generator that:

  1. Calculates summary statistics across all monitored systems
  2. Generates responsive CSS with modern styling
  3. Creates individual cards for each system with relevant metrics
  4. Includes update history showing recent macOS versions installed

Visual Result

This is what the dashboard looks like based on the sample data from the logs that has been generated:


This is a healthy server that has all the updates:


This is an unhealthy server that does not have the latest updates installed:

Usage

The final script requires minimal configuration and can be run directly of by specifying the -LogDirectory and -OutputFile from the script:

# Basic usage
.\Generate-UpdateDashboard.ps1

# Custom paths
.\Generate-UpdateDashboard.ps1 -LogDirectory "C:\Logs\AutomatedUpdates" -OutputFile "dashboard.html"

The script automatically:

  1. Discovers all .log files in the specified directory
  2. Extracts site names from filenames
  3. Parses log content for update events
  4. Calculates health metrics
  5. Generates a complete HTML dashing 
Previous Post Next Post

نموذج الاتصال