您的位置:首页 > 健康 > 养生 > 武汉建站网站_安卓软件开发需要学什么软件_搜索引擎广告投放_网络营销的应用

武汉建站网站_安卓软件开发需要学什么软件_搜索引擎广告投放_网络营销的应用

2025/1/11 3:46:12 来源:https://blog.csdn.net/qq_38688267/article/details/145022997  浏览:    关键词:武汉建站网站_安卓软件开发需要学什么软件_搜索引擎广告投放_网络营销的应用
武汉建站网站_安卓软件开发需要学什么软件_搜索引擎广告投放_网络营销的应用

版权说明: 本文由CSDN博主keep丶原创,转载请保留此块内容在文首。
原文地址: https://blog.csdn.net/qq_38688267/article/details/145022997

背景

  实现输出带动态标签的日志需求后,实际操作过程中,输出日志的代码为:log.info(LogHelper.WTC.tag("log content")),用起来不太方便,提出直接通过LogHelper输出日志,但是常规实现通过LogHelper输出日志会导致日志中的类信息是LogHelper的,解决该问题后可实现LogHelper.WTC.logTag("log content")的方式实现日志输出。预期效果如下:
在这里插入图片描述

实现原理

重写日志类信息输出转换类

  重写Logback类信息输出转换类,通过回溯堆栈的方式找到调用LogHelper方法的堆栈,输出调用方的类信息。

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.pattern.DynamicConverter;
import cn.xx.log.util.LogHelper;/*** Logback日志 类信息动态转换类* <br/>* 在{@code logback-spring.xml}中使用:<br/>* {@code <define name="traceId" class="cn.xx.log.core.log.TraceLogConverter"/>}* @author zeng.zf*/
public class ClassMethodLineConverter extends DynamicConverter<ILoggingEvent> {@Overridepublic String convert(ILoggingEvent event) {StackTraceElement[] stackTrace = event.getCallerData();if (stackTrace != null && stackTrace.length > 0) {int idx = LogHelper.UTIL.stackDepth();if(idx > stackTrace.length - 1) {idx = 0;}StackTraceElement element = stackTrace[idx];return String.format("%s.%s(%s:%d)",element.getClassName(),element.getMethodName(),element.getFileName(),element.getLineNumber());}return "unknown";}
}

缓存传递堆栈深度

在调用LogHelper输出日志时,缓存当前堆栈深度:
在这里插入图片描述
在这里插入图片描述

配置logback-spring.xml

<configuration><!-- 引用 Spring Boot 的 logback 基础配置 --><include resource="org/springframework/boot/logging/logback/defaults.xml" /><!-- 引用 traceId 动态参数转换类 --><define name="traceId" class="cn.xx.log.core.log.TraceLogConverter"/><!-- 注册自定义转换器 --><conversionRule conversionWord="CDC" converterClass="cn.xx.log.core.log.ClassMethodLineConverter" /><!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度,%msg:日志消息,%n是换行符 --><property name="PATTERN_CONSOLE" value="%green(%d{${yyyy-MM-dd HH:mm:ss.SSS}})|%highlight(%-5level)|%t|%magenta(%X{traceId})|%cyan(%CDC): %m%n"/><property name="PATTERN_FILE" value="%d{${yyyy-MM-dd HH:mm:ss.SSS}}|${LOG_LEVEL_PATTERN:-%4p}|%t|%X{traceId}|%CDC: %m%n"/><property name="LOG_FILE" value="trace.log"/>

至此,实现预期功能。

整理Loghelper类代码

package cn.xx.log.util;import cn.xx.log.core.exception.BizExceptionMark;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.lang.Nullable;import java.util.function.Consumer;
import java.util.function.Supplier;import static cn.xx.log.util.LogHelper.UTIL.getCacheTag;/*** 日志输出辅助类* <br/>* 注意:所有格式化参数在格式化时都是调用其toString()方法<br/>* 因此对象需要重写toString()方法或者使用{@code JSONUtil.toJsonStr()}转成JSON字符串。<br/>* <br/>* <b>如果自行输出日志,请按照该格式: {@code "[TAG][SUB_TAG] CONTENT"}</b>* <p>如: 1. {@code "[AddUser] add success"}</p>* <p>&emsp;&emsp;2. {@code "[AddUser][GenRole] add success"}</p>* <p>&emsp;&emsp;2. {@code "[AddUser][BizException] 用户名重复"}</p>* <p>更多请参考源文件中的LogHelperTest测试类</p>*/
@Slf4j
public class LogHelper {/*** 缓存{@link cn.xx.log.core.aop.log.BizLog} 注解的value值*/private static final ThreadLocal<String> logTagCache = new ThreadLocal<>();private static final ThreadLocal<Integer> stackDepth = new ThreadLocal<>();private static final String DEFAULT_TAG = "TAG_NOT_CONFIG";private static void helperLog(Consumer<String> logger, String logContent) {stackDepth.set(4);logger.accept(logContent);stackDepth.remove();}private static void helperLog(Runnable runnable) {stackDepth.set(4);runnable.run();stackDepth.remove();}private static void helperLog(Runnable runnable, int depth) {stackDepth.set(4 + depth);runnable.run();stackDepth.remove();}/*===========以下为工具方法,提供Tag缓存相关方法============*/public interface UTIL {/*** 缓存给定tag后执行给定方法<br/>* 使用:{@code LogHelper.beginTrace("AddUser", () -> userService.addUser(user))}** @param tag      日志标签* @param runnable 执行内容*/static void beginTrace(String tag, Runnable runnable) {try {cacheTag(tag);runnable.run();} finally {cleanCache();}}/*** 缓存给定tag后执行给定方法<br/>* 使用:{@code return LogHelper.beginTrace("AddUser", () -> userService.addUser(user))}** @param tag      日志标签* @param supplier 有返回值的执行内容*/static <T> T beginTrace(String tag, Supplier<T> supplier) {try {cacheTag(tag);return supplier.get();} finally {cleanCache();}}/*** 缓存给定tag后执行给定方法,提供默认异常处理<br/>* 使用:{@code LogHelper.catchBeginTrace(log, "AddUser", () -> userService.addUser(user))}** @param tag      日志标签* @param runnable 执行内容*/static void catchBeginTrace(String tag, Runnable runnable) {try {cacheTag(tag);runnable.run();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(WCT.bizEx((BizExceptionMark) e)));} else {helperLog(() -> log.error(WCT.otherEx(e)));}} finally {cleanCache();}}/*** 缓存给定tag后执行给定方法,提供默认异常处理<br/>* 使用:{@code return LogHelper.catchBeginTrace(log, "AddUser", () -> userService.addUser(user))}** @param tag      日志标签* @param supplier 有返回值的执行内容*/static <T> @Nullable T catchBeginTrace(String tag, Supplier<T> supplier) {try {cacheTag(tag);return supplier.get();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(WCT.bizEx((BizExceptionMark) e)));} else {helperLog(() -> log.error(WCT.otherEx(e)));}} finally {cleanCache();}return null;}/*** 获取缓存的标签值* <b style="color:red">只有缓存了标签之后才可用</b>*/static String getCacheTag() {String temp = logTagCache.get();if (temp == null) {log.warn("[LogHelper] 缓存标签为空, 请及时配置@BizLog注解或手动缓存标签.");return DEFAULT_TAG;}return temp;}static void cacheTag(String logTag) {logTagCache.set(logTag);}static void cacheTagIfAbsent(String logTag) {if (logTagCache.get() == null) {logTagCache.set(logTag);}}/*** 清空当前线程缓存* <br/>* <b>使用set()或init()之后,请在合适的地方调用clean(),一般用try-finally语法在finally块中调用</b>*/static void cleanCache() {logTagCache.remove();}static int stackDepth() {return stackDepth.get() == null ? 0 : stackDepth.get();}}/*=========================以下为基础方法,提供基础日志输出方法=======================*/public interface BASIC {/*** 标签日志<br/>* 例:* {@code LogHelper.tag("AddUser", "GenRole", "add success, user id = {}, name = {}", 1L, "zs")}<br/>* 返回 {@code "[AddUser][GenRole] add success, user id = 1, name = zs"}** @param tag     标签* @param content 需要格式化内容* @param arg     格式化参数* @return 最终日志*/static String tag(String tag, String content, Object... arg) {return StrUtil.format("[{}] {}", tag, StrUtil.format(content, arg));}static void logTag(String tag, String content, Object... arg) {helperLog(() -> log.info(tag(tag, content, arg)));}/*** 两级标签日志<br/>* 例:* {@code LogHelper.tag("AddUser", "GenRole", "add success")}<br/>* 返回 {@code "[AddUser][GenRole] add success"}** @param tag     标签* @param subTag  子标签* @param content 内容* @return 最终日志*/static String doubleTag(String tag, String subTag, String content, Object... args) {return StrUtil.format("[{}][{}] {}", tag, subTag, StrUtil.format(content, args));}static void logDoubleTag(String tag, String subTag, String content, Object... args) {helperLog(() -> log.info(doubleTag(tag, subTag, content, args)));}/*** 业务异常tag日志内容生成*/static String bizEx(BizExceptionMark bizException) {return StrUtil.format("[{}] code={},msg={}",bizException.getClass().getSimpleName(),bizException.getCode(),bizException.getMsg());}static void logBizEx(BizExceptionMark bizException) {helperLog(() -> log.warn(bizEx(bizException)));}/*** 业务异常tag日志内容生成*/static String bizEx(String tag, BizExceptionMark bizException) {return StrUtil.format("[{}][{}] code={},msg={}",tag,bizException.getClass().getSimpleName(),bizException.getCode(),bizException.getMsg());}static void logBizEx(String tag, BizExceptionMark bizException) {helperLog(() -> log.warn(bizEx(tag, bizException)));}/*** 业务异常tag日志内容生成*/static String bizEx(String tag, BizExceptionMark bizException, String extraInfo, Object... args) {return StrUtil.format("[{}][{}] code={},msg={}, extraInfo={{}}",tag,bizException.getClass().getSimpleName(),bizException.getCode(),bizException.getMsg(),StrUtil.format(extraInfo, args));}static void logBizEx(String tag, BizExceptionMark bizException, String extraInfo, Object... args) {helperLog(() -> log.warn(bizEx(tag, bizException, extraInfo, args)));}/*** 其他异常tag日志内容生成*/static String otherEx(Exception e) {return StrUtil.format("[{}] msg={}, stackTrace={}",e.getClass().getSimpleName(),e.getMessage(),TraceUtils.getStackTraceStr(e.getStackTrace()));}static void logOtherEx(Exception e) {helperLog(() -> log.error(otherEx(e)));}/*** 运行时异常tag日志内容生成*/static String otherEx(String tag, Exception e) {return StrUtil.format("[{}][{}] msg={}, stackTrace={}",tag,e.getClass().getSimpleName(),e.getMessage(),TraceUtils.getStackTraceStr(e.getStackTrace()));}static void logOtherEx(String tag, Exception e) {helperLog(() -> log.error(otherEx(tag, e)));}/*** 运行时异常tag日志内容生成*/static String otherEx(String tag, Exception e, String extraInfo, Object... args) {return StrUtil.format("[{}][{}] msg={}, extraInfo={{}}, stackTrace={}",tag,e.getClass().getSimpleName(),e.getMessage(),StrUtil.format(extraInfo, args),TraceUtils.getStackTraceStr(e.getStackTrace()));}static void logOtherEx(String tag, Exception e, String extraInfo, Object... args) {helperLog(() -> log.error(otherEx(tag, e, extraInfo, args)));}/*** 通用标签日志包装<br/>* <p>使用案例:</p>* 1. {@code tagLogWrap(() -> bizMethod(param1, param2))}<br/>* 2.* <pre><code>* \@Slf4j* public class UserServiceImpl{**     public void addUsers(List<User> users) {*          for(user in users) {*              LogHelper.tagLogWrap(log, "AddUsers", () -> addUser(user));*          }*     }*     public void addUser(User user) {*         xxx*         xxx*         ...*     }* }* </code></pre>** @param tag      日志标签* @param runnable 你要执行的无返回值方法*/static void catchLog(String tag, Runnable runnable) {try {runnable.run();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx(tag, (BizExceptionMark) e)));} else {helperLog(() -> log.error(otherEx(tag, e)));}}}/*** 通用标签日志包装<br/>* <p>使用案例:</p>* 1. {@code tagLogWrap(() -> bizMethod(param1, param2))}<br/>* 2.* <pre><code>* \@Slf4j* public class UserServiceImpl{**     public void addUsers(List<User> users) {*          for(user in users) {*              LogHelper.tagLogWrap(*                  log,*                  "AddUsers",*                  () -> addUser(user),*                  "id = {}, name={}",*                  user.getId(),*                  user.getName()*                  );*          }*     }*     public void addUser(User user) {*         xxx*         xxx*         ...*     }* }* </code></pre>** @param tag      日志标签* @param runnable 你要执行的无返回值方法*/static void catchLog(String tag, Runnable runnable, String extraInfo, Object... args) {try {runnable.run();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx(tag, (BizExceptionMark) e, extraInfo, args)));} else {helperLog(() -> log.error(otherEx(tag, e, extraInfo, args)));}}}/*** 通用标签日志包装<br/>* <p>使用案例:</p>* 1. {@code return tagLogWrap(() -> bizMethod(param1, param2))}<br/>* 2.* <pre><code>* \@Slf4j* public class UserServiceImpl{**     public List<User> getUserByIds(List<Long> ids) {*          return ids.map(id ->*              LogHelper.tagLogWrap(log, "getUserByIds", () -> getUserById(id))*          ).collect(Collectors.toList());*     }*     public User getUserById(Long userId) {*         xxx*         xxx*         ...*         return user;*     }* }* </code></pre>** @param tag      日志标签* @param supplier 你要执行的有返回值方法* @return 方法执行结果(可能为null)*/static <R> @Nullable R catchLog(String tag, Supplier<R> supplier) {try {return supplier.get();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx(tag, (BizExceptionMark) e)));} else {helperLog(() -> log.error(otherEx(tag, e)));}}return null;}/*** 通用标签日志包装<br/>* <p>使用案例:</p>* 1. {@code return tagLogWrap(() -> bizMethod(param1, param2))}<br/>* 2.* <pre><code>* \@Slf4j* public class UserServiceImpl{**     public List<User> getUserByIds(List<Long> ids) {*          return ids.map(id ->*              LogHelper.tagLogWrap(*                  log,*                  "getUserByIds",*                  () -> getUserById(id),*                  "id={}",*                  id*                  )*          ).collect(Collectors.toList());*     }*     public User getUserById(Long userId) {*         xxx*         xxx*         ...*         return user;*     }* }* </code></pre>** @param tag      日志标签* @param supplier 你要执行的有返回值方法* @return 方法执行结果(可能为null)*/static <R> @Nullable R catchLog(String tag, Supplier<R> supplier, String extraInfo, Object... args) {try {return supplier.get();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx(tag, (BizExceptionMark) e, extraInfo, args)));} else {helperLog(() -> log.error(otherEx(tag, e, extraInfo, args)));}}return null;}}/*===================以下为基于缓存标签的方法,理论上上方基础方法都要在下面有对应的方法==================*//* WCT = with cached tag *//*** <b style="color:red">只有缓存了标签之后才可用</b>*/public interface WCT {/*** <b style="color:red">只有缓存了标签之后才可用</b>*/static String tag(String content, Object... args) {return BASIC.tag(getCacheTag(), content, args);}static void logTag(String content, Object... args) {helperLog(() -> log.info(tag(content, args)));}/*** <b style="color:red">只有缓存了标签之后才可用</b>*/static String doubleTag(String subTag, String content, Object... args) {return BASIC.doubleTag(getCacheTag(), subTag, content, args);}static void logDoubleTag(String subTag, String content, Object... args) {helperLog(() -> log.info(doubleTag(subTag, content, args)));}/*** 业务异常tag日志内容生成* <b style="color:red">只有缓存了标签之后才可用</b>*/static String bizEx(BizExceptionMark bizException) {return BASIC.bizEx(getCacheTag(), bizException);}static void logBizEx(BizExceptionMark bizException) {helperLog(() -> log.warn(bizEx(bizException)));}/*** 业务异常tag日志内容生成* <b style="color:red">只有缓存了标签之后才可用</b>*/static String bizEx(BizExceptionMark bizException, String extraInfo, Object... args) {return BASIC.bizEx(getCacheTag(), bizException, extraInfo, args);}static void logBizEx(BizExceptionMark bizException, String extraInfo, Object... args) {helperLog(() -> log.warn(bizEx(bizException, extraInfo, args)));}/*** 运行时异常tag日志内容生成* <b style="color:red">只有缓存了标签之后才可用</b>*/static String otherEx(Exception e) {return BASIC.otherEx(getCacheTag(), e);}static void logOtherEx(Exception e) {helperLog(() -> log.error(otherEx(e)));}/*** 运行时异常tag日志内容生成* <b style="color:red">只有缓存了标签之后才可用</b>*/static String otherEx(Exception e, String extraInfo, Object... args) {return BASIC.otherEx(getCacheTag(), e, extraInfo, args);}static void logOtherEx(Exception e, String extraInfo, Object... args) {helperLog(() -> log.error(otherEx(e, extraInfo, args)));}/*** 通用标签日志包装<br/>* <b style="color:red">只有缓存了标签之后才可用</b>** @param runnable 你要执行的无返回值方法*/static void catchLog(Runnable runnable) {try {runnable.run();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx((BizExceptionMark) e)));} else {helperLog(() -> log.error(otherEx(e)));}}}/*** 通用标签日志包装<br/>* <b style="color:red">只有缓存了标签之后才可用</b>** @param runnable 你要执行的无返回值方法*/static void catchLog(Runnable runnable, String extraInfo, Object... args) {try {runnable.run();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx((BizExceptionMark) e, extraInfo, args)));} else {helperLog(() -> log.error(otherEx(e, extraInfo, args)));}}}/*** 通用标签日志包装<br/>* <b style="color:red">只有缓存了标签之后才可用</b>** @param supplier 你要执行的有返回值方法* @return 方法执行结果(可能为null)*/static <R> @Nullable R catchLog(Supplier<R> supplier) {try {return supplier.get();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx((BizExceptionMark) e)));} else {helperLog(() -> log.error(otherEx(e)));}}return null;}/*** 通用标签日志包装<br/>* <b style="color:red">只有缓存了标签之后才可用</b>** @param supplier 你要执行的有返回值方法* @return 方法执行结果(可能为null)*/static <R> @Nullable R catchLog(Supplier<R> supplier, String extraInfo, Object... args) {try {return supplier.get();} catch (Exception e) {if (e instanceof BizExceptionMark) {helperLog(() -> log.warn(bizEx((BizExceptionMark) e, extraInfo, args)));} else {helperLog(() -> log.error(otherEx(e, extraInfo, args)));}}return null;}}
}

相关博客

  • Spring实现Logback日志模板设置动态参数
  • Spring实现输出带动态标签的日志

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com