Bagaimana Anda bisa menemukan URL apa yang digunakan dalam inisialisasi default log4j?

Inisialisasi default Log4j melewati prosedur untuk menemukan dan menggunakan URL untuk mengonfigurasi dengan. Setelah itu, bagaimana Anda bisa mengetahui URL apa yang akhirnya digunakan, tanpa harus membuat sendiri kode prosedur yang sama? (Jika Anda harus membuat kodenya sendiri, Anda mungkin tidak akan mendapatkannya sama persis dengan log4j, dan mungkin juga akan berubah di rilis mendatang.)


person skiphoppy    schedule 28.08.2012    source sumber


Jawaban (4)


Jika Anda ingin menggunakan AspectJ LTW (load-timeweaving), Anda dapat melihat inisialisasi statis LogManager yang disebutkan oleh Ian Roberts. Di log4j 1.2.14 tampilannya seperti ini:

static {
    // (...)
    // if there is no default init override, then get the resource
    // specified by the user or the default config file.
    if (override == null || "false".equalsIgnoreCase(override)) {
        // (...)
        URL url = null;

        // (...)    
        // If we have a non-null url, then delegate the rest of the
        // configuration to the OptionConverter.selectAndConfigure method.
        if (url != null) {
            LogLog.debug("Using URL [" + url + "] for automatic log4j configuration.");
            OptionConverter.selectAndConfigure(
                url, configuratorClassName, LogManager.getLoggerRepository()
            );
        } else {
            LogLog.debug("Could not find resource: [" + configurationOptionStr + "].");
        }
    }
}

Tentunya jika URL default dapat ditentukan maka OptionConverter.selectAndConfigure(URL, ..) akan dipanggil pada satu titik dalam blok statis untuk menginisialisasi log4j dengan URL tersebut.

Melalui AspectJ cukup mudah untuk menangkap pemanggilan metode tersebut:

import java.net.URL;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.LogManager;

public aspect Log4jAspect {
    before(URL defaultURL) :
        within(LogManager) &&
        cflow(staticinitialization(LogManager)) &&
        call(* OptionConverter.selectAndConfigure(URL, ..)) &&
        args(defaultURL, ..)
    {
        System.out.println("log4j default URL = " + defaultURL);
    }
}

Dalam bentuk prosa, kode ini berarti:

  • Jika kita berada dalam kelas LogManager dan
  • dalam aliran kontrol inisialisasi kelas statis dan
  • OptionConverter.selectAndConfiguredipanggil,
  • lalu tangkap argumen pertama (URL) dan
  • cetak ke konsol (sebaiknya Anda melakukan hal lain).

Jika tidak ada URL default, tidak ada yang akan dicetak. Daripada mencetak URL, Anda dapat menetapkannya ke anggota statis kelas mana pun atau apa pun yang Anda suka.

Ini adalah solusi untuk masalah Anda, saya mengujinya dan berhasil. Saya akan dengan senang hati menerima imbalan karena menjawab pertanyaan Anda, meskipun mungkin solusinya menggunakan teknologi yang tidak Anda pikirkan. Tapi itu memecahkan masalah. :-)


Sunting: Dimungkinkan juga untuk mencegat panggilan log secara eksplisit jika tidak ada URL default yang ditemukan, meskipun menurut saya hal itu tidak perlu. Saya hanya ingin menyebutkannya.

person kriegaex    schedule 30.08.2012
comment
Jawaban Anda sangat informatif. Terima kasih. Cara yang bagus untuk mendekati sesuatu yang tampaknya tidak dapat dilakukan sesuai keinginan saya. - person skiphoppy; 04.09.2012
comment
›1000 repetisi sehari. mengesankan :P - person Matthias; 05.09.2012

Prosedur yang digunakan dikodekan secara keras dalam blok penginisialisasi statis di LogManager, jadi sepertinya tidak ada cara untuk menghubungkannya. Satu-satunya tempat di mana ia memberitahu Anda apa yang sedang terjadi adalah

LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");

tetapi LogLog sendiri memiliki kode keras untuk menggunakan System.out.println untuk pesan-pesan ini sehingga satu-satunya kemungkinan yang dapat saya lihat adalah mengaktifkan debugging (-Dlog4j.debug=true) dan entah bagaimana menghubungkan ke System.setOut sebelum log4j diinisialisasi, kemudian mengurai pesan log debug. Tapi itu mungkin lebih rapuh daripada mengkodekan sendiri prosedur konfigurasinya.

Meski begitu, mungkin ada konfigurasi terprogram lain yang diterapkan setelah prosedur konfigurasi default (misalnya Spring Log4jConfigListener) - belum tentu ada satu URL konfigurasi seperti itu.

Mungkin ada baiknya memasukkan permintaan fitur log4j untuk memfaktorkan kode pencarian file konfigurasi ke dalam metode statis yang dapat Anda panggil dari tempat lain, tetapi itu tidak akan membantu ketika Anda mungkin harus menangani versi log4j yang lebih lama.

person Ian Roberts    schedule 30.08.2012

Jika Anda dapat mengatur Configurator Anda sendiri, Anda dapat melakukan sesuatu seperti itu:

Siapkan properti sistem JAVA: -Dlog4j.configuratorClass=MyConfigurator Dan kemudian minta instance konfigurator Anda mencegat panggilan doConfigure.

public class MyConfigurator implements Configurator
{
    public static URL url;

    @Override
    public void doConfigure(URL url, LoggerRepository repository)
    {
        this.url = url;
        new PropertyConfigurator().doConfigure(url, repository);
    }
}
person Marc Polizzi    schedule 03.09.2012
comment
Ini menyarankan ide cerdas lainnya: mengganti Configurator dengan memasukkan milik Anda sebelumnya di classpath... - person skiphoppy; 04.09.2012

Masukkan ini ke dalam panggilan Java Anda:

-Dlog4j.configDebug=true

Itu saja.

person Mirko    schedule 31.08.2012
comment
Saya mencari cara agar program saya dapat menemukan informasi ini. - person skiphoppy; 31.08.2012