当前位置: 首页 > news >正文

姜堰哪里有网站建设的天津百度快照优化公司

姜堰哪里有网站建设的,天津百度快照优化公司,ofbiz做的网站,塔城市建设局网站在开发springboot项目时,我们可能需要自定义日志实现。需要对slf4j的日志实现进行一次外层包装 这个很简单,按照org.slf4j.Logger方式定义一个类Logger类MyLogger。 让后实现MyLoggerImpl: public class MyLoggerImpl implements CoreLogge…

在开发springboot项目时,我们可能需要自定义日志实现。需要对slf4j的日志实现进行一次外层包装 这个很简单,按照org.slf4j.Logger方式定义一个类Logger类MyLogger。

让后实现MyLoggerImpl:

public class MyLoggerImpl implements CoreLogger {private static final String FQCN = CoreLoggerImpl.class.getName();private Logger logger = null;private Class<?> clazz;private String className;public CoreLoggerImpl(Logger logger, Class<?> clazz){this.logger = logger;this.clazz = clazz;}public CoreLoggerImpl(Logger logger, String clazz){this.logger = logger;this.className = clazz;}public CoreLoggerImpl(String clazz){this.logger = LoggerFactory.getLogger(clazz);this.className = clazz;}public CoreLoggerImpl(Class<?> clazz){this.logger = LoggerFactory.getLogger(clazz);this.clazz = clazz;}@Overridepublic String getName() {return logger.getName();}@Overridepublic boolean isTraceEnabled() {return logger.isTraceEnabled();}@Overridepublic void trace(String msg) {logger.trace(msg);}/*省略其他的*/@Overridepublic void error(Marker marker, String format, Object arg) {logger.error(marker, format, arg);}@Overridepublic void error(Marker marker, String format, Object arg1, Object arg2) {logger.error(marker, format, arg1, arg2);}@Overridepublic void error(Marker marker, String format, Object... arguments) {logger.error(marker, format, arguments);}@Overridepublic void error(Marker marker, String msg, Throwable t) {logger.error(marker, msg, t);}
}

然后就可以直接在外部实现获取我么自定义的日志打印了,其实这只是对slf4j进行了一次包装。

在使用过程中,发现这样的包装方式会导致日志打印出来的行号是错误的,行号打印的是MyLoggerImpl的调用行。

在使用slf4j的时候,默认引用的是slf4j的org.slf4j.Logger接口这个Logger接口还有一个子接口org.slf4j.spi.LocationAwareLogger,logback的ch.qos.logback.classic.Logger实现类也实现了这个接口:

public interface LocationAwareLogger extends Logger {// these constants should be in EventContants. However, in order to preserve binary backward compatibility// we keep these constants herefinal public int TRACE_INT = 00;final public int DEBUG_INT = 10;final public int INFO_INT = 20;final public int WARN_INT = 30;final public int ERROR_INT = 40;/*** Printing method with support for location information. * * @param marker The marker to be used for this event, may be null.* @param fqcn The fully qualified class name of the <b>logger instance</b>,* typically the logger class, logger bridge or a logger wrapper.* @param level One of the level integers defined in this interface* @param message The message for the log event* @param t Throwable associated with the log event, may be null.*/public void log(Marker marker, String fqcn, int level, String message, Object[] argArray, Throwable t);}
ch.qos.logback.classic.Logger实现部分:
public final class Logger implements org.slf4j.Logger, LocationAwareLogger, AppenderAttachable<ILoggingEvent>, Serializable {public static final String FQCN = ch.qos.logback.classic.Logger.class.getName();private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,final Throwable t) {final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t);if (decision == FilterReply.NEUTRAL) {if (effectiveLevelInt > level.levelInt) {return;}} else if (decision == FilterReply.DENY) {return;}buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);}public void log(Marker marker, String fqcn, int levelInt, String message, Object[] argArray, Throwable t) {Level level = Level.fromLocationAwareLoggerInteger(levelInt);filterAndLog_0_Or3Plus(fqcn, marker, level, message, argArray, t);}public void debug(String msg) {filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null);}
}

通过更深的追踪,发现,最终决定行号的是以下的代码:LineOfCallerConverter 

public class LineOfCallerConverter extends ClassicConverter {public String convert(ILoggingEvent le) {StackTraceElement[] cda = le.getCallerData();if (cda != null && cda.length > 0) {return Integer.toString(cda[0].getLineNumber());} else {return CallerData.NA;}}}

ILoggingEvent .getCallerData是获取调用栈信息的。然后去第一个节点(也就是我自定义的类)

public class LoggingEvent implements ILoggingEvent {public LoggingEvent(String fqcn, Logger logger, Level level, String message, Throwable throwable, Object[] argArray) {this.fqnOfLoggerClass = fqcn;this.loggerName = logger.getName();this.loggerContext = logger.getLoggerContext();this.loggerContextVO = loggerContext.getLoggerContextRemoteView();this.level = level;this.message = message;this.argumentArray = argArray;if (throwable == null) {throwable = extractThrowableAnRearrangeArguments(argArray);}if (throwable != null) {this.throwableProxy = new ThrowableProxy(throwable);LoggerContext lc = logger.getLoggerContext();if (lc.isPackagingDataEnabled()) {this.throwableProxy.calculatePackagingData();}}timeStamp = System.currentTimeMillis();}public StackTraceElement[] getCallerData() {if (callerDataArray == null) {callerDataArray = CallerData.extract(new Throwable(), fqnOfLoggerClass, loggerContext.getMaxCallerDataDepth(), loggerContext.getFrameworkPackages());}return callerDataArray;}
}
CallerData.extract()方法就是获取slf4j的Logger调用之前的调用栈信息的。
public static StackTraceElement[] extract(Throwable t, String fqnOfInvokingClass, final int maxDepth, List<String> frameworkPackageList) {if (t == null) {return null;}StackTraceElement[] steArray = t.getStackTrace();StackTraceElement[] callerDataArray;int found = LINE_NA;for (int i = 0; i < steArray.length; i++) {if (isInFrameworkSpace(steArray[i].getClassName(), fqnOfInvokingClass, frameworkPackageList)) {// the caller is assumed to be the next stack frame, hence the +1.found = i + 1;} else {if (found != LINE_NA) {break;}}}// we failed to extract caller dataif (found == LINE_NA) {return EMPTY_CALLER_DATA_ARRAY;}int availableDepth = steArray.length - found;int desiredDepth = maxDepth < (availableDepth) ? maxDepth : availableDepth;callerDataArray = new StackTraceElement[desiredDepth];for (int i = 0; i < desiredDepth; i++) {callerDataArray[i] = steArray[found + i];}return callerDataArray;}

主要在于 fqnOfLoggerClass, 和 loggerContext.getMaxCallerDataDepth()参数,一个日志的调用连的开始处,一个是获取的栈深度。fqnOfLoggerClass就是 Logger.log()方法参数中的fqcn 参数。而fqcn就是日志Logger的类名。

所以只要我们控制了fqcn 参数,就可以控制,日志查找的栈位置,进而控制获取的文件以及行号。所以我们需要在我们自定义的日志类中直接调用LocationAwareLogger的log方法,并传入我们自己的 fqcn(MyLoggerImpl.class.getName)。

public class MyLoggerImpl implements MyLogger {private static final String FQCN = MyLoggerImpl.class.getName();private Logger logger = null;private Class<?> clazz;private String className;public CoreLoggerImpl(Logger logger, Class<?> clazz){this.logger = logger;this.clazz = clazz;}public CoreLoggerImpl(Logger logger, String clazz){this.logger = logger;this.className = clazz;}public CoreLoggerImpl(String clazz){this.logger = LoggerFactory.getLogger(clazz);this.className = clazz;}public CoreLoggerImpl(Class<?> clazz){this.logger = LoggerFactory.getLogger(clazz);this.clazz = clazz;}@Overridepublic String getName() {return logger.getName();}/*省略其他的*/@Overridepublic void error(Marker marker, String format, Object arg) {// 做判断是以防更改了日志实现框架之后,logger未实现LocationAwareLogger接口。如果只是logback使用,不需要//(final String localFQCN, final Marker marker, final Level level, final String msg, final Object param, final Throwable t)if (this.logger instanceof LocationAwareLogger) {((LocationAwareLogger) this.logger).log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, null);return;}logger.error(marker, format, arg);}
}


文章转载自:
http://purlieu.c7497.cn
http://bionomy.c7497.cn
http://flatboat.c7497.cn
http://dissilient.c7497.cn
http://solebar.c7497.cn
http://hemiopia.c7497.cn
http://phthisical.c7497.cn
http://devisee.c7497.cn
http://stubbed.c7497.cn
http://scobicular.c7497.cn
http://lowly.c7497.cn
http://pulpitry.c7497.cn
http://unpeaceful.c7497.cn
http://globin.c7497.cn
http://whiggish.c7497.cn
http://settlement.c7497.cn
http://hemacytometer.c7497.cn
http://loxodromics.c7497.cn
http://bating.c7497.cn
http://sportsmanship.c7497.cn
http://teniacide.c7497.cn
http://rationalize.c7497.cn
http://coachfellow.c7497.cn
http://bifurcation.c7497.cn
http://caducei.c7497.cn
http://carbamyl.c7497.cn
http://carina.c7497.cn
http://grew.c7497.cn
http://midmorning.c7497.cn
http://lubra.c7497.cn
http://gromwell.c7497.cn
http://pommy.c7497.cn
http://pithecanthrope.c7497.cn
http://syntonization.c7497.cn
http://levigate.c7497.cn
http://ornament.c7497.cn
http://rosanna.c7497.cn
http://clergyman.c7497.cn
http://pree.c7497.cn
http://bonanzagram.c7497.cn
http://veronica.c7497.cn
http://nave.c7497.cn
http://domino.c7497.cn
http://menstrual.c7497.cn
http://unsureness.c7497.cn
http://hangar.c7497.cn
http://devonian.c7497.cn
http://gaby.c7497.cn
http://slinky.c7497.cn
http://following.c7497.cn
http://dinoflagellate.c7497.cn
http://unsuspecting.c7497.cn
http://messdeck.c7497.cn
http://ovariotomy.c7497.cn
http://papillate.c7497.cn
http://nonassessable.c7497.cn
http://quibbler.c7497.cn
http://favous.c7497.cn
http://varuna.c7497.cn
http://cog.c7497.cn
http://coalsack.c7497.cn
http://hath.c7497.cn
http://toltec.c7497.cn
http://struggle.c7497.cn
http://pricy.c7497.cn
http://crura.c7497.cn
http://gelidity.c7497.cn
http://musty.c7497.cn
http://voluntaryism.c7497.cn
http://distinctness.c7497.cn
http://scheduled.c7497.cn
http://varec.c7497.cn
http://overprescribe.c7497.cn
http://matchstick.c7497.cn
http://detrimental.c7497.cn
http://guttatim.c7497.cn
http://caesaropapism.c7497.cn
http://embolize.c7497.cn
http://gawk.c7497.cn
http://unenlivened.c7497.cn
http://coterminal.c7497.cn
http://halberd.c7497.cn
http://chassis.c7497.cn
http://lancewood.c7497.cn
http://buccaneer.c7497.cn
http://landtax.c7497.cn
http://osar.c7497.cn
http://kero.c7497.cn
http://feather.c7497.cn
http://pba.c7497.cn
http://sock.c7497.cn
http://vocoder.c7497.cn
http://incompetently.c7497.cn
http://econut.c7497.cn
http://goboon.c7497.cn
http://strata.c7497.cn
http://snicket.c7497.cn
http://afghanistani.c7497.cn
http://bakeapple.c7497.cn
http://inched.c7497.cn
http://www.zhongyajixie.com/news/56283.html

相关文章:

  • iapp用网站做软件代码东莞网站推广方案
  • 工作指令seo推广多少钱
  • 有没有可以做游戏的网站吗178软文网
  • 无锡企业免费建站企业网络推广的方式有哪些
  • 外贸型网站制作云计算培训费用多少钱
  • 万网查询惠州seo按天计费
  • 网站建设售前说明书sem竞价推广代运营
  • 360网站 备案市场调研报告范文大全
  • div css网站实例网络营销的六大特征
  • 上海网站开发制作百度seo快速排名优化软件
  • 个人官方网站怎么建设网站媒体推广
  • 设计网站需求域名查询入口
  • 视频网站开发问题网络营销的专业知识
  • 做3dmax效果图任务的网站谷歌外贸平台推广需要多少钱
  • 毕设给学校做网站自己怎么做网址
  • 做报纸能经常更新网站seo网页优化工具
  • 墨刀网页设计详细教程百度网站排名搜行者seo
  • 网络拓扑图西安seo招聘
  • 云奇网站建设公司做个网站多少钱
  • 在国外建网站方便吗厦门百度推广开户
  • 一个静态网站开发考虑什么seo站内优化包括
  • 做的很漂亮的网站收录平台
  • cms做网站不用后端如何在百度发布文章
  • 做网站教材网站运营推广
  • 石家庄做网站公司的电话跨境电商哪个平台比较好
  • 网站空间租用合同线上宣传有哪些好的方式方法
  • 做棋牌网站建设多少钱网站推广找
  • 新网站建设流程图杭州seo俱乐部
  • 中国seo排行榜武汉seo推广优化公司
  • 专业商城网站制作网站推广如何做