Konfigurasi Terprogram dengan Log4j 2

1. Pengenalan

Dalam tutorial ini, kita akan melihat pelbagai cara untuk mengkonfigurasi Apache Log4j 2 secara terprogram.

2. Persediaan Awal

Untuk mula menggunakan Log4j 2, kita hanya perlu memasukkan kebergantungan log4j-core dan log4j-slf4j-impl dalam pom.xml kami :

 org.apache.logging.log4j log4j-core 2.11.0   org.apache.logging.log4j log4j-slf4j-impl 2.11.0 

3. Pembangun Konfigurasi

Setelah Maven dikonfigurasi, maka kita perlu membuat ConfigurationBuilder , yang merupakan kelas yang memungkinkan kita mengkonfigurasi appenders, filter, layout dan logger.

Log4j 2 menyediakan beberapa cara untuk mendapatkan ConfigurationBuilder .

Mari mulakan dengan cara yang paling langsung:

ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder();

Dan untuk mula mengkonfigurasi komponen, ConfigurationBuilder dilengkapi dengan kaedah baru yang sesuai , seperti newAppender atau newLayout , untuk setiap komponen.

Beberapa komponen mempunyai subtipe yang berbeza, seperti FileAppender atau ConsoleAppender, dan ini disebut dalam API sebagai pemalam .

3.1. Mengkonfigurasi Appenders

Mari beritahu pembangun di mana untuk menghantar setiap baris log dengan mengkonfigurasi pelengkap :

AppenderComponentBuilder console = builder.newAppender("stdout", "Console"); builder.add(console); AppenderComponentBuilder file = builder.newAppender("log", "File"); file.addAttribute("fileName", "target/logging.log"); builder.add(file);

Walaupun kebanyakan kaedah baru tidak menyokong ini, newAppender (name, plugin) membolehkan kita memberikan nama kepada appender, yang akan menjadi penting di kemudian hari. Pelengkap ini, kami telah memanggil stdout dan log, walaupun kami boleh menamakannya dengan apa saja.

Kami juga telah memberitahu pembina yang appender plugin (atau, lebih mudah, yang jenis appender) untuk digunakan. Konsol dan Fail merujuk kepada lampiran Log4j 2 untuk menulis ke standard standard dan sistem fail, masing-masing.

Walaupun Log4j 2 menyokong beberapa appenders, mengkonfigurasinya menggunakan Java dapat sedikit rumit kerana AppenderComponentBuilder adalah kelas generik untuk semua jenis appender.

Ini menjadikannya mempunyai kaedah seperti addAttribute dan addComponent dan bukannya setFileName dan addTriggeringPolicy :

AppenderComponentBuilder rollingFile = builder.newAppender("rolling", "RollingFile"); rollingFile.addAttribute("fileName", "rolling.log"); rollingFile.addAttribute("filePattern", "rolling-%d{MM-dd-yy}.log.gz"); builder.add(rollingFile); 

Dan akhirnya, jangan lupa untuk memanggil builder.tambah untuk menambahkannya ke konfigurasi utama!

3.2. Mengkonfigurasi Penapis

Kita boleh menambahkan penapis pada setiap pelengkap kita, yang menentukan setiap baris log sama ada harus ditambahkan atau tidak.

Mari gunakan pemalam MarkerFilter pada appender konsol kami:

FilterComponentBuilder flow = builder.newFilter( "MarkerFilter", Filter.Result.ACCEPT, Filter.Result.DENY); flow.addAttribute("marker", "FLOW"); console.add(flow);

Perhatikan bahawa kaedah baru ini tidak membenarkan kami memberi nama penapis, tetapi ia meminta kami menunjukkan apa yang harus dilakukan jika penapis lulus atau gagal.

Dalam kes ini, kami menjadikannya mudah, dengan menyatakan bahawa jika MarkerFilter berlalu, maka TERIMA logline. Jika tidak, TAHNIAH .

Perhatikan dalam hal ini bahawa kita tidak menambahkannya ke pembangun tetapi sebaliknya kepada pelengkap yang ingin kita gunakan penapis ini.

3.3. Mengkonfigurasi Tata Letak

Seterusnya, mari tentukan susun atur untuk setiap baris log. Dalam kes ini, kami akan menggunakan plugin PatternLayout :

LayoutComponentBuilder standard = builder.newLayout("PatternLayout"); standard.addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"); console.add(standard); file.add(standard); rolling.add(standard);

Sekali lagi, kami telah menambahkannya terus ke appenders yang sesuai dan bukannya ke pembangun secara langsung.

3.4. Mengkonfigurasi Root Logger

Sekarang kita tahu di mana log akan dihantar, kita ingin mengkonfigurasi log mana yang akan pergi ke setiap destinasi.

Logger root adalah logger tertinggi, seperti Objek di Java. Logger inilah yang akan digunakan secara lalai kecuali diganti.

Oleh itu, mari gunakan root logger untuk menetapkan tahap logging lalai ke ERROR dan appender lalai ke appd stdout kami dari atas:

RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.ERROR); rootLogger.add(builder.newAppenderRef("stdout")); builder.add(rootLogger);

Untuk menunjukkan pembalak kami ke pelekat tertentu, kami tidak memberikan contoh pembangunnya. Sebaliknya, kami merujuknya dengan nama yang kami berikan sebelumnya.

3.5. Mengkonfigurasi Pembalak Tambahan

Pembalak kanak-kanak boleh digunakan untuk menargetkan pakej atau nama pembalak tertentu.

Mari tambahkan logger untuk pakej com dalam aplikasi kami, tetapkan tahap pembalakan ke DEBUG dan minta mereka masuk ke appender log kami :

LoggerComponentBuilder logger = builder.newLogger("com", Level.DEBUG); logger.add(builder.newAppenderRef("log")); logger.addAttribute("additivity", false); builder.add(logger);

Perhatikan bahawa kami dapat menetapkan penambahan dengan pembalak kami, yang menunjukkan sama ada penebang ini harus mewarisi sifat seperti tahap pembalakan dan jenis penambah dari nenek moyangnya.

3.6. Mengkonfigurasi Komponen Lain

Tidak semua komponen mempunyai kaedah baru khusus untuk ConfigurationBuilder .

Oleh itu, dalam kes ini, kita memanggil Komponen baru.

For example, because there isn't a TriggeringPolicyComponentBuilder, we need to use newComponent for something like specifying our triggering policy for rolling file appenders:

ComponentBuilder triggeringPolicies = builder.newComponent("Policies") .addComponent(builder.newComponent("CronTriggeringPolicy") .addAttribute("schedule", "0 0 0 * * ?")) .addComponent(builder.newComponent("SizeBasedTriggeringPolicy") .addAttribute("size", "100M")); rolling.addComponent(triggeringPolicies);

3.7. The XML Equivalent

ConfigurationBuilder comes equipped with a handy method to print out the equivalent XML:

builder.writeXmlConfiguration(System.out);

Running the above line prints out:

This comes in handy when we want to double-check our configuration or if we want to persist our configuration, say, to the file system.

3.8. Putting It All Together

Now that we are fully configured, let's tell Log4j 2 to use our configuration:

Configurator.initialize(builder.build());

After this is invoked, future calls to Log4j 2 will use our configuration.

Note that this means that we need to invoke Configurator.initialize before we make any calls to LogManager.getLogger.

4. ConfigurationFactory

Now that we've seen one way to get and apply a ConfigurationBuilder, let's take a look at one more:

public class CustomConfigFactory extends ConfigurationFactory { public Configuration createConfiguration( LoggerContext context, ConfigurationSource src) { ConfigurationBuilder builder = super .newConfigurationBuilder(); // ... configure appenders, filters, etc. return builder.build(); } public String[] getSupportedTypes() { return new String[] { "*" }; } }

In this case, instead of using ConfigurationBuilderFactory, we subclassed ConfigurationFactory, an abstract class targetted for creating instances of Configuration.

Then, instead of calling Configurator.initialize like we did the first time, we simply need to let Log4j 2 know about our new configuration factory.

There are three ways to do this:

  • Static initialization
  • A runtime property, or
  • The @Plugin annotation

4.1. Use Static Initialization

Log4j 2 supports calling setConfigurationFactory during static initialization:

static { ConfigurationFactory custom = new CustomConfigFactory(); ConfigurationFactory.setConfigurationFactory(custom); }

This approach has the same limitation as for the last approach we saw, which is that we'll need to invoke it before any calls to LogManager.getLogger.

4.2. Use a Runtime Property

If we have access to the Java startup command, then Log4j 2 also supports specifying the ConfigurationFactory to use via a -D parameter:

-Dlog4j2.configurationFactory=com.baeldung.log4j2.CustomConfigFactory

The main benefit of this approach is that we don't have to worry about initialization order as we do with the first two approaches.

4.3. Use the @Plugin Annotation

And finally, in circumstances where we don't want to fiddle with the Java startup command by adding a -D, we can simply annotate our CustomConfigurationFactory with the Log4j 2 @Plugin annotation:

@Plugin( name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY) @Order(50) public class CustomConfigFactory extends ConfigurationFactory { // ... rest of implementation }

Log4j 2 will scan the classpath for classes having the @Plugin annotation, and, finding this class in the ConfigurationFactory category, will use it.

4.4. Combining With Static Configuration

Another benefit to using a ConfigurationFactory extension is that we can easily combine our custom configuration with other configuration sources like XML:

public Configuration createConfiguration( LoggerContext context, ConfigurationSource src) { return new WithXmlConfiguration(context, src); } 

The source parameter represents the static XML or JSON configuration file that Log4j 2 finds if any.

Kami dapat mengambil fail konfigurasi itu dan mengirimkannya ke implementasi XmlConfiguration khusus kami di mana kami dapat meletakkan konfigurasi apa pun yang kami perlukan:

public class WithXmlConfiguration extends XmlConfiguration { @Override protected void doConfigure() { super.doConfigure(); // parse xml document // ... add our custom configuration } }

5. Kesimpulan

Dalam artikel ini, kami melihat bagaimana menggunakan API ConfigurationBuilder baru yang tersedia di Log4j 2.

Kami juga melihat penyesuaian ConfigurationFactory dalam kombinasi dengan ConfigurationBuilder untuk kes penggunaan yang lebih maju.

Jangan lupa untuk melihat contoh lengkap saya di GitHub.