1212import org .apache .logging .log4j .LogManager ;
1313import org .apache .logging .log4j .Logger ;
1414import org .apache .logging .log4j .core .Appender ;
15+ import org .apache .logging .log4j .core .Filter ;
1516import org .apache .logging .log4j .core .LoggerContext ;
1617import org .apache .logging .log4j .core .appender .ConsoleAppender ;
1718import org .apache .logging .log4j .core .config .AbstractConfiguration ;
2122import org .apache .logging .log4j .core .config .builder .api .ConfigurationBuilder ;
2223import org .apache .logging .log4j .core .config .builder .api .ConfigurationBuilderFactory ;
2324import org .apache .logging .log4j .core .config .builder .impl .BuiltConfiguration ;
25+ import org .apache .logging .log4j .core .config .builder .impl .DefaultConfigurationBuilder ;
2426import org .apache .logging .log4j .core .config .composite .CompositeConfiguration ;
2527import org .apache .logging .log4j .core .config .plugins .util .PluginManager ;
2628import org .apache .logging .log4j .core .config .properties .PropertiesConfiguration ;
2729import org .apache .logging .log4j .core .config .properties .PropertiesConfigurationBuilder ;
2830import org .apache .logging .log4j .core .config .properties .PropertiesConfigurationFactory ;
31+ import org .apache .logging .log4j .jul .Log4jBridgeHandler ;
2932import org .apache .logging .log4j .status .StatusConsoleListener ;
3033import org .apache .logging .log4j .status .StatusData ;
3134import org .apache .logging .log4j .status .StatusListener ;
@@ -222,6 +225,7 @@ public PropertiesConfiguration getConfiguration(final LoggerContext loggerContex
222225 properties .setProperty (name , value .replace ("%marker" , "[%node_name]%marker " ));
223226 }
224227 }
228+
225229 // end hack
226230 return new PropertiesConfigurationBuilder ().setConfigurationSource (source )
227231 .setRootProperties (properties )
@@ -241,6 +245,8 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr
241245 });
242246 assert configurations .isEmpty () == false ;
243247
248+ configurations .add (createStaticConfiguration (context ));
249+
244250 context .start (new CompositeConfiguration (configurations ));
245251
246252 configureLoggerLevels (settings );
@@ -257,26 +263,13 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr
257263 );
258264 }
259265
266+ Log4jBridgeHandler .install (true , "" , true );
267+
260268 // Redirect stdout/stderr to log4j. While we ensure Elasticsearch code does not write to those streams,
261269 // third party libraries may do that. Note that we do NOT close the streams because other code may have
262270 // grabbed a handle to the streams and intend to write to it, eg log4j for writing to the console
263- System .setOut (
264- new PrintStream (new LoggingOutputStream (LogManager .getLogger ("stdout" ), Level .INFO , List .of ()), false , StandardCharsets .UTF_8 )
265- );
266- System .setErr (
267- new PrintStream (
268- new LoggingOutputStream (
269- LogManager .getLogger ("stderr" ),
270- Level .WARN ,
271- // MMapDirectory messages come from Lucene, suggesting to users as a warning that they should enable preview features in
272- // the JDK. Vector logs come from Lucene too, but only if the used explicitly disables the Vector API - no point warning
273- // in this case.
274- List .of ("MMapDirectory" , "VectorUtilProvider" , "WARNING: Java vector incubator module is not readable" )
275- ),
276- false ,
277- StandardCharsets .UTF_8
278- )
279- );
271+ System .setOut (new PrintStream (new LoggingOutputStream (LogManager .getLogger ("stdout" ), Level .INFO ), false , StandardCharsets .UTF_8 ));
272+ System .setErr (new PrintStream (new LoggingOutputStream (LogManager .getLogger ("stderr" ), Level .WARN ), false , StandardCharsets .UTF_8 ));
280273
281274 final Logger rootLogger = LogManager .getRootLogger ();
282275 Appender appender = Loggers .findAppender (rootLogger , ConsoleAppender .class );
@@ -289,6 +282,29 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr
289282 }
290283 }
291284
285+ /**
286+ * Creates a log4j configuration that is not changeable by users.
287+ */
288+ private static AbstractConfiguration createStaticConfiguration (LoggerContext context ) {
289+ var builder = new DefaultConfigurationBuilder <>();
290+ builder .setConfigurationSource (ConfigurationSource .NULL_SOURCE );
291+ builder .setLoggerContext (context );
292+
293+ // adding filters for confusing Lucene messages
294+ addRegexFilter (builder , "org.apache.lucene.store.MemorySegmentIndexInputProvider" , "Using MemorySegmentIndexInput.*" );
295+ addRegexFilter (builder , "org.apache.lucene.util.VectorUtilProvider" , ".* incubator module is not readable.*" );
296+
297+ return builder .build ();
298+ }
299+
300+ private static void addRegexFilter (DefaultConfigurationBuilder <BuiltConfiguration > builder , String loggerName , String pattern ) {
301+ var filterBuilder = builder .newFilter ("RegexFilter" , Filter .Result .DENY , Filter .Result .NEUTRAL );
302+ filterBuilder .addAttribute ("regex" , pattern );
303+ var loggerBuilder = builder .newLogger (loggerName );
304+ loggerBuilder .add (filterBuilder );
305+ builder .add (loggerBuilder );
306+ }
307+
292308 /**
293309 * Removes the appender for the console, if one exists.
294310 */
0 commit comments