Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
por Vishal Sood
El Advanced Logging de IIS puede ampliar la plataforma web para posibilitar el análisis en tiempo real, lo que facilita proporcionar informes en tiempo real a los clientes o trabajar con asociados para hacer lo mismo. La función de Advanced Logging contiene una opción que permite el consumo de entradas de registro en tiempo real. Agrega todos los eventos enviados durante cada solicitud y la propiedad de definición de registro publishLogEvent controla si se generan eventos en tiempo real para su consumo por otras aplicaciones.
Requisitos
- Este artículo está pensado para desarrolladores y presupone conocimientos básicos de escritura de código nativo.
- No es necesario comprender la canalización de IIS; sin embargo, puede ayudar a revisar los artículos enumerados en la sección de Material de referencia para obtener más información sobre los métodos y las estructuras de datos que se usan.
- El Advanced Logging de IIS es una extensión para Internet Information Services (IIS) 7 que ya no está disponible. Se recomienda el Enhanced Logging para IIS 8.5.
Habilitar el registro en tiempo real
El registro en tiempo real es una configuración por definición de registro en el Advanced Logging de IIS. Para habilitar el registro en tiempo real para una definición de registro, se debe hacer lo siguiente:
En el Administrador de IIS, abrir la función de Advanced Logging. Hacer clic en el servidor en el panel Conexiones y, a continuación, hacer doble clic en el icono Advanced Logging en la página de Inicio.
Habilitar la función de Advanced Logging. En el panel Acciones, hacer clic en Habilitar Advanced Logging.
Seleccionar la definición de registro para la que desea habilitar el registro en tiempo real.
- En el Administrador de IIS, abrir la función de Advanced Logging en el nivel de servidor, sitio web, directorio o aplicación.
- En la página de la función de Advanced Logging, hacer clic en la definición de registro y, a continuación, en el panel de Acciones, hacer clic en Editar definición de registro.
Habilitar el registro en tiempo real de eventos para la definición de registro seleccionada activando la casilla Publicar eventos en tiempo real.
Escribir un módulo IIS que consuma los eventos en tiempo real, tal y como se describe en la siguiente sección.
Escribir un módulo IIS para consumir eventos en tiempo real
Para registrar los eventos en tiempo real generados por la función Advanced Logging, se debe crear un módulo IIS. En esta sección se revisa la infraestructura de seguimiento de IIS y se proporciona código de ejemplo en una carpeta comprimida para crear un módulo sencillo que puede usar como referencia.
Nota:
El código de ejemplo no se ha probado para fugas de memoria y otras incidencias y está pensado para usarse solo como referencia.
Infraestructura de seguimiento de IIS
En esta sección se describen algunos conceptos de seguimiento de IIS que se usan para registrar eventos en tiempo real.
Método IGlobalTraceEventProvider::GetTraceEvent
Para consumir los eventos en tiempo real generados por Advanced Logging, el módulo IIS que se cree debe registrarse para eventos globales. Se debe llamar al método OnGlobalTraceEvent para cada evento generado por el sistema. El registro proporciona acceso a los eventos de registro en tiempo real. Para obtener más información, véase el Método CGlobalModule::OnGlobalTraceEvent.
estructuras de datos
Estructura HTTP_TRACE_EVENT
La estructura HTTP_TRACE_EVENT constituye la columna vertebral de la infraestructura de registro en tiempo real. La información de registro en tiempo real se transmite en forma de esta estructura.
struct HTTP_TRACE_EVENT{
LPCGUID pProviderGuid;
DWORD dwArea;
LPCGUID pAreaGuid;
DWORD dwEvent;
LPCWSTR pszEventName;
DWORD dwEventVersion;
DWORD dwVerbosity;
LPCGUID pActivityGuid;
LPCGUID pRelatedActivityGuid;
DWORD dwTimeStamp;
DWORD dwFlags;
DWORD cEventItems;
__field_ecount(cEventItems) HTTP_TRACE_EVENT_ITEM * pEventItems;
};
Para obtener más información sobre esta estructura, véase la Estructura HTTP_TRACE_EVENT.
Estructura HTTP_TRACE_EVENT_ITEM
La estructura HTTP_TRACE_EVENT contiene una o varias estructuras de HTTP_TRACE_EVENT_ITEM, en función del número de campos de registro incluidos en la definición de registro para la que se generó un registro.
struct HTTP_TRACE_EVENT_ITEM{
LPCWSTR pszName;
HTTP_TRACE_TYPE dwDataType;
PBYTE pbData;
DWORD cbData;
LPCWSTR pszDataDescription;
};
Para obtener más información sobre esta estructura, véase Estructura HTTP_TRACE_EVENT_ITEM.
pProviderGuid
La estructura HTTP_TRACE_EVENT contiene la propiedad pProviderGuid, un LPCGUID que contiene el identificador del proveedor. Es importante comprender su significado.
Como se describe en CAnalyticsGlobalModule::OnGlobalTraceEvent, se llama a OnGlobalTraceEvent para cada evento generado por el sistema. Esto significa que debe filtrar eventos no deseados de los eventos entrantes para que solo los eventos de interés (eventos de registro en tiempo real) estén disponibles para su consumo. Puede hacerlo mediante el valor de la propiedad pProviderGuid 3C729B22-F9A9-4096-92A4-07E0DDF403EB.
//
// {3C729B22-F9A9-4096-92A4-07E0DDF403EB}
//
static const GUID _LOGGING_PUBLISHING_GUID =
{ 0x3c729b22, 0xf9a9, 0x4096, { 0x92, 0xa4, 0x7, 0xe0, 0xdd, 0xf4, 0x3, 0xeb } };
………………
………………
if ((pTraceEvent->pProviderGuid != &_LOGGING_PUBLISHING_GUID) &&
(!IsEqualGUID(*(pTraceEvent->pProviderGuid), _LOGGING_PUBLISHING_GUID)))
{
goto Finished;
}
El código de ejemplo usa este valor para filtrar los eventos no deseados.
Código de ejemplo
En esta sección se muestra código de ejemplo que ilustra los conceptos de registro en tiempo real descritos anteriormente en este artículo. Descargue CAnalyticsGlobalModule.zip, una copia del código de ejemplo en una carpeta comprimida.
Nota:
El código de ejemplo no se ha probado para fugas de memoria y otras incidencias y está pensado para usarse solo como referencia.
CAnalyticsGlobalModule::OnGlobalTraceEvent
//
// {3C729B22-F9A9-4096-92A4-07E0DDF403EB}
//
static const GUID _LOGGING_PUBLISHING_GUID =
{ 0x3c729b22, 0xf9a9, 0x4096, { 0x92, 0xa4, 0x7, 0xe0, 0xdd, 0xf4, 0x3, 0xeb } };
//
// This call is happening on the same thread (synchronous/blocking call) as
// the call to RaiseTraceEvent, so bail a.s.a.p. if this isn't something
// we want to handle, and minimize the work we do here
//
//
GLOBAL_NOTIFICATION_STATUS
CAnalyticsGlobalModule::OnGlobalTraceEvent(
__in IGlobalTraceEventProvider * pProvider)
{
HRESULT hr = S_OK;
IHttpContext * pHttpContext = NULL;
HTTP_TRACE_EVENT * pTraceEvent = NULL;
DBG_ASSERT(pProvider != NULL
//
// We only want to handle trace events that are raised for
// logging purposes, so bail a.s.a.p. if this event isn't
// for us
//
hr = pProvider->GetTraceEvent(&pTraceEvent
if (FAILED(hr))
{
TRACEHR(hr
goto Finished;
}
if (pTraceEvent->pProviderGuid == NULL)
{
TRACEMSG(SS_DEFAULT,
TRACE_LEVEL_INFORMATION,
L"Not handling trace event - NULL value for provider GUID"
goto Finished;
}
if ((pTraceEvent->pProviderGuid != &_LOGGING_PUBLISHING_GUID) &&
(!IsEqualGUID(*(pTraceEvent->pProviderGuid), _LOGGING_PUBLISHING_GUID)))
{
goto Finished;
}
//
// We now need the HTTP context which is used to get the site info later
//
hr = pProvider->GetCurrentHttpRequestContext(&pHttpContext
if (FAILED(hr))
{
TRACEHR(hr
goto Finished;
}
ProcessLogEvent(pTraceEvent, pHttpContext
Finished:
return GL_NOTIFICATION_CONTINUE;
}
ProcessLogEvent
El método ProcessLogEvent copia los datos de registro en una estructura de datos local para que se pueda usar más adelante para insertar datos en un servicio web o una base de datos.
Nota:
Los datos de la propia solicitud no deben procesarse, ya que podrían provocar que la solicitud ralentizase las respuestas a los clientes.
Nota:
El código de ProcessLogEvent debe tener en cuenta que la memoria usada por los eventos podría ser memoria temporal asignada por AllocateRequestMemory. Para desbloquear el subproceso, se deben copiar los datos.
void ProcessLogEvent(
__in HTTP_TRACE_EVENT * pHttpTraceEvent,
__in IHttpContext * pHttpContext)
{
HRESULT hr = S_OK;
DWORD cchName = 0;
HTTP_TRACE_EVENT * pNewHttpTraceEvent = NULL;
LPCSTR pszHostName = NULL;
pNewHttpTraceEvent = new HTTP_TRACE_EVENT;
if (pNewHttpTraceEvent == NULL)
{
goto Finished;
}
pNewHttpTraceEvent->pEventItems = new HTTP_TRACE_EVENT_ITEM[pHttpTraceEvent->cEventItems];
if (pNewHttpTraceEvent->pEventItems == NULL)
{
goto Finished;
}
ZeroMemory(pNewHttpTraceEvent->pEventItems, sizeof(HTTP_TRACE_EVENT_ITEM) * pHttpTraceEvent->cEventItems);
for (DWORD ix = 0; ix < pHttpTraceEvent->cEventItems; ix++)
{
if (pHttpTraceEvent->pEventItems[ix].pszName == NULL)
{
pNewHttpTraceEvent->pEventItems[ix].pszName = NULL;
pNewHttpTraceEvent->pEventItems[ix].cbData = 0;
pNewHttpTraceEvent->pEventItems[ix].pbData = NULL;
continue;
}
//
// Copy the name of this event item
//
cchName = wcslen(pHttpTraceEvent->pEventItems[ix].pszName);
pNewHttpTraceEvent->pEventItems[ix].pszName = new WCHAR[cchName + 1];
if (pNewHttpTraceEvent->pEventItems[ix].pszName == NULL)
{
goto Finished;
}
memcpy((VOID *)pNewHttpTraceEvent->pEventItems[ix].pszName, pHttpTraceEvent->pEventItems[ix].pszName, (cchName+1) * sizeof(WCHAR));
//
// If there's no data to copy, mark it empty
//
if ((pHttpTraceEvent->pEventItems[ix].cbData == 0) ||
(pHttpTraceEvent->pEventItems[ix].pbData == NULL))
{
pNewHttpTraceEvent->pEventItems[ix].cbData = 0;
pNewHttpTraceEvent->pEventItems[ix].pbData = NULL;
continue;
}
pNewHttpTraceEvent->pEventItems[ix].pbData = new BYTE[pHttpTraceEvent->pEventItems[ix].cbData];
if (pNewHttpTraceEvent->pEventItems[ix].pbData == NULL)
{
goto Finished;
}
memcpy(pNewHttpTraceEvent->pEventItems[ix].pbData, pHttpTraceEvent->pEventItems[ix].pbData, pHttpTraceEvent->pEventItems[ix].cbData);
pNewHttpTraceEvent->pEventItems[ix].cbData = pHttpTraceEvent->pEventItems[ix].cbData;
pNewHttpTraceEvent->pEventItems[ix].dwDataType = pHttpTraceEvent->pEventItems[ix].dwDataType;
}
//
// At this point, you've copied the event into your memory and can now process your copy, queue it, etc.
//
// WriteEventViewerLog(pHttpTraceEvent->pszEventName); // Can write to eventViewer log to verify that event is processed...
Finished:
return;
}
Resumen
En este tutorial, hemos revisado cómo funciona el registro en tiempo real en la función de Advanced Logging de IIS y cómo consumir datos de registro en tiempo real mediante la creación de un módulo de IIS simple.