mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 14:06:36 +08:00
82155b8599
### 🛠 修复 - 修复了异步任务列表在成功状态下允许重试、失败状态下无重试按钮的问题。 - 修复了启用推送事件时,在无可用推送渠道配置下仍尝试触发并阻塞的问题。 - 修复了 WebDAV 存储驱动在 Put/Get/Delete 等操作中由于丢弃 context.Context 导致 HTTP 链路追踪断裂(生成无源 Root Span)的问题。 - 修复了结构化日志在没有 active span 时仍强制打印全零 traceID/spanID 产生的日志冗余噪音。 ### ⚡️ 优化与改进 - 实现了全新的系统通知推送机制,支持 Telegram Bot、Lark 机器人及自定义 Webhook 等多种推送渠道。 - 优化了路由结构设计,按照 V1 分类与业务模块实现扁平化的路由解耦。 - 引入了全局 OpenTelemetry 链路追踪(Tracer)框架,集成 Gin, GORM 与 Redis 自动化耗时度量,并补充了统一的全局错误处理中间件。 - 优化了采样器命名,将 ParentBasedErrorAwareSampler 重命名为更契合其真实机制的 ParentBasedRatioSampler。 - 重构并统一了项目架构为基于 Feature 的功能模块化结构,将 internal/util/ 拆分得更加纯净,优化了验证码等公共库提取(pkg/cap)。 - 实现了推送事件与自定义通道的 Redis 缓存机制,极大降低了推送触发时的高频 DB 查询压力。 ### 💄 其他/体验 - 优化了前端界面布局,同步系统菜单与侧边栏配置显示。 - 优化了前端自定义通道表格的布局与样式,使其与事件管理 Tab 页面保持一致。 - 更新了项目开发技能手册(Skills),包括新增接口路由规范(new-api)和异步任务开发指南(new-async-task)。
100 lines
2.3 KiB
Go
100 lines
2.3 KiB
Go
// Copyright 2025 linux.do
|
|
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package logger
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"go.opentelemetry.io/otel/trace"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
"gopkg.in/natefinch/lumberjack.v2"
|
|
)
|
|
|
|
// logDirPerm 日志目录权限
|
|
const logDirPerm = 0750
|
|
|
|
func getLogWriterForConfig(cfg Config) (zapcore.WriteSyncer, error) {
|
|
if cfg.Output == "file" {
|
|
// 初始化日志目录
|
|
logPath := cfg.FilePath
|
|
logDir := filepath.Dir(logPath)
|
|
if err := os.MkdirAll(logDir, logDirPerm); err != nil {
|
|
return nil, fmt.Errorf(errCreateLogFileDirFailed, err)
|
|
}
|
|
|
|
// 配置日志轮转
|
|
logOutput := &lumberjack.Logger{
|
|
Filename: logPath,
|
|
MaxSize: cfg.MaxSize,
|
|
MaxBackups: cfg.MaxBackups,
|
|
MaxAge: cfg.MaxAge,
|
|
Compress: cfg.Compress,
|
|
}
|
|
|
|
return zapcore.AddSync(logOutput), nil
|
|
}
|
|
|
|
return zapcore.AddSync(os.Stdout), nil
|
|
}
|
|
|
|
// getEncoderForConfig 获取日志编码器
|
|
func getEncoderForConfig(cfg Config) zapcore.Encoder {
|
|
// 编码器配置
|
|
encoderConfig := zapcore.EncoderConfig{
|
|
TimeKey: "time",
|
|
LevelKey: "level",
|
|
NameKey: "logger",
|
|
CallerKey: "caller",
|
|
MessageKey: "msg",
|
|
StacktraceKey: "stacktrace",
|
|
LineEnding: zapcore.DefaultLineEnding,
|
|
EncodeLevel: zapcore.LowercaseLevelEncoder,
|
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
|
EncodeCaller: zapcore.ShortCallerEncoder,
|
|
}
|
|
|
|
if cfg.Format == "json" {
|
|
return zapcore.NewJSONEncoder(encoderConfig)
|
|
}
|
|
return zapcore.NewConsoleEncoder(encoderConfig)
|
|
}
|
|
|
|
// getLogLevelForConfig 获取日志级别
|
|
func getLogLevelForConfig(cfg Config) zapcore.Level {
|
|
level := cfg.Level
|
|
|
|
switch level {
|
|
case "debug":
|
|
return zapcore.DebugLevel
|
|
case "info":
|
|
return zapcore.InfoLevel
|
|
case "warn":
|
|
return zapcore.WarnLevel
|
|
case "error":
|
|
return zapcore.ErrorLevel
|
|
default:
|
|
log.Printf("[Logger] invalid log level: %s, defaulting to info\n", level)
|
|
return zapcore.InfoLevel
|
|
}
|
|
}
|
|
|
|
func getTraceIDFields(ctx context.Context) []zap.Field {
|
|
span := trace.SpanFromContext(ctx)
|
|
spanContext := span.SpanContext()
|
|
if !spanContext.IsValid() {
|
|
return nil
|
|
}
|
|
return []zap.Field{
|
|
zap.String("traceID", spanContext.TraceID().String()),
|
|
zap.String("spanID", spanContext.SpanID().String()),
|
|
}
|
|
}
|