我在Log4j2上开发了一个包装器类。使用OSGi的声明性服务,我发布了一个定制的记录器服务,使用我自己的记录器接口,包装器类作为实现。包装器类仅用于以编程方式配置记录器,即消息格式
我想打印日志文件中请求的每个日志的源类/文件名和行号。选项%C/%F和%L只打印有关包装器类中我实际调用log方法的位置的信息。
因此,作为一种锻炼,我每次都把新的Throwable作为参数传递,这样我就可以使用布局%Throwable{short.lineNumber}。但对于嵌入式应用程序来说,这是一个昂贵的过程。
我的主要问题是获取行号,因为对于文件名,我至少可以从Log4j2请求一个新的记录器,其中包含请求记录器服务的每个服务的名称,并将其保存在地图中。
有没有办法追踪来电者?我希望有一个类似的解决方案,适用于那些不想让logger服务的每个消费者都使用LOG4j2 JAR的应用程序。仅供参考,我不想使用任何XML文件,所有配置都是以编程方式进行的。
正如@Remko Popma所说,这里有一个简单的实现:
首先创建ExtendedLogger类:
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.spi.ExtendedLoggerWrapper;
public class ExtLogWithLine extends ExtendedLoggerWrapper {
private static final long serialVersionUID = 8239280349129059055L;
// define your wrapper class here
private static final String FQCN = WrapperLog.class.getName();
private final ExtendedLoggerWrapper logger;
private ExtLogWithLine(final Logger logger) {
super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory());
this.logger = this;
}
public static ExtLogWithLine create(final String name) {
final Logger wrapped = LogManager.getLogger(name);
return new ExtLogWithLine(wrapped);
}
@Override
public void debug(String info) {
if (isDebugEnabled()) {
logger.logIfEnabled(FQCN, Level.DEBUG, null, info, (Throwable) null);
}
}
@Override
public void info(String info) {
if (isInfoEnabled()) {
logger.logIfEnabled(FQCN, Level.INFO, null, info, (Throwable) null);
}
}
@Override
public void warn(String info) {
if (isWarnEnabled()) {
logger.logIfEnabled(FQCN, Level.WARN, null, info, (Throwable) null);
}
}
@Override
public void error(String info) {
if (isErrorEnabled()) {
logger.logIfEnabled(FQCN, Level.ERROR, null, info, (Throwable) null);
}
}
}
public class WrapperLog {
public void testLog() {
ExtLogWithLine logger = ExtLogWithLine.create("xxx");
// log will print out with correct line number
logger.info("see the line number");
}
}
Log4j2在内部遍历stackTrace以提取位置信息,它通过向org.apache.logging.log4j.spi.ExtendedLogger#logMessage
方法指定正确的FQCN(完全限定类名)来知道在堆栈跟踪中停止的位置。
Log4j2包含一个为记录器包装器生成代码的工具。文档如下(在自定义日志级别手册页面中):http://logging.apache.org/log4j/2.x/manual/customloglevels.html#CustomLoggers
尝试使用此工具生成记录器包装,并基于生成的代码创建自定义包装。此生成的代码将使用正确的FQCN,并能够生成正确的位置信息。
你可以用
StackTraceElement[] stes = Thread.currentThread().getStackTrace();
然而,我不确定这是否便宜得多。
我要做的是使每一条消息都是唯一的(对于这个类),并避免包含行号。您可以在IDE中搜索唯一的消息以查找行号。该类应使用记录器的名称。
问题内容: 在C#中,我们有和有或没有命名空间(包在Java世界中)得到一个类型(类在这种情况下)的名称。 java等于什么? 显然,有比手动使用和删除软件包名称更好的方法。 问题答案: 返回源代码中给定的基础类的简单名称。如果基础类是匿名的,则返回一个空字符串。 数组的简单名称是组件类型的简单名称,后接“ []”。特别是其组件类型为匿名的数组的简单名称为“ []”。 它实际上是从名称中删除软件包
首先,如果这是一个很长的代码段,我很抱歉,但是,我想做一个模态窗口,它将你在我的用户表单中写的东西写下来,并要求你确认它。我目前正在学习Javascript,我不允许使用innerHTML,我必须动态地编写“名字”等(名字的文本),不允许只在弹出窗口内写它。我已经让大多数东西工作,但“名字”“名字”等显示为“未定义”,或者(正如你可以看到的,我在这种情况下只用名字尝试的事情)显示为“空”。 希望有
我有一个正在使用Azure AD身份验证的应用程序。我还需要访问Microsoft Graph API以获取用户数据。我发现的每个向Graph API发出请求的示例都使用了缓存的会话令牌,但由于我使用的是JWT,因此显然不需要存储会话状态。如何使用JWT将我的应用程序作为受众来获得具有适当受众的JWT? 例如,这里有一个从Microsoft Graph AspNetCore示例检索令牌的请求: 它
我们能在不使用互联网的情况下获取设备当前的纬度和经度吗?我使用以下代码。。单击按钮后,我将触发位置侦听器。 当它连接到internet时,可以很好地获取经度和纬度值,但当它未连接到internet时,返回null。 有什么问题吗?LocationManager.NETWORK_PROVIDER,5000,20, locationListener需要互联网来获取延迟和长时间吗? 如果需要互联网,那么
尝试使用Request.GetParameter但结果检索到第一个值,即第一个索引: 将名称取为“MyArray[]”,并在下一页使用 访问该值` 现在我应该做什么,有没有替代方法或者要在这里做一些更改: 这是page One.jsp中的表单: 下面是代码片段: 注意:忽略计数器值,因为这里只是为了检查,代码运行正常,但它只使用Request.GetParameter检索第一个索引值。 请给我一些
我有一个带有复合骆驼用例名称的Java实体,例如。 我需要将这些实体映射到带有snake case名称的表上,例如,而不是Quarkus/Panache使用的默认值,例如。 我知道我可以用设置自定义表名,但我想知道是否有某种应用程序属性为我做同样的工作。