- 📝 @PrintLog - 自动打印方法参数、返回值、执行时间
- 🔐 @Hidden - 敏感字段自动脱敏(手机号、身份证、密码等)
- 🚨 异常告警 - 支持微信、钉钉、飞书、邮件多渠道告警
- 📊 @Monitor - 性能监控与调用链追踪
- 🌐 @PrintCurl - 自动生成 HTTP 请求的 curl 命令
- 🔗 TraceId - 全链路请求追踪
- ⚡ 零侵入 - 基于 AOP,无需修改业务代码
- ✅ 支持 Spring Boot 2.x 和 3.x
- ✅ 支持 Java 8 和 Java 17+
- ✅ 异常排除机制(unException)
- ✅ 自定义异常处理器
- ✅ 异步告警发送
- ✅ 线程池配置
- ✅ 堆栈信息过滤
Spring Boot 3.x (Java 17+):
<dependency>
<groupId>io.github.tianhaocui</groupId>
<artifactId>loghelper-spring-boot-start</artifactId>
<version>2.1.1-RELEASE</version>
</dependency>Spring Boot 2.x (Java 8):
<dependency>
<groupId>io.github.tianhaocui</groupId>
<artifactId>loghelper-spring-boot-start</artifactId>
<version>2.0.6-java8</version>
</dependency>// Spring Boot 3.x
implementation 'io.github.tianhaocui:loghelper-spring-boot-start:2.1.1-RELEASE'
// Spring Boot 2.x
implementation 'io.github.tianhaocui:loghelper-spring-boot-start:2.0.6-java8'在 Spring Boot 启动类上添加 @EnableLogHelper 注解:
@SpringBootApplication
@EnableLogHelper // 👈 添加这个注解
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}@RestController
@RequestMapping("/api")
public class UserController {
// 自动打印参数和返回值
@PrintLog
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
return userService.getById(id);
}
// 异常时自动发送微信告警
@PrintLog(
remark = "用户创建接口",
onException = WechatAlertHandler.class
)
@PostMapping("/user")
public User createUser(@RequestBody User user) {
return userService.create(user);
}
}日志输出示例:
[loghelper.traceId:abc123def456] [UserController.getUser] remark:[]id:{}
1001
[loghelper.traceId:abc123def456] [UserController.getUser] result:{}
{"id":1001,"name":"张三","phone":"138****5678"}
自动打印方法的参数、返回值、执行时间,支持异常告警。
@PrintLog
public User getUser(Long id) {
return userService.getById(id);
}@PrintLog(
// 日志级别:TRACE, DEBUG, INFO, WARN, ERROR
level = PrintLog.Level.INFO,
// 备注信息
remark = "用户查询接口",
// 是否打印参数(默认 true)
printParameter = true,
// 是否打印返回值(默认 true)
printResult = true,
// 异常处理器(支持微信、钉钉、飞书、邮件)
onException = WechatAlertHandler.class,
// 排除的异常类型(这些异常不会触发告警)
unException = {IllegalArgumentException.class, NullPointerException.class},
// 不触发 onException 的异常类型
exceptException = {NothingException.class},
// 异常时的额外参数
exceptionParam = {"userId", "orderId"},
// 使用 SpEL 表达式提取异常值
exceptionValue = "#user.id"
)
public User createUser(User user) {
return userService.create(user);
}| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
level |
Level | INFO | 日志级别 |
remark |
String | "" | 备注信息,会显示在日志中 |
printParameter |
boolean | true | 是否打印方法参数 |
printResult |
boolean | true | 是否打印返回值 |
onException |
Class | DefaultOnExceptionHandler | 异常处理器 |
unException |
Class[] | {} | 排除的异常类型 |
exceptException |
Class[] | {NothingException} | 不触发 onException 的异常 |
exceptionParam |
String[] | {} | 异常时的参数 |
exceptionValue |
String | "" | SpEL 表达式,提取异常值 |
2️⃣ @Hidden - 字段脱敏
自动对敏感字段进行脱敏处理,支持多种脱敏策略。
public class User {
private Long id;
private String name;
// 手机号脱敏:138****5678
@Hidden(type = HiddenType.MOBILE)
private String phone;
// 身份证脱敏:110***********1234
@Hidden(type = HiddenType.ID_CARD)
private String idCard;
// 邮箱脱敏:abc***@example.com
@Hidden(type = HiddenType.EMAIL)
private String email;
// 密码完全隐藏:******
@Hidden(type = HiddenType.PASSWORD)
private String password;
// 自定义脱敏:保留前3后4位
@Hidden(type = HiddenType.CUSTOM, prefixLength = 3, suffixLength = 4)
private String bankCard;
}| 类型 | 说明 | 示例 |
|---|---|---|
MOBILE |
手机号:保留前3后4位 | 138****5678 |
ID_CARD |
身份证:保留前3后4位 | 110***********1234 |
EMAIL |
邮箱:保留前3位和域名 | abc***@example.com |
PASSWORD |
密码:完全隐藏 | ****** |
NAME |
姓名:保留姓氏 | 张** |
ADDRESS |
地址:保留前6位 | 北京市朝阳区****** |
BANK_CARD |
银行卡:保留前4后4位 | 6222****1234 |
CUSTOM |
自定义:指定保留位数 | 可配置 |
支持多种告警渠道:微信、钉钉、飞书、邮件。
配置:
spring:
loghelper:
alert:
package-prefix: com.example,com.myapp
wechat:
webhook: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY使用:
@PrintLog(onException = WechatAlertHandler.class)
public void processOrder(Order order) {
// 业务逻辑
}告警消息示例:
### processOrder exception alert
> {"orderId": "12345", "amount": 99.99}
**exception type:** java.lang.RuntimeException
**exception traceId:** abc123def456
**exception message:** 库存不足
**stack trace:**
- com.example.service.OrderService.processOrder(OrderService.java:42)
- com.example.controller.OrderController.createOrder(OrderController.java:28)配置:
spring:
loghelper:
alert:
package-prefix: com.example
dingtalk:
webhook: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
secret: YOUR_SECRET # 可选,加签密钥使用:
@PrintLog(onException = DingtalkAlertHandler.class)
public void processPayment(Payment payment) {
// 业务逻辑
}配置:
spring:
loghelper:
alert:
package-prefix: com.example
feishu:
webhook: https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_TOKEN
secret: YOUR_SECRET # 可选,加签密钥使用:
@PrintLog(onException = FeishuAlertHandler.class)
public void processRefund(Refund refund) {
// 业务逻辑
}配置:
spring:
loghelper:
alert:
package-prefix: com.example
email:
host: smtp.example.com
port: 465
ssl: true
username: alert@example.com
password: your-password
from-name: System Alert
to: admin1@example.com,admin2@example.com
cc: manager@example.com使用:
@PrintLog(onException = EmailAlertHandler.class)
public void batchProcess() {
// 批处理逻辑
}public class CustomAlertHandler extends OnExceptionHandler {
@Override
public void onException(ProceedingJoinPoint point,
Exception e,
Class<? extends Exception>[] exception,
String[] exceptionParam,
Object o) {
// 自定义告警逻辑
String methodName = point.getSignature().getName();
String errorMessage = e.getMessage();
// 发送到自定义渠道
sendToCustomChannel(methodName, errorMessage, e);
}
private void sendToCustomChannel(String method, String message, Exception e) {
// 实现你的告警逻辑
}
}使用:
@PrintLog(onException = CustomAlertHandler.class)
public void yourMethod() {
// 业务逻辑
}监控方法执行时间,记录调用链,自动识别慢方法。
@Monitor
public List<Order> queryOrders(String userId) {
return orderDao.findByUserId(userId);
}@Monitor(
// 监控点名称
name = "订单查询",
// 慢方法阈值(毫秒),超过此值会告警
threshold = 500,
// 是否记录参数
recordParams = true,
// 是否记录返回值
recordResult = false
)
public List<Order> queryOrders(String userId) {
return orderDao.findByUserId(userId);
}性能监控配置:
spring:
loghelper:
performance:
enabled: true # 是否启用性能监控
threshold: 1000 # 全局慢方法阈值(毫秒)日志输出示例:
[PERFORMANCE] OrderService.queryOrders executed in 1234ms (threshold: 500ms)
[CALL_CHAIN]
└─ OrderService.queryOrders [1234ms]
├─ OrderDao.findByUserId [890ms]
└─ CacheService.get [344ms]
自动生成 HTTP 请求的 curl 命令,便于调试和问题重现。
@RestController
public class ApiController {
@PrintCurl
@PostMapping("/api/external")
public String callExternalApi(@RequestBody Request request) {
// 调用外部 API
return restTemplate.postForObject(url, request, String.class);
}
}日志输出:
curl -X POST 'https://api.example.com/v1/orders' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer xxx' \
-d '{"orderId":"12345","amount":99.99}'自动为每个请求生成唯一的 TraceId,便于日志追踪和问题排查。
spring:
loghelper:
enable-trace: true # 启用 TraceId(默认 true)[loghelper.traceId:abc123def456] [UserController.getUser] 用户查询
[loghelper.traceId:abc123def456] [UserService.getById] 从数据库查询用户
[loghelper.traceId:abc123def456] [UserDao.selectById] SQL: SELECT * FROM user WHERE id = ?
String traceId = LogHelperTraceHandler.getTraceLog();spring:
loghelper:
# 是否启用 TraceId(默认 true)
enable-trace: true
# 是否启用参数打印(默认 true)
enable-parameter-print: true
# 告警配置
alert:
# 包名前缀,用于过滤堆栈信息(多个用逗号分隔)
package-prefix: com.example,com.myapp
# 企业微信告警
wechat:
webhook: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY
# 钉钉告警
dingtalk:
webhook: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
secret: YOUR_SECRET # 可选,加签密钥
# 飞书告警
feishu:
webhook: https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_TOKEN
secret: YOUR_SECRET # 可选,加签密钥
# 邮件告警
email:
host: smtp.example.com
port: 465
ssl: true
username: alert@example.com
password: your-password
from-name: System Alert
to: admin1@example.com,admin2@example.com
cc: manager@example.com
# 性能监控配置
performance:
enabled: true # 是否启用性能监控(默认 true)
threshold: 1000 # 慢方法阈值(毫秒,默认 1000)
# 异步告警线程池配置(一般无需修改)
thread-pool:
core-pool-size: 1
max-pool-size: 1
queue-capacity: 100
thread-name-prefix: LogHelper-Async-@Service
public class UserService {
/**
* 用户注册 - 打印参数、返回值,异常时发送微信告警
*/
@PrintLog(
remark = "用户注册",
onException = WechatAlertHandler.class,
unException = {IllegalArgumentException.class} // 参数校验异常不告警
)
public User register(UserRegisterDTO dto) {
// 参数校验
if (dto.getPhone() == null) {
throw new IllegalArgumentException("手机号不能为空");
}
// 业务逻辑
User user = new User();
user.setPhone(dto.getPhone());
user.setPassword(dto.getPassword());
return userDao.insert(user);
}
/**
* 用户查询 - 性能监控
*/
@Monitor(threshold = 500)
public User getById(Long id) {
return userDao.selectById(id);
}
}@Service
public class OrderService {
/**
* 订单创建 - 多渠道告警
*/
@PrintLog(
remark = "订单创建 - 核心业务",
level = PrintLog.Level.ERROR,
onException = DingtalkAlertHandler.class
)
public Order createOrder(OrderCreateDTO dto) {
// 检查库存
if (!checkStock(dto.getProductId(), dto.getQuantity())) {
throw new BusinessException("库存不足");
}
// 创建订单
Order order = new Order();
order.setUserId(dto.getUserId());
order.setProductId(dto.getProductId());
order.setQuantity(dto.getQuantity());
return orderDao.insert(order);
}
/**
* 支付处理 - 使用 SpEL 提取异常值
*/
@PrintLog(
remark = "支付处理",
onException = FeishuAlertHandler.class,
exceptionValue = "#order.orderId",
exceptionParam = {"orderId", "amount"}
)
public void processPayment(Order order, BigDecimal amount) {
// 支付逻辑
paymentService.pay(order.getOrderId(), amount);
}
}@Data
public class User {
private Long id;
private String username;
@Hidden(type = HiddenType.MOBILE)
private String phone;
@Hidden(type = HiddenType.EMAIL)
private String email;
@Hidden(type = HiddenType.ID_CARD)
private String idCard;
@Hidden(type = HiddenType.PASSWORD)
private String password;
@Hidden(type = HiddenType.CUSTOM, prefixLength = 4, suffixLength = 4)
private String bankCard;
}打印效果:
{
"id": 1001,
"username": "zhangsan",
"phone": "138****5678",
"email": "zha***@example.com",
"idCard": "110***********1234",
"password": "******",
"bankCard": "6222****1234"
}A: 按以下步骤排查:
- 开启 DEBUG 日志:
logging:
level:
com.loghelper: DEBUG- 检查配置是否生效:
@Autowired
private LogHelperProperties properties;
@GetMapping("/test-config")
public String testConfig() {
return properties.getAlert().getWechat().getWebhook();
}-
检查异常是否被全局异常处理器拦截:
- 如果有
@RestControllerAdvice,异常可能在到达方法前就被拦截 - 确保异常在方法内部抛出
- 如果有
-
手动测试告警功能:
@GetMapping("/test-alert")
public String testAlert() {
RuntimeException e = new RuntimeException("测试告警");
WeChatAlertUtil.sendAlert("测试标题", "测试消息", e);
return "已发送";
}A:
- 打开企业微信,进入需要接收告警的群聊
- 点击右上角
···→ 群机器人 → 添加机器人 - 创建机器人,复制 Webhook 地址
- 将地址配置到
spring.loghelper.alert.wechat.webhook
A: 可以在不同的方法上使用不同的告警渠道:
// 订单服务用微信告警
@PrintLog(onException = WechatAlertHandler.class)
public void createOrder() { }
// 支付服务用钉钉告警
@PrintLog(onException = DingtalkAlertHandler.class)
public void processPayment() { }
// 批处理任务用邮件告警
@PrintLog(onException = EmailAlertHandler.class)
public void batchJob() { }A: 使用 unException 参数:
@PrintLog(
onException = WechatAlertHandler.class,
unException = {
IllegalArgumentException.class, // 参数校验异常
ValidationException.class, // 数据验证异常
NotFoundException.class // 资源未找到异常
}
)
public User createUser(User user) {
// 业务逻辑
}A:
- 日志打印采用异步方式,对性能影响很小
- JSON 序列化使用 Jackson,性能优异
- 可以通过配置关闭参数打印:
@PrintLog(printParameter = false, printResult = false)A: 不会。@Hidden 只在日志打印时生效,不影响实际的数据处理和存储。
A: 需要配合 Spring Cloud Sleuth 或手动在 HTTP 请求头中传递:
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Collections.singletonList(
(request, body, execution) -> {
String traceId = LogHelperTraceHandler.getTraceLog();
request.getHeaders().add("X-Trace-Id", traceId);
return execution.execute(request, body);
}
));
return restTemplate;
}A: 使用工具类直接调用:
// 发送告警
WeChatAlertUtil.sendAlert("标题", "消息", exception);
// 获取配置
LogHelperProperties properties = LogHelperPropertiesUtil.getProperties();
// 获取 TraceId
String traceId = LogHelperTraceHandler.getTraceLog();| LogHelper 版本 | Spring Boot 版本 | Java 版本 | 说明 |
|---|---|---|---|
| 2.1.x | 3.x | 17+ | 最新版本,推荐使用 |
| 2.0.x-java8 | 2.x | 8+ | Java 8 兼容版本 |
从 2.0.x 升级到 2.1.x:
- 升级 Spring Boot 到 3.x
- 升级 Java 到 17+
- 修改依赖版本为 2.1.1-RELEASE
- 将
javax.*包名改为jakarta.*
- 🐛 修复 WeChatAlertUtil 配置获取问题
- ✨ 优化异常告警性能
- 📖 完善文档和使用示例
- ✨ 支持 Spring Boot 3.x
- ✨ 支持 Java 17+
- ✨ 新增性能监控功能 @Monitor
- ✨ 新增调用链追踪
- 🐛 修复若干已知问题
- ✨ 新增飞书告警支持
- ✨ 优化脱敏逻辑
- 📖 完善文档
欢迎提交 Issue 和 Pull Request!
- Fork 本仓库
- 创建你的特性分支 (
git checkout -b feature/AmazingFeature) - 提交你的修改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 打开一个 Pull Request
本项目基于 MIT License 开源。
- 作者:cuitianhao
- 邮箱:hoopoo@163.com
- GitHub:https://github.com/tianhaocui/logHelper
如果这个项目对你有帮助,请给它一个 Star ⭐️
Made with ❤️ by cuitianhao