Log4j 2 API

Markers

日志记录框架的主要目的之一是提供一种仅在需要时才生成调试和诊断信息的方法,并允许对该信息进行过滤,以使其不会淹没系统或需要使用该信息的个人。它。例如,应用程序希望与执行的 SQL 语句分开记录其进入,退出和其他操作,并希望能够记录与更新分开的查询。实现此目的的一种方法如下所示:

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.MarkerManager;
import java.util.Map;

public class MyApp {

    private Logger logger = LogManager.getLogger(MyApp.class.getName());
    private static final Marker SQL_MARKER = MarkerManager.getMarker("SQL");
    private static final Marker UPDATE_MARKER = MarkerManager.getMarker("SQL_UPDATE").setParents(SQL_MARKER);
    private static final Marker QUERY_MARKER = MarkerManager.getMarker("SQL_QUERY").setParents(SQL_MARKER);

    public String doQuery(String table) {
        logger.traceEntry();

        logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);

        String result = ... 

        return logger.traceExit(result);
    }

    public String doUpdate(String table, Map<String, String> params) {
        logger.traceEntry();

        if (logger.isDebugEnabled()) {
            logger.debug(UPDATE_MARKER, "UPDATE {} SET {}", table, formatCols());
        }
	
        String result = ... 

        return logger.traceExit(result);
    }

    private String formatCols(Map<String, String> cols) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : cols.entrySet()) {
            if (!first) {
                sb.append(", ");
            }
            sb.append(entry.getKey()).append("=").append(entry.getValue());
            first = false;
        }
        return sb.toString();
    }
}

在上面的示例中,现在可以添加 MarkerFilters,以仅允许记录 SQL 更新操作,记录所有 SQL 更新或将所有内容记录在 MyApp 中。

使用标记时必须考虑一些重要的规则。

  • 标记必须唯一。它们是通过名称永久注册的,因此请小心以确保在您的应用程序中使用的标记与应用程序的依赖项中的标记不同,除非需要这样做。

  • 可以动态添加或删除父标记。但是,这样做相当昂贵。相反,建议如上例所示,在首次获得标记时识别 parent。具体而言,set 方法在一次操作中替换了所有标记,而一次只能对单个标记执行添加和删除操作。

  • 评估具有多个祖先的标记比没有 parent 的标记要昂贵得多。例如,在一组评估标记是否与祖 parent 相匹配的测试中,其花费是评估标记本身的三倍。即使这样,与解析呼叫者的类名或线路号相比,评估标记还是便宜的。