Mengubah log level log4j secara dinamis

127

Apa saja pendekatan berbeda untuk mengubah level log log4j secara dinamis, sehingga saya tidak perlu memindahkan aplikasi. Apakah perubahan akan permanen dalam kasus tersebut?

Ravi
sumber
Sangat mirip dengan stackoverflow.com/questions/2115900/…
vsingh
3
Pertanyaan yang diperbarui untuk log4j2: stackoverflow.com/questions/23434252/…
slaadvak
1
Perhatikan bahwa (hampir) semua yang ada di halaman ini adalah tentang log4j, bukan log4j2. Seluruh halaman ini begitu penuh kebingungan dan penyesatan sehingga tidak berguna. Pergi ke stackoverflow.com/questions/23434252/… seperti yang direkomendasikan @slaadvak.
Lambart

Jawaban:

86

Mengubah level log itu sederhana; memodifikasi bagian lain dari konfigurasi akan menimbulkan pendekatan yang lebih mendalam.

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

Perubahan bersifat permanen melalui life cyle Logger . Pada reinisialisasi konfigurasi akan dibaca dan digunakan sebagai pengaturan level saat runtime tidak bertahan perubahan level.

UPDATE: Jika Anda menggunakan Log4j 2 Anda harus menghapus panggilan setLevelsesuai dokumentasi karena ini dapat dicapai melalui kelas implementasi.

Panggilan ke logger.setLevel () atau metode serupa tidak didukung di API. Aplikasi harus menghapus ini. Fungsionalitas yang setara disediakan di kelas implementasi Log4j 2 tetapi dapat membuat aplikasi rentan terhadap perubahan di internal Log4j 2.

Aaron McIver
sumber
5
Hanya untuk dependensi runtimeLogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC
8
Perhatikan bahwa log4j 2 API tidak menyediakan metode "setLevel".
ChrisCantrell
5
Tapi ini hanya mengatur logger root, bukan? Jika level individu ditetapkan untuk logger di bawah root, pengaturan logger root tidak akan berpengaruh pada LOGGER itu. Bukankah kita harus melakukan sesuatu seperti root.getLoggerRepository (). GetCurrentCategories (), beralih pada setiap instance dari logger dan atur LEVEL untuk setiap logger? @AaronMcIver
TheMonkWhoSoldHisCode
8
@ChrisCantrell Log4j 2 memang menyediakan cara untuk melakukan ini , meskipun tidak sesederhana itu.
CorayThan
2
Log4j2 dapat dikonfigurasi untuk menyegarkan konfigurasinya dengan memindai file log4j2.xml (atau yang setara) pada interval yang diberikan. Misalnya <Status konfigurasi = "peringatkan" monitorInterval = "5" name = "tryItApp" package = "">
Kimball Robinson
89

File Watchdog

Log4j dapat menonton log4j.xmlfile untuk perubahan konfigurasi. Jika Anda mengubah file log4j, log4j akan secara otomatis me-refresh level log sesuai dengan perubahan Anda. Lihat dokumentasiorg.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long ) untuk detail. Waktu tunggu default antara pemeriksaan adalah 60 detik. Perubahan ini akan tetap ada, karena Anda secara langsung mengubah file konfigurasi pada sistem file. Yang perlu Anda lakukan adalah memanggil DOMConfigurator.configureAndWatch () sekali.

Perhatian: metode configureAndWatch tidak aman untuk digunakan di lingkungan J2EE karena kebocoran Thread

JMX

Cara lain untuk mengatur level log (atau mengkonfigurasi ulang secara umum) log4j adalah dengan menggunakan JMX. Log4j mendaftarkan logger-nya sebagai JMX MB artinya. Menggunakan server aplikasi konsol MBeanServer (atau jconsole.exe JDK), Anda dapat mengonfigurasi ulang setiap logger individual. Perubahan ini tidak persisten dan akan direset ke konfigurasi seperti yang diatur dalam file konfigurasi setelah Anda me-restart aplikasi Anda (server).

Buatan sendiri

Seperti yang dijelaskan oleh Aaron, Anda dapat mengatur level log secara terprogram. Anda dapat menerapkannya dalam aplikasi Anda dengan cara yang Anda inginkan terjadi. Misalnya, Anda bisa memiliki GUI di mana pengguna atau admin mengubah level log dan kemudian memanggil setLevel()metode pada logger. Apakah Anda bertahan pengaturan di suatu tempat atau tidak, itu terserah Anda.

mhaller
sumber
8
Peringatan tentang pendekatan pengawas log4j: "Karena configureAndWatch meluncurkan utas pengawas terpisah, dan karena tidak ada cara untuk menghentikan utas ini di log4j 1.2, metode configureAndWatch tidak aman untuk digunakan di lingkungan J2EE di mana aplikasi didaur ulang". Referensi: Log4J FAQ
Somu
Jika saya menggunakan fungsi configureAndWatch dari Log4j, saya dapat menghentikan utas pengawas dalam metode @PostDestroy EJB (itu indikator yang cukup baik ketika wadah dimatikan) Itu dia? Atau ada lagi yang hilang dari saya ..!
robin bajaj
maaf saya maksud metode @PreDestroy
robin bajaj
" Log4j mendaftarkan loggernya sebagai JMX MBeans. " Servlet saya menggunakan log4j 1.2 Saya tidak melihat log4j MB artinya.
Abdull
Yang perlu Anda lakukan adalah memanggil DOMConfigurator.configureAndWatch () sekali. Bagaimana saya bisa mencapai ini?
gstackoverflow
5

Log4j2 dapat dikonfigurasikan untuk menyegarkan konfigurasinya dengan memindai file log4j 2 .xml (atau setara) pada interval yang diberikan. Cukup tambahkan parameter " monitorInterval " ke tag konfigurasi Anda. Lihat baris 2 dari file log4j 2 .xml sampel , yang memberitahu log4j untuk memindai ulang konfigurasinya jika lebih dari 5 detik telah berlalu sejak peristiwa log terakhir.

<?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>

Ada langkah-langkah tambahan untuk membuat pekerjaan ini jika Anda menggunakan instance kucing jantan, di dalam IDE, atau saat menggunakan booting musim semi. Yang tampaknya agak di luar jangkauan di sini dan mungkin pantas mendapat pertanyaan terpisah.

Kimball Robinson
sumber
@vsingh, apakah Anda menggunakan boot musim semi, kucing jantan, atau sebuah wadah atau dengan IDE? Kadang-kadang ada langkah-langkah tambahan dalam kasus-kasus itu (bukan kesalahan log4j2) - pada dasarnya aplikasi tidak dapat melihat file berubah karena telah disalin ke lokasi lain oleh kerangka kerja atau alat.
Kimball Robinson
Hai Saya menguji ini pada Jboss6.4 dan saya memperbarui file konfigurasi log4j2 di bawah lokasi (di dalam file .war) di mana aplikasi dapat melihat file. Namun itu masih tidak berhasil. Ada saran?
MidTierDeveloper
3

Jawaban ini tidak akan membantu Anda untuk mengubah level logging secara dinamis, Anda perlu me-restart layanan, jika Anda baik-baik saja memulai kembali layanan, silakan gunakan solusi di bawah ini

Saya melakukan ini untuk mengubah tingkat log4j log dan itu berhasil untuk saya, saya belum merujuk dokumen apa pun. Saya menggunakan nilai properti sistem ini untuk menetapkan nama file log saya. Saya menggunakan teknik yang sama untuk mengatur tingkat logging juga, dan itu berhasil

melewati ini sebagai parameter JVM (saya menggunakan Java 1.7)

Maaf ini tidak akan secara dinamis mengubah level logging, itu membutuhkan restart layanan

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

dalam file log4j.properties, saya menambahkan entri ini

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

Saya mencoba

 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

Itu semua berhasil. semoga ini membantu!

Saya memiliki dependensi berikut ini di pom.xml saya

<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>
Anandkumar
sumber
2
Apa pun yang Anda sebutkan tampaknya baik-baik saja, tetapi pertanyaannya adalah tentang mengubah tingkat logging secara dinamis.
Azim
Untuk melakukan ini, Anda harus memulai kembali layanan. Ini tidak mengubah level logging secara dinamis.
kk.
2

Dengan log4j 1.x Saya menemukan cara terbaik adalah dengan menggunakan DOMConfigurator untuk mengirimkan salah satu set konfigurasi log XML yang telah ditentukan (katakanlah, satu untuk penggunaan normal dan satu untuk debugging).

Memanfaatkan ini dapat dilakukan dengan sesuatu seperti ini:

  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");
    }
  }

Sebut saja ini dengan nama konfigurasi yang sesuai, dan pastikan Anda meletakkan templat di classpath.

ISparkes
sumber
apa titik pemicu dari metode ini? bagaimana ia tahu metode ini harus dipanggil setiap kali ada perubahan dalam konfigurasi log4j?
asgs
Saya masih tidak mendapatkan apa yang Anda maksudkan "sesuai permintaan". Bisakah Anda tunjukkan cuplikan di mana Anda menghubungkan metode ini?
asgs
2
Ini dia: Ini adalah cuplikan dari Controller tempat kami menggunakannya. Kami memiliki halaman admin dengan beberapa tautan untuk mengonfigurasi ulang pencatatan secara dinamis, yang kemudian membuat GET ke tautan / admin / setLogLevel? Level = Kesalahan dan kemudian kami menangkapnya di pengontrol seperti @RequestMapping
ISparkes
Jadi, "sesuai permintaan" berarti "ketika pengguna mengklik tombol" dalam kasus saya
ISparkes
Ah, mengerti. Jadi konsol admin Anda harus membuat permintaan untuk memanggil metode ini.
asgs
0

Saya telah menggunakan metode ini dengan sukses untuk mengurangi verbositas log "org.apache.http":

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

Untuk log4j 2 API, Anda dapat menggunakan

Logger logger = LogManager.getRootLogger();
Configurator.setAllLevels(logger.getName(), Level.getLevel(level));
mohamed stitane
sumber
-1

Jika Anda ingin mengubah tingkat logging semua penebang, gunakan metode di bawah ini. Ini akan menghitung semua penebang dan mengubah level logging ke level yang diberikan. Harap pastikan bahwa Anda TIDAK memiliki log4j.appender.loggerName.Threshold=DEBUGproperti di log4j.propertiesfile Anda .

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

Anda dapat menggunakan potongan kode berikut

((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(packageName)).setLevel(ch.qos.logback.classic.Level.toLevel(logLevel));
pengguna2606570
sumber
Aku harus mencobanya.
user2045474