2009-07-12 13 views
5

Estoy creando un java.util.logging.FileHandler que puede recorrer los archivos. Cuando se ejecutan varias instancias de mi aplicación, se crea un nuevo archivo de registro para cada instancia de la aplicación. Necesito saber qué archivo está utilizando la aplicación porque quiero subir el archivo de registro a mis servidores para su posterior revisión. ¿Cómo puedo saber qué archivo está usando un determinado FileHandler?Determine el archivo que está utilizando FileHandler

Respuesta

2

La manera más fácil es colocar algún tipo de identificador en el nombre del archivo, es decir, el argumento pattern al crear el FileHandler. Como estas son instancias de la misma aplicación, una forma de distinguirlas es mediante su identificación de proceso, por lo que podría hacer esa parte del patrón. Un mejor enfoque es pasar un identificador a través de la línea de comando y usarlo para crear su nombre de archivo. De esta forma, usted controla los archivos que se crean en algún sentido. Finalmente, si su aplicación tiene algún conocimiento de por qué es diferente de todas las demás, por ejemplo, se conecta a un servidor de base de datos en particular, entonces podría simplemente usar ese nombre de servidor de base de datos como parte del nombre del archivo.

EDITAR: Parece que no hay ninguna API para obtener el nombre del archivo que está utilizando un FileHandler. Yo sugeriría mirar en las extensiones de explotación forestal en x4juli (los puertos que una gran cantidad de la funcionalidad log4j a las especificaciones java.util.logging):

usted debería ser capaz de sustituir una instancia de su FileHandler que proporciona un método getFile():

+0

Bueno, cada vez que se ejecuta una nueva instancia, el archivo de registro se incrementa de modo que: primera instancia - log.0 segunda instancia - log.1 tercera instancia - log.2 –

+0

Tal vez he malentendido tu pregunta Parece que ya puedes asociar una instancia con un archivo, ¿qué más necesitas? Si necesita más información de identificación, como qué significa la instancia 1, 2 o 3, entonces debe mejorarla de la manera que he especificado anteriormente. Si no, entonces aclare. – ars

+0

Digamos que tengo 3 instancias ejecutándose, y cada una tiene su propio archivo de registro, como se indica en mi último comentario.La instancia 2 encuentra un error y registra el error en su archivo de registro (log.1), luego deberá cargar el archivo de registro en un servidor, pero para poder cargarlo, debe saber a qué archivo de registro acaba de escribir, que ser el mismo que subirá –

0

Bien, tengo que decir que FileHandler no proporciona una forma de determinar el archivo de registro. Es realmente tonto.

Terminé escribiendo una función llamada "chooseFile()" que busca/tmp para el siguiente nombre de archivo de registro disponible y devuelve ese archivo. A continuación, puede pasar el nombre de ese archivo al nuevo FileHandler().

/** 
* Utility: select a log file. File is created immediately to reserve 
* its name. 
*/ 
static public File chooseFile(final String basename) throws IOException { 
    final int nameLen = basename.length(); 
    File tmpDir = new File(System.getProperty("java.io.tmpdir")); 
    String[] logs = tmpDir.list(new FilenameFilter() { 
     public boolean accept(File d, String f) { 
      return f.startsWith(basename); 
     } 
    }); 
    int count = 0; 
    if (logs.length > 0) { 
     for (String name : logs) { 
      int n = atoi(name.substring(nameLen)); 
      if (n >= count) count = n + 1; 
     } 
    } 
    String filename = String.format("%s%d.log", basename, count); 
    File logFile = new File(tmpDir, filename); 
    logFile.createNewFile(); 
    return logFile; 
} 
1

En realidad, puede hacer esto mucho más simple simplemente extendiendo FileHandler usted mismo. Por ejemplo ...

MyFileHandler.java:

import java.io.IOException; 
import java.util.logging.FileHandler; 
public class MyFileHandler extends FileHandler { 
    protected String _MyFileHandler_Patern; 
    public MyFileHandler(String pattern) throws IOException { 
     _MyFileHandler_Patern = pattern; 
    } 
    public String getMyFileHandlerPattern() { 
     return _MyFileHandler_Patern; 
    } 
} 

DeleteMe.java:

import java.io.IOException; 
import java.util.logging.Handler; 
import java.util.logging.Logger; 
public class DeleteMe { 
    public static void main(String[] args) throws IOException { 
     Logger log = Logger.getLogger(DeleteMe.class.getName()); 
     MyFileHandler output = new MyFileHandler("output.log"); 
     log.addHandler(output); 
     for (Handler handler : log.getHandlers()) { 
      if (handler instanceof MyFileHandler) { 
       MyFileHandler x = (MyFileHandler) handler; 
       if ("output.log".equals(x.getMyFileHandlerPattern())) { 
        System.out.println("found hanlder writing to output.log"); 
       } 
      } 
     } 
    } 
} 
+0

El problema con esto es si usó patrones ¿cómo sabe el archivo real que se utiliza? – PhoneixS

+0

También necesita agregar una llamada a super (patrón) en el controlador MyFileHandler, de lo contrario, el archivo no se usa para escribir los registros. Excelente enfoque, funciona como un encanto. –

0

Aquí es mi manera bastante hacky alrededor de ella. Funciona de manera predeterminada si no usa cadenas de formato, y debería funcionar si utiliza las cadenas de formato g y u en nombre de archivo, pero no las demás.

public class FriendlyFileHandler extends FileHandler { 

    /*** 
    * In order to ensure the most recent log file is the file this one owns, 
    * we flush before checking the directory for most recent file. 
    * 
    * But we must keep other log handlers from flushing in between and making 
    * a NEW recent file. 
    */ 
    private static Object[] flushLock = new Object[0]; 

    private String pattern; 

    public FriendlyFileHandler(String pattern, int maxLogLengthInBytes, int count) throws IOException, 
      SecurityException { 
     super(pattern, maxLogLengthInBytes, count); 

     this.pattern = pattern; 
    } 

    /*** 
    * Finds the most recent log file matching the pattern. 
    * This is just a guess - if you have a complicated pattern 
    * format it may not work. 
    * 
    * IMPORTANT: This log file is still in use. You must 
    * removeHandler() on the logger first, .close() this handler, 
    * then add a NEW handler to your logger. THEN, you can read 
    * the file. 
    * 
    * Currently supported format strings: g, u 
    * 
    * @return A File of the current log file, or null on error. 
    */ 
    public synchronized File getCurrentLogFile() { 

     synchronized(flushLock) { 

      // so the file has the most recent date on it. 
      flush(); 


      final String patternRegex = 
        // handle incremental number formats 
        pattern.replaceAll("%[gu]", "\\d*") + 
        // handle default case where %g is appended to end 
        "(\\.\\d*)?$"; 

      final Pattern re = Pattern.compile(patternRegex); 
      final Matcher matcher = re.matcher(""); 

      // check all files in the directory where this log would be 
      final File basedir = new File(pattern).getParentFile(); 
      final File[] logs = basedir.listFiles(new FileFilter() { 

       @Override 
       public boolean accept(final File pathname) { 
        // only get files that are part of the pattern 
        matcher.reset(pathname.getAbsolutePath()); 

        return matcher.find(); 
       } 

      }); 

      return findMostRecentLog(logs); 
     } 
    } 

    private File findMostRecentLog(File[] logs) { 

     if (logs.length > 0) { 
      long mostRecentDate = 0; 
      int mostRecentIdx = 0; 

      for (int i = 0; i < logs.length; i++) { 
       final long d = logs[i].lastModified(); 

       if (d >= mostRecentDate) { 
        mostRecentDate = d; 
        mostRecentIdx = i; 
       } 

      } 

      return logs[mostRecentIdx]; 
     } 
     else { 
      return null; 
     } 

    } 


    @Override 
    public synchronized void flush() { 

     // only let one Handler flush at a time. 
     synchronized(flushLock) { 
      super.flush(); 
     } 
    } 

} 
Cuestiones relacionadas