Custom IIS log files with PowerShell

on Friday, June 27, 2014

Depending on your infrastructure you may have a need to place IIS logs onto a separate disk. A disk which can fill up without taking down the server. The easiest solution to this is to set the Default Site Settings with log file locations other than the C: drive. But, then you still run into the problem of each log file being written under a folder with a name like W3SVC12.

The name W3SVC12 corresponds with the website which has SiteID 12. Unfortunately, you can only find out that information if you have access to IIS manager. And, most developers don’t have access to IIS manager on the production servers. So, it would be nice to give the log files a location with a more friendly name.

I’m sure there’s an appcmd which can setup both IIS log files and Failed Request Tracing log files for an individual website. But, in this post, I’ll show the few commands needed to setup those locations by directly editing the applicationHost.config file.

When an individual website is setup with custom IIS log file and Failed Request Tracing log file locations, the applicationHost.config file will look like this:

<site name="unittest.dev.yoursite.com" id="15" serverAutoStart="true">
<application path="/">
  <virtualDirectory path="/" physicalPath="D:\AllContent\Websites\unittest.dev.yoursite.com\" />
 </application>
 <application path="/normal/childapp">
  <virtualDirectory path="/" />
 </application>
 <bindings>
  <binding protocol="http" bindingInformation="*:80:" />
 </bindings>
 <traceFailedRequestsLogging enabled="false" directory="D:\AllContent\logs\unittest.dev.yoursite.com\FailedReqLogFiles" />
 <logFile directory="D:\AllContent\logs\unittest.dev.yoursite.com\LogFiles" />
</site>

The two commands below create and remove those xml elements. The script will also use the name of the website when creating the log file location path.

<#
.SYNOPSIS
 Adds a specialized log folder and FRT folder. See ConvertTo-WebUriPaths to create a $UriPaths Hashtable.

.EXAMPLE
 New-WebAppLogFile -UriPaths $paths

#>
Function New-WebAppLogFile {
Param (
 [Parameter(Mandatory = $true)]
 [Hashtable]$UriPaths,
 [string]$PhysicalPath = "",
 [string]$ServerName = $env:COMPUTERNAME
)
Process {
 # if the web application can't be found, then skip
 $configPath = Get-WebConfigPath $ServerName;
 $appHost = [System.Xml.XmlDocument](Read-WebConfig -ConfigPath $configPath);
 $sites = $appHost.configuration.'system.applicationHost'.sites;
 $site = [System.Xml.XmlElement]($sites.site |? { $_.name -eq $UriPaths.SiteName });
 if($site -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) couldn't be found. The log and FRT paths will be skipped.";
  return;
 }

 # get the physical path
 $rootLogsPath = $PhysicalPath;
 if($rootLogsPath -eq "") {
  $rootLogsPath = Join-Path $global:WebAdministrationUcsb.DefaultLogPath $UriPaths.SiteName;
 }
 $frtPath = Join-Path $rootLogsPath "FailedReqLogFiles";
 $logPath = Join-Path $rootLogsPath "LogFiles";

 # add the FRT location
 $frt = [System.Xml.XmlElement]($appHost.CreateElement("traceFailedRequestsLogging"));
 $frt.SetAttribute("enabled", "false");
 $frt.SetAttribute("directory", $frtPath);
 $frt = $site.AppendChild($frt);
 
 Write-Warning "IIS $ServerName - Adding custom FRT path for $($UriPaths.SiteName) to $frtPath.";
 Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
 Write-Host "IIS $ServerName - Added custom FRT path for $($UriPaths.SiteName) to $frtPath.";

 # add the log location
 $log = [System.Xml.XmlElement]($appHost.CreateElement("logFile"));
 $log.SetAttribute("directory", $logPath);
 $log = $site.AppendChild($log);
 
 Write-Warning "IIS $ServerName - Adding custom log file path for $($UriPaths.SiteName) to $logPath.";
 Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
 Write-Host "IIS $ServerName - Added custom log file path for $($UriPaths.SiteName) to $logPath.";
}
}


<#
.SYNOPSIS
 Remove a specialized log folder and FRT folder. See ConvertTo-WebUriPaths to create a $UriPaths Hashtable.

.EXAMPLE
 Remove-WebAppLogFile -UriPaths $paths
#>
Function Remove-WebAppLogFile {
Param (
 [Parameter(Mandatory = $true)]
 [Hashtable]$UriPaths,
 [string]$ServerName = $env:COMPUTERNAME
)
Process {
 # if the web application can't be found, then skip
 $configPath = Get-WebConfigPath $ServerName;
 $appHost = Read-WebConfig -ConfigPath $configPath;
 $sites = $appHost.configuration.'system.applicationHost'.sites;
 $site = $sites.site |? { $_.name -eq $UriPaths.SiteName };
 if($site -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) couldn't be found. The log and FRT path removal will be skipped.";
  return;
 }

 # remove the FRT location
 $frt = $site.traceFailedRequestsLogging
 if($frt -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) doesn't have a custom FRT path. Skipping its removal.";
 } else {
  $frt = $site.RemoveChild($frt)

  Write-Warning "IIS $ServerName - Removing custom FRT path from $($UriPaths.SiteName).";
  Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
  Write-Host "IIS $ServerName - Removed custom FRT path from $($UriPaths.SiteName).";
 }

 # remove the log location
 $log = $site.logFile
 if($log -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) doesn't have a custom log file path. Skipping its removal.";
 } else {
  $log = $site.RemoveChild($log)

  Write-Warning "IIS $ServerName - Removing custom log file path from $($UriPaths.SiteName).";
  Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
  Write-Host "IIS $ServerName - Removed custom log file path from $($UriPaths.SiteName).";
 }
}
}

These commands rely on the Read-WebConfig and Save-WebConfig from an earlier post.

0 comments:

Post a Comment


Creative Commons License
This site uses Alex Gorbatchev's SyntaxHighlighter, and hosted by herdingcode.com's Jon Galloway.