3 Star 5 Fork 3

三三物联网/ssiot-core

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
default.go 4.07 KB
一键复制 编辑 原始数据 按行查看 历史
三三物联网 提交于 2023-04-01 18:08 . 结构调整
package logger
import (
"context"
"fmt"
dlog "gitee.com/sansaniot/ssiot-core/logger/debug/log"
"log"
"os"
"runtime"
"sort"
"strings"
"sync"
"time"
)
func init() {
lvl, err := GetLevel(os.Getenv("GO_ADMIN_LOG_LEVEL"))
if err != nil {
lvl = InfoLevel
}
DefaultLogger = NewHelper(NewLogger(WithLevel(lvl)))
}
type defaultLogger struct {
sync.RWMutex
opts Options
}
// Init (opts...) should only overwrite provided options
func (l *defaultLogger) Init(opts ...Option) error {
for _, o := range opts {
o(&l.opts)
}
return nil
}
func (l *defaultLogger) String() string {
return "default"
}
func (l *defaultLogger) Fields(fields map[string]interface{}) Logger {
l.Lock()
l.opts.Fields = copyFields(fields)
l.Unlock()
return l
}
func copyFields(src map[string]interface{}) map[string]interface{} {
dst := make(map[string]interface{}, len(src))
for k, v := range src {
dst[k] = v
}
return dst
}
// logCallerfilePath returns a package/file:line description of the caller,
// preserving only the leaf directory name and file name.
func logCallerfilePath(loggingFilePath string) string {
// To make sure we trim the path correctly on Windows too, we
// counter-intuitively need to use '/' and *not* os.PathSeparator here,
// because the path given originates from Go stdlib, specifically
// runtime.Caller() which (as of Mar/17) returns forward slashes even on
// Windows.
//
// See https://github.com/golang/go/issues/3335
// and https://github.com/golang/go/issues/18151
//
// for discussion on the issue on Go side.
idx := strings.LastIndexByte(loggingFilePath, '/')
if idx == -1 {
return loggingFilePath
}
idx = strings.LastIndexByte(loggingFilePath[:idx], '/')
if idx == -1 {
return loggingFilePath
}
return loggingFilePath[idx+1:]
}
func (l *defaultLogger) Log(level Level, v ...interface{}) {
l.logf(level, "", v...)
}
func (l *defaultLogger) Logf(level Level, format string, v ...interface{}) {
l.logf(level, format, v...)
}
func (l *defaultLogger) logf(level Level, format string, v ...interface{}) {
// TODO decide does we need to write message if log level not used?
if !l.opts.Level.Enabled(level) {
return
}
l.RLock()
fields := copyFields(l.opts.Fields)
l.RUnlock()
fields["level"] = level.String()
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
fields["file"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
}
rec := dlog.Record{
Timestamp: time.Now(),
Metadata: make(map[string]string, len(fields)),
}
if format == "" {
rec.Message = fmt.Sprint(v...)
} else {
rec.Message = fmt.Sprintf(format, v...)
}
keys := make([]string, 0, len(fields))
for k, v := range fields {
keys = append(keys, k)
rec.Metadata[k] = fmt.Sprintf("%v", v)
}
sort.Strings(keys)
metadata := ""
for i, k := range keys {
if i == 0 {
metadata += fmt.Sprintf("%s:%v", k, fields[k])
} else {
metadata += fmt.Sprintf(" %s:%v", k, fields[k])
}
}
var name string
if l.opts.Name != "" {
name = "[" + l.opts.Name + "]"
}
t := rec.Timestamp.Format("2006-01-02 15:04:05.000Z0700")
//fmt.Printf("%s\n", t)
//fmt.Printf("%s\n", name)
//fmt.Printf("%s\n", metadata)
//fmt.Printf("%v\n", rec.Message)
logStr := ""
if name == "" {
logStr = fmt.Sprintf("%s %s %v\n", t, metadata, rec.Message)
} else {
logStr = fmt.Sprintf("%s %s %s %v\n", name, t, metadata, rec.Message)
}
_, err := l.opts.Out.Write([]byte(logStr))
if err != nil {
log.Printf("log [Logf] write error: %s \n", err.Error())
}
}
func (l *defaultLogger) Options() Options {
// not guard against options Context values
l.RLock()
opts := l.opts
opts.Fields = copyFields(l.opts.Fields)
l.RUnlock()
return opts
}
// NewLogger builds a new logger based on options
func NewLogger(opts ...Option) Logger {
// Default options
options := Options{
Level: InfoLevel,
Fields: make(map[string]interface{}),
Out: os.Stderr,
CallerSkipCount: 3,
Context: context.Background(),
Name: "",
}
l := &defaultLogger{opts: options}
if err := l.Init(opts...); err != nil {
l.Log(FatalLevel, err)
}
return l
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/sansaniot/ssiot-core.git
git@gitee.com:sansaniot/ssiot-core.git
sansaniot
ssiot-core
ssiot-core
v1.8.0

搜索帮助