重构日志与可观测性体系

新增单行文本编码器与结构化 GORM 日志,统一错误记录与请求日志策略,收紧日志文件权限并修复按天切分与压缩,支付回调参数脱敏,生产强制阿里云短信,RequestID 校验防注入,日志文案中文化。
This commit is contained in:
yml2213
2026-07-29 16:19:35 +08:00
parent e75f1a8519
commit 88d74aca7d
64 changed files with 896 additions and 277 deletions
+6 -6
View File
@@ -83,7 +83,7 @@ func (j *Job) acquireLock(ctx context.Context) (func(), bool) {
}
ok, err := j.redis.SetNX(ctx, orderTimeoutLockKey, j.instanceID, j.lockTTL()).Result()
if err != nil {
j.logger.Warn("order timeout job acquire lock failed, run without lock", zap.Error(err))
j.logger.Warn("订单超时任务获取锁失败,将以单实例模式执行", zap.Error(err))
return func() {}, true
}
if !ok {
@@ -101,7 +101,7 @@ func (j *Job) releaseLock() {
defer cancel()
script := redis.NewScript(`if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end`)
if err := script.Run(relCtx, j.redis, []string{orderTimeoutLockKey}, j.instanceID).Err(); err != nil {
j.logger.Warn("order timeout job release lock failed", zap.Error(err))
j.logger.Warn("订单超时任务释放锁失败", zap.Error(err))
}
}
@@ -131,7 +131,7 @@ func (j *Job) loop(ctx context.Context) {
for {
select {
case <-ctx.Done():
j.logger.Info("order timeout job stopped")
j.logger.Debug("订单超时任务已停止")
return
case <-ticker.C:
j.run(ctx)
@@ -148,7 +148,7 @@ func (j *Job) run(ctx context.Context) {
cfg, err := j.loadThresholds(ctx)
if err != nil {
j.logger.Warn("order timeout job config load failed", zap.Error(err))
j.logger.Warn("订单超时任务加载配置失败", zap.Error(err))
return
}
now := time.Now()
@@ -164,13 +164,13 @@ func (j *Job) run(ctx context.Context) {
for _, handler := range handlers {
count, err := handler(ctx, now, cfg)
if err != nil {
j.logger.Warn("order timeout handler failed", zap.Error(err))
j.logger.Warn("订单超时处理失败", zap.Error(err))
continue
}
total += count
}
if total > 0 {
j.logger.Info("order timeout job processed orders", zap.Int("count", total))
j.logger.Info("订单超时处理完成", zap.Int("count", total))
}
}
+15 -15
View File
@@ -51,7 +51,7 @@ func (j *Job) acquireLock(ctx context.Context) (func(), bool) {
}
ok, err := j.redis.SetNX(ctx, refundRetryLockKey, j.instanceID, j.lockTTL()).Result()
if err != nil {
j.logger.Warn("refund retry job acquire lock failed, run without lock", zap.Error(err))
j.logger.Warn("退款重试任务获取锁失败,将以单实例模式执行", zap.Error(err))
return func() {}, true
}
if !ok {
@@ -69,7 +69,7 @@ func (j *Job) releaseLock() {
defer cancel()
script := redis.NewScript(`if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end`)
if err := script.Run(relCtx, j.redis, []string{refundRetryLockKey}, j.instanceID).Err(); err != nil {
j.logger.Warn("refund retry job release lock failed", zap.Error(err))
j.logger.Warn("退款重试任务释放锁失败", zap.Error(err))
}
}
@@ -99,7 +99,7 @@ func (j *Job) loop(ctx context.Context) {
for {
select {
case <-ctx.Done():
j.logger.Info("refund retry job stopped")
j.logger.Debug("退款重试任务已停止")
return
case <-ticker.C:
j.run(ctx)
@@ -117,14 +117,14 @@ func (j *Job) run(ctx context.Context) {
now := time.Now()
processed, err := j.syncRefundPayments(ctx, now)
if err != nil {
j.logger.Warn("refund retry job sync payments failed", zap.Error(err))
j.logger.Warn("退款重试任务同步失败", zap.Error(err))
}
missing, rebuilt, err := j.warnMissingRefundOrders(ctx, now)
if err != nil {
j.logger.Warn("refund retry job scan missing refund orders failed", zap.Error(err))
j.logger.Warn("退款重试任务扫描缺失退款单失败", zap.Error(err))
}
if processed > 0 || missing > 0 {
j.logger.Info("refund retry job finished",
j.logger.Info("退款重试任务处理完成",
zap.Int("processed", processed),
zap.Int("missing_refund_orders", missing),
zap.Int("rebuilt_arbitration_refunds", rebuilt),
@@ -147,13 +147,13 @@ func (j *Job) syncRefundPayments(ctx context.Context, now time.Time) (int, error
for _, row := range rows {
if _, err := j.payments.SyncRefundStatusByPaymentID(ctx, row.ID); err != nil {
if markErr := j.markRetryFailed(ctx, row, now); markErr != nil {
j.logger.Warn("refund retry mark failure failed",
j.logger.Warn("退款重试失败状态保存失败",
zap.Uint64("payment_id", row.ID),
zap.Uint64("order_id", row.OrderID),
zap.Error(markErr),
)
}
j.logger.Warn("refund retry sync failed",
j.logger.Warn("退款状态同步失败",
zap.Uint64("payment_id", row.ID),
zap.Uint64("order_id", row.OrderID),
zap.String("biz_type", row.BizType),
@@ -164,7 +164,7 @@ func (j *Job) syncRefundPayments(ctx context.Context, now time.Time) (int, error
continue
}
if err := j.resetRetry(ctx, row.ID); err != nil {
j.logger.Warn("refund retry reset counter failed",
j.logger.Warn("退款重试计数重置失败",
zap.Uint64("payment_id", row.ID),
zap.Uint64("order_id", row.OrderID),
zap.Error(err),
@@ -222,7 +222,7 @@ func (j *Job) warnMaxRetryRefunds(ctx context.Context, now time.Time) {
Limit(50).
Find(&rows).Error
if err != nil {
j.logger.Warn("refund retry max count scan failed", zap.Error(err))
j.logger.Warn("退款最大重试次数扫描失败", zap.Error(err))
return
}
if len(rows) == 0 {
@@ -235,7 +235,7 @@ func (j *Job) warnMaxRetryRefunds(ctx context.Context, now time.Time) {
ids = append(ids, row.ID)
orderIDs = append(orderIDs, row.OrderID)
}
j.logger.Warn("refund retry reached max count, need manual check",
j.logger.Warn("退款已达最大重试次数,需要人工处理",
zap.Int("count", len(rows)),
zap.Uint64s("payment_ids", ids),
zap.Uint64s("order_ids", orderIDs),
@@ -243,7 +243,7 @@ func (j *Job) warnMaxRetryRefunds(ctx context.Context, now time.Time) {
if err := j.db.WithContext(ctx).Model(&model.PaymentOrder{}).
Where("id IN ?", ids).
Update("last_retry_at", now).Error; err != nil {
j.logger.Warn("refund retry bump last_retry_at failed", zap.Error(err))
j.logger.Warn("退款重试时间更新失败", zap.Error(err))
}
}
@@ -284,7 +284,7 @@ func (j *Job) warnMissingRefundOrders(ctx context.Context, now time.Time) (int,
rebuildFailOrderIDs = append(rebuildFailOrderIDs, row.ID)
} else {
rebuilt++
j.logger.Info("auto rebuild arbitration refund submitted",
j.logger.Info("仲裁退款单已自动补建",
zap.Uint64("order_id", row.ID),
zap.Int64("refund_amount_cent", row.RefundAmountCent),
)
@@ -295,13 +295,13 @@ func (j *Job) warnMissingRefundOrders(ctx context.Context, now time.Time) (int,
}
// 汇总告警 + Redis 24h 去重,避免每轮扫描刷屏
if len(missingOrderIDs) > 0 && j.shouldWarn(ctx, "missing_payment", 0) {
j.logger.Warn("refund order missing payment record, need manual check",
j.logger.Warn("退款订单缺少支付记录,需要人工处理",
zap.Int("count", len(missingOrderIDs)),
zap.Uint64s("order_ids", missingOrderIDs),
)
}
if len(rebuildFailOrderIDs) > 0 && j.shouldWarn(ctx, "rebuild_fail", 0) {
j.logger.Warn("auto rebuild arbitration refund failed, need manual check",
j.logger.Warn("仲裁退款单自动补建失败,需要人工处理",
zap.Int("count", len(rebuildFailOrderIDs)),
zap.Uint64s("order_ids", rebuildFailOrderIDs),
)