0
# Logging and Test Resources
1
2
Comprehensive logging collection, filtering, and test resource management for capturing and analyzing test execution logs.
3
4
## LogCollectingTestResource
5
6
A test resource that collects log records during test execution with filtering capabilities.
7
8
### Core API
9
10
```java { .api }
11
public class LogCollectingTestResource implements QuarkusTestResourceLifecycleManager {
12
13
public static LogCollectingTestResource current();
14
public List<LogRecord> getRecords();
15
public void clear();
16
17
// QuarkusTestResourceLifecycleManager implementation
18
public void init(Map<String, String> initArgs);
19
public Map<String, String> start();
20
public void stop();
21
}
22
```
23
24
### Configuration Constants
25
26
```java { .api }
27
public static final String LOGGER = "logger";
28
public static final String LEVEL = "level";
29
public static final String EXCLUDE = "exclude";
30
public static final String INCLUDE = "include";
31
```
32
33
### Utility Methods
34
35
```java { .api }
36
public static String format(LogRecord record);
37
```
38
39
## InMemoryLogHandler
40
41
A log handler that stores log records in memory with predicate-based filtering.
42
43
### Core API
44
45
```java { .api }
46
public class InMemoryLogHandler extends ExtHandler {
47
48
public InMemoryLogHandler(Predicate<LogRecord> predicate);
49
50
public void publish(LogRecord record);
51
public void flush();
52
public Level getLevel();
53
public void close() throws SecurityException;
54
public List<LogRecord> getRecords();
55
}
56
```
57
58
## Usage Examples
59
60
### Basic Log Collection
61
62
```java
63
import io.quarkus.test.LogCollectingTestResource;
64
import io.quarkus.test.QuarkusUnitTest;
65
import io.quarkus.test.common.QuarkusTestResource;
66
import org.junit.jupiter.api.Test;
67
import org.junit.jupiter.api.extension.RegisterExtension;
68
69
@QuarkusTestResource(LogCollectingTestResource.class)
70
public class LoggingTest {
71
72
@RegisterExtension
73
static final QuarkusUnitTest config = new QuarkusUnitTest()
74
.withApplicationRoot(jar -> jar.addClasses(LoggingService.class));
75
76
@Test
77
public void testLogging() {
78
// Perform operations that generate logs
79
80
// Access collected logs
81
LogCollectingTestResource logResource = LogCollectingTestResource.current();
82
List<LogRecord> records = logResource.getRecords();
83
84
assertTrue(records.stream()
85
.anyMatch(record -> record.getMessage().contains("Expected message")));
86
}
87
}
88
```
89
90
### Filtered Log Collection
91
92
```java
93
@QuarkusTestResource(value = LogCollectingTestResource.class, initArgs = {
94
@ResourceArg(name = LogCollectingTestResource.LOGGER, value = "org.example"),
95
@ResourceArg(name = LogCollectingTestResource.LEVEL, value = "INFO"),
96
@ResourceArg(name = LogCollectingTestResource.INCLUDE, value = ".*important.*")
97
})
98
public class FilteredLoggingTest {
99
100
@Test
101
public void testFilteredLogs() {
102
LogCollectingTestResource logResource = LogCollectingTestResource.current();
103
104
// Only logs from org.example logger, INFO level or above,
105
// containing "important" will be collected
106
List<LogRecord> records = logResource.getRecords();
107
108
records.forEach(record -> {
109
assertTrue(record.getLoggerName().startsWith("org.example"));
110
assertTrue(record.getLevel().intValue() >= Level.INFO.intValue());
111
assertTrue(record.getMessage().contains("important"));
112
});
113
}
114
}
115
```
116
117
### Exclude Pattern Log Collection
118
119
```java
120
@QuarkusTestResource(value = LogCollectingTestResource.class, initArgs = {
121
@ResourceArg(name = LogCollectingTestResource.EXCLUDE, value = ".*debug.*|.*trace.*")
122
})
123
public class ExcludePatternLoggingTest {
124
125
@Test
126
public void testExcludePattern() {
127
LogCollectingTestResource logResource = LogCollectingTestResource.current();
128
List<LogRecord> records = logResource.getRecords();
129
130
// No debug or trace messages should be collected
131
records.forEach(record -> {
132
assertFalse(record.getMessage().toLowerCase().contains("debug"));
133
assertFalse(record.getMessage().toLowerCase().contains("trace"));
134
});
135
}
136
}
137
```
138
139
### Manual Log Handler Usage
140
141
```java
142
import io.quarkus.test.InMemoryLogHandler;
143
import java.util.logging.LogRecord;
144
import java.util.logging.Logger;
145
146
public class ManualLogHandlerTest {
147
148
@Test
149
public void testInMemoryLogHandler() {
150
// Create handler with predicate
151
InMemoryLogHandler handler = new InMemoryLogHandler(
152
record -> record.getLevel().intValue() >= Level.WARNING.intValue()
153
);
154
155
// Add to logger
156
Logger logger = Logger.getLogger("test.logger");
157
logger.addHandler(handler);
158
159
try {
160
// Generate logs
161
logger.info("This will be filtered out");
162
logger.warning("This will be captured");
163
logger.severe("This will also be captured");
164
165
// Check captured records
166
List<LogRecord> records = handler.getRecords();
167
assertEquals(2, records.size());
168
169
assertTrue(records.stream()
170
.allMatch(record -> record.getLevel().intValue() >= Level.WARNING.intValue()));
171
172
} finally {
173
logger.removeHandler(handler);
174
handler.close();
175
}
176
}
177
}
178
```
179
180
### Log Formatting
181
182
```java
183
@Test
184
public void testLogFormatting() {
185
LogCollectingTestResource logResource = LogCollectingTestResource.current();
186
187
// Generate a log record
188
// ...
189
190
List<LogRecord> records = logResource.getRecords();
191
LogRecord record = records.get(0);
192
193
// Format the log record
194
String formatted = LogCollectingTestResource.format(record);
195
196
// Use formatted output for assertions or debugging
197
System.out.println("Formatted log: " + formatted);
198
}
199
```
200
201
### Clearing Logs Between Tests
202
203
```java
204
public class MultipleTestsWithLogging {
205
206
@Test
207
public void testFirst() {
208
LogCollectingTestResource logResource = LogCollectingTestResource.current();
209
210
// Perform test operations
211
// ...
212
213
// Verify logs
214
List<LogRecord> records = logResource.getRecords();
215
assertFalse(records.isEmpty());
216
217
// Clear logs for next test
218
logResource.clear();
219
}
220
221
@Test
222
public void testSecond() {
223
LogCollectingTestResource logResource = LogCollectingTestResource.current();
224
225
// Logs from previous test should not be present
226
List<LogRecord> records = logResource.getRecords();
227
assertTrue(records.isEmpty());
228
229
// Perform new test operations
230
// ...
231
}
232
}
233
```
234
235
### Complex Log Analysis
236
237
```java
238
@Test
239
public void testComplexLogAnalysis() {
240
LogCollectingTestResource logResource = LogCollectingTestResource.current();
241
242
// Perform operations that generate various logs
243
// ...
244
245
List<LogRecord> records = logResource.getRecords();
246
247
// Analyze log patterns
248
Map<Level, Long> logsByLevel = records.stream()
249
.collect(Collectors.groupingBy(
250
LogRecord::getLevel,
251
Collectors.counting()
252
));
253
254
// Verify log distribution
255
assertTrue(logsByLevel.get(Level.INFO) > 0);
256
assertEquals(0, logsByLevel.getOrDefault(Level.SEVERE, 0L));
257
258
// Check log sequence
259
List<String> messages = records.stream()
260
.map(LogRecord::getMessage)
261
.collect(Collectors.toList());
262
263
assertTrue(messages.indexOf("Operation started") <
264
messages.indexOf("Operation completed"));
265
266
// Verify logger names
267
Set<String> loggerNames = records.stream()
268
.map(LogRecord::getLoggerName)
269
.collect(Collectors.toSet());
270
271
assertTrue(loggerNames.contains("org.example.MyService"));
272
}
273
```
274
275
## Configuration Options
276
277
### Logger Configuration
278
279
- **LOGGER**: Specify which logger to capture (e.g., "org.example", "ROOT")
280
- **LEVEL**: Minimum log level to capture (e.g., "DEBUG", "INFO", "WARN", "ERROR")
281
282
### Pattern Filtering
283
284
- **INCLUDE**: Regex pattern for messages to include
285
- **EXCLUDE**: Regex pattern for messages to exclude
286
287
### Example Configuration
288
289
```java
290
@QuarkusTestResource(value = LogCollectingTestResource.class, initArgs = {
291
@ResourceArg(name = "logger", value = "org.example.MyService"),
292
@ResourceArg(name = "level", value = "DEBUG"),
293
@ResourceArg(name = "include", value = ".*transaction.*|.*request.*"),
294
@ResourceArg(name = "exclude", value = ".*heartbeat.*")
295
})
296
```
297
298
This configuration will:
299
- Only capture logs from "org.example.MyService" logger
300
- Include DEBUG level and above
301
- Only include messages containing "transaction" or "request"
302
- Exclude any messages containing "heartbeat"