ai-engineering-init 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/skill-forced-eval.js +2 -0
- package/.claude/settings.json +3 -3
- package/.claude/skills/add-skill/SKILL.md +79 -32
- package/.claude/skills/api-development/SKILL.md +83 -377
- package/.claude/skills/architecture-design/SKILL.md +138 -632
- package/.claude/skills/backend-annotations/SKILL.md +134 -506
- package/.claude/skills/banana-image/SKILL.md +10 -3
- package/.claude/skills/brainstorm/SKILL.md +103 -535
- package/.claude/skills/bug-detective/SKILL.md +147 -1097
- package/.claude/skills/bug-detective/references/error-patterns.md +242 -0
- package/.claude/skills/code-patterns/SKILL.md +116 -426
- package/.claude/skills/code-patterns/references/leniu-code-patterns.md +87 -0
- package/.claude/skills/crud-development/SKILL.md +64 -304
- package/.claude/skills/data-permission/SKILL.md +105 -412
- package/.claude/skills/data-permission/references/custom-data-scope.md +90 -0
- package/.claude/skills/file-oss-management/SKILL.md +106 -714
- package/.claude/skills/file-oss-management/references/entities.md +105 -0
- package/.claude/skills/file-oss-management/references/service-impl.md +104 -0
- package/.claude/skills/leniu-api-development/SKILL.md +142 -626
- package/.claude/skills/leniu-api-development/references/real-examples.md +273 -0
- package/.claude/skills/leniu-architecture-design/SKILL.md +176 -391
- package/.claude/skills/leniu-backend-annotations/SKILL.md +132 -519
- package/.claude/skills/leniu-brainstorm/SKILL.md +132 -541
- package/.claude/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
- package/.claude/skills/leniu-crud-development/SKILL.md +232 -938
- package/.claude/skills/leniu-crud-development/references/templates.md +597 -0
- package/.claude/skills/leniu-customization-location/SKILL.md +410 -0
- package/.claude/skills/leniu-data-permission/SKILL.md +70 -0
- package/.claude/skills/leniu-java-entity/SKILL.md +76 -590
- package/.claude/skills/leniu-java-entity/references/templates.md +237 -0
- package/.claude/skills/leniu-java-export/SKILL.md +94 -379
- package/.claude/skills/leniu-java-logging/SKILL.md +106 -709
- package/.claude/skills/leniu-java-logging/references/data-mask.md +46 -0
- package/.claude/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
- package/.claude/skills/leniu-java-mybatis/SKILL.md +73 -446
- package/.claude/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
- package/.claude/skills/leniu-report-customization/SKILL.md +111 -365
- package/.claude/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.claude/skills/leniu-report-standard-customization/SKILL.md +111 -334
- package/.claude/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.claude/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.claude/skills/leniu-security-guard/SKILL.md +133 -347
- package/.claude/skills/mysql-debug/SKILL.md +364 -0
- package/.claude/skills/openspec-apply-change/SKILL.md +10 -1
- package/.claude/skills/openspec-archive-change/SKILL.md +9 -1
- package/.claude/skills/openspec-bulk-archive-change/SKILL.md +9 -1
- package/.claude/skills/openspec-continue-change/SKILL.md +9 -1
- package/.claude/skills/openspec-explore/SKILL.md +10 -1
- package/.claude/skills/openspec-ff-change/SKILL.md +9 -1
- package/.claude/skills/openspec-new-change/SKILL.md +9 -1
- package/.claude/skills/openspec-onboard/SKILL.md +15 -130
- package/.claude/skills/openspec-sync-specs/SKILL.md +9 -1
- package/.claude/skills/openspec-verify-change/SKILL.md +9 -1
- package/.claude/skills/performance-doctor/SKILL.md +110 -434
- package/.claude/skills/redis-cache/SKILL.md +89 -595
- package/.claude/skills/redis-cache/references/listeners.md +23 -0
- package/.claude/skills/scheduled-jobs/SKILL.md +88 -407
- package/.claude/skills/security-guard/SKILL.md +137 -532
- package/.claude/skills/security-guard/references/encrypt-config.md +103 -0
- package/.claude/skills/security-guard/references/sensitive-strategies.md +42 -0
- package/.claude/skills/sms-mail/SKILL.md +116 -574
- package/.claude/skills/sms-mail/references/mail-config.md +88 -0
- package/.claude/skills/sms-mail/references/sms-config.md +74 -0
- package/.claude/skills/social-login/SKILL.md +112 -514
- package/.claude/skills/social-login/references/provider-configs.md +118 -0
- package/.claude/skills/tenant-management/SKILL.md +129 -444
- package/.claude/skills/tenant-management/references/tenant-scenarios.md +91 -0
- package/.claude/skills/test-development/SKILL.md +86 -540
- package/.claude/skills/test-development/references/parameterized-examples.md +119 -0
- package/.claude/skills/utils-toolkit/SKILL.md +52 -305
- package/.claude/skills/utils-toolkit/references/redis-utils-api.md +56 -0
- package/.claude/skills/websocket-sse/SKILL.md +105 -550
- package/.claude/skills/workflow-engine/SKILL.md +147 -502
- package/.codex/skills/add-skill/SKILL.md +79 -32
- package/.codex/skills/api-development/SKILL.md +172 -599
- package/.codex/skills/architecture-design/SKILL.md +138 -504
- package/.codex/skills/backend-annotations/SKILL.md +134 -496
- package/.codex/skills/banana-image/SKILL.md +10 -3
- package/.codex/skills/brainstorm/SKILL.md +103 -535
- package/.codex/skills/bug-detective/SKILL.md +147 -1097
- package/.codex/skills/bug-detective/references/error-patterns.md +242 -0
- package/.codex/skills/code-patterns/SKILL.md +120 -282
- package/.codex/skills/code-patterns/references/leniu-code-patterns.md +87 -0
- package/.codex/skills/crud-development/SKILL.md +64 -292
- package/.codex/skills/data-permission/SKILL.md +108 -407
- package/.codex/skills/data-permission/references/custom-data-scope.md +90 -0
- package/.codex/skills/database-ops/SKILL.md +8 -154
- package/.codex/skills/error-handler/SKILL.md +10 -0
- package/.codex/skills/file-oss-management/SKILL.md +106 -714
- package/.codex/skills/file-oss-management/references/entities.md +105 -0
- package/.codex/skills/file-oss-management/references/service-impl.md +104 -0
- package/.codex/skills/git-workflow/SKILL.md +27 -5
- package/.codex/skills/leniu-api-development/SKILL.md +142 -626
- package/.codex/skills/leniu-api-development/references/real-examples.md +273 -0
- package/.codex/skills/leniu-architecture-design/SKILL.md +176 -391
- package/.codex/skills/leniu-backend-annotations/SKILL.md +132 -519
- package/.codex/skills/leniu-brainstorm/SKILL.md +132 -541
- package/.codex/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
- package/.codex/skills/leniu-crud-development/SKILL.md +232 -938
- package/.codex/skills/leniu-crud-development/references/templates.md +597 -0
- package/.codex/skills/leniu-customization-location/SKILL.md +410 -0
- package/.codex/skills/leniu-data-permission/SKILL.md +70 -0
- package/.codex/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.codex/skills/leniu-java-entity/SKILL.md +76 -590
- package/.codex/skills/leniu-java-entity/references/templates.md +237 -0
- package/.codex/skills/leniu-java-export/SKILL.md +94 -379
- package/.codex/skills/leniu-java-logging/SKILL.md +106 -709
- package/.codex/skills/leniu-java-logging/references/data-mask.md +46 -0
- package/.codex/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
- package/.codex/skills/leniu-java-mybatis/SKILL.md +73 -446
- package/.codex/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
- package/.codex/skills/leniu-report-customization/SKILL.md +111 -365
- package/.codex/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.codex/skills/leniu-report-standard-customization/SKILL.md +111 -334
- package/.codex/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.codex/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.codex/skills/leniu-security-guard/SKILL.md +133 -347
- package/.codex/skills/mysql-debug/SKILL.md +364 -0
- package/.codex/skills/openspec-apply-change/SKILL.md +10 -1
- package/.codex/skills/openspec-archive-change/SKILL.md +9 -1
- package/.codex/skills/openspec-bulk-archive-change/SKILL.md +9 -1
- package/.codex/skills/openspec-continue-change/SKILL.md +9 -1
- package/.codex/skills/openspec-explore/SKILL.md +10 -1
- package/.codex/skills/openspec-ff-change/SKILL.md +9 -1
- package/.codex/skills/openspec-new-change/SKILL.md +9 -1
- package/.codex/skills/openspec-onboard/SKILL.md +15 -130
- package/.codex/skills/openspec-sync-specs/SKILL.md +9 -1
- package/.codex/skills/openspec-verify-change/SKILL.md +9 -1
- package/.codex/skills/performance-doctor/SKILL.md +110 -434
- package/.codex/skills/project-navigator/SKILL.md +20 -1
- package/.codex/skills/redis-cache/SKILL.md +93 -589
- package/.codex/skills/redis-cache/references/listeners.md +23 -0
- package/.codex/skills/scheduled-jobs/SKILL.md +88 -407
- package/.codex/skills/security-guard/SKILL.md +141 -527
- package/.codex/skills/security-guard/references/encrypt-config.md +103 -0
- package/.codex/skills/security-guard/references/sensitive-strategies.md +42 -0
- package/.codex/skills/sms-mail/SKILL.md +116 -574
- package/.codex/skills/sms-mail/references/mail-config.md +88 -0
- package/.codex/skills/sms-mail/references/sms-config.md +74 -0
- package/.codex/skills/social-login/SKILL.md +112 -514
- package/.codex/skills/social-login/references/provider-configs.md +118 -0
- package/.codex/skills/store-pc/SKILL.md +258 -383
- package/.codex/skills/tenant-management/SKILL.md +129 -444
- package/.codex/skills/tenant-management/references/tenant-scenarios.md +91 -0
- package/.codex/skills/test-development/SKILL.md +86 -540
- package/.codex/skills/test-development/references/parameterized-examples.md +119 -0
- package/.codex/skills/ui-pc/SKILL.md +350 -387
- package/.codex/skills/utils-toolkit/SKILL.md +52 -283
- package/.codex/skills/utils-toolkit/references/redis-utils-api.md +56 -0
- package/.codex/skills/websocket-sse/SKILL.md +105 -550
- package/.codex/skills/workflow-engine/SKILL.md +147 -502
- package/.cursor/hooks.json +3 -3
- package/.cursor/skills/add-skill/SKILL.md +79 -32
- package/.cursor/skills/api-development/SKILL.md +83 -377
- package/.cursor/skills/architecture-design/SKILL.md +138 -632
- package/.cursor/skills/backend-annotations/SKILL.md +134 -506
- package/.cursor/skills/banana-image/SKILL.md +10 -3
- package/.cursor/skills/brainstorm/SKILL.md +103 -535
- package/.cursor/skills/bug-detective/SKILL.md +147 -1097
- package/.cursor/skills/bug-detective/references/error-patterns.md +242 -0
- package/.cursor/skills/code-patterns/SKILL.md +116 -426
- package/.cursor/skills/code-patterns/references/leniu-code-patterns.md +87 -0
- package/.cursor/skills/crud-development/SKILL.md +64 -304
- package/.cursor/skills/data-permission/SKILL.md +105 -412
- package/.cursor/skills/data-permission/references/custom-data-scope.md +90 -0
- package/.cursor/skills/file-oss-management/SKILL.md +106 -714
- package/.cursor/skills/file-oss-management/references/entities.md +105 -0
- package/.cursor/skills/file-oss-management/references/service-impl.md +104 -0
- package/.cursor/skills/git-workflow/SKILL.md +27 -5
- package/.cursor/skills/leniu-api-development/SKILL.md +142 -626
- package/.cursor/skills/leniu-api-development/references/real-examples.md +273 -0
- package/.cursor/skills/leniu-architecture-design/SKILL.md +176 -391
- package/.cursor/skills/leniu-backend-annotations/SKILL.md +132 -519
- package/.cursor/skills/leniu-brainstorm/SKILL.md +132 -541
- package/.cursor/skills/leniu-brainstorm/references/business-scenarios.md +162 -0
- package/.cursor/skills/leniu-crud-development/SKILL.md +232 -938
- package/.cursor/skills/leniu-crud-development/references/templates.md +597 -0
- package/.cursor/skills/leniu-customization-location/SKILL.md +410 -0
- package/.cursor/skills/leniu-data-permission/SKILL.md +70 -0
- package/.cursor/skills/leniu-java-code-style/SKILL.md +510 -0
- package/.cursor/skills/leniu-java-entity/SKILL.md +76 -590
- package/.cursor/skills/leniu-java-entity/references/templates.md +237 -0
- package/.cursor/skills/leniu-java-export/SKILL.md +94 -379
- package/.cursor/skills/leniu-java-logging/SKILL.md +106 -709
- package/.cursor/skills/leniu-java-logging/references/data-mask.md +46 -0
- package/.cursor/skills/leniu-java-logging/references/logging-scenarios.md +113 -0
- package/.cursor/skills/leniu-java-mybatis/SKILL.md +73 -446
- package/.cursor/skills/leniu-java-mybatis/references/report-mapper.md +88 -0
- package/.cursor/skills/leniu-report-customization/SKILL.md +111 -365
- package/.cursor/skills/leniu-report-customization/references/table-fields.md +93 -0
- package/.cursor/skills/leniu-report-standard-customization/SKILL.md +111 -334
- package/.cursor/skills/leniu-report-standard-customization/references/analysis-module.md +64 -0
- package/.cursor/skills/leniu-report-standard-customization/references/table-fields.md +113 -0
- package/.cursor/skills/leniu-security-guard/SKILL.md +133 -347
- package/.cursor/skills/mysql-debug/SKILL.md +364 -0
- package/.cursor/skills/openspec-apply-change/SKILL.md +10 -1
- package/.cursor/skills/openspec-archive-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-bulk-archive-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-continue-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-explore/SKILL.md +10 -1
- package/.cursor/skills/openspec-ff-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-new-change/SKILL.md +9 -1
- package/.cursor/skills/openspec-onboard/SKILL.md +15 -130
- package/.cursor/skills/openspec-sync-specs/SKILL.md +9 -1
- package/.cursor/skills/openspec-verify-change/SKILL.md +9 -1
- package/.cursor/skills/performance-doctor/SKILL.md +110 -434
- package/.cursor/skills/redis-cache/SKILL.md +89 -595
- package/.cursor/skills/redis-cache/references/listeners.md +23 -0
- package/.cursor/skills/scheduled-jobs/SKILL.md +88 -407
- package/.cursor/skills/security-guard/SKILL.md +137 -532
- package/.cursor/skills/security-guard/references/encrypt-config.md +103 -0
- package/.cursor/skills/security-guard/references/sensitive-strategies.md +42 -0
- package/.cursor/skills/sms-mail/SKILL.md +116 -574
- package/.cursor/skills/sms-mail/references/mail-config.md +88 -0
- package/.cursor/skills/sms-mail/references/sms-config.md +74 -0
- package/.cursor/skills/social-login/SKILL.md +112 -514
- package/.cursor/skills/social-login/references/provider-configs.md +118 -0
- package/.cursor/skills/tenant-management/SKILL.md +129 -444
- package/.cursor/skills/tenant-management/references/tenant-scenarios.md +91 -0
- package/.cursor/skills/test-development/SKILL.md +86 -540
- package/.cursor/skills/test-development/references/parameterized-examples.md +119 -0
- package/.cursor/skills/utils-toolkit/SKILL.md +52 -305
- package/.cursor/skills/utils-toolkit/references/redis-utils-api.md +56 -0
- package/.cursor/skills/websocket-sse/SKILL.md +105 -550
- package/.cursor/skills/workflow-engine/SKILL.md +147 -502
- package/package.json +1 -1
|
@@ -1,488 +1,106 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: leniu-java-logging
|
|
3
3
|
description: |
|
|
4
|
-
leniu-tengyun-core / leniu-yunshitang 项目日志规范。当编写日志代码时使用此 skill
|
|
4
|
+
leniu-tengyun-core / leniu-yunshitang 项目日志规范。当编写日志代码时使用此 skill。
|
|
5
5
|
|
|
6
6
|
触发场景:
|
|
7
7
|
- 编写日志记录代码(@Slf4j、log.info/error/debug)
|
|
8
|
-
- 配置日志级别和输出格式
|
|
9
8
|
- 记录异常日志(含完整堆栈)
|
|
10
|
-
-
|
|
11
|
-
-
|
|
9
|
+
- 业务关键路径日志埋点(订单/支付/MQ/定时任务)
|
|
10
|
+
- 配置日志级别和 Logback
|
|
11
|
+
- 敏感信息脱敏处理
|
|
12
12
|
|
|
13
|
-
触发词:日志、@Slf4j、log.info、log.error、log.debug、日志级别、logback
|
|
13
|
+
触发词:日志、@Slf4j、log.info、log.error、log.debug、日志级别、logback、日志格式、日志脱敏、异常日志
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
# leniu
|
|
16
|
+
# leniu 日志规范
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## 基本规则
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
- 使用 `@Slf4j`(Lombok),禁止直接用 Log4j/Logback API
|
|
21
|
+
- 使用 `{}` 占位符,禁止字符串拼接
|
|
22
|
+
- 异常对象作为 `log.error` 的**最后一个参数**(自动打印堆栈)
|
|
23
|
+
- 日志用**中文**,用 `【模块名】` 前缀便于检索
|
|
24
|
+
- 禁止记录密码、完整手机号等敏感信息
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## 日志级别选择
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
| 级别 | 场景 | 示例 |
|
|
29
|
+
|------|------|------|
|
|
30
|
+
| ERROR | 系统错误、需立即处理 | 数据库异常、外部服务失败 |
|
|
31
|
+
| WARN | 非预期但可处理 | 配置缺失用默认值、数据不存在 |
|
|
32
|
+
| INFO | 关键业务节点 | 订单创建/支付成功、定时任务完成 |
|
|
33
|
+
| DEBUG | 开发调试(生产不输出) | 查询参数、中间结果 |
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
import lombok.extern.slf4j.Slf4j;
|
|
30
|
-
|
|
31
|
-
@Slf4j
|
|
32
|
-
@Service
|
|
33
|
-
public class XxxService {
|
|
34
|
-
|
|
35
|
-
public void doSomething() {
|
|
36
|
-
log.info("开始处理");
|
|
37
|
-
log.debug("详细信息");
|
|
38
|
-
log.warn("警告信息");
|
|
39
|
-
log.error("错误信息");
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### 不要直接使用日志实现
|
|
45
|
-
|
|
46
|
-
```java
|
|
47
|
-
// ❌ 错误:直接使用 Log4j/Logback
|
|
48
|
-
import org.apache.log4j.Logger;
|
|
49
|
-
Logger logger = Logger.getLogger(XxxService.class);
|
|
50
|
-
|
|
51
|
-
// ✅ 正确:使用 SLF4J
|
|
52
|
-
import lombok.extern.slf4j.Slf4j;
|
|
53
|
-
@Slf4j
|
|
54
|
-
public class XxxService { }
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### 日志配置文件
|
|
58
|
-
|
|
59
|
-
项目使用 Logback 日志框架,配置文件位于:
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
core-starter/src/main/resources/logback-spring.xml
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
```xml
|
|
66
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
67
|
-
<configuration>
|
|
68
|
-
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
|
69
|
-
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
|
70
|
-
<include resource="org/springframework/boot/logging/logback/file-appender.xml"/>
|
|
71
|
-
|
|
72
|
-
<springProfile name="!no_log_console">
|
|
73
|
-
<root level="INFO">
|
|
74
|
-
<appender-ref ref="CONSOLE"/>
|
|
75
|
-
</root>
|
|
76
|
-
</springProfile>
|
|
77
|
-
|
|
78
|
-
<springProfile name="!no_log_file">
|
|
79
|
-
<root level="INFO">
|
|
80
|
-
<appender-ref ref="FILE"/>
|
|
81
|
-
</root>
|
|
82
|
-
</springProfile>
|
|
83
|
-
</configuration>
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Profile 控制
|
|
87
|
-
|
|
88
|
-
| Profile | 作用 |
|
|
89
|
-
|---------|------|
|
|
90
|
-
| `no_log_console` | 不输出到控制台 |
|
|
91
|
-
| `no_log_file` | 不输出到文件 |
|
|
92
|
-
|
|
93
|
-
## 日志级别
|
|
94
|
-
|
|
95
|
-
### ERROR - 错误日志
|
|
96
|
-
|
|
97
|
-
用于记录系统错误、异常情况,需要立即关注和处理。
|
|
35
|
+
## 模块标识格式
|
|
98
36
|
|
|
99
37
|
```java
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@Service
|
|
105
|
-
public class OrderService {
|
|
106
|
-
|
|
107
|
-
public void processOrder(Long orderId) {
|
|
108
|
-
try {
|
|
109
|
-
// 业务逻辑
|
|
110
|
-
doProcess(orderId);
|
|
111
|
-
} catch (Exception e) {
|
|
112
|
-
log.error("订单处理失败, orderId:{}", orderId, e);
|
|
113
|
-
throw new LeException("订单处理失败");
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 业务异常
|
|
118
|
-
public void validateOrder(Order order) {
|
|
119
|
-
if (ObjectUtil.isNull(order)) {
|
|
120
|
-
log.error("订单不存在, orderId:{}", orderId);
|
|
121
|
-
throw new LeException("订单不存在");
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// 业务数据异常
|
|
126
|
-
public void checkGoods(List<String> missingNames) {
|
|
127
|
-
log.error("以下{}个货品在系统中不存在: {}", missingNames.size(), missingNames);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### WARN - 警告日志
|
|
133
|
-
|
|
134
|
-
用于记录非预期但可处理的情况,不影响系统运行但需要关注。
|
|
135
|
-
|
|
136
|
-
```java
|
|
137
|
-
import cn.hutool.core.util.ObjectUtil;
|
|
138
|
-
import cn.hutool.core.util.StrUtil;
|
|
139
|
-
import lombok.extern.slf4j.Slf4j;
|
|
140
|
-
|
|
141
|
-
@Slf4j
|
|
142
|
-
@Service
|
|
143
|
-
public class ConfigService {
|
|
144
|
-
|
|
145
|
-
// 数据不存在
|
|
146
|
-
public Config getConfig(String key) {
|
|
147
|
-
Config config = configMapper.selectById(key);
|
|
148
|
-
if (ObjectUtil.isNull(config)) {
|
|
149
|
-
log.warn("配置不存在, key:{}", key);
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
return config;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// 配置缺失
|
|
156
|
-
public String getConfigWithDefault(String key, String defaultValue) {
|
|
157
|
-
String value = getConfigValue(key);
|
|
158
|
-
if (StrUtil.isBlank(value)) {
|
|
159
|
-
log.warn("配置项缺失, key:{}, 使用默认值", key);
|
|
160
|
-
return defaultValue;
|
|
161
|
-
}
|
|
162
|
-
return value;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### INFO - 信息日志
|
|
168
|
-
|
|
169
|
-
用于记录关键业务节点、重要操作,便于追踪业务流程。
|
|
170
|
-
|
|
171
|
-
```java
|
|
172
|
-
import lombok.extern.slf4j.Slf4j;
|
|
173
|
-
|
|
174
|
-
@Slf4j
|
|
175
|
-
@Service
|
|
176
|
-
public class OrderService {
|
|
177
|
-
|
|
178
|
-
@Transactional(rollbackFor = Exception.class)
|
|
179
|
-
public Long createOrder(OrderParam param) {
|
|
180
|
-
log.info("【订单】开始创建订单, userId:{}, productId:{}",
|
|
181
|
-
param.getUserId(), param.getProductId());
|
|
182
|
-
|
|
183
|
-
// 业务逻辑
|
|
184
|
-
Order order = buildOrder(param);
|
|
185
|
-
orderMapper.insert(order);
|
|
186
|
-
|
|
187
|
-
log.info("【订单】订单创建成功, orderId:{}", order.getId());
|
|
188
|
-
return order.getId();
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
public void payOrder(Long orderId, Long amount) {
|
|
192
|
-
log.info("【支付】开始支付, orderId:{}, amount:{}", orderId, amount);
|
|
193
|
-
|
|
194
|
-
// 支付逻辑
|
|
195
|
-
PaymentResult result = paymentService.pay(orderId, amount);
|
|
196
|
-
|
|
197
|
-
log.info("【支付】支付成功, orderId:{}, transactionId:{}",
|
|
198
|
-
orderId, result.getTransactionId());
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### DEBUG - 调试日志
|
|
204
|
-
|
|
205
|
-
用于开发调试,记录详细的执行过程和数据。生产环境不输出。
|
|
206
|
-
|
|
207
|
-
```java
|
|
208
|
-
import lombok.extern.slf4j.Slf4j;
|
|
209
|
-
|
|
210
|
-
@Slf4j
|
|
211
|
-
@Service
|
|
212
|
-
public class OrderService {
|
|
213
|
-
|
|
214
|
-
public List<OrderVO> queryList(OrderQueryParam param) {
|
|
215
|
-
log.debug("查询参数: {}", param);
|
|
216
|
-
|
|
217
|
-
// 执行查询
|
|
218
|
-
List<OrderEntity> entities = orderMapper.selectList(buildWrapper(param));
|
|
219
|
-
|
|
220
|
-
log.debug("查询结果数量: {}", entities.size());
|
|
221
|
-
log.debug("查询结果: {}", entities);
|
|
222
|
-
|
|
223
|
-
return BeanUtil.copyToList(entities, OrderVO.class);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
## 日志输出格式
|
|
229
|
-
|
|
230
|
-
### 使用占位符
|
|
231
|
-
|
|
232
|
-
```java
|
|
233
|
-
import lombok.extern.slf4j.Slf4j;
|
|
234
|
-
|
|
235
|
-
@Slf4j
|
|
236
|
-
@Service
|
|
237
|
-
public class UserService {
|
|
238
|
-
|
|
239
|
-
// ✅ 正确:使用占位符
|
|
240
|
-
public void login(String username, String password) {
|
|
241
|
-
log.info("用户登录, userId:{}, userName:{}", userId, userName);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// ❌ 错误:字符串拼接
|
|
245
|
-
public void loginWrong(String username, String password) {
|
|
246
|
-
log.info("用户登录, userId:" + userId + ", userName:" + userName);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### 条件输出
|
|
252
|
-
|
|
253
|
-
```java
|
|
254
|
-
import lombok.extern.slf4j.Slf4j;
|
|
255
|
-
|
|
256
|
-
@Slf4j
|
|
257
|
-
@Service
|
|
258
|
-
public class QueryService {
|
|
259
|
-
|
|
260
|
-
// ✅ 对于 debug/trace 级别,使用条件输出
|
|
261
|
-
public void queryWithDebug(Data param) {
|
|
262
|
-
if (log.isDebugEnabled()) {
|
|
263
|
-
log.debug("详细数据: {}", expensiveOperation());
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// ✅ 或使用 Lambda 形式(推荐)
|
|
268
|
-
public void queryWithLambda(Data param) {
|
|
269
|
-
log.debug("详细数据: {}", () -> expensiveOperation());
|
|
270
|
-
}
|
|
271
|
-
}
|
|
38
|
+
log.info("【订单】开始创建订单, userId:{}", userId);
|
|
39
|
+
log.info("【支付】支付成功, orderId:{}, transactionId:{}", orderId, txId);
|
|
40
|
+
log.info("【库存】扣减库存, productId:{}, quantity:{}", productId, qty);
|
|
41
|
+
log.error("【远程调用】用户服务调用失败, userId:{}", userId, e);
|
|
272
42
|
```
|
|
273
43
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
使用 `【模块名】` 标识,便于日志检索:
|
|
277
|
-
|
|
44
|
+
MQ 消费用方括号:
|
|
278
45
|
```java
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
@Service
|
|
283
|
-
public class OrderService {
|
|
284
|
-
|
|
285
|
-
public void createOrder(OrderParam param) {
|
|
286
|
-
log.info("【订单】开始创建订单, userId:{}", param.getUserId());
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
@Slf4j
|
|
291
|
-
@Service
|
|
292
|
-
public class PaymentService {
|
|
293
|
-
|
|
294
|
-
public void pay(Long orderId) {
|
|
295
|
-
log.info("【支付】开始支付, orderId:{}", orderId);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
@Slf4j
|
|
300
|
-
@Service
|
|
301
|
-
public class InventoryService {
|
|
302
|
-
|
|
303
|
-
public void reduceStock(Long productId, Integer quantity) {
|
|
304
|
-
log.info("【库存】扣减库存, productId:{}, quantity:{}", productId, quantity);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
46
|
+
log.info("[xxx事件]MQ消费:开始");
|
|
47
|
+
log.info("[xxx事件]MQ消费:消息消费完成");
|
|
48
|
+
log.error("[xxx事件]MQ消费:处理异常", e);
|
|
307
49
|
```
|
|
308
50
|
|
|
309
|
-
##
|
|
310
|
-
|
|
311
|
-
### 记录异常堆栈
|
|
51
|
+
## 异常日志(最重要)
|
|
312
52
|
|
|
313
53
|
```java
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
@Slf4j
|
|
317
|
-
@Service
|
|
318
|
-
public class OrderService {
|
|
319
|
-
|
|
320
|
-
public void processOrder(Long orderId) {
|
|
321
|
-
try {
|
|
322
|
-
doProcess(orderId);
|
|
323
|
-
} catch (Exception e) {
|
|
324
|
-
// ✅ 正确:异常作为最后一个参数
|
|
325
|
-
log.error("订单处理失败, orderId:{}", orderId, e);
|
|
326
|
-
throw new LeException("订单处理失败");
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
```java
|
|
333
|
-
// ❌ 错误:只记录异常消息,丢失堆栈信息
|
|
54
|
+
// ✅ 正确:异常 e 作为最后参数,保留完整堆栈
|
|
334
55
|
try {
|
|
335
|
-
|
|
56
|
+
doProcess(orderId);
|
|
336
57
|
} catch (Exception e) {
|
|
337
|
-
log.error("
|
|
58
|
+
log.error("订单处理失败, orderId:{}", orderId, e);
|
|
59
|
+
throw new LeException("订单处理失败");
|
|
338
60
|
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### 记录案发现场
|
|
342
|
-
|
|
343
|
-
```java
|
|
344
|
-
import lombok.extern.slf4j.Slf4j;
|
|
345
|
-
|
|
346
|
-
@Slf4j
|
|
347
|
-
@Service
|
|
348
|
-
public class OrderService {
|
|
349
|
-
|
|
350
|
-
public void updateOrderStatus(Long orderId, Integer status) {
|
|
351
|
-
try {
|
|
352
|
-
// 业务逻辑
|
|
353
|
-
updateStatus(orderId, status);
|
|
354
|
-
} catch (Exception e) {
|
|
355
|
-
// ✅ 记录关键参数和上下文
|
|
356
|
-
log.error("订单状态更新失败, orderId:{}, oldStatus:{}, newStatus:{}",
|
|
357
|
-
orderId, oldStatus, status, e);
|
|
358
|
-
throw new LeException("订单状态更新失败");
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
61
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
@Slf4j
|
|
372
|
-
@Service
|
|
373
|
-
public class UserService {
|
|
374
|
-
|
|
375
|
-
// ❌ 错误:记录密码
|
|
376
|
-
public void login(String username, String password) {
|
|
377
|
-
log.info("用户登录, username:{}, password:{}", username, password);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// ✅ 正确:不记录密码
|
|
381
|
-
public void login(String username, String password) {
|
|
382
|
-
log.info("用户登录, username:{}", username);
|
|
383
|
-
// 验证密码
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// ❌ 错误:记录完整手机号
|
|
387
|
-
public void sendSms(String mobile, String code) {
|
|
388
|
-
log.info("发送验证码, mobile:{}, code:{}", mobile, code);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// ✅ 正确:脱敏处理
|
|
392
|
-
public void sendSms(String mobile, String code) {
|
|
393
|
-
log.info("发送验证码, mobile:{}", maskMobile(mobile));
|
|
394
|
-
// 发送短信
|
|
395
|
-
}
|
|
62
|
+
// ✅ 记录案发现场(关键参数 + 上下文)
|
|
63
|
+
try {
|
|
64
|
+
updateStatus(orderId, status);
|
|
65
|
+
} catch (Exception e) {
|
|
66
|
+
log.error("订单状态更新失败, orderId:{}, oldStatus:{}, newStatus:{}",
|
|
67
|
+
orderId, oldStatus, status, e);
|
|
68
|
+
throw new LeException("订单状态更新失败");
|
|
396
69
|
}
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### 脱敏工具方法
|
|
400
|
-
|
|
401
|
-
```java
|
|
402
|
-
public class DataMaskUtil {
|
|
403
|
-
|
|
404
|
-
// 手机号脱敏:138****1234
|
|
405
|
-
public static String maskMobile(String mobile) {
|
|
406
|
-
if (StrUtil.isBlank(mobile) || mobile.length() != 11) {
|
|
407
|
-
return mobile;
|
|
408
|
-
}
|
|
409
|
-
return mobile.substring(0, 3) + "****" + mobile.substring(7);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// 身份证脱敏:1234**********5678
|
|
413
|
-
public static String maskIdCard(String idCard) {
|
|
414
|
-
if (StrUtil.isBlank(idCard) || idCard.length() < 8) {
|
|
415
|
-
return idCard;
|
|
416
|
-
}
|
|
417
|
-
return idCard.substring(0, 4) + "**********" + idCard.substring(idCard.length() - 4);
|
|
418
|
-
}
|
|
419
70
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (StrUtil.isBlank(bankCard) || bankCard.length() < 8) {
|
|
423
|
-
return bankCard;
|
|
424
|
-
}
|
|
425
|
-
return bankCard.substring(0, 4) + "************" + bankCard.substring(bankCard.length() - 4);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
71
|
+
// ❌ 错误:只记录 message,丢失堆栈
|
|
72
|
+
log.error("处理失败:{}", e.getMessage());
|
|
428
73
|
```
|
|
429
74
|
|
|
430
|
-
##
|
|
75
|
+
## 各层日志规范
|
|
431
76
|
|
|
432
|
-
###
|
|
77
|
+
### Business/Service 层(关键业务)
|
|
433
78
|
|
|
434
79
|
```java
|
|
435
|
-
import lombok.extern.slf4j.Slf4j;
|
|
436
|
-
|
|
437
80
|
@Slf4j
|
|
438
81
|
@Service
|
|
439
82
|
public class OrderService {
|
|
440
83
|
|
|
441
84
|
@Transactional(rollbackFor = Exception.class)
|
|
442
|
-
public Long
|
|
85
|
+
public Long create(OrderParam param) {
|
|
443
86
|
log.info("【订单】开始创建订单, userId:{}, productId:{}",
|
|
444
87
|
param.getUserId(), param.getProductId());
|
|
445
|
-
|
|
446
|
-
// 业务逻辑
|
|
447
|
-
Order order = buildOrder(param);
|
|
448
|
-
orderMapper.insert(order);
|
|
449
|
-
|
|
450
|
-
log.info("【订单】订单创建成功, orderId:{}", order.getId());
|
|
451
|
-
return order.getId();
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
### 2. 外部调用
|
|
457
|
-
|
|
458
|
-
```java
|
|
459
|
-
import lombok.extern.slf4j.Slf4j;
|
|
460
|
-
|
|
461
|
-
@Slf4j
|
|
462
|
-
@Service
|
|
463
|
-
public class RemoteUserService {
|
|
464
|
-
|
|
465
|
-
public UserDTO getUserFromRemote(Long userId) {
|
|
466
|
-
log.info("【远程调用】开始调用用户服务, userId:{}", userId);
|
|
467
|
-
|
|
468
88
|
try {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
89
|
+
Order order = buildOrder(param);
|
|
90
|
+
orderMapper.insert(order);
|
|
91
|
+
log.info("【订单】订单创建成功, orderId:{}", order.getId());
|
|
92
|
+
return order.getId();
|
|
472
93
|
} catch (Exception e) {
|
|
473
|
-
log.error("
|
|
474
|
-
throw new LeException("
|
|
94
|
+
log.error("【订单】订单创建失败, param:{}", param, e);
|
|
95
|
+
throw new LeException("订单创建失败");
|
|
475
96
|
}
|
|
476
97
|
}
|
|
477
98
|
}
|
|
478
99
|
```
|
|
479
100
|
|
|
480
|
-
###
|
|
101
|
+
### 定时任务
|
|
481
102
|
|
|
482
103
|
```java
|
|
483
|
-
import com.xxl.job.core.handler.annotation.XxlJob;
|
|
484
|
-
import lombok.extern.slf4j.Slf4j;
|
|
485
|
-
|
|
486
104
|
@Slf4j
|
|
487
105
|
@Component
|
|
488
106
|
public class DataSyncJob {
|
|
@@ -490,7 +108,6 @@ public class DataSyncJob {
|
|
|
490
108
|
@XxlJob("syncDataJob")
|
|
491
109
|
public void syncData() {
|
|
492
110
|
log.info("【定时任务】开始同步数据");
|
|
493
|
-
|
|
494
111
|
try {
|
|
495
112
|
int count = doSync();
|
|
496
113
|
log.info("【定时任务】数据同步完成, 同步数量:{}", count);
|
|
@@ -501,14 +118,9 @@ public class DataSyncJob {
|
|
|
501
118
|
}
|
|
502
119
|
```
|
|
503
120
|
|
|
504
|
-
###
|
|
121
|
+
### MQ 消费者
|
|
505
122
|
|
|
506
123
|
```java
|
|
507
|
-
import lombok.extern.slf4j.Slf4j;
|
|
508
|
-
import net.xnzn.framework.mq.MQListener;
|
|
509
|
-
import net.xnzn.framework.mq.MQMessageListener;
|
|
510
|
-
|
|
511
|
-
// ✅ 正确:leniu 项目 MQ 消费者用 @MQMessageListener + implements MQListener
|
|
512
124
|
@Slf4j
|
|
513
125
|
@MQMessageListener(group = "order-order-v3-xxx", topic = "order", tag = "order-v3-xxx")
|
|
514
126
|
public class OrderMqListenerXxx implements MQListener<MqPayload<String>> {
|
|
@@ -516,317 +128,102 @@ public class OrderMqListenerXxx implements MQListener<MqPayload<String>> {
|
|
|
516
128
|
@Override
|
|
517
129
|
public void onMessage(MqPayload<String> payload) {
|
|
518
130
|
log.info("[xxx事件]MQ消费:开始");
|
|
519
|
-
// 委托给 Handler 处理
|
|
520
131
|
orderMqHandler.handleMessage(payload, OrderXxxPO.class, OrderMqHandler::handleXxx);
|
|
521
132
|
}
|
|
522
133
|
}
|
|
523
|
-
|
|
524
|
-
// Handler 中的日志规范
|
|
525
|
-
public void handleXxx(OrderXxxPO payload) {
|
|
526
|
-
try {
|
|
527
|
-
log.info("[xxx事件]MQ消费:开始");
|
|
528
|
-
processXxx(payload);
|
|
529
|
-
log.info("[xxx事件]MQ消费:消息消费完成");
|
|
530
|
-
} catch (Exception e) {
|
|
531
|
-
log.error("[xxx事件]MQ消费:处理异常", e);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
134
|
```
|
|
535
135
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
### 1. 避免大对象序列化
|
|
136
|
+
### 外部调用
|
|
539
137
|
|
|
540
138
|
```java
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
log.info("查询结果: {}", BeanUtil.beanToString(orders)); // 可能产生大量日志
|
|
551
|
-
return orders;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// ✅ 推荐:只记录关键信息
|
|
555
|
-
public List<Order> queryOrders() {
|
|
556
|
-
List<Order> orders = orderMapper.selectList(null);
|
|
557
|
-
log.info("查询结果数量: {}", orders.size());
|
|
558
|
-
return orders;
|
|
139
|
+
public UserDTO getUserFromRemote(Long userId) {
|
|
140
|
+
log.info("【远程调用】开始调用用户服务, userId:{}", userId);
|
|
141
|
+
try {
|
|
142
|
+
UserDTO user = remoteUserService.getUser(userId);
|
|
143
|
+
log.info("【远程调用】用户服务调用成功, userId:{}", userId);
|
|
144
|
+
return user;
|
|
145
|
+
} catch (Exception e) {
|
|
146
|
+
log.error("【远程调用】用户服务调用失败, userId:{}", userId, e);
|
|
147
|
+
throw new LeException("用户信息获取失败");
|
|
559
148
|
}
|
|
560
149
|
}
|
|
561
150
|
```
|
|
562
151
|
|
|
563
|
-
|
|
152
|
+
## 性能规则
|
|
564
153
|
|
|
565
154
|
```java
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
public class DebugService {
|
|
155
|
+
// ✅ debug 级别用条件判断或 Lambda(避免无用计算)
|
|
156
|
+
if (log.isDebugEnabled()) {
|
|
157
|
+
log.debug("详细数据: {}", expensiveOperation());
|
|
158
|
+
}
|
|
571
159
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
}
|
|
160
|
+
// ✅ 批量操作:前后各一条,不在循环内打印
|
|
161
|
+
log.info("开始处理订单, 数量:{}", orders.size());
|
|
162
|
+
int success = 0, fail = 0;
|
|
163
|
+
for (Order order : orders) {
|
|
164
|
+
try { process(order); success++; }
|
|
165
|
+
catch (Exception e) { log.error("订单处理失败, orderId:{}", order.getId(), e); fail++; }
|
|
578
166
|
}
|
|
167
|
+
log.info("订单处理完成, 成功:{}, 失败:{}", success, fail);
|
|
168
|
+
|
|
169
|
+
// ✅ 只记录关键信息,不序列化大对象
|
|
170
|
+
log.info("查询结果数量: {}", orders.size()); // ✅
|
|
171
|
+
// log.info("查询结果: {}", orders); // ❌ 大对象
|
|
579
172
|
```
|
|
580
173
|
|
|
581
|
-
|
|
174
|
+
## 敏感信息脱敏
|
|
582
175
|
|
|
583
176
|
```java
|
|
584
|
-
|
|
177
|
+
// ❌ 禁止记录:密码、完整手机号、身份证、银行卡
|
|
178
|
+
log.info("用户登录, username:{}, password:{}", username, password);
|
|
585
179
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
public class BatchOrderService {
|
|
589
|
-
|
|
590
|
-
// ❌ 避免:循环中打印日志
|
|
591
|
-
public void batchProcess(List<Order> orders) {
|
|
592
|
-
for (Order order : orders) {
|
|
593
|
-
log.info("处理订单, orderId:{}", order.getId()); // 可能产生大量日志
|
|
594
|
-
process(order);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// ✅ 推荐:批量处理后打印
|
|
599
|
-
public void batchProcess(List<Order> orders) {
|
|
600
|
-
log.info("开始处理订单, 数量:{}", orders.size());
|
|
601
|
-
|
|
602
|
-
int successCount = 0;
|
|
603
|
-
int failCount = 0;
|
|
604
|
-
for (Order order : orders) {
|
|
605
|
-
try {
|
|
606
|
-
process(order);
|
|
607
|
-
successCount++;
|
|
608
|
-
} catch (Exception e) {
|
|
609
|
-
log.error("订单处理失败, orderId:{}", order.getId(), e);
|
|
610
|
-
failCount++;
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
log.info("订单处理完成, 成功:{}, 失败:{}", successCount, failCount);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
180
|
+
// ✅ 脱敏后记录
|
|
181
|
+
log.info("发送验证码, mobile:{}", maskMobile(mobile)); // 138****1234
|
|
617
182
|
```
|
|
618
183
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
### 日志保留时间
|
|
622
|
-
|
|
623
|
-
- 所有日志文件至少保存 **15天**
|
|
624
|
-
- 重要业务日志建议保存 **30天** 或更长
|
|
184
|
+
脱敏工具:详见 `references/data-mask.md`
|
|
625
185
|
|
|
626
|
-
|
|
186
|
+
## Logback 配置
|
|
627
187
|
|
|
628
|
-
|
|
629
|
-
# application.properties
|
|
630
|
-
# 按模块分类日志
|
|
631
|
-
logging.level.net.xnzn.core.order=INFO
|
|
632
|
-
logging.level.net.xnzn.core.payment=INFO
|
|
633
|
-
logging.level.net.xnzn.core.inventory=INFO
|
|
188
|
+
配置文件:`core-starter/src/main/resources/logback-spring.xml`
|
|
634
189
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
```
|
|
640
|
-
|
|
641
|
-
## 日志级别配置
|
|
642
|
-
|
|
643
|
-
### application.yml 配置
|
|
190
|
+
| Profile | 作用 |
|
|
191
|
+
|---------|------|
|
|
192
|
+
| `no_log_console` | 不输出到控制台 |
|
|
193
|
+
| `no_log_file` | 不输出到文件 |
|
|
644
194
|
|
|
645
195
|
```yaml
|
|
196
|
+
# application.yml 日志级别
|
|
646
197
|
logging:
|
|
647
198
|
level:
|
|
648
|
-
#
|
|
649
|
-
net.xnzn.core.order: INFO
|
|
650
|
-
net.xnzn.core.payment: INFO
|
|
651
|
-
net.xnzn.core.inventory: INFO
|
|
652
|
-
|
|
653
|
-
# 框架日志级别
|
|
199
|
+
net.xnzn.core: INFO # 项目
|
|
654
200
|
com.baomidou.mybatisplus: INFO
|
|
655
201
|
org.springframework: WARN
|
|
656
|
-
org.apache.ibatis: WARN
|
|
657
|
-
|
|
658
|
-
# 日志文件配置
|
|
659
|
-
file:
|
|
660
|
-
name: logs/application.log
|
|
661
202
|
```
|
|
662
203
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
```yaml
|
|
666
|
-
spring:
|
|
667
|
-
profiles:
|
|
668
|
-
active: dev
|
|
669
|
-
|
|
670
|
-
---
|
|
671
|
-
# 开发环境
|
|
672
|
-
spring:
|
|
673
|
-
profiles: dev
|
|
674
|
-
|
|
675
|
-
logging:
|
|
676
|
-
level:
|
|
677
|
-
net.xnzn.core: DEBUG
|
|
678
|
-
|
|
679
|
-
---
|
|
680
|
-
# 生产环境
|
|
681
|
-
spring:
|
|
682
|
-
profiles: prod
|
|
683
|
-
|
|
684
|
-
logging:
|
|
685
|
-
level:
|
|
686
|
-
net.xnzn.core: INFO
|
|
687
|
-
# 生产环境不输出到控制台
|
|
688
|
-
profiles:
|
|
689
|
-
include: no_log_console
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
## 常见场景
|
|
693
|
-
|
|
694
|
-
### 场景1:Controller 层
|
|
695
|
-
|
|
696
|
-
```java
|
|
697
|
-
import lombok.extern.slf4j.Slf4j;
|
|
698
|
-
|
|
699
|
-
@Slf4j
|
|
700
|
-
@RequiresAuthentication
|
|
701
|
-
@RestController
|
|
702
|
-
@RequestMapping("/api/order")
|
|
703
|
-
@Api(value = "订单管理", tags = "订单管理")
|
|
704
|
-
public class OrderController {
|
|
705
|
-
|
|
706
|
-
@Autowired
|
|
707
|
-
private OrderService orderService;
|
|
708
|
-
|
|
709
|
-
@ApiOperation(value = "创建订单")
|
|
710
|
-
@PostMapping("/create")
|
|
711
|
-
public Long create(@Valid @RequestBody LeRequest<OrderParam> request) {
|
|
712
|
-
OrderParam param = request.getContent();
|
|
713
|
-
log.info("【订单】创建订单请求, userId:{}, productId:{}",
|
|
714
|
-
param.getUserId(), param.getProductId());
|
|
715
|
-
|
|
716
|
-
Long orderId = orderService.create(param);
|
|
717
|
-
|
|
718
|
-
log.info("【订单】订单创建成功, orderId:{}", orderId);
|
|
719
|
-
return orderId;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
### 场景2:Service 层
|
|
725
|
-
|
|
726
|
-
```java
|
|
727
|
-
import lombok.extern.slf4j.Slf4j;
|
|
728
|
-
import org.springframework.transaction.annotation.Transactional;
|
|
729
|
-
|
|
730
|
-
@Slf4j
|
|
731
|
-
@Service
|
|
732
|
-
public class OrderService {
|
|
733
|
-
|
|
734
|
-
@Autowired
|
|
735
|
-
private OrderMapper orderMapper;
|
|
736
|
-
|
|
737
|
-
@Transactional(rollbackFor = Exception.class)
|
|
738
|
-
public Long create(OrderParam param) {
|
|
739
|
-
log.info("【订单】开始创建订单, param:{}", param);
|
|
740
|
-
|
|
741
|
-
try {
|
|
742
|
-
// 业务逻辑
|
|
743
|
-
Order order = buildOrder(param);
|
|
744
|
-
orderMapper.insert(order);
|
|
745
|
-
|
|
746
|
-
log.info("【订单】订单创建成功, orderId:{}", order.getId());
|
|
747
|
-
return order.getId();
|
|
748
|
-
} catch (Exception e) {
|
|
749
|
-
log.error("【订单】订单创建失败, param:{}", param, e);
|
|
750
|
-
throw new LeException("订单创建失败");
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
```
|
|
204
|
+
开发环境 `net.xnzn.core: DEBUG`,生产环境 `INFO` + `no_log_console`。
|
|
755
205
|
|
|
756
|
-
|
|
206
|
+
## 禁止项
|
|
757
207
|
|
|
758
208
|
```java
|
|
759
|
-
|
|
760
|
-
import
|
|
761
|
-
import com.github.pagehelper.PageHelper;
|
|
762
|
-
|
|
763
|
-
@Slf4j
|
|
764
|
-
@Service
|
|
765
|
-
public class OrderService {
|
|
766
|
-
|
|
767
|
-
public Page<OrderVO> pageList(OrderQueryParam param) {
|
|
768
|
-
log.info("【订单】分页查询订单, pageNum:{}, pageSize:{}, keyword:{}",
|
|
769
|
-
param.getPage().getPageNum(),
|
|
770
|
-
param.getPage().getPageSize(),
|
|
771
|
-
param.getKeyword());
|
|
772
|
-
|
|
773
|
-
// 开启分页
|
|
774
|
-
PageMethod.startPage(param.getPage().getPageNum(), param.getPage().getPageSize());
|
|
775
|
-
|
|
776
|
-
List<OrderEntity> records = orderMapper.selectList(buildWrapper(param));
|
|
777
|
-
Page<OrderVO> result = new Page<>(BeanUtil.copyToList(records, OrderVO.class));
|
|
778
|
-
|
|
779
|
-
log.info("【订单】分页查询完成, total:{}", result.getTotal());
|
|
780
|
-
return result;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
```
|
|
784
|
-
|
|
785
|
-
## 最佳实践
|
|
209
|
+
// ❌ 直接用 Log4j API
|
|
210
|
+
import org.apache.log4j.Logger;
|
|
786
211
|
|
|
787
|
-
|
|
212
|
+
// ❌ 字符串拼接
|
|
213
|
+
log.info("userId:" + userId + ", name:" + name);
|
|
788
214
|
|
|
789
|
-
|
|
790
|
-
// ❌ 无意义的日志
|
|
215
|
+
// ❌ 无意义日志
|
|
791
216
|
log.info("进入方法");
|
|
792
217
|
log.info("退出方法");
|
|
793
218
|
|
|
794
|
-
//
|
|
795
|
-
log.info("
|
|
796
|
-
log.info("【订单】订单创建成功, orderId:{}", orderId);
|
|
797
|
-
```
|
|
798
|
-
|
|
799
|
-
### 2. 日志要完整
|
|
800
|
-
|
|
801
|
-
```java
|
|
802
|
-
// ✅ 记录完整的业务流程
|
|
803
|
-
log.info("【支付】开始支付, orderId:{}, amount:{}", orderId, amount);
|
|
804
|
-
// 调用支付接口
|
|
805
|
-
log.info("【支付】支付接口调用成功, orderId:{}, transactionId:{}", orderId, transactionId);
|
|
806
|
-
// 更新订单状态
|
|
807
|
-
log.info("【支付】订单状态更新成功, orderId:{}", orderId);
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
### 3. 日志要准确
|
|
811
|
-
|
|
812
|
-
```java
|
|
813
|
-
// ✅ 准确描述操作结果
|
|
814
|
-
log.info("【库存】扣减库存成功, productId:{}, quantity:{}", productId, quantity);
|
|
815
|
-
log.warn("【库存】库存不足, productId:{}, available:{}, required:{}",
|
|
816
|
-
productId, available, required);
|
|
817
|
-
```
|
|
818
|
-
|
|
819
|
-
### 4. 使用中文
|
|
820
|
-
|
|
821
|
-
```java
|
|
822
|
-
// ❌ 英文日志
|
|
823
|
-
log.info("Order created successfully, orderId:{}", orderId);
|
|
219
|
+
// ❌ 英文日志(项目要求中文)
|
|
220
|
+
log.info("Order created successfully");
|
|
824
221
|
|
|
825
|
-
//
|
|
826
|
-
log.
|
|
222
|
+
// ❌ 丢失异常堆栈
|
|
223
|
+
log.error("失败:{}", e.getMessage());
|
|
827
224
|
```
|
|
828
225
|
|
|
829
226
|
## 参考文档
|
|
830
227
|
|
|
831
|
-
-
|
|
832
|
-
-
|
|
228
|
+
- 详细场景示例(Controller/分页/远程调用):详见 `references/logging-scenarios.md`
|
|
229
|
+
- 脱敏工具方法:详见 `references/data-mask.md`
|