Download Registro de traza en Java

Document related concepts
no text concepts found
Transcript
Registro de traza en
Java
[email protected] / [email protected]
¿…y qué es la traza?
Veremos dentro de poco como
crear el objeto “log”.
public int suma(int a, int b)
{
log.debug(“Entrando en suma”);
int sum;
sum = a + b;
log.info(“Resultado de la suma:”+sum);
log.debug(“Saliendo de suma”);
return sum;
}
<debug> Entrando en suma
<info> Resultado de la suma: X
<debug> Saliendo de suma
1
Utilidad de la traza
Ayuda a encontrar errores.
Ayuda a depurar programas (multihilo,
distribuidos, etc…)
Permite mejorar el rendimiento.
¿Cuál es más útil para detectar lo que ha pasado?
java.sql.SQLException: Table not found: TEO in statement [SELECT * FROM Teo;]
at org.hsqldb.Trace.getError(Unknown Source)
at org.hsqldb.jdbcResultSet.<init>(Unknown Source)
at org.hsqldb.jdbcConnection.executeStandalone(Unknown Source)
at org.hsqldb.jdbcConnection.execute(Unknown Source)
at org.hsqldb.jdbcStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbcStatement.executeQuery(Unknown Source)
at org.rquery.helppers.Metadata.GetFieldList(Metadata.java:115)
at org.rquery.analex.ra.SQLBuilderAR.buildRelation(SQLBuilderAR.java:69)
at org.rquery.analex.ra.ParserLLAR.generate(ParserLLAR.java:204)
at org.rquery.analex.ra.ParserLLAR.translateQuery(ParserLLAR.java:99)
at org.rquery.analex.AnalexDecorator.translateQuery(AnalexDecorator.java:36)
at org.rquery.gui.RQueryAdvancedGUI$EjecutarAction.doQuery(RQueryAdvancedGUI.java:776)
at org.rquery.gui.RQueryAdvancedGUI$EjecutarAction.actionPerformed(RQueryAdvancedGUI.java:755)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown
Source)
<info> GUI - Pulsado botón ejecutar.
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
<info> Parser – Consulta
recibida ‘TEO;’
at java.awt.Container.dispatchEventImpl(Unknown
Source)
at java.awt.Window.dispatchEventImpl(Unknown
Source) válida ‘TEO;’
<info> Parser – Consulta
at java.awt.Component.dispatchEvent(Unknown Source)
<info> SQLTranslator – Consulta traducida a ‘select * from TEO;‘
at java.awt.EventQueue.dispatchEvent(Unknown Source)
<info> SQLExec – Ejecutando consulta
‘select * from TEO;‘
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown
Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown
Source)
<error> SQLExec – Excepción Table
not found: TEO in statement
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
<debug> SQLExec – Consulta
at java.awt.EventDispatchThread.pumpEvents(Unknown
Source) abortada
at java.awt.EventDispatchThread.run(Unknown
Source)
<info> GUI – Consulta
terminada.
1
2
[SELECT * FROM Teo;]
2
Características de Log4j
Habilitar o desabilitar logs.
Priorizar mensajes.
Redirección de la salida.
Formato de los mensajes.
Configuración por código o archivos
externos.
Organización jerárquiza.
Creando un log
import org.apache.log4j.Logger;
Aunque hay más, de momento
es suficiente.
public class PruebaLog {
Uno para todos….
static Logger log;
static {
log =
Logger.getLogger(PruebaLog.class.getName());
El nombre de un log es el
nombre de la clase y de los
paquetes donde está.
Si no existe lo crea y si ya se
creo devuelve una referencia
}
}
Todo log tiene una
configuración por defecto que
podemos cambiar desde el
código o desde un archivo
externo.
3
Niveles de prioridad
DEBUG: Mensajes de depuración.
INFO: Mensajes similares al modo "verbose" en otras aplicaciones.
WARN: Mensajes de alerta sobre eventos que se desea mantener
constancia, pero que no afectan el funcionamiento del programa.
ERROR: Mensajes de error de la aplicación que se desea guardar,
estos eventos afectan al programa pero lo dejan seguir
funcionando.
FATAL: Mensajes críticos del sistema, generalmente después de
guardar el mensaje el programa abortará.
(Solo para el archivo de configuración):
ALL: este es el nivel más bajo posible, habilita todos los logs.
OFF: este es el nivel más alto posible, deshabilita todos los logs.
FATAL < ERROR < WARN < INFO < DEBUG
Un log para Intercambiar
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
public static void Intercambia(List l1, List l2)
{
Object b1=null;
Object aux=null;
Collections.sort(l1);
Collections.sort(l2);
ListIterator i1=l1.listIterator();
while (i1.hasNext())
{
b1=i1.next();
int pos=Collections.binarySearch(l2,b1);
if (pos<0) {
if (i1.hasNext()){
aux=i1.next();
if (b1.equals(aux)) {
i1.remove();
l2.add(b1);
Collections.sort(l2);
}
}
}
}
}
¿En qué líneas y
con qué nivel se
colocaría la traza?
4
Un log para Intercambiar
Una solución
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
public static void Intercambia(List l1, List l2) {
Object b1=null; Object aux=null;
log.info("LLamada a Intercambia(l1, l2);");
if ((l1 == null) || (l2==null)) {
log.error("Lista nula:\nl1="+l1+"\nl2="+l2+"\nOperación abortada.");
0 [main] INFO IntercambiaConLog - LLamada a Intercambia(l1, l2);
return;
}
0 [main] DEBUG IntercambiaConLog - Parßmetros:
Collections.sort(l1);l1=[1,
Collections.sort(l2);
2, 2, 3]|l2=[4, 5, 6]
log.debug("Parámetros:\nl1="+l1+"\nl2="+l2);
0 [main] DEBUG IntercambiaConLog - Elemento procesado: 1
ListIterator i1=l1.listIterator();
0 [main] DEBUG IntercambiaConLog - Elemento no encontrado en l2
while (i1.hasNext()) {
0 [main] DEBUG IntercambiaConLog - Elemento procesado: 2
b1=i1.next();
[main] DEBUG
IntercambiaConLog - Elemento no encontrado en l2
log.debug("Elemento0 procesado:
"+b1);
int pos=Collections.binarySearch(l2,b1);
0 [main] INFO IntercambiaConLog - Salida de Intercambia(l1, l2);
if (pos<0) {
if (i1.hasNext()) {
log.debug("Elemento no encontrado en l2");
aux=i1.next();
0 [main] INFO {IntercambiaConLog - LLamada a Intercambia(l1, l2);
if (b1.equals(aux))
log.debug("Elemento
repetido
encontrado en - l1");
16 [main] ERROR
IntercambiaConLog
Lista nula:
i1.remove();
l2.add(b1);
l1=null|
l2=[3, 4, 2, 6, 4]
Collections.sort(l2);
Operaci¾n abortada.
log.debug("Nuevo valor de l2 ="+l2);
}
}
} else
log.debug("Elemento encontrado en l2");
}
log.info("Salida de Intercambia(l1, l2);");
}
Cambio del nivel del log.
0 [main] INFO IntercambiaConLog - LLamada a Intercambia(l1, l2);
0 [main] DEBUG IntercambiaConLog - Parßmetros:
l1=[1, 2, 2, 3]|l2=[4, 5, 6]
0 [main] DEBUG IntercambiaConLog - Elemento procesado: 1
0 [main] DEBUG IntercambiaConLog - Elemento no encontrado en l2
0 [main] DEBUG IntercambiaConLog - Elemento procesado: 2
0 [main] DEBUG IntercambiaConLog - Elemento no encontrado en l2
0 [main] INFO IntercambiaConLog - Salida de Intercambia(l1, l2);
0 [main] INFO IntercambiaConLog - LLamada a Intercambia(l1, l2);
0 [main] INFO IntercambiaConLog - Salida de Intercambia(l1, l2);
log.setLevel(Level.INFO);
5
Conceptos
Dos conceptos importantes:
„
„
Appender: indica que hacer con la
información que recibe.
Layout: indica el formato de la información.
Ejemplo anterior
„
„
Appender: mostrarlo por salida estándar.
Layout: todo lo que añadía almensaje.
Vamos a ver estos conceptos junto con el
archivo de propiedades
El archivo de propiedades
Nombre del log.
log4j.logger.IntercambiaConLog=DEBUG, stdout
Nivel del log.
log4j.appender.stdout =
org.apache.log4j.ConsoleAppender
Lista de appenders.
log4j.appender.stdout.layout =
org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =
%5p (%F:%L) - %m%n
El appender “stdout” manda el
mensaje a la consola.
El layout de “stdout” sige un
patrón. Si no indicamos el
patrón se muestra solo el
mensaje.
Un posible patrón:
%p: nivel del mensaje.
%F: nombre del fichero.
%L: Núm. de línea.
%m: Mensaje.
6
Como usarlo
import org.apache.log4j.Logger;
public class PruebaLog {
static Logger log;
static {
PropertyConfigurator.configure("log.prop");
log = Logger.getLogger(PruebaLog.class.getName());
}
}
INFO (IntercambiaConLog.java:31) - LLamada a Intercambia(l1, l2);
DEBUG (IntercambiaConLog.java:39) - Parßmetros:
l1=[1, 2, 2, 3]|l2=[4, 5, 6]
DEBUG (IntercambiaConLog.java:44) - Elemento procesado: 1
DEBUG (IntercambiaConLog.java:50) - Elemento no encontrado en l2
DEBUG (IntercambiaConLog.java:44) - Elemento procesado: 2
DEBUG (IntercambiaConLog.java:50) - Elemento no encontrado en l2
INFO (IntercambiaConLog.java:65) - Salida de Intercambia(l1, l2);
Otro appender
Ahora los mensajes irán tanto a
“stdout” como a “logfile”.
log4j.logger.IntercambiaConLog=
DEBUG, stdout, logfile
log4j.appender.logfile =
org.apache.log4j.RollingFileAppender
log4j.appender.logfile.layout =
org.apache.log4j.SimpleLayout
El appender guarda los
mensajes en ficheros del
tamaño indicado.
Solo el nivel y el mensaje.
log4j.appender.logfile.File=log.log
Nombre del fichero
log4j.appender.logfile.MaxFileSize=100KB
Tamaño
7
Otro ejemplo
Un fragmento del temporizador
1.
public class Temporizador {
2.
// Atributos…
3.
4.
public Temporizador(int numPruebas) {
if (numPruebas>0){
this.numPruebas=numPruebas;
tiempos= new long [numPruebas];
5.
6.
7.
8.
} else {
throw new
IllegalArgumentException();
}
}
9.
10.
11.
public Temporizador() {
this(1);
}
12.
// ….
13
Escribir la inicialización y
los mensajes del log.
}
Otro ejemplo
Un fragmento del temporizador
1. public class Temporizador {
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
// Atributos…
public Temporizador(int numPruebas) {
log.debug("Nuevo temporizador con "+numPruebas+"
pruebas");
if (numPruebas>0){
this.numPruebas=numPruebas;
tiempos= new long [numPruebas];
} else {
log.error("Núm de pruebas
Se lanza
importinvalido.
org.apache.log4j.Logger;
IllegalArgumentException.");
throw new IllegalArgumentException();
public class Temporizador {
}
static Logger log;
}
static {
BasicConfigurator.configure();
public Temporizador() {
//PropertyConfigurator.configure("log.prop");
this(1);
log =
log.warn("Creado temporizadorLogger.getLogger(PruebaLog.class.getName());
con 1 sola prueba\n"+
"Probablemente el tiempo de ejecución sea 0.");
}
}
// ….
//…..
}
}
8
El problema de los temporizadores
Escribir un archivo de
propiedades para este
problema.
El problema de los temporizadores
# Log padre de todos los demás
log4j.rootLogger=DEBUG, stdout
## Logs
log4j.logger.Temporizador=DEBUG, stdout
log4j.logger.Busqueda=DEBUG, stdout
## Estas dos ya nos las dan hechas, por lo que es probable que funcionen
log4j.logger.BusquedaBinaria=ERROR, busquedas
log4j.logger.BusquedaLineal=ERROR, busquedas
# Este appener va a la consola - Salida por pantalla
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%F:%L) - %m%n
# Appender de las búsquedas ya implementadas
log4j.appender.busquedas=org.apache.log4j.FileAppender
log4j.appender.busquedas.File=busquedas.log
# Mostramos el número de línea, el archivo y el mensaje
log4j.appender.busquedas.layout=org.apache.log4j.PatternLayout
log4j.appender.busquedas.layout.ConversionPattern= (%L) - [%F] %m%n
9
Ant
¿Qué es Ant?
Una versión evolucionada de “make”.
http://jakarta.apache.org/ant/index.html
Ant busca automatiza la ejecución de
tareas.
Las tareas se guardan en un archivo XML.
10
Algunos ejemplos de tareas
automatizables.
Crear la estructura de carpetas de nuestro
proyecto.
Compilación incremental
Generar la documentación javadoc.
Generar la versión de distribución.
Un ejemplo de ejecución I. Tareas.
build.xml
Nombre por defecto.
<?xml version="1.0" encoding="UTF-8"?>
<project name="PruebaAnt" basedir=".">
<target name="init"
description="o Crea la estructura de directorios">
<mkdir dir="bin"> </mkdir>
<mkdir dir="src"> </mkdir>
<mkdir dir="lib"> </mkdir>
</target>
</project>
11
Más tareas.
build.xml
Compila todos los .java excepto las pruebas.
<?xml version="1.0" encoding="UTF-8"?>
<project name="PruebaAnt" basedir=".“ default="Compile">
<target name="compile" description="o Compila el codigo">
<javac destdir="bin" deprecation="true“ debug="true“
optimize="false" excludes="**/Test*">
<src>
<pathelement location="src"> </pathelement>
</src>
<classpath>
<fileset dir="lib">
<include name="*.jar"> </include>
</fileset>
</classpath>
</javac>
</target>
</project>
Documentación sobre las tareas
En la documentación de ant se pueden
encontrar todas las tareas y sus atributos.
12
Ant + Junit
Ejecutándo las pruebas desde ant
<target name="test" description="o Ejecuta las pruebas">
<junit printsummary="yes">
<!-- Por defecto el resultado siempre se
envia a un archivo. -->
<formatter type="plain" usefile="false"/>
<batchtest fork="yes">
<fileset dir=".">
<include name="*Test*.class"/>
</fileset>
</batchtest>
</junit>
</target>
Dependencias entre tareas
Crea un archivo ZIP con
todo lo necesario.
> ant crear-distribución
Primero compila todos los
fuentes.
> compilar
Después ejecuta las pruebas para
asegurar que no hay ningún error.
> probar
> Borrar o crear directorios
> copiar-archivos
> crear-javadoc
> empaquetar
Borra la antigua distribución o
crea los directorios si no existen.
Copia los archivos de la
distribución
Crea la documentación
del código
Empaqueta toda la
distribución
13
FIN
[email protected] / [email protected]
14