0
# Logging Configuration
1
2
Spring Boot's logging system provides abstraction over multiple logging frameworks with automatic configuration, log level management, and flexible output formatting. It supports Logback, Log4j2, and Java Util Logging with sensible defaults.
3
4
## Capabilities
5
6
### Logging System Abstraction
7
8
Core abstraction for logging system configuration and management.
9
10
```java { .api }
11
/**
12
* Common abstraction over logging systems
13
*/
14
public abstract class LoggingSystem {
15
16
/**
17
* The property used to configure the logging system
18
*/
19
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
20
21
/**
22
* The value that disables the logging system
23
*/
24
public static final String NONE = "none";
25
26
/**
27
* Get the logging system for the given class loader
28
* @param classLoader the class loader
29
* @return the logging system or null if not available
30
*/
31
public static LoggingSystem get(ClassLoader classLoader) {
32
String loggingSystemClassName = System.getProperty(SYSTEM_PROPERTY);
33
if (StringUtils.hasLength(loggingSystemClassName)) {
34
if (NONE.equals(loggingSystemClassName)) {
35
return new NoOpLoggingSystem();
36
}
37
return get(classLoader, loggingSystemClassName);
38
}
39
return LOGGING_SYSTEM_FACTORY.getLoggingSystem(classLoader);
40
}
41
42
/**
43
* Detect if a logging system is present on the classpath
44
* @param classLoader the class loader to check
45
* @return true if available
46
*/
47
public static boolean get(ClassLoader classLoader) {
48
try {
49
return get(classLoader) != null;
50
} catch (Exception ex) {
51
return false;
52
}
53
}
54
55
/**
56
* Initialize the logging system
57
* @param initializationContext the initialization context
58
* @param configLocation the config location or null if default should be used
59
* @param logFile the log file that should be written or null for console output
60
*/
61
public abstract void initialize(LoggingInitializationContext initializationContext,
62
String configLocation, LogFile logFile);
63
64
/**
65
* Clean up the logging system. The default implementation does nothing.
66
*/
67
public void cleanUp() {
68
}
69
70
/**
71
* Returns a Runnable that can handle shutdown of this logging system when the JVM
72
* exits. The default implementation returns null, indicating that no shutdown
73
* is required
74
* @return the shutdown handler, or null
75
*/
76
public Runnable getShutdownHandler() {
77
return null;
78
}
79
80
/**
81
* Set the log level for the given logger name
82
* @param loggerName the name of the logger to set (null indicates the root logger)
83
* @param level the log level (null removes any custom level for the logger and
84
* uses the default configuration instead)
85
*/
86
public abstract void setLogLevel(String loggerName, LogLevel level);
87
88
/**
89
* Return the supported log levels
90
* @return the supported levels
91
*/
92
public abstract List<LogLevel> getSupportedLogLevels();
93
}
94
95
/**
96
* Logging initialization context used by LoggingSystem implementations
97
*/
98
public interface LoggingInitializationContext {
99
100
/**
101
* Return the Spring Environment (may be null)
102
* @return the environment
103
*/
104
Environment getEnvironment();
105
}
106
107
/**
108
* A reference to a log output file
109
*/
110
public class LogFile {
111
112
/**
113
* The name of the Spring property that contains the name of the log file. Names can
114
* be an exact location or relative to the current directory
115
*/
116
public static final String FILE_PROPERTY = "logging.file.name";
117
118
/**
119
* The name of the Spring property that contains the directory where log files are
120
* written
121
*/
122
public static final String PATH_PROPERTY = "logging.file.path";
123
124
/**
125
* Get a LogFile from the given Spring Environment
126
* @param environment the Spring environment
127
* @return a LogFile instance or null if the environment contains no log file
128
* properties
129
*/
130
public static LogFile get(Environment environment);
131
132
/**
133
* Return the name of the log file
134
* @return the log file name
135
*/
136
public String getName();
137
138
/**
139
* Return a string representation of the log file
140
* @return the log file as a string
141
*/
142
@Override
143
public String toString();
144
}
145
```
146
147
**Usage Examples:**
148
149
```java
150
@Component
151
public class LoggingManager {
152
153
private final LoggingSystem loggingSystem;
154
155
public LoggingManager() {
156
this.loggingSystem = LoggingSystem.get(getClass().getClassLoader());
157
}
158
159
public void setLogLevel(String loggerName, LogLevel level) {
160
if (loggingSystem != null) {
161
loggingSystem.setLogLevel(loggerName, level);
162
System.out.println("Set log level for " + loggerName + " to " + level);
163
}
164
}
165
166
public List<LogLevel> getSupportedLevels() {
167
return loggingSystem != null ?
168
loggingSystem.getSupportedLogLevels() :
169
Collections.emptyList();
170
}
171
172
@EventListener
173
public void onApplicationReady(ApplicationReadyEvent event) {
174
// Set debug level for specific packages during development
175
setLogLevel("com.example.service", LogLevel.DEBUG);
176
setLogLevel("org.springframework.security", LogLevel.TRACE);
177
178
System.out.println("Supported log levels: " + getSupportedLevels());
179
}
180
}
181
```
182
183
### Log Levels
184
185
Enumeration of log levels supported by Spring Boot.
186
187
```java { .api }
188
/**
189
* Logging levels supported by a LoggingSystem
190
*/
191
public enum LogLevel {
192
193
TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF;
194
195
/**
196
* Return the name of this log level in lower case
197
* @return the lower case name
198
*/
199
public String name() {
200
return super.name().toLowerCase();
201
}
202
203
/**
204
* Return the name of this log level in upper case
205
* @return the upper case name
206
*/
207
public String toString() {
208
return super.toString();
209
}
210
211
/**
212
* Return a LogLevel for the given String representation
213
* @param name the log level name
214
* @return the LogLevel or null if not found
215
*/
216
public static LogLevel valueOf(String name) {
217
if (name == null) {
218
return null;
219
}
220
try {
221
return LogLevel.valueOf(name.trim().toUpperCase());
222
} catch (IllegalArgumentException ex) {
223
return null;
224
}
225
}
226
}
227
```
228
229
**Usage Examples:**
230
231
```java
232
@RestController
233
@RequestMapping("/admin/logging")
234
public class LoggingController {
235
236
@Autowired
237
private LoggingSystem loggingSystem;
238
239
@PostMapping("/level")
240
public ResponseEntity<?> setLogLevel(@RequestParam String logger,
241
@RequestParam String level) {
242
try {
243
LogLevel logLevel = LogLevel.valueOf(level.toUpperCase());
244
if (logLevel == null) {
245
return ResponseEntity.badRequest()
246
.body("Invalid log level. Supported levels: " +
247
loggingSystem.getSupportedLogLevels());
248
}
249
250
loggingSystem.setLogLevel(logger, logLevel);
251
return ResponseEntity.ok()
252
.body(String.format("Set log level for '%s' to %s", logger, logLevel));
253
254
} catch (IllegalArgumentException e) {
255
return ResponseEntity.badRequest()
256
.body("Invalid log level: " + level);
257
}
258
}
259
260
@GetMapping("/levels")
261
public List<LogLevel> getSupportedLevels() {
262
return loggingSystem.getSupportedLogLevels();
263
}
264
265
@PostMapping("/reset")
266
public ResponseEntity<?> resetLogLevel(@RequestParam String logger) {
267
loggingSystem.setLogLevel(logger, null); // Reset to default
268
return ResponseEntity.ok()
269
.body("Reset log level for '" + logger + "' to default");
270
}
271
}
272
```
273
274
### Logging Configuration Properties
275
276
Spring Boot properties for configuring logging behavior.
277
278
```java { .api }
279
/**
280
* Configuration properties for logging
281
*/
282
@ConfigurationProperties(prefix = "logging")
283
public class LoggingProperties {
284
285
/**
286
* Logging pattern for the console. Supported only with the default Logback setup
287
*/
288
private String pattern;
289
290
/**
291
* Logging pattern for file output. Supported only with the default Logback setup
292
*/
293
private String filePattern;
294
295
/**
296
* Log level severity mapping. For instance, `logging.level.org.springframework=DEBUG`
297
*/
298
private Map<String, LogLevel> level = new LinkedHashMap<>();
299
300
/**
301
* Location of the logging configuration file. For instance, `classpath:logback-spring.xml` for Logback
302
*/
303
private String config;
304
305
/**
306
* Whether to enable debug logging of auto-configuration conditions
307
*/
308
private boolean enableAutoConfigurationReport = false;
309
310
private final File file = new File();
311
private final Logback logback = new Logback();
312
private final Log4j2 log4j2 = new Log4j2();
313
314
public static class File {
315
316
/**
317
* Log file name (for instance, `myapp.log`). Names can be an exact location or relative to the current directory
318
*/
319
private String name;
320
321
/**
322
* Location of the log file. For instance, `/var/log`
323
*/
324
private String path;
325
326
/**
327
* Maximum log file size. Only supported with the default logback setup
328
*/
329
private DataSize maxSize = DataSize.ofMegabytes(10);
330
331
/**
332
* Maximum number of archive log files to keep. Only supported with the default logback setup
333
*/
334
private int maxHistory = 7;
335
336
/**
337
* Total size of log backups to be kept. Only supported with the default logback setup
338
*/
339
private DataSize totalSizeCap = DataSize.ofGigabytes(0);
340
341
// Getters and setters
342
}
343
344
public static class Logback {
345
346
/**
347
* Rollover policy to use when log files exceed the maximum size
348
*/
349
private RollingPolicy rollingPolicy = new RollingPolicy();
350
351
public static class RollingPolicy {
352
353
/**
354
* Filename pattern used to create log archives
355
*/
356
private String fileNamePattern = "${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz";
357
358
/**
359
* Whether to clean history on start up
360
*/
361
private boolean cleanHistoryOnStart = false;
362
363
/**
364
* Maximum number of archive files to keep
365
*/
366
private int maxFileSize = 7;
367
368
/**
369
* Maximum size of the log file before it gets archived
370
*/
371
private DataSize maxFileSize = DataSize.ofMegabytes(10);
372
373
/**
374
* Total size of all log files
375
*/
376
private DataSize totalSizeCap = DataSize.ofGigabytes(0);
377
}
378
}
379
}
380
```
381
382
**Usage Examples:**
383
384
```java
385
# Application properties for logging configuration
386
logging.level.org.springframework.security=DEBUG
387
logging.level.org.hibernate.SQL=DEBUG
388
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
389
logging.level.com.example=INFO
390
391
# File logging
392
logging.file.name=application.log
393
logging.file.path=/var/log/myapp
394
logging.file.max-size=50MB
395
logging.file.max-history=30
396
logging.file.total-size-cap=1GB
397
398
# Pattern configuration
399
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
400
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
401
402
# Custom logback configuration
403
logging.config=classpath:logback-spring.xml
404
405
# Enable auto-configuration report
406
logging.level.org.springframework.boot.autoconfigure=DEBUG
407
408
@Configuration
409
@EnableConfigurationProperties(LoggingProperties.class)
410
public class CustomLoggingConfiguration {
411
412
@Autowired
413
private LoggingProperties loggingProperties;
414
415
@Bean
416
public LoggingSystemProperties loggingSystemProperties(Environment environment) {
417
return new LoggingSystemProperties(environment);
418
}
419
420
@PostConstruct
421
public void configureLogging() {
422
// Apply custom log levels from properties
423
LoggingSystem loggingSystem = LoggingSystem.get(getClass().getClassLoader());
424
425
loggingProperties.getLevel().forEach((logger, level) -> {
426
System.out.println("Setting log level for " + logger + " to " + level);
427
loggingSystem.setLogLevel(logger, level);
428
});
429
}
430
}
431
```
432
433
### Environment Post Processors for Logging
434
435
Post-processors that can modify the environment before logging system initialization.
436
437
```java { .api }
438
/**
439
* EnvironmentPostProcessor to configure logging based on the Environment
440
*/
441
public class LoggingApplicationListener implements ApplicationListener<ApplicationEvent>,
442
Ordered, EnvironmentPostProcessor {
443
444
/**
445
* The default order for the LoggingApplicationListener
446
*/
447
public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 20;
448
449
/**
450
* The name of the Spring property that contains the name of the log file
451
*/
452
public static final String CONFIG_PROPERTY = "logging.config";
453
454
/**
455
* The name of the Spring property that controls the registration of a shutdown hook
456
* to shut down the logging system when the JVM exits
457
*/
458
public static final String REGISTER_SHUTDOWN_HOOK_PROPERTY = "logging.register-shutdown-hook";
459
460
@Override
461
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
462
// Configure logging system properties from environment
463
configureLoggingSystem(environment);
464
}
465
466
@Override
467
public void onApplicationEvent(ApplicationEvent event) {
468
if (event instanceof ApplicationStartingEvent) {
469
onApplicationStartingEvent((ApplicationStartingEvent) event);
470
} else if (event instanceof ApplicationEnvironmentPreparedEvent) {
471
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
472
} else if (event instanceof ApplicationPreparedEvent) {
473
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
474
} else if (event instanceof ContextClosedEvent) {
475
onContextClosedEvent((ContextClosedEvent) event);
476
} else if (event instanceof ApplicationFailedEvent) {
477
onApplicationFailedEvent((ApplicationFailedEvent) event);
478
}
479
}
480
481
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
482
this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
483
this.loggingSystem.beforeInitialize();
484
}
485
486
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
487
ConfigurableEnvironment environment = event.getEnvironment();
488
if (this.loggingSystem != null) {
489
initializeSystem(environment, this.loggingSystem, event.getSpringApplication());
490
}
491
}
492
}
493
```
494
495
**Usage Examples:**
496
497
```java
498
// Custom environment post-processor for logging
499
public class CustomLoggingEnvironmentPostProcessor implements EnvironmentPostProcessor {
500
501
@Override
502
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
503
// Add logging-related properties based on active profiles
504
String[] activeProfiles = environment.getActiveProfiles();
505
506
Properties loggingProps = new Properties();
507
508
if (Arrays.asList(activeProfiles).contains("dev")) {
509
// Development logging configuration
510
loggingProps.put("logging.level.org.springframework", "DEBUG");
511
loggingProps.put("logging.level.com.example", "DEBUG");
512
loggingProps.put("logging.pattern.console", "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
513
} else if (Arrays.asList(activeProfiles).contains("prod")) {
514
// Production logging configuration
515
loggingProps.put("logging.level.org.springframework", "WARN");
516
loggingProps.put("logging.level.com.example", "INFO");
517
loggingProps.put("logging.file.name", "/var/log/myapp/application.log");
518
loggingProps.put("logging.file.max-size", "100MB");
519
loggingProps.put("logging.file.max-history", "30");
520
}
521
522
if (!loggingProps.isEmpty()) {
523
PropertiesPropertySource propertySource = new PropertiesPropertySource(
524
"customLoggingProperties", loggingProps);
525
environment.getPropertySources().addLast(propertySource);
526
}
527
}
528
}
529
530
// Register the post-processor in spring.factories
531
// META-INF/spring.factories:
532
// org.springframework.boot.env.EnvironmentPostProcessor=\
533
// com.example.CustomLoggingEnvironmentPostProcessor
534
```
535
536
### Conditional Logging Configuration
537
538
Utilities for conditionally applying logging configuration based on environment conditions.
539
540
```java { .api }
541
/**
542
* Condition that matches when a logging system is available on the classpath
543
*/
544
public class LoggingSystemCondition extends SpringBootCondition {
545
546
@Override
547
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
548
String loggingSystem = System.getProperty(LoggingSystem.SYSTEM_PROPERTY);
549
if (LoggingSystem.NONE.equals(loggingSystem)) {
550
return ConditionOutcome.noMatch("Logging system is disabled");
551
}
552
553
if (LoggingSystem.get(context.getClassLoader()) != null) {
554
return ConditionOutcome.match("Logging system found on classpath");
555
}
556
557
return ConditionOutcome.noMatch("No logging system found on classpath");
558
}
559
}
560
```
561
562
**Usage Examples:**
563
564
```java
565
// Conditional logging beans
566
@Configuration
567
public class ConditionalLoggingConfiguration {
568
569
@Bean
570
@ConditionalOnProperty(name = "logging.structured.enabled", havingValue = "true")
571
public StructuredLoggingConfigurer structuredLoggingConfigurer() {
572
return new StructuredLoggingConfigurer();
573
}
574
575
@Bean
576
@ConditionalOnClass(name = "ch.qos.logback.classic.Logger")
577
public LogbackConfigurationCustomizer logbackCustomizer() {
578
return configuration -> {
579
// Custom Logback configuration
580
configuration.setLevel("org.springframework.security", Level.DEBUG);
581
};
582
}
583
584
@Bean
585
@ConditionalOnMissingBean(LoggingMetrics.class)
586
public LoggingMetrics loggingMetrics() {
587
return new LoggingMetrics();
588
}
589
}
590
591
// Custom structured logging
592
public class StructuredLoggingConfigurer {
593
594
@EventListener
595
public void configureStructuredLogging(ApplicationEnvironmentPreparedEvent event) {
596
ConfigurableEnvironment environment = event.getEnvironment();
597
598
// Configure JSON logging pattern
599
System.setProperty("logging.pattern.console",
600
"{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ}\",\"level\":\"%level\"," +
601
"\"thread\":\"%thread\",\"logger\":\"%logger\",\"message\":\"%msg\"}%n");
602
}
603
}
604
```