Go语言(十四)日志项目

栏目: IT技术 · 发布时间: 4年前

内容简介:log_base.go 基类log.golevel.go

日志项目

日志库需求分析

  • 日志库产生的背景

    • 程序运行是个黑盒
    • 日志是程序之外的表现
    • 通过日志,可以知道程序的健康状态
  • 日志打印的级别

    • Debug:日志最详细,对程序的影响比较大
    • Trace: 用来追踪问题
    • Info: 比较重要的信息,比如访问日志
    • Warn:警告日志,表明程序存在问题
    • Error: 错误日志,运行程序时发生的错误
    • Fatal: 严重错误日志
  • 日志存储的位置

    • 直接输出到控制台
    • 打印到文件里
    • 直接打印到网络中,比如kafka
  • 为什么使用接口

    • 定义日志库的标准或者规范
    • 易于扩展
    • 利于程序维护
  • 日志库的设计
    • 打印各个level的日志
    • 设置级别
    • 构造函数

日志库接口设计

log_base.go 基类

package xlog

import (
   "fmt"
   "os"
   "path/filepath"
   "time"
)

type LogData struct {
   timeStr  string
   levelStr string
   module   string
   filename string
   funcName string
   lineNo   int
   data     string
}

type XLogBase struct {
   level   int
   module  string
}

func (l *XLogBase) writeLog(file *os.File,logData *LogData) {
   fmt.Fprintf(file,"%s %s %s (%s:%s:%d) %s\n",
      logData.timeStr, logData.levelStr, logData.module,
      logData.filename, logData.funcName, logData.lineNo, logData.data)
}

func (l *XLogBase) formatLogger(level int, module, format string, args ...interface{}) *LogData {
   now := time.Now()
   timeStr := now.Format("2006-01-02 15:04:05.000")
   levelStr := getLevelStr(level)
   filename, funcName, lineNo := GetLineInfo(3)
   filename = filepath.Base(filename)
   data := fmt.Sprintf(format, args...)
   //fmt.Printf("%s %s %s (%s:%s:%d) %s\n",timeStr,leveStr,module,filename,funcName,lineNo,data)
   return &LogData{
      timeStr:  timeStr,
      levelStr: levelStr,
      module:   module,
      filename: filename,
      funcName: funcName,
      lineNo:   lineNo,
      data:     data,
   }
}

log.go

package xlog

type XLog interface {
   Init() error   //文件初始化
   LogDebug(format string, args ...interface{})
   LogTrace(format string, args ...interface{})
   LogInfo(format string, args ...interface{})
   LogWarn(format string, args ...interface{})
   LogError(format string, args ...interface{})
   LogFatal(format string, args ...interface{})
   Close()
   SetLevel(level int)
}

func NewXLog(logType, level int, filename, module string) XLog {
   //定义接口
   var logger XLog
   switch logType {
   case XLogTypeFile:
      logger = NewXFile(level,filename, module)
   case XLogTypeConsole:
      logger = NewXConsole(level, module)
   default:
      logger = NewXFile(level,filename, module)
   }
   return logger
}

level.go

package xlog

const (
   XLogLevelDebug = iota
   XLogLevelTrace
   XLogLevelInfo
   XLogLevelWarn
   XLogLevelError
   XLogLevelFatal
)

const (
   XLogTypeFile = iota
   XLogTypeConsole
)

func getLevelStr(level int) string {
   switch level {
   case XLogLevelDebug:
      return "DEBUG"
   case XLogLevelTrace:
      return "TRACE"
   case XLogLevelInfo:
      return "INFO"
   case XLogLevelWarn:
      return "WARN"
   case XLogLevelError:
      return "ERROR"
   case XLogLevelFatal:
      return "FATAL"
   default:
      return "UNKNOWN"
   }
}

tool.go: 获取程序运行所在行以及函数名

package xlog

import "runtime"

func GetLineInfo(skip int) (filename, funcName string, lineNo int) {
   pc, file, line, ok := runtime.Caller(skip)
   if ok {
      fun := runtime.FuncForPC(pc)
      funcName = fun.Name()
   }
   filename = file
   lineNo = line
   return
}

文件日志库开发

package xlog

import (
   "os"
)

type XFile struct {
   *XLogBase
   filename string
   file     *os.File
}

func (c *XFile) Init() (err error) {
   c.file,err = os.OpenFile(c.filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY,0755)
   if err != nil {
      return
   }
   return
}

func NewXFile(level int, filename, module string) XLog {
   logger := &XFile{
      filename: filename,
   }
   logger.XLogBase = &XLogBase{
      module: module,
      level: level,
   }
   return logger
}

func (c *XFile) LogDebug(format string, args ...interface{}) {
   if c.level > XLogLevelDebug {
      return
   }
   logData := c.formatLogger(XLogLevelDebug, c.module, format, args...)
   c.writeLog(c.file,logData)
}
func (c *XFile) LogTrace(format string, args ...interface{}) {
   if c.level > XLogLevelTrace {
      return
   }
   logData := c.formatLogger(XLogLevelTrace, c.module, format, args...)
   c.writeLog(c.file,logData)
}
func (c *XFile) LogInfo(format string, args ...interface{}) {
   if c.level > XLogLevelInfo {
      return
   }
   logData := c.formatLogger(XLogLevelInfo, c.module, format, args...)
   c.writeLog(c.file,logData)
}
func (c *XFile) LogWarn(format string, args ...interface{}) {
   if c.level > XLogLevelWarn {
      return
   }
   logData := c.formatLogger(XLogLevelWarn, c.module, format, args...)
   c.writeLog(c.file,logData)
}
func (c *XFile) LogError(format string, args ...interface{}) {
   if c.level > XLogLevelError {
      return
   }
   logData := c.formatLogger(XLogLevelError, c.module, format, args...)
   c.writeLog(c.file,logData)
}
func (c *XFile) LogFatal(format string, args ...interface{}) {
   if c.level > XLogLevelFatal {
      return
   }
   logData := c.formatLogger(XLogLevelFatal, c.module, format, args...)
   c.writeLog(c.file,logData)
}

func (c *XFile) SetLevel(level int) {
   c.level = level
}

func (c *XFile)Close()  {
   if c.file != nil {
      c.file.Close()
   }
}

Console日志开发

package xlog

import (
   "os"
)

type XConsole struct {
   *XLogBase   //指针实现
}

func NewXConsole(level int, module string) XLog {
   logger := &XConsole{}
   //初始化指针,防止panic
   logger.XLogBase = &XLogBase{
      level: level,
      module: module,
   }
   return logger
}

//不需要初始化文件写入
func (c *XConsole)Init() error {
   return nil
}

func (c *XConsole) LogDebug(format string, args ...interface{}) {
   if c.level > XLogLevelDebug {
      return
   }
   logData := c.formatLogger(XLogLevelDebug, c.module, format, args...)
   c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogTrace(format string, args ...interface{}) {
   if c.level > XLogLevelTrace {
      return
   }
   logData := c.formatLogger(XLogLevelTrace, c.module, format, args...)
   c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogInfo(format string, args ...interface{}) {
   if c.level > XLogLevelInfo {
      return
   }
   logData := c.formatLogger(XLogLevelInfo, c.module, format, args...)
   c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogWarn(format string, args ...interface{}) {
   if c.level > XLogLevelWarn {
      return
   }
   logData := c.formatLogger(XLogLevelWarn, c.module, format, args...)
   c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogError(format string, args ...interface{}) {
   if c.level > XLogLevelError {
      return
   }
   logData := c.formatLogger(XLogLevelError, c.module, format, args...)
   c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogFatal(format string, args ...interface{}) {
   if c.level > XLogLevelFatal {
      return
   }
   logData := c.formatLogger(XLogLevelFatal, c.module, format, args...)
   c.writeLog(os.Stdout,logData)
}
func (c *XConsole) SetLevel(level int) {
   c.level = level
}

func (c *XConsole) Close() {}

日志使用以及测试

xlog_example/main.go

package main

import (
   "flag"
   "fmt"
   _"fmt"
   "oldBoy/day9/xlog"
)

func logic(logger xlog.XLog) {
   logger.LogDebug("dads1,user_id:%d,username:%s",12331,"sadsaf")
   logger.LogTrace("dads2")
   logger.LogInfo("dads3")
   logger.LogWarn("dads4")
   logger.LogError("sss")
   logger.LogFatal("sss")
}
/*
func testGetLine() {
   //skip =2 深度为2的调用位置,也就是main下的22行
   filename,funcName,lineNo := xlog.GetLineInfo(2)
   fmt.Printf("filename=%s,funcname=%s,linenum=%d\n",filename,funcName,lineNo)
}
 */
func main() {
   //testGetLine()
   var logTypeStr string
   flag.StringVar(&logTypeStr,"type","file","please input a logger type")
   flag.Parse()

   var logType int
   if (logTypeStr == "file") {
      logType = xlog.XLogTypeFile
   }else {
      logType = xlog.XLogTypeConsole
   }
   logger := xlog.NewXLog(logType,xlog.XLogLevelDebug,"./xlog.log","xlog_example")
   err := logger.Init()
   if err != nil {
      fmt.Printf("init error:%v\n",err)
      return
   }
   logic(logger)
}

备注

  • 缺少的功能:
    • 异步写盘
    • 日志切分

欢迎关注我们的微信公众号,每天学习 Go 知识

Go语言(十四)日志项目

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构

数据结构

严蔚敏、吴伟民 / 清华大学出版社 / 2007-3-1 / 30.0

《数据结构》(C语言版)是为“数据结构”课程编写的教材,也可作为学习数据结构及其算法的C程序设计的参数教材。 本书的前半部分从抽象数据类型的角度讨论各种基本类型的数据结构及其应用;后半部分主要讨论查找和排序的各种实现方法及其综合分析比较。其内容和章节编排1992年4月出版的《数据结构》(第二版)基本一致,但在本书中更突出了抽象数据类型的概念。全书采用类C语言作为数据结构和算法的描述语言。 ......一起来看看 《数据结构》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具