文档章节

保存一个别人的golang 日志库

敲代码中
 敲代码中
发布于 2014/06/17 11:22
字数 863
阅读 150
收藏 0
点赞 0
评论 0

package logger


import (

"fmt"

"log"

"os"

"runtime"

"strconv"

"sync"

"time"

)


const (

_VER string = "1.0.0"

)


type LEVEL int32


var logLevel LEVEL = 1

var maxFileSize int64

var maxFileCount int32

var dailyRolling bool = true

var consoleAppender bool = true

var RollingFile bool = false

var logObj *_FILE


const DATEFORMAT = "2006-01-02"


type UNIT int64


const (

_       = iota

KB UNIT = 1 << (iota * 10)

MB

GB

TB

)


const (

ALL LEVEL = iota

DEBUG

INFO

WARN

ERROR

FATAL

OFF

)


type _FILE struct {

dir      string

filename string

_suffix  int

isCover  bool

_date    *time.Time

mu       *sync.RWMutex

logfile  *os.File

lg       *log.Logger

}


func SetConsole(isConsole bool) {

consoleAppender = isConsole

}


func SetLevel(_level LEVEL) {

logLevel = _level

}


func SetRollingFile(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {

maxFileCount = maxNumber

maxFileSize = maxSize * int64(_unit)

RollingFile = true

dailyRolling = false

logObj = &_FILE{dir: fileDir, filename: fileName, isCover: false, mu: new(sync.RWMutex)}

logObj.mu.Lock()

defer logObj.mu.Unlock()

for i := 1; i <= int(maxNumber); i++ {

if isExist(fileDir + "/" + fileName + "." + strconv.Itoa(i)) {

logObj._suffix = i

} else {

break

}

}

if !logObj.isMustRename() {

logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0)

logObj.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)

} else {

logObj.rename()

}

go fileMonitor()

}


func SetRollingDaily(fileDir, fileName string) {

RollingFile = false

dailyRolling = true

t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))

logObj = &_FILE{dir: fileDir, filename: fileName, _date: &t, isCover: false, mu: new(sync.RWMutex)}

logObj.mu.Lock()

defer logObj.mu.Unlock()


if !logObj.isMustRename() {

logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0)

logObj.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)

} else {

logObj.rename()

}

}


func console(s ...interface{}) {

if consoleAppender {

_, file, line, _ := runtime.Caller(2)

short := file

for i := len(file) - 1; i > 0; i-- {

if file[i] == '/' {

short = file[i+1:]

break

}

}

file = short

log.Println(file+":"+strconv.Itoa(line), s)

}

}


func catchError() {

if err := recover(); err != nil {

log.Println("err", err)

}

}


func Debug(v ...interface{}) {

if dailyRolling {

fileCheck()

}

defer catchError()

logObj.mu.RLock()

defer logObj.mu.RUnlock()


if logLevel <= DEBUG {

logObj.lg.Output(2, fmt.Sprintln("debug", v))

console("debug", v)

}

}

func Info(v ...interface{}) {

if dailyRolling {

fileCheck()

}

defer catchError()

logObj.mu.RLock()

defer logObj.mu.RUnlock()

if logLevel <= INFO {

logObj.lg.Output(2, fmt.Sprintln("info", v))

console("info", v)

}

}

func Warn(v ...interface{}) {

if dailyRolling {

fileCheck()

}

defer catchError()

logObj.mu.RLock()

defer logObj.mu.RUnlock()

if logLevel <= WARN {

logObj.lg.Output(2, fmt.Sprintln("warn", v))

console("warn", v)

}

}

func Error(v ...interface{}) {

if dailyRolling {

fileCheck()

}

defer catchError()

logObj.mu.RLock()

defer logObj.mu.RUnlock()

if logLevel <= ERROR {

logObj.lg.Output(2, fmt.Sprintln("error", v))

console("error", v)

}

}

func Fatal(v ...interface{}) {

if dailyRolling {

fileCheck()

}

defer catchError()

logObj.mu.RLock()

defer logObj.mu.RUnlock()

if logLevel <= FATAL {

logObj.lg.Output(2, fmt.Sprintln("fatal", v))

console("fatal", v)

}

}


func (f *_FILE) isMustRename() bool {

if dailyRolling {

t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))

if t.After(*f._date) {

return true

}

} else {

if maxFileCount > 1 {

if fileSize(f.dir+"/"+f.filename) >= maxFileSize {

return true

}

}

}

return false

}


func (f *_FILE) rename() {

if dailyRolling {

fn := f.dir + "/" + f.filename + "." + f._date.Format(DATEFORMAT)

if !isExist(fn) && f.isMustRename() {

if f.logfile != nil {

f.logfile.Close()

}

err := os.Rename(f.dir+"/"+f.filename, fn)

if err != nil {

f.lg.Println("rename err", err.Error())

}

t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))

f._date = &t

f.logfile, _ = os.Create(f.dir + "/" + f.filename)

f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)

}

} else {

f.coverNextOne()

}

}


func (f *_FILE) nextSuffix() int {

return int(f._suffix%int(maxFileCount) + 1)

}


func (f *_FILE) coverNextOne() {

f._suffix = f.nextSuffix()

if f.logfile != nil {

f.logfile.Close()

}

if isExist(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix))) {

os.Remove(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix)))

}

os.Rename(f.dir+"/"+f.filename, f.dir+"/"+f.filename+"."+strconv.Itoa(int(f._suffix)))

f.logfile, _ = os.Create(f.dir + "/" + f.filename)

f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)

}


func fileSize(file string) int64 {

fmt.Println("fileSize", file)

f, e := os.Stat(file)

if e != nil {

fmt.Println(e.Error())

return 0

}

return f.Size()

}


func isExist(path string) bool {

_, err := os.Stat(path)

return err == nil || os.IsExist(err)

}


func fileMonitor() {

timer := time.NewTicker(1 * time.Second)

for {

select {

case <-timer.C:

fileCheck()

}

}

}


func fileCheck() {

defer func() {

if err := recover(); err != nil {

log.Println(err)

}

}()

if logObj != nil && logObj.isMustRename() {

logObj.mu.Lock()

defer logObj.mu.Unlock()

logObj.rename()

}

}


使用方法

package example

import (
"github.com/donnie4w/go-logger/logger"
"runtime"
"strconv"
"testing"
"time"
)

func log(i int) {
logger.Debug("Debug>>>>>>>>>>>>>>>>>>>>>>" + strconv.Itoa(i))
logger.Info("Info>>>>>>>>>>>>>>>>>>>>>>>>>" + strconv.Itoa(i))
logger.Warn("Warn>>>>>>>>>>>>>>>>>>>>>>>>>" + strconv.Itoa(i))
logger.Error("Error>>>>>>>>>>>>>>>>>>>>>>>>>" + strconv.Itoa(i))
logger.Fatal("Fatal>>>>>>>>>>>>>>>>>>>>>>>>>" + strconv.Itoa(i))
}

func Test(t *testing.T) {
runtime.GOMAXPROCS(runtime.NumCPU())

//指定是否控制台打印,默认为true
logger.SetConsole(true)
//指定日志文件备份方式为文件大小的方式
//第一个参数为日志文件存放目录
//第二个参数为日志文件命名
//第三个参数为备份文件最大数量
//第四个参数为备份文件大小
//第五个参数为文件大小的单位
//logger.SetRollingFile("d:/logtest", "test.log", 10, 5, logger.KB)

//指定日志文件备份方式为日期的方式
//第一个参数为日志文件存放目录
//第二个参数为日志文件命名
logger.SetRollingDaily("d:/logtest", "test.log")

//指定日志级别  ALL,DEBUG,INFO,WARN,ERROR,FATAL,OFF 级别由低到高
//一般习惯是测试阶段为debug,生成环境为info以上
logger.SetLevel(logger.ERROR)

for i := 10000; i > 0; i-- {
go log(i)
time.Sleep(1000 * time.Millisecond)
}
time.Sleep(15 * time.Second)
}



本文转载自:https://github.com/donnie4w/go-logger

共有 人打赏支持
敲代码中
粉丝 1
博文 16
码字总数 5522
作品 0
厦门
学习golang并做一个简单分布式存储项目

从14年中开始陆续一年,断断续续学习了下Golang,看了Go语言编程,Go语言程序设计2本书。 始终觉得应该做点项目锻炼下,因为正好看《从paxos到zookeeper》,就尝试写一些网络应用,分布式存储...

丁永 ⋅ 2015/11/19 ⋅ 0

Golang中使用log(二):Golang 标准库log的实现

前一篇文章我们看到了Golang标准库中log模块的使用,那么它是如何实现的呢?下面我从log.Logger开始逐步分析其实现。 其源码可以参考官方地址 1.Logger结构 首先来看下类型Logger的定义: ty...

gotaly ⋅ 2014/05/05 ⋅ 0

Golang中使用log(一):Golang 标准库提供的Log

Golang的标准库提供了log的机制,但是该模块的功能较为简单(看似简单,其实他有他的设计思路)。不过比手写fmt. Printxxx还是强很多的。至少在输出的位置做了线程安全的保护。其官方手册见G...

gotaly ⋅ 2014/05/03 ⋅ 0

简单扩展性好的日志库 - Go Logger

go-logger 一个简单而强大的 golang 日志工具包 English document 功能 支持同时输出到 console, file, url 命令行输出字体可带颜色 文件输出支持根据 文件大小,文件行数,日期三种方式切分...

phachon ⋅ 2017/10/12 ⋅ 1

Golang依赖关联工具:glide从入门到精通使用

介绍 不论是开发Java还是你正在学习的Golang,都会遇到依赖管理问题。Java有牛逼轰轰的Maven和Gradle。 Golang亦有godep、govendor、glide、gvt、gopack等等,本文主要给大家介绍gilde。 gl...

梦朝思夕 ⋅ 2017/07/19 ⋅ 0

golang连接mysql操作及动态连接池设置

golang本身没有提供连接mysql的驱动,但是定义了标准接口供第三方开发驱动。这里连接mysql可以使用第三方库,第三方库推荐使用https://github.com/Go-SQL-Driver/MySQL这个驱动,更新维护都比...

mickelfeng ⋅ 03/02 ⋅ 0

梁大帅/mqant

mqant mqant是一款基于Golang语言的简洁,高效,高性能的分布式游戏服务器框架,研发的初衷是要实现一款能支持高并发,高性能,高实时性,的游戏服务器框架,也希望mqant未来能够做即时通讯和物联网...

梁大帅 ⋅ 2017/07/03 ⋅ 0

Golang使用redis protocol实现pubsub通信

前言: 闲来无事,加工作不饱和,饱思淫欲的状态下,用golang实现了一个基于redis通信协议的pubsub通信服务端. 这个轮子实现的还很粗暴,内部实现主要用的是golang channel ,不仅可以高效的控...

rfyiamcool ⋅ 2017/11/15 ⋅ 0

go-logger 日志工具包 v1.1 发布

go-logger 一个简单而强大的 golang 日志工具包 English document 更新 重构了日志输出文件 输出到文件支持根据日志级别输出到不同的日志文件 功能 支持同时输出到 console, file, url 命令行...

phachon ⋅ 03/23 ⋅ 8

Golang 学习笔记(安装)

这份笔记按照的参考资料为《GO并发编程实战》 和 无闻的《跟无闻学Go语言:Go编程基础视频教程》 ,按照《GO并发编程实战》的章节顺序缓慢更新。。冏 Golang简介啥的就忙了吧-。- , 不知道g...

Marmot_Alex ⋅ 2014/12/28 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

行政区划代码转为字典形式

原数据为: http://www.mca.gov.cn/article/sj/xzqh/2018/201804-12/201804-06041553.html 手动替换了一下格式,并使用下面的代码处理. # 输入格式s = """110000:北京市110101:东城区1101...

漫步海边小路 ⋅ 20分钟前 ⋅ 0

android apk 签名

创建key,需要用到keytool.exe (位于C:\Program Files\Java\jdk1.6.0_10\bin目录下),使用产生的key对apk签名用到的是jarsigner.exe (位于C:\Program Files\Java\jdk1.6.0_10\bin目录下),把...

国仔饼 ⋅ 29分钟前 ⋅ 0

springcloud+jps+mybatis多数据库配置

多数据库配置 配置我们目录结构设置: config ---datasource ----jpa ----mybatis ----redis Datasource中是数据的相关配置 Jap中是springDatajpa的相关配置 Mybatis中是mybatis的相关配置 ...

大-智-若-愚 ⋅ 36分钟前 ⋅ 0

Spring mvc HandlerMapping 实现机制

概述 当DispatcherServlet接受到客户端的请求后,SpringMVC 通过 HandlerMapping 找到请求的Controller。 HandlerMapping 在这里起到路由的作用,负责找到请求的Controller。 Spring MVC 默认...

轨迹_ ⋅ 39分钟前 ⋅ 0

JavaScript零基础入门——(十)JavaScript的DOM基础

JavaScript零基础入门——(十)JavaScript的DOM基础 欢迎大家回到我们的JavaScript零基础入门,上一节课,我们了解了JavaScript中的函数,这一节课,我们来了解一下JavaScript的DOM。 第一节...

JandenMa ⋅ 今天 ⋅ 0

Weex起步

本教程假设你已经在你的本地环境安装了node 其实weex起步教程在 https://github.com/lilugirl/incubator-weex 项目说明文件中都已经有了,但为了有些同学看到英文秒变文盲,所以这里我重新写...

lilugirl ⋅ 今天 ⋅ 0

Jenkins实践1 之安装

1 下载 http://mirrors.jenkins.io/war/latest/jenkins.war 2 启动 java -jar jenkins.war 前提:安装jdk并配置环境变量 启动结果节选: ************************************************......

晨猫 ⋅ 今天 ⋅ 0

组合数学 1-2000 中,能被6或10整除的数的个数

1--2000 中,能被6或10整除的数的个数 利用集合的性质 能被6整除的个数 2000/6 = 333 能被10整除的个数 2000/10 = 200 能被6和10整除的个数 2000/30 = 66 能被6或10整除的个数 333+200-66 =...

阿豪boy ⋅ 今天 ⋅ 0

一篇文章学懂Shell脚本

Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合。 Shell可以直接使用在win/Unix/Linux上面,并且可以调用...

Jake_xun ⋅ 今天 ⋅ 0

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部