{"repo":"qqxx6661/log-record","free":true,"listed":false,"github":"https://github.com/qqxx6661/log-record","clone":"git clone https://github.com/qqxx6661/log-record.git","description":"使用注解优雅记录系统日志，操作日志，后端埋点等，支持SpEL表达式，自定义上下文，自定义函数，实体类DIFF等其他高阶处理。","language":"Java","stars":1060,"topics":["java","logging"],"license":"Apache-2.0","category":"analytics","readme_excerpt":"log-record 注意：本仓库最初灵感来源于美团技术博客 ，若您需要寻找的是原文中作者的代码仓库，可以跳转这里 。本仓库从零实现了原文中描述的大部分特性，并吸取大量生产环境实践和用户反馈，随着持续稳定的维护和更新，期望给用户提供更多差异化的功能。 通过 Java 注解优雅的记录操作日志，并支持 SpEL 表达式，自定义上下文，自定义函数，实体类 DIFF 等功能，最终日志可由用户自行采集并处理，或推送至预配置的消息队列，支持SpringBoot1&2&3（JDK8 JDK21）。 采用 SpringBoot Starter 的方式，只需一个依赖，一句注解，日志轻松记录，不侵入业务逻辑： SpringBoot1&SpringBoot2(JDK8+)请引用： SpringBoot3(JDK17+)请引用： 最新版本号请查阅 Maven 公共仓库 项目背景 大家一定见过下图的操作日志： 在代码层面，如何优雅的记录上面的日志呢？ 能想到最粗暴的方式， 封装一个操作日志记录类 ，如下： 这种方式会导致业务代码被记录日志的代码侵入， 对于代码的可读性和可维护性来说是一个灾难。 这个方式显然不够优雅，让我们试试使用注解： 日志的记录被放到了注解，对业务代码没有侵入。 但是新的问题来了，我们该如何把 订单ID、用户信息、数据库里的旧地址、函数入参的新地址传递给注解呢？ Spring 的 SpEL 表达式（ Spring Expression Language ） 可以帮助我们，通过引入 SpEL 表达式，我们可以获取函数的入参。这样我们就可以对上面的注解进行修改： - 订单ID： #request.orderId - 新地址\"王五\"： #request.newFollower 如此一来，订单ID和地址的新值就可以通过解析入参动态获取了。 问题还没有结束，通常我们的用户信息（ user ），以及老的跟进人（ oldFollower ），是需要在方法中查询后才能获取， 入参里一般不会包含这些数据。 解决方案也不是没有，我们创建一个可以保存上下文的 LogRecordContext 变量， 让用户手动传递代码中计算出来的值，再交给 SpEL 解析 ，代码如下 什么？你说这不就又侵入了业务逻辑了么？ 确实是的，不过这种方法足够便捷易懂，并不会有什么理解的困难。 但是对于有“强迫症”的同学，这样的实现还是不够优雅，我们可以用 SpEL 支持的自定义函数，解决这个问题。 SpEL 支持在表达式中传入用户自定义函数，我们将 queryUserName 和 queryOldFollower 这两个函数提前放入 SpEL 的解析器中， SpEL 在解析表达式时，会执行对应函数。 最终，我们的注解变成了这样，并且最终记录了日志： 用户 张三 修改了订单的跟进人：从 李四 修改到 王五 以上便是本库的大致实现原理。 项目介绍 本库帮助你通过注解优雅地记录项目中的操作日志，对业务代码无侵入。 本项目特点： - 快速接入：使用 Spring Boot Starter 实现，用户直接在 pom.xml 引入依赖即可使用 - 业务无侵入：无需侵入业务代码，日志切面发生任何异常不会影响原方法执行 - SpEL 解析：支持 SpEL 表达式 - 实体类 Diff ：支持相同甚至不同类对象的 Diff - 条件注解：满足 Condition 条件后才记录日志，通过 SpEL 进行解析 - 自定义上下文：支持手动传递键值对，通过 SpEL 进行解析 - 自定义函数：支持注册自定义函数，通过 Sp","default_branch":null,"files":null,"tree":[],"storefront":"/r/qqxx6661","claimed":false,"request_supported":{"post":"https://gitbuyer.com/r/qqxx6661/log-record/request-supported","requests":0},"note":"indexed from public GitHub; nothing is for sale on this page. Clone it from GitHub. Paid listings live at /search."}