CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-slf4j--log4j-over-slf4j

Log4j 1.x API compatibility layer that implements Apache Log4j API over SLF4J for seamless migration

Pending
Overview
Eval results
Files

diagnostic-contexts.mddocs/

Diagnostic Contexts

Mapped Diagnostic Context (MDC) and Nested Diagnostic Context (NDC) for adding contextual information to log messages. Both contexts bridge to SLF4J's MDC mechanism for thread-local diagnostic data.

Capabilities

Mapped Diagnostic Context (MDC)

Thread-local key-value storage for contextual information that can be included in log messages. All operations delegate to SLF4J's MDC.

/**
 * Put a key-value pair in the MDC
 * @param key The key
 * @param value The value as String
 */
public static void put(String key, String value);

/**
 * Put a key-value pair in the MDC (Object converted to String)
 * @param key The key
 * @param value The value as Object (converted to String via toString())
 */
public static void put(String key, Object value);

/**
 * Get value by key from MDC
 * @param key The key to lookup
 * @return The value or null if not found
 */
public static Object get(String key);

/**
 * Remove key-value pair from MDC
 * @param key The key to remove
 */
public static void remove(String key);

/**
 * Clear all MDC data for current thread
 */
public static void clear();

/**
 * Get MDC context as Hashtable (deprecated)
 * @return Copy of MDC context as Hashtable
 * @deprecated This method may be removed in future versions
 */
@Deprecated
public static Hashtable<String, String> getContext();

Usage Examples:

import org.apache.log4j.MDC;
import org.apache.log4j.Logger;

Logger logger = Logger.getLogger(MyClass.class);

// Set context information
MDC.put("userId", "12345");
MDC.put("sessionId", "abc-def-ghi");
MDC.put("requestId", UUID.randomUUID().toString());

// Log messages will include MDC context (if configured in SLF4J implementation)
logger.info("Processing user request");

// Can put different types (converted to String)
MDC.put("timestamp", System.currentTimeMillis());
MDC.put("userRole", UserRole.ADMIN);

// Retrieve values
String userId = (String) MDC.get("userId");
String sessionId = (String) MDC.get("sessionId");

// Remove specific key
MDC.remove("requestId");

// Clear all context for thread
MDC.clear();

// Example in web application filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    try {
        // Set context for request
        MDC.put("requestId", generateRequestId());
        MDC.put("remoteAddr", request.getRemoteAddr());
        
        chain.doFilter(request, response);
    } finally {
        // Always clean up
        MDC.clear();
    }
}

Nested Diagnostic Context (NDC)

Stack-based diagnostic context for hierarchical information. Implemented using SLF4J's MDC with numbered keys.

/**
 * NDC key prefix used for MDC storage
 */
public static final String PREFIX = "NDC";

/**
 * Push a message onto the NDC stack
 * @param message Message to push
 */
public static void push(String message);

/**
 * Pop the top message from NDC stack
 * @return The popped message or empty string if stack is empty
 */
public static String pop();

/**
 * Peek at the top message without removing it
 * @return The top message or empty string if stack is empty
 */
public static String peek();

/**
 * Get current depth of NDC stack
 * @return Stack depth
 */
public static int getDepth();

/**
 * Clear all NDC data for current thread
 */
public static void clear();

/**
 * Get NDC string (always returns null in this implementation)
 * @return null
 */
public static String get();

/**
 * Remove all NDC data (same as clear())
 */
public static void remove();

/**
 * Clone NDC stack (always returns null in this implementation)
 * @return null
 */
public static Stack<?> cloneStack();

/**
 * Inherit NDC stack from another thread (no-op in this implementation)
 * @param stack Stack to inherit from
 */
public static void inherit(Stack<?> stack);

/**
 * Set maximum NDC depth (no-op in this implementation)
 * @param maxDepth Maximum depth
 */
public static void setMaxDepth(int maxDepth);

Usage Examples:

import org.apache.log4j.NDC;
import org.apache.log4j.Logger;

Logger logger = Logger.getLogger(MyClass.class);

// Build nested context
NDC.push("UserService");
logger.info("Starting user operation"); // Context: [UserService]

NDC.push("validateUser");
logger.debug("Validating user credentials"); // Context: [UserService, validateUser]

NDC.push("checkDatabase");
logger.debug("Querying user database"); // Context: [UserService, validateUser, checkDatabase]

// Check depth
int depth = NDC.getDepth(); // 3

// Peek without removing
String current = NDC.peek(); // "checkDatabase"

// Pop as operations complete
String finished = NDC.pop(); // "checkDatabase", depth now 2
logger.debug("Database check completed"); // Context: [UserService, validateUser]

NDC.pop(); // "validateUser", depth now 1
logger.info("User validation completed"); // Context: [UserService]

NDC.pop(); // "UserService", depth now 0
logger.info("User operation completed"); // Context: []

// Clear all context
NDC.clear();

// Example in method call hierarchy
public void processOrder(Order order) {
    NDC.push("processOrder(" + order.getId() + ")");
    try {
        logger.info("Processing order");
        validateOrder(order);
        saveOrder(order);
        notifyCustomer(order);
    } finally {
        NDC.pop();
    }
}

private void validateOrder(Order order) {
    NDC.push("validateOrder");
    try {
        logger.debug("Validating order data");
        // validation logic
    } finally {
        NDC.pop();
    }
}

Context Best Practices

Guidelines for effective use of diagnostic contexts.

MDC Best Practices:

// Use try-finally to ensure cleanup
public void handleRequest(HttpServletRequest request) {
    try {
        MDC.put("requestId", generateRequestId());
        MDC.put("userId", getCurrentUserId());
        
        // Process request
        processRequest(request);
        
    } finally {
        // Always clean up to prevent memory leaks
        MDC.clear();
    }
}

// Use meaningful, consistent key names
MDC.put("user.id", userId);
MDC.put("session.id", sessionId);
MDC.put("request.method", request.getMethod());
MDC.put("request.uri", request.getRequestURI());

NDC Best Practices:

// Use try-finally pattern for NDC as well
public void complexOperation() {
    NDC.push("complexOperation");
    try {
        logger.info("Starting complex operation");
        
        subOperation1();
        subOperation2();
        
        logger.info("Complex operation completed");
    } finally {
        NDC.pop();
    }
}

// Use descriptive context names
NDC.push("OrderService.processPayment");
NDC.push("PaymentGateway.authorizeCard");
NDC.push("BankAPI.validateAccount");

Combined Usage:

// MDC for request-wide context, NDC for call hierarchy
public void processUserRequest(String userId, String operation) {
    try {
        // Set request context with MDC
        MDC.put("userId", userId);
        MDC.put("operation", operation);
        MDC.put("timestamp", Instant.now().toString());
        
        // Track call hierarchy with NDC
        NDC.push("processUserRequest");
        
        logger.info("Processing user request");
        performOperation(operation);
        
    } finally {
        NDC.clear();
        MDC.clear();
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-slf4j--log4j-over-slf4j

docs

appenders-layouts.md

configuration.md

core-logging.md

diagnostic-contexts.md

index.md

level-management.md

tile.json