IIS Log Folders Data On Demand Task

Hi,

This isn’t a question but simply a small script i’d like to share with the community. I have no idea if people will find a use for it.

It’s always amazed me that IIS has no in built mechanism for log management. It’s very good at writing log data but there is no provision for handling log retention or deleting old logs when they get to a specific age. In many cases we would often see that when a low disk space alert was fired the ‘go to’ fix was simply to clean the log files down.

I’ve therefore written a simple script which will clear the logs down based on some JSON configuration; I will happily share that but this first one will read the IIS configuration and then report some metrics for each website that is defined on the Server.

Once the the task is defined you can use Squared Ups On-Demand Task widget to have it present information about the logs alongside other IIS information (in my case I just added it to the existing perspective).

The script is below for those that want it.

 <#
.SYNOPSIS
    Get CSV formatted metrics that give details of the IIS Log Folders
    on the targetted machine.
.DESCRIPTION
    This script will enumerate the host to find all websites which are
    present on it.  It then gets details of the size and age of IIS
    log files for each site before presenting the results in a table.
.PARAMETER Format
    Permitted values: text, csv, json
.EXAMPLE
.NOTES
.LINK
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")]
Param(
    [ValidateSet("text","csv","csvEx","json","list")]
    [string] $Format = "csv"
)

if the machine has the web administration module then…

if ((Get-Module -ListAvailable WebAdministration) -eq $null)
{
# write out an error string
Write-Host “This task cannot continue because the necessary PowerShell Modules are not present on this host.\nAre you sure that this host has an implementation of Internet Information Server installed?”

# exit now as we can't continue
exit

}

import the module

Import-Module WebAdministration

variable to hold total log size

[double]$totalSize = 0

create a variable to hold the output

$output = @()

get all websites

$webSites = (Get-WebSite | Sort-Object id)

create the header string

$output += ‘Website Name,Log Folder,Log Size (MB),Oldest Log File Date,Oldest Log File Age (Days),Volume Free Space (MB)%EOL%’

loop through all of the websites

foreach ($site in $webSites)
{
# get the path where the logs for this website exist
[string]$logFolder = [System.Environment]::ExpandEnvironmentVariables($site.logFile.directory)

# append a slash if required
if (!($logFolder.EndsWith("\"))) { $logFolder += "\" }

# append the default folder name and the ID of the current set
$logFolder += "W3SVC" + $site.id.ToString()

# get the number of bytes in this folder
$folderMBytes = ((Get-ChildItem $logFolder -Recurse | Measure-Object -Property Length -Sum -ErrorAction Stop).Sum /1MB)

# add to the total
$totalSize += $folderMBytes
   
# if the folder bytes is null then set it to zero as there are no longs
if ($folderMBytes -eq $null) { $folderMBytes = 0 }

# get the oldest log file
$oldestLogFile = (Get-ChildItem $logFolder -Recurse | Sort-Object CreationTime | Select -First 1).CreationTime

# if there is an oldest log file then...
if ($oldestLogFile -ne $null)
{
    # calculate the age in days
    $oldestLogAgeDays = ([Math]::Floor((New-TimeSpan -Start $oldestLogFile -End (Get-Date)).TotalDays))
}
else
{
    # no oldest log file because there are no logs so set the oldest log age in days to a blank string
    $oldestLogAgeDays = ""
}

# build the WMI filter to get free space
$wmiFilter = "deviceid='" + $logFolder.Substring(0,1) + ":'"

# get the free space on the disk where the logs resize
$freeSpaceMBytes = ((Get-WMIObject Win32_Logicaldisk -filter $wmiFilter).FreeSpace / 1MB).ToString("0.00")

# create a new line in the output file
$output += '"{0}","{1}","{2}","{3}","{4}","{5}"%EOL%' -f `
    $site.name,
    $logFolder,
    $folderMBytes.ToString("0.00"),
    $oldestLogFile,
    $oldestLogAgeDays,
    $freeSpaceMBytes

}

write out the total too

create a new line in the output file

$output += ‘"{0}","{1}","{2}","{3}","{4}","{5}"%EOL%’ -f `
“”,
“Total Size:”,
$totalSize.ToString(“0.00”),
“”,
“”,
“”

if ($Format -eq ‘text’)
{
ConvertFrom-Csv ($output -replace ‘%EOL%’,’’) | Format-Table -AutoSize
| Out-String -Width 4096 | Write-Host } elseif ($Format -eq 'csv') { $output -replace '%EOL%',''
| Out-String -Width 4096 | Write-Host } elseif ($Format -eq 'csvEx') { $output
| Out-String -Width 4096 | Write-Host } elseif ($Format -eq 'json') { ConvertFrom-Csv ($output -replace '%EOL%','')
| ConvertTo-Json | Out-String -Width 4096
| Write-Host
}
elseif ($Format -eq ‘list’)
{
ConvertFrom-Csv ($output -replace ‘%EOL%’,’’) | Format-List
| Out-String -Width 4096 `
| Write-Host
}


If people would like me to post the cleanup script as well then please let me know.

Any questions or issues then please let me know and i’ll do my best to help.

Pete

3 Likes

This is great, please post the cleanup script too!

1 Like

Thanks for the kind word Peter.

Squared Up asked me to write a blog post on this so both the metrics script and the cleanup can now be found here: https://squaredup.com/blog/iis-log-management-with-scom-and-squared-up/

I hope to be contributing more in the future.

All the best

Pete

1 Like

Hi Pete,

 

nice work && many thanks for sharing! - I also started working on that topic a week ago.

Luckily from another angle :slight_smile:

 

Ruben

1 Like