基于 logger sdk-logger 封装

package logger

import (
    "io/ioutil"
    "os"
    "path/filepath"
    "sync"

    "github.com/pkg/errors"
    "github.com/rifflock/lfshook"
    "github.com/sirupsen/logrus"
)

var loggerIns *logger

type logger struct {
    loggerMap *sync.Map
    logPath   string
    env       string //环境变量
}

type Config struct {
    Env  string //环境变量
    Path string //日志文件路径
}

//初始化
func InitLogger(config Config) error {
    if config.Path == "" {
        return errors.New("config path require")
    }
    if config.Env == "" {
        return errors.New("config env require")
    }

    loggerIns = &logger{
        loggerMap: new(sync.Map),
        env:       config.Env,
        logPath:   config.Path,
    }
    return nil
}

//获取实例
func GetLogger(arg ...string) *logrus.Logger {
    logName := "all"
    if len(arg) > 0 {
        logName = arg[0]
    }

    if log, ok := loggerIns.loggerMap.Load(logName); ok {
        return log.(*logrus.Logger)
    }

    newLog, _ := newLogger(logName)
    loggerIns.loggerMap.Store(logName, newLog)
    return newLog
}

func newLogger(logName string) (*logrus.Logger, error) {
    if logName == "" {
        return nil, errors.New("logName require")
    }
    var logger *logrus.Logger
    if _, err := os.Stat(loggerIns.logPath); os.IsNotExist(err) {
        if err := os.MkdirAll(loggerIns.logPath, os.ModePerm); err != nil {
            return nil, err
        }
    }

    hook := lfshook.NewHook(lfshook.PathMap{
        logrus.InfoLevel:  filepath.Join(loggerIns.logPath, logName) + ".out.log",
        logrus.ErrorLevel: filepath.Join(loggerIns.logPath, logName) + ".err.log",
        logrus.DebugLevel: filepath.Join(loggerIns.logPath, logName) + ".debug.log",
        logrus.TraceLevel: filepath.Join(loggerIns.logPath, logName) + ".trace.log",
    }, &logrus.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"})
    logger = logrus.New()

    if loggerIns.env == "online" {
        logger.Out = ioutil.Discard
        logger.SetLevel(logrus.InfoLevel)
    } else {
        logger.Out = ioutil.Discard
        logger.SetLevel(logrus.DebugLevel)
    }

    logger.Hooks.Add(hook)
    return logger, nil
}

测试文件

package logger_test

import (
    "testing"

    "xxxx/sdk-logger"
)

func TestMain(t *testing.M) {
    config := logger.Config{
        Env:  "dev",
        Path: "./log",
    }

    if err := logger.InitLogger(config); err != nil {
        panic(err)
    }
    t.Run()
}

func TestGetLogger(t *testing.T) {
    logger.GetLogger().Infof("测试日志呀")
    logger.GetLogger().WithField("title","测试 key").Debugf("这是 debug 日志")
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
by JeffreyBool blog :point_right: link
JeffreyBool
讨论数量: 17
ALMAS

要是能封装成laravel 的log组件一样支持多个channel就更完美了

4年前 评论
yourself

好的 感谢分享@kenuo

4年前 评论
JeffreyBool

下次再发基于 mysql 和 Redis 的provider 封装

4年前 评论
JeffreyBool

@yourself 我上面封装的这个日志包投入到项目中使用了。还不错。我做支付网关。各种日志都是基于这个日志。 要做日志切分。直接用 linux 系统切分也很方便。 而且性能比程序做更好

4年前 评论
yourself

@kenuo 期待版主能找到好的用包,或者开源一个

4年前 评论
JeffreyBool

@yourself 我知道这个。这个不好。是软链的。 还不如直接用 linux 系统默认的文件大小切分

4年前 评论
yourself

可以用这个做切分:github.com/lestrrat-go/file-rotatelogs

4年前 评论
JeffreyBool

@ALMAS 这本来就是同一个目录啊,代码很清晰,看代码吧,改也很好改

4年前 评论
ALMAS

@kenuo 可同一个目录?

4年前 评论
JeffreyBool

@ALMAS 当然是不同的文件了

4年前 评论
ALMAS

@kenuo 那这多个实例写入的日志都写入同一个文件里还是每个实例可以指定文件?

4年前 评论
JeffreyBool
package logger_test

import (
    "testing"

    "xxxx/sdk-logger"
)

func TestMain(t *testing.M) {
    config := logger.Config{
        Env:  "dev",
        Path: "./log",
    }

    if err := logger.InitLogger(config); err != nil {
        panic(err)
    }
    t.Run()
}

func TestGetLogger(t *testing.T) {
    logger.GetLogger().Infof("测试日志呀")
    logger.GetLogger().WithField("title","测试 key").Debugf("这是 debug 日志")

   logger.GetLogger("wechat").Infof("测试日志呀")
   logger.GetLogger("wechat").WithField("title","测试 key").Debugf("这是 debug 日志")

   logger.GetLogger("alipay").Infof("测试日志呀")
   logger.GetLogger("alipay").WithField("title","测试 key").Debugf("这是 debug 日志")
}
4年前 评论
JeffreyBool

@ALMAS 支持多实例

4年前 评论
ALMAS

@kenuo 是的

4年前 评论
JeffreyBool

@ALMAS 在我的理解,他的多通道就是日志多实例?

4年前 评论
JeffreyBool

@ALMAS 没懂你说的 支持多个channel 是啥意思

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!