0
# Logging and Audit
1
2
Apache ActiveMQ Artemis Commons provides a comprehensive logging framework with internationalization support and audit capabilities for system events and operations.
3
4
## Core Logging Interfaces
5
6
### ActiveMQUtilLogger
7
8
Primary logging interface for utility operations in Artemis.
9
10
```java { .api }
11
interface ActiveMQUtilLogger {
12
// Standard logging methods
13
void info(String message);
14
void info(String message, Object... params);
15
void warn(String message);
16
void warn(String message, Object... params);
17
void warn(String message, Throwable cause);
18
void error(String message);
19
void error(String message, Object... params);
20
void error(String message, Throwable cause);
21
void debug(String message);
22
void debug(String message, Object... params);
23
void trace(String message);
24
void trace(String message, Object... params);
25
26
// Conditional logging
27
boolean isInfoEnabled();
28
boolean isWarnEnabled();
29
boolean isErrorEnabled();
30
boolean isDebugEnabled();
31
boolean isTraceEnabled();
32
}
33
```
34
35
### ActiveMQUtilBundle
36
37
Message bundle interface for internationalized messages.
38
39
```java { .api }
40
interface ActiveMQUtilBundle {
41
// Internationalized message methods
42
String getMessage(String key);
43
String getMessage(String key, Object... params);
44
45
// Formatted exception messages
46
String getExceptionMessage(String key);
47
String getExceptionMessage(String key, Object... params);
48
49
// Bundle metadata
50
String getBundleName();
51
Locale getLocale();
52
}
53
```
54
55
## Audit Logging
56
57
### AuditLogger
58
59
Specialized logging for audit events and security-related operations.
60
61
```java { .api }
62
class AuditLogger {
63
// Audit event logging
64
static void logAuditEvent(String event);
65
static void logAuditEvent(String event, Object... params);
66
static void logAuditEvent(String event, String details);
67
static void logAuditEvent(String event, String details, Object... params);
68
69
// Security audit events
70
static void logSecurityEvent(String event, String user);
71
static void logSecurityEvent(String event, String user, String details);
72
73
// Administrative audit events
74
static void logAdminEvent(String event, String admin);
75
static void logAdminEvent(String event, String admin, String details);
76
77
// Configuration and setup
78
static void setEnabled(boolean enabled);
79
static boolean isEnabled();
80
static void setAuditLevel(String level);
81
}
82
```
83
84
## Bundle Factory
85
86
### BundleFactory
87
88
Factory for creating message bundles with internationalization support.
89
90
```java { .api }
91
class BundleFactory {
92
// Create message bundles
93
static <T> T newBundle(Class<T> bundleInterface);
94
static <T> T newBundle(Class<T> bundleInterface, Locale locale);
95
static <T> T newBundle(Class<T> bundleInterface, String baseName);
96
static <T> T newBundle(Class<T> bundleInterface, String baseName, Locale locale);
97
98
// Bundle configuration
99
static void setDefaultLocale(Locale locale);
100
static Locale getDefaultLocale();
101
static void setFallbackLocale(Locale locale);
102
static Locale getFallbackLocale();
103
}
104
```
105
106
## Usage Examples
107
108
### Basic Logging
109
110
```java
111
import org.apache.activemq.artemis.logs.ActiveMQUtilLogger;
112
113
// Get logger instance (typically injected or created by framework)
114
ActiveMQUtilLogger logger = getLogger();
115
116
// Basic logging
117
logger.info("Server started successfully");
118
logger.warn("Connection pool nearing capacity: {0}/{1}", currentConnections, maxConnections);
119
logger.error("Failed to process message", exception);
120
121
// Conditional logging for performance
122
if (logger.isDebugEnabled()) {
123
logger.debug("Processing message with ID: {0}, size: {1} bytes",
124
message.getId(), message.getSize());
125
}
126
127
// Trace logging for detailed debugging
128
if (logger.isTraceEnabled()) {
129
logger.trace("Buffer state: readable={0}, writable={1}, position={2}",
130
buffer.readableBytes(), buffer.writableBytes(), buffer.readerIndex());
131
}
132
```
133
134
### Audit Logging
135
136
```java
137
import org.apache.activemq.artemis.logs.AuditLogger;
138
139
// Enable audit logging
140
AuditLogger.setEnabled(true);
141
AuditLogger.setAuditLevel("INFO");
142
143
// Log administrative events
144
AuditLogger.logAdminEvent("QUEUE_CREATED", "admin", "Queue 'orders' created with max consumers: 10");
145
AuditLogger.logAdminEvent("QUEUE_DELETED", "admin", "Queue 'temp-queue' deleted");
146
147
// Log security events
148
AuditLogger.logSecurityEvent("USER_LOGIN", "john.doe", "Successful login from 192.168.1.100");
149
AuditLogger.logSecurityEvent("ACCESS_DENIED", "anonymous", "Attempt to access admin queue without permission");
150
151
// Log general audit events
152
AuditLogger.logAuditEvent("MESSAGE_SENT", "Queue: orders, Size: {0} bytes", messageSize);
153
AuditLogger.logAuditEvent("CONNECTION_ESTABLISHED", "Client: {0}, Protocol: {1}", clientId, protocol);
154
155
// Check if audit logging is enabled before expensive operations
156
if (AuditLogger.isEnabled()) {
157
String details = buildDetailedAuditInfo(operation);
158
AuditLogger.logAuditEvent("COMPLEX_OPERATION", details);
159
}
160
```
161
162
### Internationalized Message Bundles
163
164
```java
165
import org.apache.activemq.artemis.logs.BundleFactory;
166
import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;
167
168
// Create message bundle for default locale
169
ActiveMQUtilBundle bundle = BundleFactory.newBundle(ActiveMQUtilBundle.class);
170
171
// Create bundle for specific locale
172
ActiveMQUtilBundle spanishBundle = BundleFactory.newBundle(
173
ActiveMQUtilBundle.class,
174
new Locale("es", "ES")
175
);
176
177
// Use internationalized messages
178
String errorMessage = bundle.getMessage("queue.not.found", queueName);
179
String warningMessage = bundle.getMessage("connection.timeout", timeout, TimeUnit.SECONDS);
180
181
// Exception messages
182
String exceptionMsg = bundle.getExceptionMessage("invalid.configuration", configKey);
183
throw new ActiveMQException(exceptionMsg);
184
185
// Bundle information
186
String bundleName = bundle.getBundleName();
187
Locale currentLocale = bundle.getLocale();
188
```
189
190
### Custom Message Bundle Interface
191
192
```java
193
// Define custom message bundle interface
194
public interface MyComponentBundle {
195
@Message(id = 1001, value = "Queue {0} created successfully")
196
String queueCreated(String queueName);
197
198
@Message(id = 1002, value = "Failed to connect to broker at {0}:{1}")
199
String connectionFailed(String host, int port);
200
201
@Message(id = 1003, value = "Message processing completed in {0}ms")
202
String processingCompleted(long durationMs);
203
204
@Message(id = 1004, value = "Invalid routing type: {0}. Expected: {1}")
205
ActiveMQException invalidRoutingType(String actual, String expected);
206
}
207
208
// Use custom bundle
209
MyComponentBundle messages = BundleFactory.newBundle(MyComponentBundle.class);
210
211
// Log with internationalized messages
212
logger.info(messages.queueCreated("orders"));
213
logger.error(messages.connectionFailed("localhost", 61616));
214
logger.debug(messages.processingCompleted(processingTime));
215
216
// Throw internationalized exceptions
217
throw messages.invalidRoutingType("UNKNOWN", "ANYCAST or MULTICAST");
218
```
219
220
### Structured Logging with Context
221
222
```java
223
public class QueueManager {
224
private final ActiveMQUtilLogger logger;
225
private final String componentName;
226
227
public QueueManager(String componentName) {
228
this.componentName = componentName;
229
this.logger = getLogger();
230
}
231
232
public void createQueue(QueueConfiguration config) {
233
String queueName = config.getName().toString();
234
235
// Log operation start
236
logger.info("[{0}] Creating queue: {1}", componentName, queueName);
237
238
try {
239
// Perform queue creation
240
doCreateQueue(config);
241
242
// Log success with details
243
logger.info("[{0}] Queue created successfully: name={1}, durable={2}, maxConsumers={3}",
244
componentName, queueName, config.getDurable(), config.getMaxConsumers());
245
246
// Audit the administrative action
247
AuditLogger.logAdminEvent("QUEUE_CREATED", getCurrentUser(),
248
String.format("Queue: %s, Component: %s", queueName, componentName));
249
250
} catch (Exception e) {
251
// Log error with context
252
logger.error("[{0}] Failed to create queue: {1}", componentName, queueName, e);
253
254
// Audit the failure
255
AuditLogger.logAuditEvent("QUEUE_CREATION_FAILED",
256
"Queue: {0}, Component: {1}, Error: {2}",
257
queueName, componentName, e.getMessage());
258
throw e;
259
}
260
}
261
}
262
```
263
264
### Performance-Optimized Logging
265
266
```java
267
public class HighThroughputProcessor {
268
private final ActiveMQUtilLogger logger;
269
270
public void processMessage(Message message) {
271
// Use conditional logging to avoid expensive string operations
272
if (logger.isDebugEnabled()) {
273
logger.debug("Processing message: id={0}, type={1}, size={2}",
274
message.getId(), message.getType(), message.getSize());
275
}
276
277
try {
278
// Process message
279
Object result = doProcessMessage(message);
280
281
// Log only critical information at INFO level
282
if (result != null) {
283
logger.info("Message processed successfully: {0}", message.getId());
284
}
285
286
// Detailed trace logging
287
if (logger.isTraceEnabled()) {
288
logger.trace("Processing result: {0}, duration={1}ms, memory={2}MB",
289
result.toString(), getDuration(), getMemoryUsage());
290
}
291
292
} catch (Exception e) {
293
// Always log errors
294
logger.error("Message processing failed: {0}", message.getId(), e);
295
296
// Audit critical failures
297
if (isCriticalError(e)) {
298
AuditLogger.logAuditEvent("CRITICAL_PROCESSING_ERROR",
299
"Message: {0}, Error: {1}",
300
message.getId(), e.getClass().getSimpleName());
301
}
302
}
303
}
304
}
305
```
306
307
### Configuration-Based Logging Setup
308
309
```java
310
public class LoggingConfiguration {
311
312
public void configureLogging() {
313
// Set up bundle factory defaults
314
BundleFactory.setDefaultLocale(Locale.getDefault());
315
BundleFactory.setFallbackLocale(Locale.ENGLISH);
316
317
// Configure audit logging based on system properties
318
boolean auditEnabled = Boolean.parseBoolean(
319
System.getProperty("artemis.audit.enabled", "false"));
320
AuditLogger.setEnabled(auditEnabled);
321
322
if (auditEnabled) {
323
String auditLevel = System.getProperty("artemis.audit.level", "INFO");
324
AuditLogger.setAuditLevel(auditLevel);
325
}
326
327
// Log configuration
328
ActiveMQUtilLogger logger = getLogger();
329
logger.info("Logging configured: audit={0}, locale={1}",
330
auditEnabled, BundleFactory.getDefaultLocale());
331
}
332
}
333
```
334
335
## Integration Patterns
336
337
### Exception Logging Pattern
338
339
```java
340
public class ServiceComponent {
341
private final ActiveMQUtilLogger logger;
342
private final MyComponentBundle messages;
343
344
public ServiceComponent() {
345
this.logger = getLogger();
346
this.messages = BundleFactory.newBundle(MyComponentBundle.class);
347
}
348
349
public void performOperation() throws ActiveMQException {
350
logger.info("Starting operation");
351
352
try {
353
doOperation();
354
logger.info("Operation completed successfully");
355
356
} catch (ActiveMQException e) {
357
// Log and re-throw ActiveMQ exceptions
358
logger.error(messages.operationFailed(), e);
359
throw e;
360
361
} catch (Exception e) {
362
// Wrap and log other exceptions
363
String errorMsg = messages.unexpectedError(e.getMessage());
364
logger.error(errorMsg, e);
365
throw new ActiveMQInternalErrorException(errorMsg, e);
366
}
367
}
368
}
369
```
370
371
### Request/Response Logging Pattern
372
373
```java
374
public class MessageHandler {
375
private final ActiveMQUtilLogger logger;
376
377
public void handleRequest(String requestId, Object request) {
378
// Log request start
379
logger.info("Processing request: {0}", requestId);
380
381
if (logger.isDebugEnabled()) {
382
logger.debug("Request details: {0}, type={1}",
383
requestId, request.getClass().getSimpleName());
384
}
385
386
long startTime = System.currentTimeMillis();
387
388
try {
389
Object response = processRequest(request);
390
long duration = System.currentTimeMillis() - startTime;
391
392
// Log successful completion
393
logger.info("Request completed: {0}, duration={1}ms", requestId, duration);
394
395
// Trace response details
396
if (logger.isTraceEnabled()) {
397
logger.trace("Response for {0}: {1}", requestId, response);
398
}
399
400
} catch (Exception e) {
401
long duration = System.currentTimeMillis() - startTime;
402
logger.error("Request failed: {0}, duration={1}ms", requestId, duration, e);
403
404
// Audit significant failures
405
AuditLogger.logAuditEvent("REQUEST_PROCESSING_FAILED",
406
"RequestId: {0}, Duration: {1}ms, Error: {2}",
407
requestId, duration, e.getMessage());
408
}
409
}
410
}
411
```