Wie stelle ich die log4j-Ebene in der Befehlszeile ein?

77

Ich möchte einer Klasse, an der ich arbeite, einige log.debug-Anweisungen hinzufügen, und ich möchte dies beim Ausführen des Tests in der Ausgabe sehen. Ich möchte die log4j-Eigenschaften in der Befehlszeile folgendermaßen überschreiben:

-Dlog4j.logger.com.mypackage.Thingie=DEBUG

Ich mache so etwas häufig. Ich bin speziell nur an einer Möglichkeit interessiert, dies auf der Kommandozeile zu übergeben. Ich weiß, wie man es mit einer Konfigurationsdatei macht, und das passt nicht zu meinem Workflow.

Kevin Peterson
quelle

Antworten:

15

log4j unterstützt dies nicht direkt.

Da Sie keine Konfigurationsdatei möchten, verwenden Sie höchstwahrscheinlich die programmgesteuerte Konfiguration. Ich würde vorschlagen, dass Sie sich mit dem Scannen aller Systemeigenschaften befassen und darauf basierend explizit programmieren, was Sie möchten.

Thorbjørn Ravn Andersen
quelle
49

Als Teil Ihrer JVM-Argumente können Sie festlegen -Dlog4j.configuration=file:"<FILE_PATH>". Dabei ist FILE_PATH der Pfad Ihrer Datei log4j.properties.

Bitte beachten Sie, dass ab log4j2 die neue zu verwendende Systemvariable lautet log4j.configurationFileund Sie den tatsächlichen Pfad zur Datei eingeben (dh ohne file:Präfix). Die Factory wird basierend auf der Erweiterung der Konfigurationsdatei automatisch geladen:

-Dlog4j.configurationFile=/path/to/log4jconfig.{ext}
Anubis05
quelle
3
FILE_PATH wird tatsächlich im CLASSPATH durchsucht, auch in JAR-Dateien.
Robin Green
12
Sie müssen "file:" vor den Pfad stellen, wenn es sich um eine Datei auf der Festplatte handelt. Mit anderen Worten ... -Dlog4j.configuration = Datei: <Dateipfad> stackoverflow.com/questions/778933/…
Crowmagnumb
2
Dies funktioniert wie angegeben. Ich versuche jedoch, eine Einstellung einer Eigenschaftendatei im JAR zu überschreiben, und letztere scheint danach festgelegt zu werden. Irgendein Rat?
John Lehmann
34

Diese Antworten haben mich tatsächlich davon abgehalten, das Einfachste zu versuchen! Geben Sie einfach einen Schwellenwert für eine appender (sagen wir, „Konsole“) in der in log4j.configurationetwa so:

log4j.appender.console.threshold=${my.logging.threshold}

Fügen Sie dann in der Befehlszeile die Systemeigenschaft ein -Dlog4j.info -Dmy.logging.threshold=INFO. Ich gehe davon aus, dass jede andere Eigenschaft auf diese Weise parametrisiert werden kann, aber dies ist der einfachste Weg, um die Protokollierungsstufe global zu erhöhen oder zu senken.

AbuNassar
quelle
Ich bin mir ziemlich sicher, dass dies die einfachste Lösung für die ursprüngliche Frage ist!
Droj
@Droj Vielleicht schon, aber OP wollte das alles im Code machen. Chacun ein Sohn Gicht.
AbuNassar
In meinem Fall wollte ich es auch über die Kommandozeile einstellen, aber ich hatte bereits eine Konfiguration. Ich wollte die Datei einfach nicht bearbeiten müssen, um eine andere Protokollierung zu erhalten. Ich habe es nicht als "all in code" gelesen, aber vielleicht auch ...
Droj
1
Nur eine kleine Verbesserung: yamlLoggers:\n Logger:\n name: stuff \n level: ${sys:my.log.level:-INFO}
Ich
Ich mag die obige YAML, aber IIRC Spring führt keine variable Interpolation für YAML durch.
AbuNassar
17

Mit Log4j2 kann dies mithilfe der folgenden Dienstprogrammmethode erreicht werden, die Ihrem Code hinzugefügt wurde.

private static void setLogLevel() {
  if (Boolean.getBoolean("log4j.debug")) {
    Configurator.setLevel(System.getProperty("log4j.logger"), Level.DEBUG);
  }
}

Sie benötigen diese Importe

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;

setLogLevelRufen Sie nun die Methode in main () oder gegebenenfalls auf und übergeben Sie die Befehlszeilenparameter -Dlog4j.logger=com.mypackage.Thingieund -Dlog4j.debug=true.

Neo
quelle
2
Dies sollte die akzeptierte Antwort sein, sobald die Pakete aktualisiert wurden. Vielen Dank für eine aktualisierte Antwort. Ich freue mich sehr über aktualisierte Antworten, wenn es um langjährige Fragen geht. Du hast mir einiges an Frust erspart.
Daniel B. Chapman
6

Basierend auf dem Vorschlag von Thorbjørn Ravn Andersens habe ich einen Code geschrieben, mit dem dies funktioniert

Fügen Sie Folgendes früh in die Hauptmethode ein, und es ist jetzt möglich, die Protokollstufe über die Befehlszeile festzulegen. Dies wurde in einem meiner Projekte getestet, aber ich bin neu in log4j und habe möglicherweise einen Fehler gemacht. Wenn ja, bitte korrigieren Sie mich.

    Logger.getRootLogger().setLevel(Level.WARN);
    HashMap<String,Level> logLevels=new HashMap<String,Level>();
    logLevels.put("ALL",Level.ALL);
    logLevels.put("TRACE",Level.TRACE);
    logLevels.put("DEBUG",Level.DEBUG);
    logLevels.put("INFO",Level.INFO);
    logLevels.put("WARN",Level.WARN);
    logLevels.put("ERROR",Level.ERROR);
    logLevels.put("FATAL",Level.FATAL);
    logLevels.put("OFF",Level.OFF);
    for(String name:System.getProperties().stringPropertyNames()){
        String logger="log4j.logger.";
        if(name.startsWith(logger)){
            String loggerName=name.substring(logger.length());
            String loggerValue=System.getProperty(name);
            if(logLevels.containsKey(loggerValue))
                Logger.getLogger(loggerName).setLevel(logLevels.get(loggerValue));
            else
                Logger.getRootLogger().warn("unknown log4j logg level on comand line: "+loggerValue);
        }
    }
lijat
quelle
4

In meinem hübschen Standard-Setup habe ich Folgendes gut gesehen, wenn es als VM Option übergeben wurde (Befehlszeile vor dem Unterricht in Java oder VM Option in einer IDE):

-Droot.log.level=TRACE
Rob Dawson
quelle
2

Basierend auf @lijat ist hier eine vereinfachte Implementierung. In meiner frühlingsbasierten Anwendung lade ich diese einfach als Bohne.

public static void configureLog4jFromSystemProperties()
{
  final String LOGGER_PREFIX = "log4j.logger.";

  for(String propertyName : System.getProperties().stringPropertyNames())
  {
    if (propertyName.startsWith(LOGGER_PREFIX)) {
      String loggerName = propertyName.substring(LOGGER_PREFIX.length());
      String levelName = System.getProperty(propertyName, "");
      Level level = Level.toLevel(levelName); // defaults to DEBUG
      if (!"".equals(levelName) && !levelName.toUpperCase().equals(level.toString())) {
        logger.error("Skipping unrecognized log4j log level " + levelName + ": -D" + propertyName + "=" + levelName);
        continue;
      }
      logger.info("Setting " + loggerName + " => " + level.toString());
      Logger.getLogger(loggerName).setLevel(level);
    }
  }
}
Chris Noe
quelle