0
# Utilities and Helpers
1
2
Comprehensive utility classes for file operations, date formatting, duration handling, size parsing, thread management, and testing support. These utilities provide essential infrastructure services used throughout the logback-core framework.
3
4
## Capabilities
5
6
### File and Size Utilities
7
8
#### FileSize
9
10
Utility class for representing and parsing file sizes with unit support.
11
12
```java { .api }
13
/**
14
* Represents file sizes with unit parsing and formatting.
15
*/
16
public class FileSize {
17
/**
18
* Create FileSize with size in bytes.
19
* @param size size in bytes
20
*/
21
public FileSize(long size);
22
23
/**
24
* Set size from string with units (e.g., "10MB", "1GB").
25
* @param str size string with optional unit
26
*/
27
public void setSize(String str);
28
29
/**
30
* Get size in bytes.
31
* @return size in bytes
32
*/
33
public long getSize();
34
35
/**
36
* Get human-readable size string.
37
* @return formatted size (e.g., "10 MB")
38
*/
39
@Override
40
public String toString();
41
42
/**
43
* Parse size string to bytes.
44
* @param s size string (e.g., "100KB", "5MB", "2GB")
45
* @return size in bytes
46
*/
47
public static long valueOf(String s);
48
}
49
```
50
51
#### FileUtil
52
53
File system utility methods for directory creation and resource handling.
54
55
```java { .api }
56
/**
57
* File system utility methods.
58
*/
59
public class FileUtil {
60
/**
61
* Create missing parent directories for a file.
62
* @param file target file
63
* @return true if directories were created or already exist
64
*/
65
public static boolean createMissingParentDirectories(File file);
66
67
/**
68
* Load resource as string from classpath.
69
* @param classLoader class loader to use
70
* @param resourceName resource name
71
* @return resource content as string
72
*/
73
public static String resourceAsString(ClassLoader classLoader, String resourceName);
74
75
/**
76
* Check if parent directory creation is required.
77
* @param file target file
78
* @return true if parent directories need to be created
79
*/
80
public static boolean isParentDirectoryCreationRequired(File file);
81
82
/**
83
* Create missing target directories if necessary.
84
* @param file target file
85
* @return true if successful
86
*/
87
public static boolean createMissingTargetDirsIfNecessary(File file);
88
}
89
```
90
91
### Time and Duration Utilities
92
93
#### Duration
94
95
Utility class for representing and parsing time durations with unit support.
96
97
```java { .api }
98
/**
99
* Represents time durations with unit parsing and formatting.
100
*/
101
public class Duration {
102
/**
103
* Get duration in milliseconds.
104
* @return duration in milliseconds
105
*/
106
public long getMilliseconds();
107
108
/**
109
* Set duration in milliseconds.
110
* @param milliseconds duration in milliseconds
111
*/
112
public void setMilliseconds(long milliseconds);
113
114
/**
115
* Get human-readable duration string.
116
* @return formatted duration (e.g., "30 seconds")
117
*/
118
@Override
119
public String toString();
120
121
/**
122
* Parse duration string with units.
123
* @param s duration string (e.g., "30s", "5min", "2hours")
124
* @return Duration object
125
*/
126
public static Duration valueOf(String s);
127
}
128
```
129
130
#### CachingDateFormatter
131
132
High-performance date formatter with caching for frequently used timestamps.
133
134
```java { .api }
135
/**
136
* High-performance date formatter with timestamp caching.
137
*/
138
public class CachingDateFormatter {
139
/**
140
* Format timestamp with caching.
141
* @param now timestamp in milliseconds
142
* @return formatted date string
143
*/
144
public String format(long now);
145
146
/**
147
* Set time zone for formatting.
148
* @param tz time zone
149
*/
150
public void setTimeZone(TimeZone tz);
151
152
/**
153
* Get current time zone.
154
* @return time zone
155
*/
156
public TimeZone getTimeZone();
157
}
158
```
159
160
### Environment and System Utilities
161
162
#### EnvUtil
163
164
Environment detection and capability checking utilities.
165
166
```java { .api }
167
/**
168
* Environment detection and capability utilities.
169
*/
170
public class EnvUtil {
171
/**
172
* Check if Groovy is available on the classpath.
173
* @return true if Groovy is available
174
*/
175
public static boolean isGroovyAvailable();
176
177
/**
178
* Check if JANSI library is available for console colors.
179
* @return true if JANSI is available
180
*/
181
public static boolean isJansiAvailable();
182
183
/**
184
* Get JDK version number.
185
* @return JDK version (e.g., 8, 11, 17)
186
*/
187
public static int getJDKVersion();
188
189
/**
190
* Check if running on Windows.
191
* @return true if Windows OS
192
*/
193
public static boolean isWindows();
194
195
/**
196
* Check if running on Mac OS.
197
* @return true if Mac OS
198
*/
199
public static boolean isMac();
200
201
/**
202
* Check if running on Linux.
203
* @return true if Linux OS
204
*/
205
public static boolean isLinux();
206
}
207
```
208
209
#### ContextUtil
210
211
Context-related utility methods for hostname and collision detection.
212
213
```java { .api }
214
/**
215
* Context-related utility methods.
216
*/
217
public class ContextUtil {
218
/**
219
* Get filename collision map for detecting conflicts.
220
* @param context target context
221
* @return map of filename collisions
222
*/
223
public static Map<String, String> getFilenameCollisionMap(Context context);
224
225
/**
226
* Get filename pattern collision map.
227
* @param context target context
228
* @return map of pattern collisions
229
*/
230
public static Map<String, FileNamePattern> getFilenamePatternCollisionMap(Context context);
231
232
/**
233
* Add hostname as a context property.
234
* @param context target context
235
*/
236
public static void addHostNameAsProperty(Context context);
237
}
238
```
239
240
### Thread and Concurrency Utilities
241
242
#### InterruptUtil
243
244
Thread interruption handling utilities.
245
246
```java { .api }
247
/**
248
* Thread interruption utilities for proper cleanup.
249
*/
250
public class InterruptUtil {
251
/**
252
* Mask thread interrupt flag temporarily.
253
*/
254
public static void maskInterruptFlag();
255
256
/**
257
* Unmask thread interrupt flag.
258
*/
259
public static void unmaskInterruptFlag();
260
261
/**
262
* Check if current thread is interrupted.
263
* @return true if interrupted
264
*/
265
public static boolean isInterrupted();
266
}
267
```
268
269
#### SimpleInvocationGate
270
271
Rate limiting utility to prevent excessive method calls.
272
273
```java { .api }
274
/**
275
* Rate limiting gate to prevent excessive method invocations.
276
*/
277
public class SimpleInvocationGate {
278
/**
279
* Check if invocation is too soon (rate limited).
280
* @param currentTime current timestamp
281
* @return true if invocation should be skipped
282
*/
283
public boolean isTooSoon(long currentTime);
284
285
/**
286
* Update timing mask if necessary.
287
* @param now current timestamp
288
*/
289
public void updateMaskIfNecessary(long now);
290
291
/**
292
* Set minimum interval between invocations.
293
* @param minDelayThreshold minimum delay in milliseconds
294
*/
295
public void setMinDelayThreshold(long minDelayThreshold);
296
}
297
```
298
299
### Configuration and Instantiation
300
301
#### OptionHelper
302
303
Configuration and object instantiation utilities.
304
305
```java { .api }
306
/**
307
* Configuration and instantiation utilities.
308
*/
309
public class OptionHelper {
310
/**
311
* Check if string is empty or null.
312
* @param str string to check
313
* @return true if empty or null
314
*/
315
public static boolean isEmpty(String str);
316
317
/**
318
* Check if string is not empty.
319
* @param str string to check
320
* @return true if not empty and not null
321
*/
322
public static boolean isNotEmpty(String str);
323
324
/**
325
* Substitute variables in string using property container.
326
* @param val string with ${variable} placeholders
327
* @param pc property container for variable lookup
328
* @return string with variables substituted
329
*/
330
public static String substVars(String val, PropertyContainer pc);
331
332
/**
333
* Instantiate class by name with context injection.
334
* @param className fully qualified class name
335
* @param superClass expected superclass
336
* @param context context for dependency injection
337
* @return instantiated object
338
*/
339
public static Object instantiateByClassName(String className,
340
Class<?> superClass,
341
Context context);
342
343
/**
344
* Instantiate class with parameter.
345
* @param className class name to instantiate
346
* @param superClass expected superclass
347
* @param context context for injection
348
* @param type parameter type
349
* @param param parameter value
350
* @return instantiated object
351
*/
352
public static Object instantiateByClassNameAndParameter(String className,
353
Class<?> superClass,
354
Context context,
355
Class<?> type,
356
Object param);
357
}
358
```
359
360
### Testing Utilities
361
362
#### EnvUtilForTests
363
364
Testing-specific environment utilities.
365
366
```java { .api }
367
/**
368
* Testing-specific environment utilities.
369
*/
370
public class EnvUtilForTests {
371
/**
372
* Set unit test mode flag.
373
* @param inUnitTestMode true if running in unit tests
374
*/
375
public static void setInUnitTestMode(boolean inUnitTestMode);
376
377
/**
378
* Check if running in unit test mode.
379
* @return true if in unit test mode
380
*/
381
public static boolean isInUnitTestMode();
382
}
383
```
384
385
#### RandomUtil
386
387
Random number generation utilities for testing.
388
389
```java { .api }
390
/**
391
* Random number utilities for testing.
392
*/
393
public class RandomUtil {
394
/**
395
* Get a positive random integer.
396
* @return positive random integer
397
*/
398
public static int getPositiveInt();
399
400
/**
401
* Generate random string of specified length.
402
* @param length string length
403
* @return random string
404
*/
405
public static String randomString(int length);
406
407
/**
408
* Get random port number in valid range.
409
* @return random port number
410
*/
411
public static int getRandomServerPort();
412
}
413
```
414
415
#### TeeOutputStream
416
417
Output stream that writes to multiple targets simultaneously.
418
419
```java { .api }
420
/**
421
* Output stream that writes to multiple targets.
422
*/
423
public class TeeOutputStream extends OutputStream {
424
/**
425
* Create tee stream with two outputs.
426
* @param o1 first output stream
427
* @param o2 second output stream
428
*/
429
public TeeOutputStream(OutputStream o1, OutputStream o2);
430
431
@Override
432
public void write(int b) throws IOException;
433
434
@Override
435
public void write(byte[] b) throws IOException;
436
437
@Override
438
public void write(byte[] b, int off, int len) throws IOException;
439
440
@Override
441
public void flush() throws IOException;
442
443
@Override
444
public void close() throws IOException;
445
}
446
```
447
448
### Data Structure Utilities
449
450
#### CyclicBuffer
451
452
Generic cyclic buffer implementation for fixed-size collections.
453
454
```java { .api }
455
/**
456
* Generic cyclic buffer with fixed size.
457
*/
458
public class CyclicBuffer<E> {
459
/**
460
* Create cyclic buffer with specified capacity.
461
* @param capacity maximum number of elements
462
*/
463
public CyclicBuffer(int capacity);
464
465
/**
466
* Add element (overwrites oldest if full).
467
* @param e element to add
468
*/
469
public void add(E e);
470
471
/**
472
* Get element at index.
473
* @param index element index
474
* @return element at index
475
*/
476
public E get(int index);
477
478
/**
479
* Get current number of elements.
480
* @return current size
481
*/
482
public int length();
483
484
/**
485
* Get maximum capacity.
486
* @return maximum size
487
*/
488
public int getMaxSize();
489
490
/**
491
* Resize buffer capacity.
492
* @param newSize new capacity
493
*/
494
public void resize(int newSize);
495
496
/**
497
* Clear all elements.
498
*/
499
public void clear();
500
}
501
```
502
503
### Component Tracking
504
505
#### ComponentTracker
506
507
Utility for tracking components with timeout-based cleanup.
508
509
```java { .api }
510
/**
511
* Component tracker with timeout-based cleanup.
512
*/
513
public class ComponentTracker<C> {
514
/**
515
* Find component by key.
516
* @param key component key
517
* @return component or null if not found
518
*/
519
public C find(String key);
520
521
/**
522
* Get existing component or create new one.
523
* @param key component key
524
* @param timestamp current timestamp
525
* @return existing or new component
526
*/
527
public C getOrCreate(String key, long timestamp);
528
529
/**
530
* Remove stale components based on timestamp.
531
* @param now current timestamp
532
*/
533
public void removeStaleComponents(long now);
534
535
/**
536
* Set maximum idle time before component removal.
537
* @param maxIdleTime idle time in milliseconds
538
*/
539
public void setMaxIdleTime(long maxIdleTime);
540
541
/**
542
* Get maximum idle time.
543
* @return idle time in milliseconds
544
*/
545
public long getMaxIdleTime();
546
547
/**
548
* Get all tracked component keys.
549
* @return set of component keys
550
*/
551
public Set<String> allKeys();
552
}
553
```
554
555
## Usage Examples
556
557
### File Size Parsing and Formatting
558
559
```java
560
import ch.qos.logback.core.util.FileSize;
561
562
// Parse file sizes from strings
563
FileSize size1 = new FileSize(FileSize.valueOf("100MB"));
564
FileSize size2 = new FileSize(FileSize.valueOf("1.5GB"));
565
FileSize size3 = new FileSize(FileSize.valueOf("512KB"));
566
567
// Create from bytes
568
FileSize size4 = new FileSize(1024 * 1024 * 50); // 50MB
569
570
// Format for display
571
System.out.println(size1.toString()); // "100 MB"
572
System.out.println(size2.toString()); // "1.5 GB"
573
574
// Use in configuration
575
FileAppender<?> appender = new FileAppender<>();
576
appender.setBufferSize(new FileSize(8192)); // 8KB buffer
577
```
578
579
### Duration Parsing and Usage
580
581
```java
582
import ch.qos.logback.core.util.Duration;
583
584
// Parse duration strings
585
Duration timeout = Duration.valueOf("30 seconds");
586
Duration delay = Duration.valueOf("5 minutes");
587
Duration retention = Duration.valueOf("7 days");
588
589
// Create from milliseconds
590
Duration custom = new Duration();
591
custom.setMilliseconds(15000); // 15 seconds
592
593
// Use with appenders
594
SocketAppender socketAppender = new SocketAppender();
595
socketAppender.setReconnectionDelay(Duration.valueOf("10s"));
596
```
597
598
### Environment Detection
599
600
```java
601
import ch.qos.logback.core.util.EnvUtil;
602
603
// Check environment capabilities
604
if (EnvUtil.isJansiAvailable()) {
605
// Enable console colors
606
enableColorOutput();
607
}
608
609
if (EnvUtil.isGroovyAvailable()) {
610
// Enable Groovy-based evaluators
611
setupGroovyEvaluators();
612
}
613
614
// Platform-specific configuration
615
if (EnvUtil.isWindows()) {
616
logFile = "C:\\logs\\application.log";
617
} else {
618
logFile = "/var/log/application.log";
619
}
620
621
// JDK version specific features
622
int jdkVersion = EnvUtil.getJDKVersion();
623
if (jdkVersion >= 11) {
624
// Use modern APIs
625
}
626
```
627
628
### Variable Substitution
629
630
```java
631
import ch.qos.logback.core.util.OptionHelper;
632
633
// Substitute variables in configuration strings
634
String pattern = "${LOG_DIR}/app-${HOSTNAME}.log";
635
String resolved = OptionHelper.substVars(pattern, context);
636
// Result: "/var/log/app-server01.log"
637
638
// Check string values
639
if (OptionHelper.isEmpty(configValue)) {
640
// Use default
641
configValue = defaultValue;
642
}
643
```
644
645
### Component Instantiation
646
647
```java
648
import ch.qos.logback.core.util.OptionHelper;
649
650
// Dynamically instantiate components
651
String className = "com.example.CustomAppender";
652
Object instance = OptionHelper.instantiateByClassName(
653
className,
654
Appender.class,
655
context
656
);
657
658
if (instance instanceof Appender) {
659
Appender<?> appender = (Appender<?>) instance;
660
// Configure and use appender
661
}
662
```
663
664
### Rate Limiting with SimpleInvocationGate
665
666
```java
667
import ch.qos.logback.core.util.SimpleInvocationGate;
668
669
public class RateLimitedLogger {
670
private final SimpleInvocationGate gate = new SimpleInvocationGate();
671
672
public RateLimitedLogger() {
673
gate.setMinDelayThreshold(1000); // Maximum once per second
674
}
675
676
public void logExpensiveOperation(String message) {
677
long now = System.currentTimeMillis();
678
if (!gate.isTooSoon(now)) {
679
// Perform expensive logging operation
680
performComplexLogging(message);
681
}
682
// Otherwise skip this log event
683
}
684
}
685
```
686
687
### Cyclic Buffer for Event Storage
688
689
```java
690
import ch.qos.logback.core.util.CyclicBuffer;
691
692
public class RecentEventsBuffer<E> {
693
private final CyclicBuffer<E> buffer;
694
695
public RecentEventsBuffer(int capacity) {
696
this.buffer = new CyclicBuffer<>(capacity);
697
}
698
699
public void addEvent(E event) {
700
buffer.add(event);
701
}
702
703
public List<E> getRecentEvents() {
704
List<E> events = new ArrayList<>();
705
for (int i = 0; i < buffer.length(); i++) {
706
events.add(buffer.get(i));
707
}
708
return events;
709
}
710
711
public void clearEvents() {
712
buffer.clear();
713
}
714
}
715
```
716
717
### Component Tracking with Cleanup
718
719
```java
720
import ch.qos.logback.core.util.ComponentTracker;
721
722
public class AppenderManager {
723
private final ComponentTracker<Appender<?>> tracker = new ComponentTracker<>();
724
725
public AppenderManager() {
726
tracker.setMaxIdleTime(30 * 60 * 1000); // 30 minutes
727
}
728
729
public Appender<?> getAppender(String name) {
730
long now = System.currentTimeMillis();
731
732
// Clean up stale appenders first
733
tracker.removeStaleComponents(now);
734
735
// Get or create appender
736
return tracker.getOrCreate(name, now);
737
}
738
739
public void shutdown() {
740
// Stop all tracked appenders
741
for (String key : tracker.allKeys()) {
742
Appender<?> appender = tracker.find(key);
743
if (appender != null && appender.isStarted()) {
744
appender.stop();
745
}
746
}
747
}
748
}
749
```
750
751
### Testing with TeeOutputStream
752
753
```java
754
import ch.qos.logback.core.util.TeeOutputStream;
755
756
public class TestOutputCapture {
757
public void captureOutput() throws IOException {
758
ByteArrayOutputStream captured = new ByteArrayOutputStream();
759
TeeOutputStream tee = new TeeOutputStream(System.out, captured);
760
761
// Redirect output to both console and capture buffer
762
PrintStream originalOut = System.out;
763
System.setOut(new PrintStream(tee));
764
765
try {
766
// Run code that produces output
767
System.out.println("This goes to both console and buffer");
768
769
// Verify captured output
770
String output = captured.toString();
771
assert output.contains("This goes to both");
772
773
} finally {
774
System.setOut(originalOut);
775
tee.close();
776
}
777
}
778
}
779
```
780
781
## Best Practices
782
783
1. **File Operations**: Always use FileUtil methods for cross-platform compatibility
784
2. **Size/Duration Parsing**: Use the built-in parsers for consistent unit handling
785
3. **Environment Detection**: Check capabilities before using optional features
786
4. **Thread Safety**: Use InterruptUtil for proper interrupt handling
787
5. **Resource Management**: Always close streams and clean up resources
788
6. **Rate Limiting**: Use SimpleInvocationGate to prevent excessive operations
789
7. **Testing**: Use testing utilities for consistent test behavior
790
791
These utilities provide the foundation for robust, cross-platform logging infrastructure with proper resource management and error handling.