How to Configure IIS Logging and Analysis on Windows Server 2016

Internet Information Services (IIS) on Windows Server 2016 generates detailed access logs that record every HTTP request, response code, bytes transferred, time taken, client IP, and user agent. Properly configured IIS logging is essential for security auditing, performance troubleshooting, SEO analysis, capacity planning, and compliance requirements. This guide covers configuring IIS logging settings, enabling advanced W3C fields, centralized logging, analyzing logs with Log Parser, and forwarding logs to Azure Log Analytics for long-term analysis.

Step 1: Open IIS Manager and Locate Logging Settings

Open IIS Manager from Server Manager > Tools > Internet Information Services (IIS) Manager. In the Connections panel, select either the server node (for server-wide logging policy) or an individual site. Double-click the Logging feature icon in the center panel.

The Logging panel shows the log format, log file directory, schedule (hourly, daily, weekly, monthly, or file size), and encoding. The default log directory is C:inetpublogsLogFiles.

Step 2: Configure Log Format and Fields

Use the W3C format (default) for maximum compatibility with log analysis tools. Click Select Fields to see the full list of available W3C fields. Enable the following fields in addition to the defaults:

sc-win32-status — Windows error code, useful for diagnosing errors beyond the HTTP status. time-taken — request duration in milliseconds, essential for performance analysis. cs(Referer) — HTTP referrer for traffic source analysis. cs(User-Agent) — client browser/application identification. x-forwarded-for — real client IP when behind a load balancer or proxy.

Apply settings and click OK.

Step 3: Configure IIS Logging via PowerShell

Use the WebAdministration module to configure logging from the command line:

Import-Module WebAdministration

# Set log directory and schedule for Default Web Site
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST/Default Web Site" `
  -filter "system.webServer/httpLogging" -name logTargetW3C -value "File"

Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.directory -value "D:IISLogs"
Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.period -value "Daily"
Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.logFormat -value "W3C"

# Enable additional fields including time-taken and x-forwarded-for
Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.customLogPluginClsid -value ""
$logFieldFlags = [Microsoft.Web.Administration.LogExtFileFlags]"Date,Time,ClientIP,UserName,SiteName,ComputerName,ServerIP,Method,UriStem,UriQuery,HttpStatus,Win32Status,BytesSent,BytesRecv,TimeTaken,ServerPort,UserAgent,Referer,Host,HttpSubStatus"
Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.logExtFileFlags -value $logFieldFlags

Step 4: Enable Centralized W3C Logging

By default, each IIS site writes to its own log folder. For multi-site servers, centralized logging consolidates all site logs into a single folder, simplifying log management and analysis:

Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' `
  -filter "system.applicationHost/log" `
  -name centralLogFileMode `
  -value CentralW3C

Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' `
  -filter "system.applicationHost/log/centralW3CLogFile" `
  -name directory `
  -value "D:IISCentralLogs"

Step 5: Enable Failed Request Tracing

Failed Request Tracing (FREB) records detailed trace information for requests that fail or exceed a time threshold. Enable it in IIS Manager by selecting a site, clicking Failed Request Tracing Rules, and clicking Add. Configure rules to trace requests with status codes 400–599 or requests taking longer than 30 seconds. Traces are saved as XML files that can be opened in a browser for detailed drill-down.

Enable via appcmd:

%SystemRoot%system32inetsrvappcmd configure trace "Default Web Site" /enable
%SystemRoot%system32inetsrvappcmd set config "Default Web Site" /section:traceFailedRequests /+[path='*',customActionsEnabled='true'] /statusCodes:'500' /minStatusCode:'500' /maxStatusCode:'500'

Step 6: Analyze IIS Logs with Log Parser

Microsoft Log Parser is a free command-line tool for querying IIS log files using SQL-like syntax. Install it from the Microsoft Download Center. Common queries:

Find the top 10 most requested URLs:

logparser "SELECT cs-uri-stem, COUNT(*) AS Hits FROM D:IISLogsW3SVC1*.log GROUP BY cs-uri-stem ORDER BY Hits DESC" -i:W3C | head -11

Find the slowest requests by average time-taken:

logparser "SELECT cs-uri-stem, AVG(time-taken) AS AvgMs, COUNT(*) AS Hits FROM D:IISLogsW3SVC1*.log GROUP BY cs-uri-stem ORDER BY AvgMs DESC" -i:W3C

Count HTTP 500 errors by URL over the past 24 hours:

logparser "SELECT cs-uri-stem, COUNT(*) AS Errors FROM D:IISLogsW3SVC1*.log WHERE sc-status=500 AND TO_TIMESTAMP(date, time) > SUB(NOW(), TIMESTAMP('0000-00-00 24:00:00','yyyy-MM-dd HH:mm:ss')) GROUP BY cs-uri-stem ORDER BY Errors DESC" -i:W3C

Step 7: Configure Log Rotation and Archival

Daily log rotation is the default and recommended setting. Configure a maximum log file size as an additional safeguard:

Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.truncateSize -value 10485760
Set-ItemProperty -Path "IIS:SitesDefault Web Site" -name logFile.localTimeRollover -value $true

Create a scheduled task to compress and archive logs older than 30 days:

$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NonInteractive -Command `"Get-ChildItem D:IISLogs -Recurse -Include *.log | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } | Compress-Archive -DestinationPath D:IISArchivelogs-$(Get-Date -Format yyyyMMdd).zip; Remove-Item $_.FullName`""
$trigger = New-ScheduledTaskTrigger -Daily -At "03:00AM"
Register-ScheduledTask -TaskName "IISLogArchive" -Action $action -Trigger $trigger -RunLevel Highest -User "SYSTEM"

Step 8: Forward IIS Logs to Azure Log Analytics

Configure a custom log data source in the Log Analytics workspace to ingest IIS logs. In the Azure Portal, navigate to the Log Analytics workspace > Settings > Custom logs. Upload a sample IIS W3C log file to define the schema. Set the collection path to D:IISLogsW3SVC1*.log. Once collected, query with KQL:

W3CIISLog
| where TimeGenerated > ago(1d)
| where scStatus >= 500
| summarize ErrorCount=count() by csUriStem, scStatus
| order by ErrorCount desc

Best Practices

Store IIS logs on a separate drive from the OS and application data to prevent log I/O from impacting web application performance. Always enable time-taken and x-forwarded-for fields from the start—adding them later creates gaps in historical data. Set log rotation to Daily and archive logs older than 30 days to minimize disk usage. Forward logs to a central SIEM or Log Analytics workspace for security monitoring and long-term retention. Regularly review 4xx and 5xx error rates as an early indicator of application issues or scanning activity.