Domanda

Abbiamo diversi lavori eseguiti contemporaneamente che devono utilizzare le stesse informazioni di configurazione per log4j.Stanno tutti scaricando i log in un file utilizzando lo stesso appender.Esiste un modo per assegnare a ciascun lavoro un nome dinamico al proprio file di registro in modo che rimangano separati?

Grazie
Tom

È stato utile?

Soluzione

Puoi passare una proprietà di sistema Java per ogni lavoro?Se è così, puoi parametrizzare in questo modo:

java -Dmy_var=somevalue my.job.Classname

E poi nel tuo log4j.properties:

log4j.appender.A.File=${my_var}/A.log

Potresti popolare la proprietà di sistema Java con un valore dall'ambiente dell'host (ad esempio) che identificherebbe in modo univoco l'istanza del lavoro.

Altri suggerimenti

Se i nomi dei lavori sono noti in anticipo, è possibile includere il nome del lavoro quando si esegue la chiamata getLogger().È quindi possibile associare diversi appender a diversi logger, con nomi di file separati (o altre destinazioni).

Se non puoi conoscere il nome del lavoro in anticipo, puoi configurare il logger in fase di esecuzione invece di utilizzare un file di configurazione:

FileAppender appender = new FileAppender();
appender.setFileName(...);
appender.setLayout(...);
Logger logger = Logger.getLogger("com.company.job."+jobName);
logger.addAppender(appender);

Abbiamo qualcosa di simile implementato nel nostro sistema.Memorizziamo i logger specifici in una HashMap e inizializziamo gli appender per ciascuno di essi secondo necessità.

Ecco un esempio:

public class JobLogger {
private static Hashtable<String, Logger> m_loggers = new Hashtable<String, Logger>();
private static String m_filename = "...";  // Root log directory

public static synchronized void logMessage(String jobName, String message)
{
    Logger l = getJobLogger(jobName);
    l.info(message);
}

public static synchronized void logException(String jobName, Exception e)
{
    Logger l = getJobLogger(partner);
    l.info(e.getMessage(), e);
}

private static synchronized Logger getJobLogger(String jobName)
{
    Logger logger = m_loggers.get(jobName);
    if (logger == null) {
        Layout layout = new PatternLayout("...");
        logger = Logger.getLogger(jobName);
        m_loggers.put(jobName, logger);
        logger.setLevel(Level.INFO);
        try {
            File file = new File(m_filename);
            file.mkdirs();
            file = new File(m_filename + jobName + ".log");
            FileAppender appender = new FileAppender(layout, file.getAbsolutePath(), false);
            logger.removeAllAppenders();
            logger.addAppender(appender);
    }
        catch (Exception e)
    { ... }
    }
    return logger;
}
}

Quindi per usarlo nel tuo lavoro devi solo usare una voce di una riga come questa:

JobLogger.logMessage(jobName, logMessage);

Ciò creerà un file di registro per ciascun nome di lavoro e lo inserirà nel proprio file con quel nome di lavoro in qualunque directory specificata.

Puoi giocherellare con altri tipi di appender e simili, come scritto continuerà ad aggiungere fino al riavvio della JVM, il che potrebbe non funzionare se esegui lo stesso lavoro su un server sempre attivo, ma questo dà l'idea generale di come può lavoro.

È possibile fare in modo che ogni lavoro imposti NDC o MDC e quindi scrivere un appender che vari il nome in base al valore NDC o MDC.Creare un nuovo appender non è troppo difficile.Potrebbe anche esserci un appender che si adatterà al conto nella sandbox log4j.Inizia a guardare dentro http://svn.apache.org/viewvc/logging/log4j/trunk/contribs/

Potresti scrivere il tuo appender che compone il proprio nome file, magari usando [File.createTempFile](http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String)) metodo.Se la FileAppender class è stata scritta correttamente, dovresti essere in grado di estenderla, oppure RollingFileAppender-e sovrascrivere il getFile per restituirne uno scelto in base alle nuove proprietà che desideri aggiungere.

Basandosi su shaditè la risposta.Se è possibile identificare ciascun lavoro in base al metodo principale della classe avviato, è possibile utilizzare la proprietà di sistema sun.java.command che contiene il nome completo della classe iniziata.Ad esempio in questo modo:

log4j.appender.LOGFILE.File=${sun.java.command}.log

Lo uso insieme ad a TimestampFileAppender come questo:

log4j.appender.LOGFILE=TimestampFileAppender
log4j.appender.LOGFILE.TimestampPattern=yyyy_MM_dd__HH_mm
log4j.appender.LOGFILE.File=${sun.java.command}_{timestamp}.log

In questo modo quando sviluppo in Eclipse ottengo un nuovo file di log per ogni nuovo processo che eseguo, identificato dal nome della classe con il metodo main e dall'ora in cui è stato avviato.

Tom, potresti specificare e aggiungere accessori per ciascun lavoro.Supponiamo che tu abbia 2 lavori corrispondenti a due diversi pacchetti Java com.tom.firstbatch e com.tom.secondbatch, avresti qualcosa di simile in log4j.xml:

   <category name="com.tom.firstbatch">
      <appender-ref ref="FIRST_APPENDER"/>
   </category>
   <category name="com.tom.secondtbatch">
      <appender-ref ref="SECOND_APPENDER"/>
   </category>

È possibile configurare log4j a livello di codice quando si inizializza il lavoro.

È inoltre possibile impostare il file log4j.properties in fase di runtime tramite una proprietà di sistema.Dal Manuale:

Imposta la variabile della stringa della risorsa sul valore di log4j.configurazione proprietà del sistema.Il modo preferito per specificare il file di inizializzazione predefinito è tramite la proprietà di sistema log4j.configuration.Nel caso in cui la proprietà di sistema log4j.configuration non sia definita, impostare la risorsa variabile stringa sul suo valore predefinito "log4j.properties".

Supponendo che tu stia eseguendo i lavori da comandi Java diversi, ciò consentirà loro di utilizzare file log4j.properties diversi e nomi di file diversi per ciascuno di essi.

Senza una conoscenza specifica di come vengono gestiti i tuoi lavori è difficile dirlo!

puoi implementare quanto segue:

  • Un titolare ThreadLocal per l'identità del tuo lavoro.
  • Estendi FileAppender, il tuo FileAppender deve mantenere una mappa contenente un QuietWriter per ogni identità di lavoro.Nel metodo subAppend, ottieni l'identità del tuo lavoro da ThreadLocal, cerchi (o crei) QuietWriter e scrivi su di esso...

Posso inviarti qualche codice via mail se lo desideri...

log4j.logger.com.foo.admin =, adminfileappender log4j.logger.com.foo.report =, reportFileAppender

È un altro modo per svolgere questo compito..qui com.foo.admin è il nome completo del pacchetto

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top