Actualizado el 14-01-2007
versión para imprimir

Informes personalizados con el HK log analizer

En esta página examinaremos la plantilla modelo que se distribuye con la versión 1.0 del HKLA para ver si podemos adecuarla a nuestros propósitos.

Esta plantilla la encontrarás una vez instalado el HKLA, en el directorio archivos de programa -> chami -> html-kit -> plugins -> config -> hkloganalyzer -> samples -> sample1.lat. Te recomiendo que saques una copia (para tener siempre a mano el original) y trabajes sobre el duplicado (que guardarás en la misma carpeta que el original).

Sample1.lat nos muestra un informe acerca de los browsers que han visitado la página y tenian capacidades .NET (es decir, sistemas con .NET framework). Nosotros en este ejemplo vamos a pretender un informe diario detallado acerca de las versiones de los navegadores que nos visitan.

Comenzaremos analizando la plantilla modelo, y a continuación proponiendo los cambios necesarios para adecuarlos a nuestro nuevo informe. En las secciones de código, verás en verde las partes de las que estamos hablando en cada momento.

Comenzar diciendo que la plantilla tiene una extensión propia .lat (significa Log Analyzer Template). Está escrito en pseudo-xml (no se corresponde con ninguna DTD, por eso no es real xml).
En la plantilla podemos distinguir los siguientes bloques:

bloque contenedor

Este es el código mínimo contenedor de un informe:

<?xml version="1.0"?>

<!-- Copyright (C) 2003, Chami.com. All Rights Reserved. -->

<lp:root xmlns:lp="lp:data">
<lp:lists>

<!-- todo el contenido aqui -->

</lp:lists>
</lp:root>

Si guardasemos esta mini-plantilla como ejemplo.lat y la abriesemos con el HKLA, obtendriamos un error javascript: REPORT_HEAD_SCRIPT no esta definido asi que lo definimos, si bien la dejamos vacia:

<?xml version="1.0"?>

<!-- Copyright (C) 2003, Chami.com. All Rights Reserved. -->

<lp:root xmlns:lp="lp:data">
<lp:lists>


<lp:script export="1" exportid="{{REPORT_HEAD_SCRIPT}}">
<!--
-->
</lp:script>


</lp:lists>
</lp:root>

{{REPORT_HEAD_SCRIPT}} es la parte de la plantilla que referencia código javascript que podemos incluir en la página HTML del informe, dentro de su seccion HEAD, por ejemplo para mostrar/ocultar secciones.

Si probasemos ahora de nuevo a abrir la plantilla, se ejecutaría sin error, pero sin contenido ninguno, mostrando unicamente el texto

{{REPORT_HEAD}} {{REPORT_DATA_SUMMARY}} 
{{REPORT_DATA_HOURLY}} {{REPORT_FOOTER}}
. Estas claves serán sustituidas por nuestros valores. Ya adelantamos que {{REPORT_DATA_HOURLY}} no lo necesitaremos asi que simplemente lo definimos vacio, como hicimos con {{REPORT_HEAD_SCRIPT}}:

<lp:script export="1" exportid="{{REPORT_DATA_HOURLY}}">
<!--
-->
</lp:script>

La sección HEAD del informe

Nuestra plantilla va a generar dinámicamente una página html con los datos. Vamos a comenzar por la sección HEAD. Esto es lo que hay en Sample1.lat:

title

<?xml version="1.0"?>

<!-- Copyright (C) 2003, Chami.com. All Rights Reserved. -->

<lp:root xmlns:lp="lp:data">
<lp:lists>


<lp:script export="1" exportid="{{REPORT_HEAD_TITLE}}">
<!--
<%=sXLOGFILE_FULL%>
-->
</lp:script>

<lp:script export="1" exportid="{{REPORT_HEAD_SCRIPT}}">
<!--
-->
</lp:script>


</lp:lists>
</lp:root>

Si copiamos este texto a nuestra plantilla, vemos que la página sigue vacia, pero en la barra de la ventana aparece el título de la pagina.

<%=sXLOGFILE_FULL%>
es una variable predefinida que contiene la ruta del archivo. La sintaxis es xscl. Podriamos cambiar este valor por una cadena cualquiera, por ejemplo:

<!--
Browsers Report from <%= sTIMEFRAME_FROM %>
-->

que nos mostraria el titulo "Browsers Report from fecha_analizada"

Javascript

Las plantillas tienen soporte javascript, por ejemplo para mostrar o ocultar gráficos, como en el informe por defecto. Cualquier cosas que escribiesemos en la sección


<lp:script export="1" exportid="{{REPORT_HEAD_SCRIPT}}">
<!--
-->
</lp:script>

aparecería en la sección HEAD del informe encerrado en un bloque javascript:

<script language="JavaScript" type="text/javascript">
<!--



// -->
</script>

Nosotros en este ejemplo lo dejamos en blanco

CSS

Además de title y javascript, también podemos añadir estilos al informe. Para ello usamos la sección correspondiente en la plantilla:

<?xml version="1.0"?>

<!-- Copyright (C) 2003, Chami.com. All Rights Reserved. -->

<lp:root xmlns:lp="lp:data">
<lp:lists>


<lp:script export="1" exportid="{{REPORT_HEAD_TITLE}}">
<!--
<%=sXLOGFILE_FULL%>
-->
</lp:script>

<lp:script export="1" exportid="{{REPORT_HEAD_SCRIPT}}">
<!--
-->
</lp:script>


<lp:script export="1" exportid="{{REPORT_HEAD_CSS}}">
<!--

BODY {
background:#EEEEEE;
color: #000;
font: normal 11px Verdana, Geneva, Arial, Helvetica, sans-serif;
	
}
h2 {
font-size:1.2em;
}

-->
</lp:script>


</lp:lists>
</lp:root>

Los estilos que definas aqui se visualizan con preferencia a los que genera el HKLA por defecto.

El cuerpo de la página

<?xml version="1.0"?>

<!-- Copyright (C) 2003, Chami.com. All Rights Reserved. -->

<lp:root xmlns:lp="lp:data">
<lp:lists>


<lp:script export="1" exportid="{{REPORT_HEAD}}">
<!--
-->
</lp:script>

<lp:script export="1" exportid="{{REPORT_FOOTER}}">
<!--
<div align="left">Generated Using <%=sPROGRAM_COPYRIGHT%></div>
-->
</lp:script>


<lp:script export="1" exportid="{{REPORT_HEAD_TITLE}}">
<!--
<%=sXLOGFILE_FULL%>
-->
</lp:script>

<lp:script export="1" exportid="{{REPORT_HEAD_SCRIPT}}">
<!--
-->
</lp:script>


<lp:script export="1" exportid="{{REPORT_HEAD_CSS}}">
<!--

BODY {
background:#EEEEEE;
color: #000;
font: normal 11px Verdana, Geneva, Arial, Helvetica, sans-serif;
	
}
h2 {
font-size:1.2em;
}

-->
</lp:script>

</lp:lists>
</lp:root>

Con REPORT_HEAD y REPORT_FOOTER podemos incluir texto al comienzo o final de la página. Admite código HTML y xscl.

En nuestro ejemplo dejaremos el FOOTER tal cual está, y como encabezamiento, añadiremos simplemente un título: <h2>Informe de Browsers</h2>

<lp:script export="1" exportid="{{REPORT_HEAD}}">
<!--
<h2>Informe de Browsers</h2>
-->
</lp:script>

La tabla de fechas

Aunque tu log tenga datos de varios dias, HKLA analiza por defecto solo el último, y incluye una tabla con enlaces a los datos de dias anteriores. He aqui el bloque para generar esta tabla:

<lp:script export="1" exportid="{{REPORT_DATA_SUMMARY}}">
<!--
<div align="left">

<h3>hkLAP Report Template Sample 1</h3>

<%if(length(sDATESTABLE)>0){%>
<table border="1" cellpadding="1" cellspacing="0"><%=sDATESTABLE%></table>
<%}%>

</div>
-->
</lp:script>

sDATESTABLE es otra variable predefinida con los dias de los que hay datos en el log, y un enlace hacia ellos. Pulsando cualquier dia se genera el informe del mismo.

La generación de la tabla es automática, asi que solo podemos aprovechar para definir aqui algunos estilos aplicables en conjunto a esta tabla.

Tratando los datos

HKLA trabaja sobre el log del servidor. Se trata de archivos de texto que se generan automáticamente guardando datos de cada transacción http realizada: que recurso se solicita, cuando y por quien.

Normalmente los proveedores de espacio web niegan a los clientes acceso a los logs del servidor, o facilitan solo acceso restringido. Una solución alternativa entonces es la de crear nuestros propios logs. Aqui suponemos que ya tenemos nuestro archivo log disponible. Si tu tienes probremas para generarlo, puedes ver instrucciones aqui.

En definitiva, para cada petición http, normalmente el log guardará los datos de la fecha y la hora de la petición, la ip del solicitante, la página solicitada, la página de origen de la petición -es decir, el link desde donde se ha llegado, si existe- y la cadena de identificación del navegador, que a su vez suele informar tambien acerca del sistema operativo.

Para obtener nuestros informes personalizados, necesitamos decirle al HKLA sobre que dato debe trabajar:

<lp:list source="user_agent" var="BROWTYPES" static="1">

</lp:list>

En este bloque de código indicamos a HKLA que debe trabajar sobre la parte del log que contiene la cadena de identificación del browser. Algunos otros valores alternativos para source serían:


source="resource"    // -> Páginas solicitadas
source="ip"          // -> Ip del solicitante
source="user_agent"  // -> cadena identificativa del browser
source="ref"         // -> http refering page

A continuación y dentro de este bloque, podemos especificar los patrones de búsqueda que deseemos para filtrar los datos. Veamos los patrones que usa la plantilla suministrada Sample1.lat:

<lp:list source="user_agent" var="BROWTYPES" static="1">

<!-- match = regex to match, title = item name -->
<lp:li match="\.NET[^\;\d]+(\d+)\.(\d+)\.(\d+)" 
title=".NET v\1.\2.\3" mode="1" />

</lp:list>

Podemos incluir tantos filtros como deseemos. match es el patrón a buscar y title el nombre que se asignará a este resultado.

En el ejemplo facilitado se genera un gráfico con los navegadores con soporte .NET. El ejemplo que queremos desarrollar aqui haría una clasificación mas exhaustiva de los navegadores que han visitado nuestra página. Podríamos ir introduciendo filtros para todos los que conozcamos ...

<lp:list source="user_agent" var="BROWTYPES" static="1">


<lp:li match="MSIE ([0-9.]+)" title="IExplorer v \1\2" mode="1" />
<lp:li match="((msnbot)|(Yahoo)| (Googlebot)|F((ast)|(AST)))" title="Bot" mode="1" />
<lp:li match="Netscape/([0-9].[0-9a-zA-Z]{1,4})" title="Netscape v \1\2" mode="1" />
<lp:li match="Opera/?\s?([0-9].[0-9a-zA-Z]{1,4})" title="Opera \1\2" mode="1" />
<lp:li match="Firefox/([0-9].[0-9a-zA-Z]{1,4})" title="Firefox v \1\2" mode="1" />
<lp:li match="" title="Otros"></lp:li>


</lp:list>

Como verás los patrones los definimos con expresiones regulares. Una vez establecidos los criterios de filtrado, y el nombre asignado a cada coincidencia (incluyendo al final un patrón vacio llamado 'otros' que recogera todas aquellas entradas que no hayamos podido identificar), es el momento de especificar algunos datos adicionales:

<lp:list source="user_agent" var="BROWTYPES" static="1">

<!-- match = regex to match, title = item name -->
<lp:li match="\.NET[^\;\d]+(\d+)\.(\d+)\.(\d+)" 
title=".NET v\1.\2.\3" mode="1" />
<!-- mas filtros aqui ... -->
<lp:li match="" title="Other"></lp:li>


<lp:script srcid="v1" apply="1">

<lp:param name="{{TITLE}}" value="User agents with .NET signatures" />
<lp:param name="{{TYPE}}" value="User Agent / Browser / Spider / Robot" />
<lp:param name="{{SHOW_HS}}" value="1" />
<lp:param name="{{SHOW_SS}}" value="1" />
<lp:param name="{{SHOW_HT}}" value="1" />
<lp:param name="{{SHOW_ST}}" value="1" />
<lp:param name="{{LINK}}" value="1" />
<lp:param name="{{MAX}}" value="50" />

</lp:script>

</lp:list>

Los valores que vemos aqui son los siguientes:

{{TITLE}}    <!-- titulo de los graficos -->
{{TYPE}}     <!-- encabezado de algunas tablas -->
{{SHOW_HS}}  <!-- Hits Shares -->
{{SHOW_SS}}  <!-- Sessions Shares -->
{{SHOW_HT}}  <!-- number of hits -->
{{SHOW_ST}}  <!-- number of sessions -->
{{LINK}} 
{{MAX}}      <!-- numero maximo de ocurrencias a mostrar -->

asi que hacemos los cambios necesarios para nuestro informe, que quedaría asi:

<lp:list source="user_agent" var="BROWTYPES" static="1">

<lp:li match="MSIE ([0-9.]+)" title="IExplorer v \1\2" mode="1" />
<lp:li match="((msnbot)|(Yahoo)| (Googlebot)|F((ast)|(AST)))" title="Bot" mode="1" />
<lp:li match="Netscape/([0-9].[0-9a-zA-Z]{1,4})" title="Netscape v \1\2" mode="1" />
<lp:li match="Opera/?\s?([0-9].[0-9a-zA-Z]{1,4})" title="Opera \1\2" mode="1" />
<lp:li match="Firefox/([0-9].[0-9a-zA-Z]{1,4})" title="Firefox v \1\2" mode="1" />
<lp:li match="" title="Otros"></lp:li>

<lp:script srcid="v1" apply="1">

<lp:param name="{{TITLE}}" value="tipos de navegadores" />
<lp:param name="{{TYPE}}" value="Iexplorer / Bots /  Netscape / Opera / Firefox" />
<lp:param name="{{SHOW_HS}}" value="1" />
<lp:param name="{{SHOW_SS}}" value="1" />
<lp:param name="{{SHOW_HT}}" value="1" />
<lp:param name="{{SHOW_ST}}" value="1" />
<lp:param name="{{LINK}}" value="0" />
<lp:param name="{{MAX}}" value="50" />

</lp:script>
</lp:list>

Dando forma al código

Ya solo nos queda por ver la sección de código que reune todos los datos que hemos ido especificando y le da formato html. Usamos sintaxis xscl, encerrada en comentarios html. El bloque contenedor es así:

<!-- Custom report printer -->
<lp:script title="abc" id="v1">
<!--




-->
</lp:script>

Especificamos que el formateo solo tiene lugar si tenemos resultados:

<!-- Custom report printer -->
<lp:script title="abc" id="v1">
<!--

<%
{
  var n = 0;
  var MAX="";
  if(nH{{VAR}}_Count > 0)
  {
%>


<%
  }
}
%>

-->
</lp:script>

nH{{VAR}}_Count es otra variable predefinida que contiene el número de items a mostrar, en este caso el numero de versiones de navegadores distintas encontradas en el log.
La variable {{VAR}} la definimos antes como BROWTYPES asi que nH{{VAR}}_Count = nHBROWTYPES_Count

Bien, siempre tomando como modelo Sample1.lat, vemos que los gráficos están encerrados en una tabla, calculando el script automáticamente los datos necesarios (nombre de la imagen, anchura, altura). Los datos asi calculados van encerrados en bloques xscl <% %>:


<%
if({{SHOW_HS}}) {
%>
<tr id="hs{{VAR}}">
<td align="center" colspan="2">
<img src="<%=sHCHART_SHARE_{{VAR}}%>" 
alt="{{TITLE}} - Hit Shares" width="<%=sCHART_WIDTH%>" 
height="<%=sCHART_HEIGHT%>" />
</td>
</tr>
<%}%>

Y esto es prácticamente todo: se trata "sencillamente" de generar una tabla que contendrá las etiquetas img de los gráficos generados con los datos capturados, y al final una lista con los mismos resultados en texto. Si deseas ver el código integro del ejemplo desarrollado, aqui lo tienes. Y esta es la página html obtenida

Variables predefinidas

El programa genera cientos de variables; estas son algunas de las que podemos reutilizar en nuestros informes:


sXLOGFILE_FULL          =  path completo al archivo log
sXLOGFILE_NAMEFILEEXT   =  nombre del archivo log
sTIMEFRAME_FROM         =  fecha analizada
sDATESTABLE             =  datos de la tabla de fechas

This site powered by Phorum.