@@ -141,17 +141,28 @@ func (l *Logger) shouldLog(level Level) bool {
141141 return atomic .LoadInt64 (& l .level ) <= int64 (level )
142142}
143143
144+ // LogEntry 有序日志条目结构 - 确保字段输出顺序固定
145+ type LogEntry struct {
146+ Timestamp string `json:"timestamp"`
147+ Level string `json:"level"`
148+ File string `json:"file,omitempty"`
149+ Func string `json:"func,omitempty"`
150+ Message string `json:"message"`
151+ Fields map [string ]any `json:"-"` // 动态字段,单独处理
152+ }
153+
144154// log 内部日志记录方法(优化版本)
145155func (l * Logger ) log (level Level , msg string , fields []Field ) {
146156 if ! l .shouldLog (level ) {
147157 return
148158 }
149159
150- // 构建日志条目
151- entry := map [string ]any {
152- "timestamp" : time .Now ().Format ("2006-01-02T15:04:05.000Z07:00" ),
153- "level" : levelNames [level ],
154- "message" : msg ,
160+ // 构建标准日志条目
161+ entry := & LogEntry {
162+ Timestamp : time .Now ().Format ("2006-01-02T15:04:05.000Z07:00" ),
163+ Level : levelNames [level ],
164+ Message : msg ,
165+ Fields : make (map [string ]any ),
155166 }
156167
157168 // 按需获取调用者信息(优化:可配置)
@@ -160,28 +171,33 @@ func (l *Logger) log(level Level, msg string, fields []Field) {
160171 if idx := strings .LastIndex (file , "/" ); idx >= 0 {
161172 file = file [idx + 1 :]
162173 }
163- entry [ "file" ] = fmt .Sprintf ("%s:%d" , file , line )
174+ entry . File = fmt .Sprintf ("%s:%d" , file , line )
164175 // 提取函数名,便于快速定位日志来源
165176 if fn := runtime .FuncForPC (pc ); fn != nil {
166177 name := fn .Name ()
167178 // 裁剪包路径,仅保留最后的符号名
168179 if dot := strings .LastIndex (name , "." ); dot >= 0 && dot < len (name )- 1 {
169180 name = name [dot + 1 :]
170181 }
171- entry [ "func" ] = name
182+ entry . Func = name
172183 }
173184 }
174185 }
175186
176- // 添加字段
187+ // 收集动态字段,过滤重复的系统字段
177188 for _ , field := range fields {
178- entry [field .Key ] = field .Value
189+ // 跳过重复的系统字段
190+ if field .Key == "level" || field .Key == "log_level" ||
191+ field .Key == "timestamp" || field .Key == "message" ||
192+ field .Key == "file" || field .Key == "log_file" ||
193+ field .Key == "func" {
194+ continue
195+ }
196+ entry .Fields [field .Key ] = field .Value
179197 }
180198
181- // 优化的JSON序列化(使用sonic高性能库)
182- var jsonData []byte
183- // 使用sonic的高性能序列化
184- jsonData , _ = sonic .Marshal (entry )
199+ // 使用自定义序列化确保字段顺序
200+ jsonData := l .marshalLogEntry (entry )
185201
186202 // 直接输出日志 - log.Logger本身已经线程安全!
187203 l .logger .Println (string (jsonData ))
@@ -192,6 +208,71 @@ func (l *Logger) log(level Level, msg string, fields []Field) {
192208 }
193209}
194210
211+ // marshalLogEntry 自定义日志条目序列化,确保字段顺序
212+ func (l * Logger ) marshalLogEntry (entry * LogEntry ) []byte {
213+ // 手动构建JSON字符串确保字段顺序:timestamp > level > file > func > message > 其他字段
214+ var b strings.Builder
215+ b .WriteString (`{"timestamp":"` )
216+ b .WriteString (entry .Timestamp )
217+ b .WriteString (`","level":"` )
218+ b .WriteString (entry .Level )
219+ b .WriteString (`"` )
220+
221+ // 添加可选字段
222+ if entry .File != "" {
223+ b .WriteString (`,"file":"` )
224+ b .WriteString (entry .File )
225+ b .WriteString (`"` )
226+ }
227+ if entry .Func != "" {
228+ b .WriteString (`,"func":"` )
229+ b .WriteString (entry .Func )
230+ b .WriteString (`"` )
231+ }
232+
233+ b .WriteString (`,"message":"` )
234+ // 转义message中的特殊字符
235+ escapedMsg , _ := sonic .MarshalString (entry .Message )
236+ // 移除外层引号
237+ if len (escapedMsg ) >= 2 {
238+ b .WriteString (escapedMsg [1 :len (escapedMsg )- 1 ])
239+ }
240+ b .WriteString (`"` )
241+
242+ // 添加动态字段(按键名排序确保一致性)
243+ if len (entry .Fields ) > 0 {
244+ // 对字段名进行排序确保输出一致性
245+ var keys []string
246+ for k := range entry .Fields {
247+ keys = append (keys , k )
248+ }
249+ // 简单排序(保持性能)
250+ for i := 0 ; i < len (keys )- 1 ; i ++ {
251+ for j := i + 1 ; j < len (keys ); j ++ {
252+ if keys [i ] > keys [j ] {
253+ keys [i ], keys [j ] = keys [j ], keys [i ]
254+ }
255+ }
256+ }
257+
258+ for _ , k := range keys {
259+ v := entry .Fields [k ]
260+ b .WriteString (`,"` )
261+ b .WriteString (k )
262+ b .WriteString (`":` )
263+ // 序列化字段值
264+ if fieldJSON , err := sonic .Marshal (v ); err == nil {
265+ b .Write (fieldJSON )
266+ } else {
267+ b .WriteString (`null` )
268+ }
269+ }
270+ }
271+
272+ b .WriteString (`}` )
273+ return []byte (b .String ())
274+ }
275+
195276// SetLevel 设置日志级别(优化:原子操作)
196277func SetLevel (level Level ) {
197278 atomic .StoreInt64 (& defaultLogger .level , int64 (level ))
0 commit comments