Log4j günlük seviyesini dinamik olarak değiştirme


127

Log4j günlük düzeyini dinamik olarak değiştirmek için farklı yaklaşımlar nelerdir, böylece uygulamayı yeniden konuşlandırmak zorunda kalmayacağım. Bu durumlarda değişiklikler kalıcı olacak mı?




3
Log4j2 için güncellenmiş soru: stackoverflow.com/questions/23434252/…
slaadvak

1
Bu sayfadaki (neredeyse) her şeyin log4j2 ile değil, log4j ile ilgili olduğuna dikkat edin. Bu sayfanın tamamı o kadar karışıklık ve yanlış yönlendirme ile dolu ki, KULLANILAMAZ. @Slaadvak'ın önerdiği şekilde stackoverflow.com/questions/23434252/… adresine gidin .
Lambart

Yanıtlar:


86

Günlük düzeyini değiştirmek basittir; konfigürasyonun diğer kısımlarının değiştirilmesi daha derinlemesine bir yaklaşım ortaya koyacaktır.

LogManager.getRootLogger().setLevel(Level.DEBUG);

Değişiklikler, yaşam döngüsü boyunca kalıcıdır Logger. Yeniden başlatma sırasında, çalışma zamanında seviyenin ayarlanması seviye değişikliğini sürdürmediğinden konfigürasyon okunur ve kullanılır.

GÜNCELLEME: Log4j 2 kullanıyorsanız , bu, uygulama sınıfları aracılığıyla gerçekleştirilebileceğinden setLevel, dokümantasyona göre çağrıları kaldırmalısınız .

API'de logger.setLevel () veya benzer yöntemlere yapılan çağrılar desteklenmez. Uygulamalar bunları kaldırmalıdır. Eşdeğer işlevsellik Log4j 2 uygulama sınıflarında sağlanır ancak uygulamayı Log4j 2 dahili bileşenlerinde değişikliklere açık bırakabilir.


5
Yalnızca çalışma zamanı bağımlılıkları içinLogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC

8
Log4j 2 API'sinin bir "setLevel" yöntemi sağlamadığını unutmayın.
ChrisCantrell

5
Ancak bu yalnızca kök kaydediciyi ayarlar, değil mi? Kök altında kaydediciler için ayrı seviyeler ayarlanmışsa, kök kaydediciyi ayarlamanın bu LOGGER'lar üzerinde hiçbir etkisi olmayacaktır. Root.getLoggerRepository (). GetCurrentCategories () gibi bir şey yapmamız gerekmiyor muydu? @AaronMcIver
TheMonkWhoSoldHisCode

8
@ChrisCantrell Log4j 2 , bu kadar basit olmasa da bunu yapmanın bir yolunu sunuyor .
CorayThan

2
Log4j2, log4j2.xml dosyasını (veya eşdeğerini) belirli aralıklarla tarayarak yapılandırmasını yenileyecek şekilde yapılandırılabilir. Örneğin <Configuration status = "warn" monitorInterval = "5" name = "tryItApp" packages = "">
Kimball Robinson

89

Dosya İzleme

Log4j, log4j.xmlyapılandırma değişiklikleri için dosyayı izleyebilir . Log4j dosyasını değiştirirseniz, log4j, yaptığınız değişikliklere göre günlük düzeylerini otomatik olarak yeniler. Ayrıntılar için) belgelerine org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,longbakın. Kontroller arasındaki varsayılan bekleme süresi 60 saniyedir. Bu değişiklikler, dosya sistemindeki yapılandırma dosyasını doğrudan değiştirdiğiniz için kalıcı olacaktır. Tek yapmanız gereken DOMConfigurator.configureAndWatch () 'ı bir kez çağırmaktır.

Dikkat: configureAndWatch yöntemi bir Diş sızıntısı nedeniyle J2EE ortamlarında kullanım için güvenli değildir

JMX

Günlük düzeyini ayarlamanın (veya genel olarak yeniden yapılandırmanın) başka bir yolu, log4j'yi JMX kullanmaktır. Log4j, kaydedicilerini JMX MBean olarak kaydeder. Uygulama sunucularını MBeanServer konsollarını (veya JDK'nın jconsole.exe) kullanarak her bir günlükçüyü yeniden yapılandırabilirsiniz. Bu değişiklikler kalıcı değildir ve uygulamanızı (sunucunuzu) yeniden başlattıktan sonra yapılandırma dosyasında ayarlandığı şekliyle yapılandırmaya sıfırlanır.

Kendi emeğiyle

Aaron tarafından açıklandığı gibi, günlük seviyesini programlı olarak ayarlayabilirsiniz. Bunu, olmasını istediğiniz şekilde uygulamanıza uygulayabilirsiniz. Örneğin, kullanıcının veya yöneticinin günlük düzeyini değiştirdiği ve ardından setLevel()günlükçüdeki yöntemleri çağırdığı bir GUI'niz olabilir. Ayarları bir yerde sürdürüp sürdürmemeniz size kalmış.


8
Log4j bekçi uygulaması yaklaşımıyla ilgili bir uyarı: "configureAndWatch ayrı bir bekçi uygulaması iş parçacığı başlattığından ve bu iş parçacığını log4j 1.2'de durdurmanın bir yolu olmadığından, configureAndWatch yöntemi uygulamaların geri dönüştürüldüğü J2EE ortamlarında kullanım için güvenli değildir". Referans: Log4J SSS
Somu

Log4j'nin configureAndWatch işlevini kullanacak olsaydım, bir EJB'nin @PostDestroy yöntemindeki bu watchdog iş parçacığını durdurabilirdim (bu, kabın ne zaman kapandığına dair yeterince iyi bir gösterge) Bu mu? Yoksa özlediğim daha fazlası var mı ..!
robin bajaj

Özür demek @PreDestroy yöntemi
robin bajaj

" Log4j, kaydedicilerini JMX MBean olarak kaydeder. " Sunucu uygulamam log4j 1.2 kullanıyor Herhangi bir log4j MBean görmüyorum.
Abdull

Tek yapmanız gereken DOMConfigurator.configureAndWatch () 'ı bir kez çağırmaktır. Bunu nasıl başarabilirim ?
gstackoverflow

5

Log4j2, log4j 2 .xml dosyasını (veya eşdeğerini) belirli aralıklarla tarayarak yapılandırmasını yenileyecek şekilde yapılandırılabilir . Yapılandırma etiketinize " monitorInterval " parametresini eklemeniz yeterlidir . Son günlük olayından bu yana 5 saniyeden fazla zaman geçmişse log4j'ye yapılandırmasını yeniden taramasını söyleyen örnek log4j 2 .xml dosyasının 2. satırına bakın .

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="warn" monitorInterval="5" name="tryItApp" packages="">

    <Appenders>
        <RollingFile name="MY_TRY_IT"
                     fileName="/var/log/tryIt.log"
                     filePattern="/var/log/tryIt-%i.log.gz">
            <Policies>
                <SizeBasedTriggeringPolicy size="25 MB"/>
            </Policies>
            ...
        </RollingFile>
    </Appenders>


    <Loggers>
        <Root level="error">
            <AppenderRef ref="MY_TRY_IT"/>
        </Root>
    </Loggers>

</Configuration>

IDE içinde bir tomcat örneğine dağıtım yapıyorsanız veya yaylı önyükleme kullanıyorsanız, bunun çalışmasını sağlamak için fazladan adımlar vardır. Bu, burada biraz kapsam dışı görünüyor ve muhtemelen ayrı bir soruyu hak ediyor.


@vsingh, spring boot, tomcat veya bir konteyner veya bir IDE ile mi konuşlandırıyorsunuz? Bazen bu durumlarda fazladan adımlar olabilir (log4j2'nin hatası değil) - temelde uygulama, bir çerçeve veya araç tarafından başka bir konuma kopyalandığı için dosyanın değiştiğini göremez.
Kimball Robinson

Merhaba, bunu Jboss6.4'te test ettim ve log4j2 yapılandırma dosyasını, uygulamanın dosyayı görebileceği konumun (.war dosyasının içinde) altında güncelledim. Ancak yine de işe yaramadı. Herhangi bir öneri?
MidTierDeveloper

3

Bu cevap, günlük kaydı düzeyini dinamik olarak değiştirmenize yardımcı olmayacaktır, hizmeti yeniden başlatmanız gerekir, hizmeti yeniden başlatmanızda sorun yoksa, lütfen aşağıdaki çözümü kullanın

Bunu log4j günlük seviyesini değiştirmek için yaptım ve benim için çalıştı, herhangi bir belgeye başvurmadım. Günlük dosyası adımı ayarlamak için bu sistem özelliği değerini kullandım. Günlüğe kaydetme düzeyini ayarlamak için de aynı tekniği kullandım ve işe yaradı

bunu JVM parametresi olarak geçti (Java 1.7 kullanıyorum)

Maalesef bu, günlük düzeyini dinamik olarak değiştirmez, hizmetin yeniden başlatılmasını gerektirir

java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java

log4j.properties dosyasına bu girişi ekledim

log4j.rootLogger=${logging.level},file,stdout

denedim

 java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=INFO-cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=OFF -cp xxxxxx.jar  xxxxx.java

Hepsi çalıştı. Bu yardımcı olur umarım!

Pom.xml dosyamda aşağıdaki bağımlılıklar var

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>apache-log4j-extras</artifactId>
    <version>1.2.17</version>
</dependency>

2
Bahsettiğiniz her şey iyi görünüyor, ancak soru, günlük kaydı seviyesini dinamik olarak değiştirmekle ilgili.
Azim

Bunu yapmak için servisi yeniden başlatmanız gerekir. Bu, kayıt seviyelerini dinamik olarak değiştirmez.
kk.

2

Log4j 1.x ile, önceden tanımlanmış XML günlük yapılandırmalarından birini göndermek için en iyi yolun bir DOMConfigurator kullanmak olduğunu buluyorum (örneğin, biri normal kullanım için diğeri de hata ayıklama için).

Bunlardan yararlanmak şu şekilde yapılabilir:

  public static void reconfigurePredefined(String newLoggerConfigName) {
    String name = newLoggerConfigName.toLowerCase();
    if ("default".equals(name)) {
      name = "log4j.xml";
    } else {
      name = "log4j-" + name + ".xml";
    }

    if (Log4jReconfigurator.class.getResource("/" + name) != null) {
      String logConfigPath = Log4jReconfigurator.class.getResource("/" + name).getPath();
      logger.warn("Using log4j configuration: " + logConfigPath);
      try (InputStream defaultIs = Log4jReconfigurator.class.getResourceAsStream("/" + name)) {
        new DOMConfigurator().doConfigure(defaultIs, LogManager.getLoggerRepository());
      } catch (IOException e) {
        logger.error("Failed to reconfigure log4j configuration, could not find file " + logConfigPath + " on the classpath", e);
      } catch (FactoryConfigurationError e) {
        logger.error("Failed to reconfigure log4j configuration, could not load file " + logConfigPath, e);
      }
    } else {
      logger.error("Could not find log4j configuration file " + name + ".xml on classpath");
    }
  }

Bunu uygun yapılandırma adıyla çağırın ve şablonları sınıf yoluna koyduğunuzdan emin olun.


bu yöntemin tetikleyici noktası nedir? log4j yapılandırmasında bir değişiklik olduğunda bu yöntemin çağrılması gerektiğini nasıl biliyor?
asgs

Hala ne demek istediğini "talep üzerine" anlamadım. Lütfen bu yöntemi nereye bağladığınız bir pasaj gösterir misiniz?
2016

2
İşte gidiyorsunuz: Bu, onu kullandığımız Denetleyiciden bir pasajdır. Günlüğü dinamik olarak yeniden yapılandırmak için bazı bağlantıların bulunduğu bir yönetici sayfamız var, bu da bağlantı / admin / setLogLevel? Level = Hata için bir GET yapar ve sonra bunu denetleyicide şu @RequestMapping (value = "setLogLevel", method = RequestMethod.GET) public ModelAndView setLogLevel (@RequestParam (value = "level", required = true) String level) {Log4jReconfigurator.reconfigureExisting (level);
ISparkes

Bu nedenle, "istek üzerine", benim durumumda "kullanıcı düğmeyi tıkladığında" anlamına gelir
ISparkes

Ah, anladım. Dolayısıyla, yönetici konsolunuzun bu yöntemi çağırmak için bir istekte bulunması gerekir.
2016

0

"Org.apache.http" günlüklerinin ayrıntı düzeyini azaltmak için bu yöntemi başarıyla kullandım:

ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.apache.http");
logger.setLevel(Level.TRACE);
logger.setAdditive(false);

0

Log4j 2 API için şunları kullanabilirsiniz:

Logger logger = LogManager.getRootLogger();
Configurator.setAllLevels(logger.getName(), Level.getLevel(level));

-1

Tüm kaydedicilerin günlük düzeyini değiştirmek isterseniz aşağıdaki yöntemi kullanın. Bu, tüm kaydedicileri numaralandıracak ve günlük düzeyini belirli bir düzeye değiştirecektir. Emin olun lütfen YAPMAYIN var log4j.appender.loggerName.Threshold=DEBUGsenin mülkiyet kümesi log4j.propertiesdosyası.

public static void changeLogLevel(Level level) {
    Enumeration<?> loggers = LogManager.getCurrentLoggers();
    while(loggers.hasMoreElements()) {
        Logger logger = (Logger) loggers.nextElement();
        logger.setLevel(level);
    }
}

-3

Aşağıdaki kod parçacığını kullanabilirsiniz

((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(packageName)).setLevel(ch.qos.logback.classic.Level.toLevel(logLevel));

denemek zorundayım.
user2045474
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.