25
25
import java .util .List ;
26
26
import java .util .Map ;
27
27
import java .util .Set ;
28
+ import java .util .stream .Collectors ;
28
29
29
30
import org .apache .logging .log4j .Level ;
30
31
import org .apache .logging .log4j .LogManager ;
38
39
import org .apache .logging .log4j .core .config .ConfigurationFactory ;
39
40
import org .apache .logging .log4j .core .config .ConfigurationSource ;
40
41
import org .apache .logging .log4j .core .config .LoggerConfig ;
42
+ import org .apache .logging .log4j .core .config .composite .CompositeConfiguration ;
41
43
import org .apache .logging .log4j .core .filter .AbstractFilter ;
42
44
import org .apache .logging .log4j .core .util .NameUtil ;
43
45
import org .apache .logging .log4j .message .Message ;
44
46
47
+ import org .springframework .boot .context .properties .bind .BindResult ;
48
+ import org .springframework .boot .context .properties .bind .Bindable ;
49
+ import org .springframework .boot .context .properties .bind .Binder ;
45
50
import org .springframework .boot .logging .LogFile ;
46
51
import org .springframework .boot .logging .LogLevel ;
47
52
import org .springframework .boot .logging .LoggerConfiguration ;
53
58
import org .springframework .core .annotation .Order ;
54
59
import org .springframework .util .Assert ;
55
60
import org .springframework .util .ClassUtils ;
61
+ import org .springframework .util .CollectionUtils ;
56
62
import org .springframework .util .ResourceUtils ;
57
63
import org .springframework .util .StringUtils ;
58
64
@@ -167,33 +173,70 @@ public void initialize(LoggingInitializationContext initializationContext, Strin
167
173
@ Override
168
174
protected void loadDefaults (LoggingInitializationContext initializationContext , LogFile logFile ) {
169
175
if (logFile != null ) {
170
- loadConfiguration (getPackagedConfigFile ("log4j2-file.xml" ), logFile );
176
+ loadConfiguration (getPackagedConfigFile ("log4j2-file.xml" ), logFile , getOverrides ( initializationContext ) );
171
177
}
172
178
else {
173
- loadConfiguration (getPackagedConfigFile ("log4j2.xml" ), logFile );
179
+ loadConfiguration (getPackagedConfigFile ("log4j2.xml" ), logFile , getOverrides ( initializationContext ) );
174
180
}
175
181
}
176
182
183
+ private List <String > getOverrides (LoggingInitializationContext initializationContext ) {
184
+ BindResult <List <String >> overrides = Binder .get (initializationContext .getEnvironment ())
185
+ .bind ("logging.log4j2.config.override" , Bindable .listOf (String .class ));
186
+ return overrides .orElse (Collections .emptyList ());
187
+ }
188
+
177
189
@ Override
178
190
protected void loadConfiguration (LoggingInitializationContext initializationContext , String location ,
179
191
LogFile logFile ) {
180
192
super .loadConfiguration (initializationContext , location , logFile );
181
- loadConfiguration (location , logFile );
193
+ loadConfiguration (location , logFile , getOverrides ( initializationContext ) );
182
194
}
183
195
196
+ /**
197
+ * Load the configuration from the given {@code location}.
198
+ * @param location the location
199
+ * @param logFile log file configuration
200
+ * @deprecated since 2.6.0 for removal in 2.8.0 in favor of
201
+ * {@link #loadConfiguration(String, LogFile, List)}
202
+ */
203
+ @ Deprecated
184
204
protected void loadConfiguration (String location , LogFile logFile ) {
205
+ this .loadConfiguration (location , logFile , Collections .emptyList ());
206
+ }
207
+
208
+ /**
209
+ * Load the configuration from the given {@code location}, creating a composite using
210
+ * the configuration from the given {@code overrides}.
211
+ * @param location the location
212
+ * @param logFile log file configuration
213
+ * @param overrides the overriding locations
214
+ * @since 2.6.0
215
+ */
216
+ protected void loadConfiguration (String location , LogFile logFile , List <String > overrides ) {
185
217
Assert .notNull (location , "Location must not be null" );
186
218
try {
187
- LoggerContext ctx = getLoggerContext ();
188
- URL url = ResourceUtils .getURL (location );
189
- ConfigurationSource source = getConfigurationSource (url );
190
- ctx .start (ConfigurationFactory .getInstance ().getConfiguration (ctx , source ));
219
+ List <Configuration > configurations = new ArrayList <>();
220
+ LoggerContext context = getLoggerContext ();
221
+ configurations .add (load (location , context ));
222
+ for (String override : overrides ) {
223
+ configurations .add (load (override , context ));
224
+ }
225
+ Configuration configuration = (configurations .size () > 1 ) ? createComposite (configurations )
226
+ : configurations .iterator ().next ();
227
+ context .start (configuration );
191
228
}
192
229
catch (Exception ex ) {
193
230
throw new IllegalStateException ("Could not initialize Log4J2 logging from " + location , ex );
194
231
}
195
232
}
196
233
234
+ private Configuration load (String location , LoggerContext context ) throws IOException {
235
+ URL url = ResourceUtils .getURL (location );
236
+ ConfigurationSource source = getConfigurationSource (url );
237
+ return ConfigurationFactory .getInstance ().getConfiguration (context , source );
238
+ }
239
+
197
240
private ConfigurationSource getConfigurationSource (URL url ) throws IOException {
198
241
InputStream stream = url .openStream ();
199
242
if (FILE_PROTOCOL .equals (url .getProtocol ())) {
@@ -202,9 +245,38 @@ private ConfigurationSource getConfigurationSource(URL url) throws IOException {
202
245
return new ConfigurationSource (stream , url );
203
246
}
204
247
248
+ private CompositeConfiguration createComposite (List <Configuration > configurations ) {
249
+ return new CompositeConfiguration (
250
+ configurations .stream ().map (AbstractConfiguration .class ::cast ).collect (Collectors .toList ()));
251
+ }
252
+
205
253
@ Override
206
254
protected void reinitialize (LoggingInitializationContext initializationContext ) {
207
- getLoggerContext ().reconfigure ();
255
+ List <String > overrides = getOverrides (initializationContext );
256
+ if (!CollectionUtils .isEmpty (overrides )) {
257
+ reinitializeWithOverrides (overrides );
258
+ }
259
+ else {
260
+ LoggerContext context = getLoggerContext ();
261
+ context .reconfigure ();
262
+ }
263
+ }
264
+
265
+ private void reinitializeWithOverrides (List <String > overrides ) {
266
+ LoggerContext context = getLoggerContext ();
267
+ Configuration base = context .getConfiguration ();
268
+ List <AbstractConfiguration > configurations = new ArrayList <>();
269
+ configurations .add ((AbstractConfiguration ) base );
270
+ for (String override : overrides ) {
271
+ try {
272
+ configurations .add ((AbstractConfiguration ) load (override , context ));
273
+ }
274
+ catch (IOException ex ) {
275
+ throw new RuntimeException ("Failed to load overriding configuration from '" + override + "'" , ex );
276
+ }
277
+ }
278
+ CompositeConfiguration composite = new CompositeConfiguration (configurations );
279
+ context .reconfigure (composite );
208
280
}
209
281
210
282
@ Override
0 commit comments