Make use of Extended IT to bolster your IT Support Offering
Extend your IT

Monitoring Windows Services with AWS Cloudwatch

If you are already using AWS CloudWatch for monitoring CPU, Disk & Memory usage of your AWS EC2 instances, I’m sure you agree with me that it’s a great monitoring platform (and pretty cheap). But if you aren’t using any custom metrics you aren’t getting the most out of it. With a little bit of effort there isn’t anything you can’t monitor through CloudWatch and today I’m going to show you how to monitor services on Windows systems to ensure they are running.

The basic setup involves

  1.  Setting up a PowerShell Script
  2.  Scheduling the script to run as often as you want to check the service (5 minutes)
  3.  Checking the CloudWatch metric
  4.  Setting up a CloudWatch alarm.

(Please Note: There is a cost involved in Cloudwatch and if you are monitoring alot of services and other custom metrics the costs can quickly add up, for more details on pricing – https://aws.amazon.com/cloudwatch/pricing/)


Setting up the PowerShell Script

The basic flow of the Powershell script is to check each of your specified services, each of these that is running will be posted to a CloudWatch Metric.

Import-Module AWSPowerShell
#Set the region of your cloudwatch
Set-AWSDefaultRegion -Region eu-central-1

#Feel free to change this to match any existing namespaces you might have.
$Namespace = 'service-monitor'

#Update the log path, use this for troubleshooting. 
$logpath = "C:\Scripts\Slog.txt"

#Use an AWS Service to get this systems Instance ID
$instanceId = (New-Object System.Net.WebClient).DownloadString("")

$instanceId | Out-File -FilePath $logpath -Append

# Associate current EC2 instance with your custom cloudwatch metric
$instanceDimension = New-Object -TypeName Amazon.CloudWatch.Model.Dimension;
$instanceDimension.Name = "instanceid";
$instanceDimension.Value = $instanceId;

    $metrics = @();

    #Adjust this to  pick up your service or services, this will work fine with multiple services. 
    $runningServices = Get-Service -Name MSSQLSERVER | ? { $_.Status -eq 'Running' }
    $runningServices | Out-File -FilePath $logpath -Append

    # For each running service, add a metric to metrics collection that adds a data point to a CloudWatch Metric named 'Status' with dimensions: instanceid, servicename
        $runningServices | % { 
        $dimensions = @();

        $serviceDimension = New-Object -TypeName Amazon.CloudWatch.Model.Dimension;
        $serviceDimension.Name = "service"
        $serviceDimension.Value = $_.Name;

        Write-Output "SD = $($serviceDimension.Value)" | Out-File -FilePath $logpath -Append  

        $dimensions += $instanceDimension;
        $dimensions += $serviceDimension;

        $metric = New-Object -TypeName Amazon.CloudWatch.Model.MetricDatum;
        $metric.Timestamp = [DateTime]::UtcNow;
        $metric.MetricName = 'Status';
        $metric.Value = 1;
        $metric.Dimensions = $dimensions;

        $metrics += $metric;    
        Write-Output "$metrics" | Out-File -FilePath $logpath -Append   

        Write-Output "Service: $($_.Name) is running" | Out-File -FilePath $logpath -Append

    # This cmdlet doesn't fail gracefully so we will run it in a try / catch. 
    try {
    Write-CWMetricData -Namespace $Namespace -MetricData $metrics -Verbose
    } catch {
        Write-Output "CWMetric Failed" | Out-File -FilePath $logpath -Append 

The current version  of this script can always be found here – GitHub

You’ll want to download the script and save it somewhere on your server, I usually save them into a “C:\Scripts” directory (makes it easier to find any scripts later).

Scheduling the Script

How regularly you schedule the scripts will determine how quickly you can find out that a service is down, in my case I’m having it run every 5 minutes, to achieve this we will use Task Scheduler. You can call the task what ever you want, run it with any account you want (I use System) and then set the schedule to as often as you require. The action itself should be setup like this

Checking the CloudWatch Metric

If everything is running successfully you should be able to find your new metric in CloudWatch and it should look something like this

Now you can take this metric and create an alarm based on it!


If you have any question about AWS CloudWatch & Custom Metrics drop me an email – [email protected]