Guías · Nivel 2

IIS: leer los logs W3C, reciclado e inactividad de los grupos de aplicaciones, redirección a HTTPS y una aplicación lenta cada mañana

Dónde están los logs de IIS y cómo leerlos (campos W3C, sc-status, time-taken) con PowerShell, Failed Request Tracing por tiempo, el reciclado y el tiempo de inactividad de los grupos de aplicaciones, la precarga con AlwaysRunning y Application Initialization, la redirección de HTTP a HTTPS con URL Rewrite, y la aplicación que tarda 20 segundos en la primera petición del día.

Qué vas a conseguir

Leer un log de IIS para responder a "¿va lento?" con números, saber cuándo y por qué se recicla o se apaga el proceso de una aplicación, dejar la aplicación caliente antes de que llegue el primer usuario y redirigir todo el tráfico HTTP a HTTPS. Con eso se cierra uno de los tickets más repetidos en IIS: la aplicación tarda muchísimo la primera vez cada mañana y luego va bien.

Antes de empezar

  • Windows Server 2022 o 2025 con IIS 10 y permisos de administrador local.
  • Las características que usa esta guía: Install-WindowsFeature Web-Http-Tracing, Web-AppInit, Web-Scripting-Tools.
  • El módulo URL Rewrite 2.1, que no es una característica de Windows: se descarga de la web de IIS y se instala aparte.
  • El ID del sitio (Get-IISSite): la carpeta de logs es W3SVC<ID>. Aquí, el sitio Reservas con ID 2. La configuración básica de sitios, enlaces y certificados está en la primera guía de IIS.

1. Dónde están los logs y qué dice cada campo

Los logs de cada sitio están en %SystemDrive%\inetpub\logs\LogFiles\W3SVC2\, un fichero u_exAAMMDD.log por día. Las cuatro primeras líneas empiezan por # y la cuarta dice qué columnas hay:

u_ex261102.log
#Software: Microsoft Internet Information Services 10.0#Version: 1.0#Date: 2026-11-02 00:00:01#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken2026-11-02 07:58:12 10.10.40.15 GET / - 443 CONTOSO\lmartin 10.20.4.37 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64) - 200 0 0 218742026-11-02 07:58:34 10.10.40.15 GET /css/site.css - 443 CONTOSO\lmartin 10.20.4.37 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64) https://reservas.corp.example/ 200 0 0 152026-11-02 07:58:41 10.10.40.15 POST /api/reservas - 443 CONTOSO\lmartin 10.20.4.37 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64) - 500 0 0 312
CampoQué es
date, timeFecha y hora en UTC: 07:58 es 08:58 en Madrid en invierno
cs-uri-stemLa página o recurso pedido
cs-usernameEl usuario, si el sitio usa autenticación de Windows; - si es anónimo
c-ipLa IP del cliente, o la del balanceador si hay uno delante
sc-status, sc-substatusEl código HTTP y el subcódigo de IIS (un 401 2, un 404 0)
sc-win32-statusEl error de Windows; 64 o 1236 suelen ser el cliente que cerró la conexión
time-takenMilisegundos desde que llega la petición hasta que se envía el último byte
  • IIS escribe el log con un búfer de unos segundos: si no ves la última petición, netsh http flush logbuffer lo vuelca.
  • Con un balanceador delante, añade en Logging › Select Fields › Add Field un campo personalizado de tipo Request Header con X-Forwarded-For.

2. Buscar las peticiones lentas con PowerShell

PowerShell · peticiones de más de 5 segundos
$log = "C:\inetpub\logs\LogFiles\W3SVC2\u_ex261102.log"$campos = ((Get-Content $log -TotalCount 4)[3] -replace '^#Fields: ').Split(' ')Get-Content $log | Where-Object { $_ -notlike '#*' } | ConvertFrom-Csv -Delimiter ' ' -Header $campos | Where-Object { [int]$_.'time-taken' -gt 5000 } | Select-Object time, cs-uri-stem, sc-status, time-takentime     cs-uri-stem sc-status time-taken----     ----------- --------- ----------07:58:12 /           200       2187406:40:03 /           200       19240
  • Si en el mismo día IIS reinicia el sitio o cambia la configuración del log, aparece otra línea #Fields a mitad de fichero. El filtro #* la salta.
  • Para agrupar (peticiones por código, tiempo medio por página), Group-Object sc-status o Measure-Object time-taken -Average sobre el mismo resultado.
  • Un time-taken alto en ficheros estáticos (.css, .js) suele ser red o cliente lento; en la página principal o en la API, la aplicación.

3. Failed Request Tracing por tiempo

La primera guía de IIS usa FREB para los 500. Aquí sirve para lo contrario: peticiones que funcionan, pero tardan.

Administrador de IIS · Reservas › Failed Request Tracing Rules › Add
Content to traceAll content (*)
Status code(s)(vacío)
Time taken (in seconds): 10
ProvidersASPNET, ISAPI Extension, WWW Server · Verbosity: Verbose
Finish
  • Actívalo en el sitio (Actions › Failed Request Tracing... › Enable) y espera a la próxima petición lenta.
  • El fichero de %SystemDrive%\inetpub\logs\FailedReqLogFiles\W3SVC2\, abierto en el navegador, tiene la pestaña Performance View: qué módulo se ha llevado el tiempo. Si casi todo es ManagedPipelineHandler o AspNetCoreModuleV2, el tiempo es de la aplicación, no de IIS.
  • Desactívalo al acabar: escribe un fichero por cada petición que cumple la regla.

4. Reciclado y tiempo de inactividad de los grupos de aplicaciones

Dos ajustes de cada grupo de aplicaciones, en Advanced Settings, deciden cuándo muere el proceso w3wp.exe:

AjustePor defectoQué hace
Process Model › Idle Time-out (minutes)20Sin peticiones durante ese tiempo, el proceso se apaga
Process Model › Idle Time-out ActionTerminateTerminate lo cierra; Suspend lo deja en memoria congelado
Recycling › Regular Time Interval (minutes)1740Recicla cada 29 horas, a una hora distinta cada día
Recycling › Specific Times(vacío)Recicla a horas fijas
General › Start ModeOnDemandEl proceso solo arranca con la primera petición
  • Reciclar es arrancar un proceso nuevo y retirar el viejo. Con el reciclado solapado (por defecto) el nuevo atiende mientras el viejo termina, pero llega en frío: la aplicación vuelve a cargar, compilar y llenar cachés.
  • Activa el registro: Recycling › Generate Recycle Event Log Entry, con al menos Regular time interval, Specific time, Memory y Configuration changes. WAS lo deja en el registro Sistema: el evento 5074 es un reciclado por tiempo y el 5186, un proceso apagado por inactividad.

Un grupo de una aplicación de uso diario se deja así:

cmd · appcmd como administrador
cd %windir%\system32\inetsrvappcmd set apppool "Reservas" /recycling.periodicRestart.time:00:00:00appcmd set apppool "Reservas" /+recycling.periodicRestart.schedule.[value='04:00:00']appcmd set apppool "Reservas" /processModel.idleTimeout:00:00:00appcmd set apppool "Reservas" /startMode:AlwaysRunningappcmd list apppool "Reservas" /text:*
  • Sin reciclado por intervalo y con uno fijo a las 4:00, el corte pasa cuando nadie trabaja.
  • idleTimeout a cero: el proceso no se apaga por la noche. En un servidor con decenas de grupos que casi no se usan, mejor Suspend que cero: menos memoria y un arranque mucho más rápido que en frío.
  • AlwaysRunning arranca el proceso con el servicio WAS, sin esperar a la primera petición. Solo arranca el proceso: cargar la aplicación es el apartado siguiente.

5. Precarga con Application Initialization

Con la característica Web-AppInit instalada, IIS puede llamar a una página de la aplicación en cuanto arranca o se recicla el proceso, antes de enviarle tráfico de usuarios:

cmd · precarga en el sitio
appcmd set site "Reservas" /applicationDefaults.preloadEnabled:true

Y en el web.config de la aplicación, la página que la despierta:

web.config · system.webServer
<applicationInitialization doAppInitAfterRestart="true">  <add initializationPage="/health" /></applicationInitialization>
  • La página tiene que hacer el trabajo caro de verdad (abrir la conexión a SQL Server, cargar la configuración) y no pedir autenticación: si devuelve un 401, la precarga no calienta nada.
  • doAppInitAfterRestart repite la precarga tras cada reciclado, no solo tras arrancar el servidor.
  • Funciona igual con ASP.NET 4.x y con ASP.NET Core en IIS. El cambio en web.config es del equipo de la aplicación: acuérdalo con ellos y que vaya en su despliegue, o lo perderán en el siguiente.

6. Redirigir HTTP a HTTPS con URL Rewrite

El sitio necesita los dos enlaces: el 443 con su certificado y el 80, que solo existe para redirigir. Con URL Rewrite, la regla va en el web.config del sitio:

web.config · system.webServer
<rewrite>  <rules>    <rule name="HTTP a HTTPS" stopProcessing="true">      <match url="(.*)" />      <conditions>        <add input="{HTTPS}" pattern="^OFF$" />      </conditions>      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />    </rule>  </rules></rewrite>
  • También se crea desde el Administrador de IIS: URL Rewrite › Add Rule(s)... › Blank rule, con los mismos campos.
  • redirectType="Permanent" es un 301: el navegador lo recuerda. Pruébalo primero con Found (302) y cámbialo cuando funcione.
  • Si hay un balanceador que termina el TLS y habla con IIS por HTTP, {HTTPS} siempre vale OFF y la regla crea un bucle. En ese caso la condición mira la cabecera que pone el balanceador, {HTTP_X_FORWARDED_PROTO} con el patrón ^http$.
  • En IIS 10 (desde la versión 1709) el sitio tiene además ajustes propios de HSTS, con la opción de redirigir a HTTPS sin URL Rewrite (hsts.enabled y hsts.redirectHttpToHttps en la configuración del sitio).

7. El ticket: "la aplicación va lentísima cada mañana con la primera petición"

Lunes, 9:05. Recepción dice que la aplicación de reservas tarda "como 20 segundos" en abrir a primera hora; después va bien todo el día. Algunos días pasa también después de comer.

  1. Medirlo: el script del apartado 2 sobre el log de hoy da GET / con time-taken 21874 a las 07:58 UTC (08:58 en Madrid) y, el viernes, otro de 19240 a las 14:12 UTC. Las peticiones siguientes, por debajo de 300 ms.
  2. Qué pasó antes: en el Visor de eventos › Registros de Windows › Sistema, origen WAS:
PowerShell · eventos de WAS del grupo
Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-WAS'; Id=5074,5186; StartTime=(Get-Date).AddDays(-3)} | Where-Object Message -like "*Reservas*" | Select-Object TimeCreated, Id, Message | Format-ListTimeCreated : 02/11/2026 7:12:44Id          : 5186Message     : A worker process with process id of '6412' serving application pool 'Reservas' was shutdown due to inactivity. Application Pool timeout configuration was set to 20 minutes. A new worker process will be started when needed.TimeCreated : 01/11/2026 13:51:20Id          : 5074Message     : A worker process with process id of '5120' serving application pool 'Reservas' has requested a recycle because the worker process reached its allowed processing time limit.
  1. La causa: dos motivos con el mismo síntoma. Por la noche, tras 20 minutos sin uso, el proceso se apaga (5186) y el primer usuario de la mañana paga el arranque en frío. Y cada 29 horas el reciclado por intervalo (5074) cae a una hora distinta, a veces en plena jornada: de ahí "algunos días después de comer".
  2. El cambio, en una ventana acordada: reciclado fijo a las 4:00, idleTimeout a cero, AlwaysRunning, precarga del sitio y la página /health en applicationInitialization (apartados 4 y 5). appcmd aplica el cambio y recicla el grupo: hazlo fuera de horas.
  3. Comprobarlo a la mañana siguiente: en el log, la primera petición del día por debajo de un segundo, y en el registro de la aplicación las llamadas a /health justo después de las 4:00 con el usuario vacío, que son la precarga.
PowerShell · la primera petición del día siguiente
Get-Content $log | Where-Object { $_ -notlike '#*' } | ConvertFrom-Csv -Delimiter ' ' -Header $campos | Where-Object 'cs-uri-stem' -eq '/' | Select-Object -First 1 time, cs-username, time-takentime     cs-username    time-taken----     -----------    ----------07:41:09 CONTOSO\mgarcia 412

Quitar el reciclado no arregla una aplicación que pierde memoria: solo cambia cuándo se nota. Si el grupo crece día a día, pon un límite en Recycling › Private Memory Limit (KB) y abre un ticket al equipo de la aplicación con la gráfica de memoria.

En el ticket: tiempos antes y después, los eventos 5186 y 5074, los ajustes cambiados en el grupo y el sitio, y quién tiene el cambio de web.config en su despliegue.

Siguientes pasos

¿Falta algo o en tu entorno es distinto? Escríbeme y lo corrijo.

Tech Career Lab · newsletter

¿Te ha servido? Cada dos semanas envío una idea práctica para perfiles IT: LinkedIn, proyectos, networking y procesos de selección.

Apúntate y llévate las 33 ideas →