The logging API of the Log4j project providing a comprehensive and flexible logging framework for Java applications.
—
Marker system for adding hierarchical, filterable metadata to log events. Enables sophisticated filtering and routing based on marker taxonomy.
Hierarchical markers for adding filterable metadata to log events.
/**
* Marker interface for adding filterable information to log messages
*/
public interface Marker extends Serializable {
/** Get the marker name */
String getName();
/** Add parent markers to this marker */
Marker addParents(Marker... markers);
/** Set parent markers, replacing any existing parents */
Marker setParents(Marker... markers);
/** Remove a parent marker */
boolean remove(Marker marker);
/** Get array of parent markers */
Marker[] getParents();
/** Check if this marker has any parents */
boolean hasParents();
/** Check if this marker is an instance of the given marker (including hierarchy) */
boolean isInstanceOf(Marker marker);
/** Check if this marker is an instance of the named marker (including hierarchy) */
boolean isInstanceOf(String name);
/** Iterator over parents */
Iterator<Marker> iterator();
/** Check if marker contains the given marker in its hierarchy */
boolean contains(Marker other);
/** Check if marker contains the named marker in its hierarchy */
boolean contains(String name);
}Usage Examples:
private static final Logger logger = LogManager.getLogger();
public void demonstrateBasicMarkers() {
// Create markers
Marker networkMarker = MarkerManager.getMarker("NETWORK");
Marker securityMarker = MarkerManager.getMarker("SECURITY");
Marker databaseMarker = MarkerManager.getMarker("DATABASE");
// Use markers in logging
logger.info(networkMarker, "Network connection established");
logger.warn(securityMarker, "Invalid login attempt detected");
logger.error(databaseMarker, "Database connection failed");
// Markers can be used with all logging methods
logger.debug(networkMarker, "Network packet received: {}", packetData);
logger.error(securityMarker, "Security violation", exception);
}
// Hierarchical marker example
public void demonstrateMarkerHierarchy() {
// Create parent markers
Marker auditMarker = MarkerManager.getMarker("AUDIT");
Marker securityMarker = MarkerManager.getMarker("SECURITY");
// Create child markers
Marker loginMarker = MarkerManager.getMarker("LOGIN");
Marker accessMarker = MarkerManager.getMarker("ACCESS");
// Establish hierarchy - LOGIN and ACCESS are both types of SECURITY
loginMarker.addParents(securityMarker);
accessMarker.addParents(securityMarker);
// SECURITY is a type of AUDIT
securityMarker.addParents(auditMarker);
// Now LOGIN is also considered an instance of AUDIT through the hierarchy
logger.info(loginMarker, "User logged in"); // This log event has LOGIN, SECURITY, and AUDIT markers
// Check hierarchy
if (loginMarker.isInstanceOf(auditMarker)) {
System.out.println("Login events are audit events"); // This will print
}
if (loginMarker.isInstanceOf("SECURITY")) {
System.out.println("Login events are security events"); // This will print
}
}Factory for creating and managing Marker instances with singleton behavior.
/**
* Factory for creating and managing Marker instances
*/
public final class MarkerManager {
/** Get or create a marker with the given name */
public static Marker getMarker(String name);
/** Check if a marker with the given name exists */
public static boolean exists(String key);
/** Clear all markers (use with caution) */
public static void clear();
/**
* Actual Marker implementation
*/
public static class Log4jMarker implements Marker {
// Implementation of Marker interface
}
}Usage Examples:
public class MarkerConstants {
// Define application markers as constants
public static final Marker SECURITY = MarkerManager.getMarker("SECURITY");
public static final Marker PERFORMANCE = MarkerManager.getMarker("PERFORMANCE");
public static final Marker BUSINESS = MarkerManager.getMarker("BUSINESS");
public static final Marker TECHNICAL = MarkerManager.getMarker("TECHNICAL");
// Hierarchical markers
public static final Marker LOGIN = MarkerManager.getMarker("LOGIN");
public static final Marker LOGOUT = MarkerManager.getMarker("LOGOUT");
public static final Marker ACCESS_DENIED = MarkerManager.getMarker("ACCESS_DENIED");
static {
// Set up marker hierarchy
LOGIN.addParents(SECURITY);
LOGOUT.addParents(SECURITY);
ACCESS_DENIED.addParents(SECURITY);
SECURITY.addParents(BUSINESS);
PERFORMANCE.addParents(TECHNICAL);
}
}
public class ApplicationService {
private static final Logger logger = LogManager.getLogger();
public void login(String username, String password) {
logger.info(MarkerConstants.LOGIN, "Login attempt for user: {}", username);
if (authenticate(username, password)) {
logger.info(MarkerConstants.LOGIN, "Login successful for user: {}", username);
} else {
logger.warn(MarkerConstants.ACCESS_DENIED, "Login failed for user: {}", username);
}
}
public void checkMarkerExistence() {
if (MarkerManager.exists("SECURITY")) {
logger.debug("Security marker is available");
}
// Get the same marker instance (singleton behavior)
Marker sec1 = MarkerManager.getMarker("SECURITY");
Marker sec2 = MarkerManager.getMarker("SECURITY");
assert sec1 == sec2; // Same instance
}
}All logging methods support markers for enhanced filtering and routing.
public interface Logger {
// All logging methods have marker overloads
void trace(Marker marker, String message);
void debug(Marker marker, String message);
void info(Marker marker, String message);
void warn(Marker marker, String message);
void error(Marker marker, String message);
void fatal(Marker marker, String message);
// Parameterized logging with markers
void trace(Marker marker, String message, Object... params);
void debug(Marker marker, String message, Object... params);
void info(Marker marker, String message, Object... params);
void warn(Marker marker, String message, Object... params);
void error(Marker marker, String message, Object... params);
void fatal(Marker marker, String message, Object... params);
// Exception logging with markers
void trace(Marker marker, String message, Throwable throwable);
void debug(Marker marker, String message, Throwable throwable);
void info(Marker marker, String message, Throwable throwable);
void warn(Marker marker, String message, Throwable throwable);
void error(Marker marker, String message, Throwable throwable);
void fatal(Marker marker, String message, Throwable throwable);
// Generic logging with markers
void log(Level level, Marker marker, String message);
void log(Level level, Marker marker, String message, Object... params);
void log(Level level, Marker marker, String message, Throwable throwable);
// Level checking with markers
boolean isTraceEnabled(Marker marker);
boolean isDebugEnabled(Marker marker);
boolean isInfoEnabled(Marker marker);
boolean isWarnEnabled(Marker marker);
boolean isErrorEnabled(Marker marker);
boolean isFatalEnabled(Marker marker);
boolean isEnabled(Level level, Marker marker);
}Usage Examples:
private static final Logger logger = LogManager.getLogger();
private static final Marker PERFORMANCE = MarkerManager.getMarker("PERFORMANCE");
private static final Marker SECURITY = MarkerManager.getMarker("SECURITY");
private static final Marker AUDIT = MarkerManager.getMarker("AUDIT");
public class MarkerLoggingExamples {
public void demonstrateMarkerLogging() {
// Basic marker logging
logger.info(PERFORMANCE, "Operation completed in {}ms", executionTime);
logger.warn(SECURITY, "Suspicious activity detected from IP: {}", clientIP);
logger.error(AUDIT, "Configuration change failed", exception);
// Conditional logging with markers
if (logger.isDebugEnabled(PERFORMANCE)) {
logger.debug(PERFORMANCE, "Performance metrics: {}",
gatherDetailedMetrics());
}
// Multiple markers through hierarchy
Marker sqlMarker = MarkerManager.getMarker("SQL");
sqlMarker.addParents(PERFORMANCE); // SQL operations are performance-related
logger.debug(sqlMarker, "Executing query: {}", sql);
// This log event will match filters for both SQL and PERFORMANCE markers
}
// Web request processing with markers
public void processWebRequest(HttpServletRequest request) {
Marker requestMarker = MarkerManager.getMarker("REQUEST");
logger.info(requestMarker, "Processing {} request to {}",
request.getMethod(), request.getRequestURI());
try {
String result = handleRequest(request);
logger.info(requestMarker, "Request processed successfully");
} catch (SecurityException e) {
logger.error(SECURITY, "Security violation in request processing", e);
} catch (Exception e) {
logger.error(requestMarker, "Request processing failed", e);
}
}
// Business logic with contextual markers
public void processPayment(PaymentRequest payment) {
Marker paymentMarker = MarkerManager.getMarker("PAYMENT");
paymentMarker.addParents(AUDIT); // Payment operations are auditable
logger.info(paymentMarker, "Processing payment of ${} for user {}",
payment.getAmount(), payment.getUserId());
if (payment.getAmount().compareTo(BigDecimal.valueOf(10000)) > 0) {
Marker highValueMarker = MarkerManager.getMarker("HIGH_VALUE");
highValueMarker.addParents(paymentMarker, SECURITY);
logger.warn(highValueMarker, "High-value payment transaction: ${}",
payment.getAmount());
}
try {
PaymentResult result = paymentProcessor.process(payment);
logger.info(paymentMarker, "Payment processed successfully: {}",
result.getTransactionId());
} catch (PaymentException e) {
logger.error(paymentMarker, "Payment processing failed", e);
}
}
}Fluent API supports markers for complex log event construction.
public interface LogBuilder {
/** Add a marker to the log event */
LogBuilder withMarker(Marker marker);
// All other LogBuilder methods remain the same
LogBuilder withThrowable(Throwable throwable);
LogBuilder withLocation();
void log(String message);
void log(String message, Object... params);
}Usage Examples:
private static final Logger logger = LogManager.getLogger();
private static final Marker SECURITY = MarkerManager.getMarker("SECURITY");
private static final Marker AUDIT = MarkerManager.getMarker("AUDIT");
public void demonstrateLogBuilderWithMarkers() {
// Simple marker with LogBuilder
logger.atError()
.withMarker(SECURITY)
.log("Security violation detected");
// Complex log event with marker, exception, and location
logger.atWarn()
.withMarker(AUDIT)
.withThrowable(exception)
.withLocation()
.log("Audit event failed for user {}", userId);
// Conditional marker application
LogBuilder builder = logger.atInfo();
if (isSecurityRelated) {
builder = builder.withMarker(SECURITY);
}
if (exception != null) {
builder = builder.withThrowable(exception);
}
builder.log("Dynamic marker application: {}", eventData);
// Multiple markers through hierarchy
Marker specificMarker = MarkerManager.getMarker("SQL_INJECTION");
specificMarker.addParents(SECURITY);
logger.atError()
.withMarker(specificMarker) // Includes both SQL_INJECTION and SECURITY
.withLocation()
.log("SQL injection attempt detected from {}", clientIP);
}Common patterns for using markers in filtering and routing configurations.
// Example marker hierarchy for a web application
public class WebAppMarkers {
// Top-level categories
public static final Marker APPLICATION = MarkerManager.getMarker("APPLICATION");
public static final Marker INFRASTRUCTURE = MarkerManager.getMarker("INFRASTRUCTURE");
// Application subcategories
public static final Marker BUSINESS_LOGIC = MarkerManager.getMarker("BUSINESS_LOGIC");
public static final Marker SECURITY = MarkerManager.getMarker("SECURITY");
public static final Marker PERFORMANCE = MarkerManager.getMarker("PERFORMANCE");
// Infrastructure subcategories
public static final Marker DATABASE = MarkerManager.getMarker("DATABASE");
public static final Marker NETWORK = MarkerManager.getMarker("NETWORK");
public static final Marker CACHE = MarkerManager.getMarker("CACHE");
// Specific security markers
public static final Marker AUTHENTICATION = MarkerManager.getMarker("AUTHENTICATION");
public static final Marker AUTHORIZATION = MarkerManager.getMarker("AUTHORIZATION");
public static final Marker AUDIT = MarkerManager.getMarker("AUDIT");
static {
// Set up hierarchy
BUSINESS_LOGIC.addParents(APPLICATION);
SECURITY.addParents(APPLICATION);
PERFORMANCE.addParents(APPLICATION);
DATABASE.addParents(INFRASTRUCTURE);
NETWORK.addParents(INFRASTRUCTURE);
CACHE.addParents(INFRASTRUCTURE);
AUTHENTICATION.addParents(SECURITY);
AUTHORIZATION.addParents(SECURITY);
AUDIT.addParents(SECURITY);
}
}Usage Examples:
public class MarkerUsagePatterns {
private static final Logger logger = LogManager.getLogger();
// Service layer with business logic markers
@Service
public class OrderService {
public Order createOrder(OrderRequest request) {
logger.info(WebAppMarkers.BUSINESS_LOGIC,
"Creating order for customer {}", request.getCustomerId());
try {
validateOrderRequest(request);
Order order = processOrder(request);
logger.info(WebAppMarkers.AUDIT,
"Order {} created successfully", order.getId());
return order;
} catch (ValidationException e) {
logger.warn(WebAppMarkers.BUSINESS_LOGIC,
"Order validation failed", e);
throw e;
} catch (Exception e) {
logger.error(WebAppMarkers.BUSINESS_LOGIC,
"Order creation failed", e);
throw e;
}
}
private void validateOrderRequest(OrderRequest request) {
logger.debug(WebAppMarkers.BUSINESS_LOGIC,
"Validating order request");
// Validation with specific markers
if (!authService.hasPermission(request.getCustomerId())) {
logger.warn(WebAppMarkers.AUTHORIZATION,
"Customer {} lacks permission to create orders",
request.getCustomerId());
throw new AuthorizationException("Insufficient permissions");
}
}
}
// Data access layer with infrastructure markers
@Repository
public class OrderRepository {
public Order save(Order order) {
logger.debug(WebAppMarkers.DATABASE, "Saving order to database");
long startTime = System.currentTimeMillis();
try {
Order savedOrder = jdbcTemplate.save(order);
long duration = System.currentTimeMillis() - startTime;
if (duration > 1000) {
logger.warn(WebAppMarkers.PERFORMANCE,
"Slow database operation: {}ms", duration);
}
return savedOrder;
} catch (DataAccessException e) {
logger.error(WebAppMarkers.DATABASE,
"Database error saving order", e);
throw e;
}
}
}
// Security interceptor with authentication markers
@Component
public class SecurityInterceptor {
public boolean authenticate(String token) {
logger.debug(WebAppMarkers.AUTHENTICATION,
"Authenticating token");
if (isValidToken(token)) {
logger.info(WebAppMarkers.AUTHENTICATION,
"Token authentication successful");
return true;
} else {
logger.warn(WebAppMarkers.SECURITY,
"Invalid token authentication attempt");
return false;
}
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-apache-logging-log4j--log4j-api