初始化项目
This commit is contained in:
2
trunk/goutil/logUtil/doc.go
Normal file
2
trunk/goutil/logUtil/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package logUtil
|
||||
package logUtil
|
||||
1
trunk/goutil/logUtil/impl-console/doc.go
Normal file
1
trunk/goutil/logUtil/impl-console/doc.go
Normal file
@@ -0,0 +1 @@
|
||||
package impl_console
|
||||
84
trunk/goutil/logUtil/impl-console/logger.go
Normal file
84
trunk/goutil/logUtil/impl-console/logger.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package impl_console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
}
|
||||
|
||||
// NewLogger
|
||||
// @description: 构造控制台日志
|
||||
// parameter:
|
||||
// return:
|
||||
// @*Logger:
|
||||
func NewLogger() *Logger {
|
||||
return &Logger{}
|
||||
}
|
||||
|
||||
// InfoLog
|
||||
// @description: 信息日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (cl *Logger) InfoLog(format string, args ...interface{}) {
|
||||
c := color.New(color.FgGreen)
|
||||
s := c.Sprint("Info:")
|
||||
fmt.Println(s, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// DebugLog
|
||||
// @description: 调试日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (cl *Logger) DebugLog(format string, args ...interface{}) {
|
||||
c := color.New(color.FgGreen)
|
||||
s := c.Sprint("Debug:")
|
||||
fmt.Println(s, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// WarnLog
|
||||
// @description: 警告日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (cl *Logger) WarnLog(format string, args ...interface{}) {
|
||||
c := color.New(color.FgYellow)
|
||||
_, _ = c.Println("Warn:", fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// ErrorLog
|
||||
// @description: 错误日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (cl *Logger) ErrorLog(format string, args ...interface{}) {
|
||||
c := color.New(color.FgRed)
|
||||
_, _ = c.Println("Error:", fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// FatalLog
|
||||
// @description: 致命错误日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (cl *Logger) FatalLog(format string, args ...interface{}) {
|
||||
c := color.New(color.FgRed)
|
||||
_, _ = c.Println("Fatal:", fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// CloseLog
|
||||
// @description: 关闭日志
|
||||
// parameter:
|
||||
// @waitFinish:是否等待日志
|
||||
// return:
|
||||
func (cl *Logger) CloseLog(waitFinish bool) {
|
||||
|
||||
}
|
||||
14
trunk/goutil/logUtil/impl-console/logger_test.go
Normal file
14
trunk/goutil/logUtil/impl-console/logger_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package impl_console
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInfoLog(t *testing.T) {
|
||||
log := NewLogger()
|
||||
log.DebugLog("Debug test")
|
||||
log.InfoLog("Info test")
|
||||
log.WarnLog("Warn test")
|
||||
log.ErrorLog("Error test")
|
||||
log.FatalLog("Fatal test")
|
||||
}
|
||||
63
trunk/goutil/logUtil/impl-es/api.go
Normal file
63
trunk/goutil/logUtil/impl-es/api.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package impl_es
|
||||
|
||||
// InfoLog
|
||||
// @description: 信息日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (l *Logger) InfoLog(format string, args ...interface{}) {
|
||||
info := l.buildEsLog("Info", format, args...)
|
||||
l.cache.addCacheLog(info)
|
||||
}
|
||||
|
||||
// DebugLog
|
||||
// @description: 调试日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (l *Logger) DebugLog(format string, args ...interface{}) {
|
||||
info := l.buildEsLog("Debug", format, args...)
|
||||
l.cache.addCacheLog(info)
|
||||
}
|
||||
|
||||
// WarnLog
|
||||
// @description: 警告日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (l *Logger) WarnLog(format string, args ...interface{}) {
|
||||
info := l.buildEsLog("Warn", format, args...)
|
||||
l.cache.addCacheLog(info)
|
||||
}
|
||||
|
||||
// ErrorLog
|
||||
// @description: 错误日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (l *Logger) ErrorLog(format string, args ...interface{}) {
|
||||
info := l.buildEsLog("Error", format, args...)
|
||||
l.cache.addCacheLog(info)
|
||||
}
|
||||
|
||||
// FatalLog
|
||||
// @description: 致命错误日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
func (l *Logger) FatalLog(format string, args ...interface{}) {
|
||||
info := l.buildEsLog("Fatal", format, args...)
|
||||
l.cache.addCacheLog(info)
|
||||
}
|
||||
|
||||
// CloseLog
|
||||
// @description: 关闭日志
|
||||
// parameter:
|
||||
// @waitFinish:是否等待日志
|
||||
// return:
|
||||
func (l *Logger) CloseLog(waitFinish bool) {}
|
||||
72
trunk/goutil/logUtil/impl-es/cache.go
Normal file
72
trunk/goutil/logUtil/impl-es/cache.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package impl_es
|
||||
|
||||
import "sync"
|
||||
|
||||
const (
|
||||
// 批量保存的消息数量
|
||||
con_MAX_NUMBER_OF_MESSAGE = 20
|
||||
)
|
||||
|
||||
// logCache
|
||||
// @description: 日志缓存
|
||||
type logCache struct {
|
||||
logCacheList []*EsLogModel // logCacheList 日志缓存对象
|
||||
logCacheMutex sync.RWMutex // logCacheMutex 锁
|
||||
}
|
||||
|
||||
// newlogCache
|
||||
// @description: 构造日志缓存
|
||||
// parameter:
|
||||
// return:
|
||||
// @*logCache:
|
||||
func newlogCache() *logCache {
|
||||
m := &logCache{
|
||||
logCacheList: make([]*EsLogModel, 0, 256),
|
||||
logCacheMutex: sync.RWMutex{},
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// 写入在线日志
|
||||
// 参数:
|
||||
// 日志信息对象
|
||||
// 返回值:
|
||||
// 无
|
||||
func (c *logCache) addCacheLog(logObj *EsLogModel) {
|
||||
c.logCacheMutex.Lock()
|
||||
defer c.logCacheMutex.Unlock()
|
||||
|
||||
c.logCacheList = append(c.logCacheList, logObj)
|
||||
}
|
||||
|
||||
// 获取日志数量
|
||||
// 参数:
|
||||
// 无
|
||||
// 返回值:
|
||||
// 缓存中的日志数量
|
||||
func (c *logCache) getCacheLogCount() int {
|
||||
c.logCacheMutex.RLock()
|
||||
defer c.logCacheMutex.RUnlock()
|
||||
|
||||
return len(c.logCacheList)
|
||||
}
|
||||
|
||||
// 获取缓存中的日志
|
||||
// 参数:
|
||||
// 数量
|
||||
// 返回值:
|
||||
// 日志列表对象
|
||||
func (c *logCache) getCacheLog(logCount int) (logList []*EsLogModel) {
|
||||
if logCount > con_MAX_NUMBER_OF_MESSAGE {
|
||||
logCount = con_MAX_NUMBER_OF_MESSAGE
|
||||
}
|
||||
|
||||
c.logCacheMutex.Lock()
|
||||
defer c.logCacheMutex.Unlock()
|
||||
|
||||
logList = c.logCacheList[:logCount]
|
||||
c.logCacheList = c.logCacheList[logCount:]
|
||||
|
||||
return
|
||||
}
|
||||
1
trunk/goutil/logUtil/impl-es/doc.go
Normal file
1
trunk/goutil/logUtil/impl-es/doc.go
Normal file
@@ -0,0 +1 @@
|
||||
package impl_es
|
||||
236
trunk/goutil/logUtil/impl-es/logger.go
Normal file
236
trunk/goutil/logUtil/impl-es/logger.go
Normal file
@@ -0,0 +1,236 @@
|
||||
package impl_es
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/elastic/go-elasticsearch/v8"
|
||||
"github.com/elastic/go-elasticsearch/v8/esutil"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const (
|
||||
// 如果缓存中的日志数量超过阈值,则记录日志
|
||||
con_WRITE_LOG_THRESHOLD_NUMBER = 1000
|
||||
)
|
||||
|
||||
// Logger
|
||||
// @description: es日志处理对象
|
||||
type Logger struct {
|
||||
esClient *elasticsearch.Client // esClient es客户端
|
||||
blukIndexer esutil.BulkIndexer // blukIndexer es批量索引
|
||||
indexNamePrefix string // indexNamePrefix 索引前缀
|
||||
curIndexName string // curIndexName 当前索引名字
|
||||
innerId string // innerId 系统唯一标识
|
||||
extendCb func() string // extendCb 扩展信息获取方法
|
||||
cache *logCache // cache 日志缓存
|
||||
}
|
||||
|
||||
// NewLogger
|
||||
// @description: 构造es日志对象
|
||||
// parameter:
|
||||
// @urls:
|
||||
// @username:
|
||||
// @pwd:
|
||||
// @esIndexName:
|
||||
// @_innerId:
|
||||
// @_extendCb:
|
||||
// return:
|
||||
// @*Logger:
|
||||
// @error:
|
||||
func NewLogger(urls []string, username, pwd string, esIndexName, _innerId string, _extendCb func() string) (*Logger, error) {
|
||||
if _extendCb == nil {
|
||||
_extendCb = func() string {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
esClient, err := elasticsearch.NewClient(elasticsearch.Config{
|
||||
Addresses: urls,
|
||||
Username: username,
|
||||
Password: pwd,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l := &Logger{
|
||||
esClient: esClient,
|
||||
blukIndexer: nil,
|
||||
indexNamePrefix: esIndexName,
|
||||
curIndexName: "",
|
||||
innerId: _innerId,
|
||||
extendCb: _extendCb,
|
||||
cache: newlogCache(),
|
||||
}
|
||||
|
||||
l.curIndexName = l.getCurIndexName()
|
||||
l.blukIndexer, err = l.newBlukIndexer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 启动日志处理
|
||||
l.start()
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// start
|
||||
// @description: 启动日志处理
|
||||
// parameter:
|
||||
// @receiver l:
|
||||
// return:
|
||||
func (l *Logger) start() {
|
||||
go l.logHandlerStart()
|
||||
go l.indexNameCheck()
|
||||
}
|
||||
|
||||
// getCurIndexName
|
||||
// @description: 获取索引名字
|
||||
// parameter:
|
||||
// @receiver l:
|
||||
// return:
|
||||
// @string:
|
||||
func (l *Logger) getCurIndexName() string {
|
||||
//获取当天日期
|
||||
return fmt.Sprintf("%s_%s", l.indexNamePrefix, time.Now().Format("20060102"))
|
||||
}
|
||||
|
||||
// newBlukIndexer
|
||||
// @description: 创建新的BlukIndexer
|
||||
// parameter:
|
||||
// @receiver l:
|
||||
// return:
|
||||
// @bulkIndexer:
|
||||
// @err:
|
||||
func (l *Logger) newBlukIndexer() (bulkIndexer esutil.BulkIndexer, err error) {
|
||||
bulkIndexer, err = esutil.NewBulkIndexer(esutil.BulkIndexerConfig{
|
||||
Index: l.getCurIndexName(), // The default index name
|
||||
Client: l.esClient, // The Elasticsearch client
|
||||
FlushInterval: time.Second, // The periodic flush interval
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("[es log]: Creating the indexer err: ", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 日志处理
|
||||
func (l *Logger) logHandlerStart() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("[es log]: Creating the indexer err: ", r)
|
||||
go l.logHandlerStart()
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
for {
|
||||
// 达到指定的时间或者指定的日志数量,则保存到消息队列中去
|
||||
logCount := l.cache.getCacheLogCount()
|
||||
if logCount == 0 || l.esClient == nil {
|
||||
time.Sleep(time.Second * 1)
|
||||
continue
|
||||
}
|
||||
|
||||
// 记录在线日志待发送数量
|
||||
if logCount > con_WRITE_LOG_THRESHOLD_NUMBER {
|
||||
fmt.Printf("[es log]: 当前缓存中共有%d条未发送到在线日志系统的日志", logCount)
|
||||
}
|
||||
|
||||
// 执行刷新
|
||||
l.bulkPushToOnlineLogSystem(l.cache.getCacheLog(logCount))
|
||||
}
|
||||
}
|
||||
|
||||
// indexNameCheck
|
||||
// @description: index名字校验
|
||||
// parameter:
|
||||
// @receiver l:
|
||||
// return:
|
||||
func (l *Logger) indexNameCheck() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("[es log]: indexNameCheck err: ", r)
|
||||
go l.indexNameCheck()
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
for {
|
||||
time.Sleep(time.Second * 1)
|
||||
|
||||
tempIndexName := l.getCurIndexName()
|
||||
if tempIndexName == l.curIndexName {
|
||||
continue
|
||||
}
|
||||
|
||||
// 关闭老的blukIndexer+建立新的blukIndexer
|
||||
newBlukIndexer, err := l.newBlukIndexer()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
tempBlukIndexer := l.blukIndexer
|
||||
l.blukIndexer = newBlukIndexer
|
||||
l.curIndexName = tempIndexName
|
||||
|
||||
// 暂停3s,等待正在写入的数据写入完成
|
||||
time.Sleep(3 * time.Second)
|
||||
err = tempBlukIndexer.Close(context.Background())
|
||||
if err != nil {
|
||||
fmt.Println("[es log]:BlukIndexer close err:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bulkPushToOnlineLogSystem
|
||||
// @description: 批量保存到在线日志系统
|
||||
// parameter:
|
||||
// @receiver l:
|
||||
// @logList:
|
||||
// return:
|
||||
func (l *Logger) bulkPushToOnlineLogSystem(logList []*EsLogModel) {
|
||||
for _, logObj := range logList {
|
||||
message, err := json.Marshal(logObj)
|
||||
if err != nil {
|
||||
fmt.Println("[es log]: Marshal failed. Err:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = l.blukIndexer.Add(
|
||||
context.Background(),
|
||||
esutil.BulkIndexerItem{
|
||||
Action: "index",
|
||||
Body: bytes.NewReader(message),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println("[es log]: Add data err:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// buildOnlineLog
|
||||
// @description: 组装es日志对象
|
||||
// parameter:
|
||||
// @receiver l:
|
||||
// @logType:
|
||||
// @format:
|
||||
// @args:
|
||||
// return:
|
||||
// @newLogObj:
|
||||
func (l *Logger) buildEsLog(logType, format string, args ...interface{}) (newLogObj *EsLogModel) {
|
||||
msg := format
|
||||
if len(args) > 0 {
|
||||
msg = fmt.Sprintf(format, args...)
|
||||
}
|
||||
|
||||
// 构造新的日志对象
|
||||
newLogObj = newEsLogModel(logType, msg, l.innerId, l.extendCb)
|
||||
|
||||
return
|
||||
}
|
||||
25
trunk/goutil/logUtil/impl-es/logger_test.go
Normal file
25
trunk/goutil/logUtil/impl-es/logger_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package impl_es
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
urls := []string{"http://10.1.0.71:9101/"}
|
||||
log, err := NewLogger(urls, "", "", "es_log_test", "les_log_test", nil)
|
||||
if err != nil {
|
||||
t.Error("esLog 创建失败")
|
||||
}
|
||||
|
||||
for i := 1; i <= 1000; i++ {
|
||||
log.DebugLog("Debug test %v", i)
|
||||
log.InfoLog("Info test %v", i)
|
||||
log.WarnLog("Warn test %v", i)
|
||||
log.ErrorLog("Error test %v", i)
|
||||
log.FatalLog("Fatal test %v", i)
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
53
trunk/goutil/logUtil/impl-es/model.go
Normal file
53
trunk/goutil/logUtil/impl-es/model.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package impl_es
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
logPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &EsLogModel{}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 日志对象
|
||||
type EsLogModel struct {
|
||||
// 日志类型
|
||||
LogType string
|
||||
|
||||
// 日志消息
|
||||
Message string
|
||||
|
||||
// 程序标识
|
||||
InnerId string
|
||||
|
||||
// Extendstr 扩展信息
|
||||
Extendstr string
|
||||
|
||||
// 日志时间
|
||||
CrTime time.Time
|
||||
}
|
||||
|
||||
// newEsLogModel
|
||||
// @description: 构造esLog对象
|
||||
// parameter:
|
||||
// @logType:日志类型
|
||||
// @msg:日志内容
|
||||
// @innerId:内部唯一id
|
||||
// @extendCb:扩展信息回调方法
|
||||
// return:
|
||||
// @*EsLogModel:
|
||||
func newEsLogModel(logType string, msg string, innerId string, extendCb func() string) *EsLogModel {
|
||||
logObj := logPool.Get().(*EsLogModel)
|
||||
|
||||
logObj.CrTime = time.Now()
|
||||
logObj.LogType = logType
|
||||
logObj.Message = msg
|
||||
logObj.InnerId = innerId
|
||||
logObj.Extendstr = extendCb()
|
||||
|
||||
return logObj
|
||||
}
|
||||
35
trunk/goutil/logUtil/impl-localfile/api.go
Normal file
35
trunk/goutil/logUtil/impl-localfile/api.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package impl_localfile
|
||||
|
||||
import "sync"
|
||||
|
||||
func (l *Logger) InfoLog(format string, args ...interface{}) {
|
||||
l.log(getLog(format, args...), info, true)
|
||||
}
|
||||
|
||||
func (l *Logger) WarnLog(format string, args ...interface{}) {
|
||||
l.log(getLog(format, args...), warn, true)
|
||||
}
|
||||
|
||||
func (l *Logger) DebugLog(format string, args ...interface{}) {
|
||||
l.log(getLog(format, args...), debug, true)
|
||||
}
|
||||
|
||||
func (l *Logger) ErrorLog(format string, args ...interface{}) {
|
||||
l.log(getLog(format, args...), _error, true)
|
||||
}
|
||||
|
||||
func (l *Logger) FatalLog(format string, args ...interface{}) {
|
||||
l.log(getLog(format, args...), fatal, true)
|
||||
}
|
||||
|
||||
func (l *Logger) CloseLog(waitFinish bool) {
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
// 关闭所有的file
|
||||
for _, logger := range l.loggerMap {
|
||||
wg.Add(1)
|
||||
go logger.Close(&wg, waitFinish)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
3
trunk/goutil/logUtil/impl-localfile/doc.go
Normal file
3
trunk/goutil/logUtil/impl-localfile/doc.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package impl_localfile
|
||||
|
||||
// 包名不能采用中分线,而且前面的包已经说明了是log包,这个子文件夹不需要在加上log
|
||||
203
trunk/goutil/logUtil/impl-localfile/log_file.go
Normal file
203
trunk/goutil/logUtil/impl-localfile/log_file.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package impl_localfile
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
con_FILE_SUFFIX = "txt"
|
||||
|
||||
defaultPanicNum = 10 // 默认支持的连续panic次数
|
||||
defaultPanicIntervals = 5 // 秒
|
||||
|
||||
fileMaxSize = 1 << 27 // 128M
|
||||
)
|
||||
|
||||
type fileLog struct {
|
||||
logPath string
|
||||
|
||||
// fileDir + fileName 用于判断是否需要切换日志文件
|
||||
fileDir string
|
||||
fileName string
|
||||
lv levelType
|
||||
|
||||
msgChan chan logObject
|
||||
|
||||
f *os.File
|
||||
|
||||
// 如果出现未知panic并一直发生,那么应该要真正的panic
|
||||
panicNum int
|
||||
panicTime time.Time
|
||||
|
||||
// 当前已经写入的大小
|
||||
curWriteSize int64
|
||||
}
|
||||
|
||||
func newLog(logPath string, lv levelType) *fileLog {
|
||||
f := &fileLog{
|
||||
logPath: logPath,
|
||||
fileDir: "",
|
||||
fileName: "",
|
||||
msgChan: make(chan logObject, 10240),
|
||||
lv: lv,
|
||||
f: nil,
|
||||
}
|
||||
|
||||
go f.loop()
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *fileLog) loop() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// 将错误输出,而不是记录到文件,是因为可能导致死循环
|
||||
fmt.Println("log file lv:", f.lv, " err:", r)
|
||||
|
||||
// 超过间隔时间重置
|
||||
if time.Since(f.panicTime)/time.Second > defaultPanicIntervals {
|
||||
f.panicNum = 0
|
||||
f.panicTime = time.Now()
|
||||
}
|
||||
|
||||
// 这里处理连续panic 也是防止循环调用形成死循环
|
||||
f.panicNum++
|
||||
if f.panicNum >= defaultPanicNum {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
go f.loop()
|
||||
}()
|
||||
|
||||
for logItem := range f.msgChan {
|
||||
f.writeLog(logItem)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fileLog) writeLog(logObj logObject) {
|
||||
// 由于不使用直接 logUtil 调用,logUtilPlus 存在终端打印的控制,所以 logUtil 只作为纯文件日志组件
|
||||
// if PrintImportantLog && (logObj.level == warn || logObj.level == _error || logObj.level == fatal) {
|
||||
// fmt.Println(logObj.logInfo)
|
||||
// }
|
||||
|
||||
// 检查是否需要去切换文件或者创建文件
|
||||
f.checkFileAndLoop(logObj.level, logObj.ifIncludeHour)
|
||||
|
||||
f.curWriteSize += int64(len(logObj.logInfo))
|
||||
_, _ = f.f.WriteString(logObj.logInfo)
|
||||
}
|
||||
|
||||
// 检查文件是否需要切换
|
||||
func (f *fileLog) checkFileAndLoop(level levelType, ifIncludeHour bool) {
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
fileAbsoluteDirectory := filepath.Join(f.logPath, strconv.Itoa(now.Year()), strconv.Itoa(int(now.Month())))
|
||||
fileName := ""
|
||||
|
||||
if ifIncludeHour {
|
||||
fileName = fmt.Sprintf("%s.%s.%s", time.Now().Format("2006-01-02-15"), level, con_FILE_SUFFIX)
|
||||
} else {
|
||||
fileName = fmt.Sprintf("%s.%s.%s", time.Now().Format("2006-01-02"), level, con_FILE_SUFFIX)
|
||||
}
|
||||
|
||||
// 说明已经存在, 检查文件大小,并切换
|
||||
if f.f != nil && f.fileName == fileName && f.fileDir == fileAbsoluteDirectory {
|
||||
if f.curWriteSize < fileMaxSize {
|
||||
return
|
||||
}
|
||||
|
||||
// 大小超额切换文件
|
||||
f.switchFile()
|
||||
return
|
||||
}
|
||||
|
||||
// 创建文件夹
|
||||
if f.fileDir != fileAbsoluteDirectory {
|
||||
if err := os.MkdirAll(fileAbsoluteDirectory, os.ModePerm|os.ModeTemporary); err != nil {
|
||||
log.Println("make dir all is err :", err)
|
||||
}
|
||||
f.fileDir = fileAbsoluteDirectory
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
if f.fileName != fileName {
|
||||
f.fileName = fileName
|
||||
}
|
||||
|
||||
// 到这里说明要切换了,关闭之前的file
|
||||
if f.f != nil {
|
||||
_ = f.f.Close()
|
||||
}
|
||||
|
||||
// 正常切换文件
|
||||
f.createFile()
|
||||
}
|
||||
|
||||
func (f *fileLog) switchFile() {
|
||||
// 关闭文件
|
||||
_ = f.f.Close()
|
||||
|
||||
// 重命名
|
||||
curFileName := filepath.Join(f.fileDir, f.fileName)
|
||||
newFileName := filepath.Join(f.fileDir, fmt.Sprintf("%s.%s.%s", f.fileName, time.Now().Format("15-04-05.999"), con_FILE_SUFFIX))
|
||||
err := os.Rename(curFileName, newFileName)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
// 再次创建文件
|
||||
f.createFile()
|
||||
}
|
||||
|
||||
func (f *fileLog) createFile() {
|
||||
// 得到最终的文件绝对路径
|
||||
fileAbsolutePath := filepath.Join(f.fileDir, f.fileName)
|
||||
// 打开文件(如果文件存在就以读写模式打开,并追加写入;如果文件不存在就创建,然后以写模式打开。)
|
||||
file, err := os.OpenFile(fileAbsolutePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm|os.ModeTemporary)
|
||||
if err != nil {
|
||||
log.Println("open file is err :", err)
|
||||
return
|
||||
}
|
||||
f.f = file
|
||||
stat, _ := file.Stat()
|
||||
f.curWriteSize = stat.Size()
|
||||
}
|
||||
|
||||
func (f *fileLog) SetLogPath(logPath string) {
|
||||
f.logPath = logPath
|
||||
}
|
||||
|
||||
// Close 最后等待 3s 钟
|
||||
func (f *fileLog) Close(wg *sync.WaitGroup, waitFinish bool) {
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
|
||||
if f.f != nil {
|
||||
_ = f.f.Close()
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
for {
|
||||
if !waitFinish || len(f.msgChan) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ticker.C:
|
||||
fmt.Println("wait close log file timeout:3s")
|
||||
return
|
||||
default:
|
||||
// 1ms 写入文件500条,最多等待 15ms 检查一次就行
|
||||
time.Sleep(15 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
223
trunk/goutil/logUtil/impl-localfile/logger.go
Normal file
223
trunk/goutil/logUtil/impl-localfile/logger.go
Normal file
@@ -0,0 +1,223 @@
|
||||
package impl_localfile
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"goutil/fileUtil"
|
||||
"goutil/timeUtil"
|
||||
)
|
||||
|
||||
const (
|
||||
con_SEPERATOR = "\n------------------------------------------------------\n"
|
||||
)
|
||||
|
||||
// Logger
|
||||
// @description: 日志对象
|
||||
type Logger struct {
|
||||
logPath string
|
||||
loggerMap map[levelType]*fileLog
|
||||
bufPool *sync.Pool
|
||||
|
||||
// 压缩属性
|
||||
// 上一次日志压缩的日期 时间戳
|
||||
preCompressDate int64
|
||||
// 压缩锁对象
|
||||
compressLock sync.Mutex
|
||||
}
|
||||
|
||||
// NewLogger
|
||||
// @description: 构造日志对象
|
||||
// parameter:
|
||||
//
|
||||
// @*Logger:
|
||||
func NewLogger() *Logger {
|
||||
log := &Logger{
|
||||
logPath: "Log",
|
||||
loggerMap: make(map[levelType]*fileLog, 4),
|
||||
bufPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &strings.Builder{}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 初始化基础日志
|
||||
for lv := range levels {
|
||||
log.loggerMap[levelType(lv)] = newLog(log.logPath, levelType(lv))
|
||||
}
|
||||
return log
|
||||
}
|
||||
|
||||
// log
|
||||
// @description: 记录日志
|
||||
// parameter:
|
||||
//
|
||||
// @receiver l:
|
||||
// @logInfo:
|
||||
// @lv:
|
||||
// @ifIncludeHour:
|
||||
//
|
||||
// return:
|
||||
func (l *Logger) log(logInfo string, lv levelType, ifIncludeHour bool) {
|
||||
buf := l.bufPool.Get().(*strings.Builder)
|
||||
defer l.bufPool.Put(buf)
|
||||
buf.Reset()
|
||||
|
||||
// 组装所有需要写入的内容
|
||||
// 获取当前时间
|
||||
buf.WriteString(time.Now().Format("2006-01-02 15:04:05"))
|
||||
buf.WriteString("---->\n")
|
||||
buf.WriteString(logInfo)
|
||||
// 加上最后的分隔符
|
||||
buf.WriteString(con_SEPERATOR)
|
||||
|
||||
// 写入之前检查
|
||||
l.checkCompress()
|
||||
|
||||
// 构造对象并添加到队列中
|
||||
l.loggerMap[lv].msgChan <- newLogObject(buf.String(), lv, ifIncludeHour)
|
||||
}
|
||||
|
||||
// SetLogPath
|
||||
// @description: 设置文件路径
|
||||
// parameter:
|
||||
//
|
||||
// @receiver l:
|
||||
// @_logPath:
|
||||
//
|
||||
// return:
|
||||
func (l *Logger) SetLogPath(_logPath string) {
|
||||
l.logPath = _logPath
|
||||
for _, lf := range l.loggerMap {
|
||||
lf.SetLogPath(_logPath)
|
||||
}
|
||||
}
|
||||
|
||||
// checkCompress
|
||||
// @description: 压缩
|
||||
// parameter:
|
||||
//
|
||||
// @receiver l:
|
||||
//
|
||||
// return:
|
||||
func (l *Logger) checkCompress() {
|
||||
// 不用压缩,直接返回
|
||||
if !l.preCompress() {
|
||||
return
|
||||
}
|
||||
|
||||
// 日志压缩
|
||||
go l.doCompress()
|
||||
}
|
||||
|
||||
// closeLogFile
|
||||
// @description: 关闭日志文件
|
||||
// parameter:
|
||||
//
|
||||
// @receiver l:
|
||||
//
|
||||
// return:
|
||||
func (l *Logger) closeLogFile() {
|
||||
// 需要压缩文件,关闭已经打开的文件
|
||||
for _, lf := range l.loggerMap {
|
||||
_ = lf.f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// preCompress 确定是否要压缩
|
||||
func (l *Logger) preCompress() bool {
|
||||
// 检查是否需要进行数据压缩
|
||||
nowDate := timeUtil.GetDate(time.Now()).Unix()
|
||||
if nowDate == l.preCompressDate {
|
||||
return false
|
||||
}
|
||||
|
||||
l.compressLock.Lock()
|
||||
defer l.compressLock.Unlock()
|
||||
|
||||
// 上一次压缩的时间
|
||||
if nowDate == l.preCompressDate {
|
||||
return false
|
||||
}
|
||||
|
||||
l.closeLogFile()
|
||||
|
||||
l.preCompressDate = nowDate
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 日志压缩
|
||||
func (l *Logger) doCompress() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// 将错误输出,而不是记录到文件,是因为可能导致死循环
|
||||
fmt.Println(r)
|
||||
}
|
||||
}()
|
||||
|
||||
// 获取昨天的日期,并获取昨天对应的文件夹
|
||||
yesterday := time.Now().AddDate(0, 0, -1)
|
||||
dateString := timeUtil.Format(yesterday, "yyyy-MM-dd")
|
||||
fileAbsoluteDirectory := filepath.Join(l.logPath, strconv.Itoa(yesterday.Year()), strconv.Itoa(int(yesterday.Month())))
|
||||
|
||||
// 判断是否已经存在压缩文件
|
||||
compressFileName := fmt.Sprintf("%s.tar.gz", dateString)
|
||||
compressAbsolutePath := filepath.Join(fileAbsoluteDirectory, compressFileName)
|
||||
if exists, err := fileUtil.IsFileExists(compressAbsolutePath); err == nil && exists {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取昨天的文件列表
|
||||
fileList, err := fileUtil.GetFileList2(fileAbsoluteDirectory, dateString, con_FILE_SUFFIX)
|
||||
if err != nil {
|
||||
fmt.Printf("logUtil.compress.fileUtil.GetFileList2 err:%s\n", err)
|
||||
return
|
||||
}
|
||||
if len(fileList) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 进行tar操作,得到yyyy-MM-dd.tar
|
||||
tarFileName := fmt.Sprintf("%s.tar", dateString)
|
||||
tarAbsolutePath := filepath.Join(fileAbsoluteDirectory, tarFileName)
|
||||
if err := fileUtil.Tar(fileList, tarAbsolutePath); err != nil {
|
||||
fmt.Printf("logUtil.compress.fileUtil.Tar err:%s\n", err)
|
||||
}
|
||||
|
||||
// 进行gzip操作,得到yyyy-MM-dd.tar.gz
|
||||
if err := fileUtil.Gzip(tarAbsolutePath, ""); err != nil {
|
||||
fmt.Printf("logUtil.compress.fileUtil.Gzip err:%s\n", err)
|
||||
}
|
||||
|
||||
// 删除原始文件
|
||||
for _, item := range fileList {
|
||||
_ = fileUtil.DeleteFile(item)
|
||||
}
|
||||
|
||||
// 删除tar文件
|
||||
_ = fileUtil.DeleteFile(tarAbsolutePath)
|
||||
}
|
||||
|
||||
// getLog
|
||||
// @description: 组装日志
|
||||
// parameter:
|
||||
//
|
||||
// @format:
|
||||
// @args:
|
||||
//
|
||||
// return:
|
||||
//
|
||||
// @string:
|
||||
func getLog(format string, args ...interface{}) string {
|
||||
if len(args) == 0 {
|
||||
return format
|
||||
} else {
|
||||
return fmt.Sprintf(format, args...)
|
||||
}
|
||||
}
|
||||
33
trunk/goutil/logUtil/impl-localfile/logtype.go
Normal file
33
trunk/goutil/logUtil/impl-localfile/logtype.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package impl_localfile
|
||||
|
||||
type levelType int
|
||||
|
||||
// 日志等级
|
||||
const (
|
||||
// info 信息
|
||||
info levelType = iota
|
||||
|
||||
// warn 警告
|
||||
warn
|
||||
|
||||
// debug 调试
|
||||
debug
|
||||
|
||||
// _error 错误
|
||||
_error
|
||||
|
||||
// fatal 致命
|
||||
fatal
|
||||
)
|
||||
|
||||
var levels = [...]string{
|
||||
"info",
|
||||
"warn",
|
||||
"debug",
|
||||
"error",
|
||||
"fatal",
|
||||
}
|
||||
|
||||
func (t levelType) String() string {
|
||||
return levels[t]
|
||||
}
|
||||
20
trunk/goutil/logUtil/impl-localfile/model.go
Normal file
20
trunk/goutil/logUtil/impl-localfile/model.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package impl_localfile
|
||||
|
||||
type logObject struct {
|
||||
// 日志信息
|
||||
logInfo string
|
||||
|
||||
// 日志等级
|
||||
level levelType
|
||||
|
||||
// 日志文件名称是否包含小时
|
||||
ifIncludeHour bool
|
||||
}
|
||||
|
||||
func newLogObject(logInfo string, level levelType, ifIncludeHour bool) logObject {
|
||||
return logObject{
|
||||
logInfo: logInfo,
|
||||
level: level,
|
||||
ifIncludeHour: ifIncludeHour,
|
||||
}
|
||||
}
|
||||
52
trunk/goutil/logUtil/interface.go
Normal file
52
trunk/goutil/logUtil/interface.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package logUtil
|
||||
|
||||
// ILog
|
||||
// @description: 日志接口
|
||||
type ILog interface {
|
||||
// InfoLog
|
||||
// @description: 信息日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
InfoLog(format string, args ...interface{})
|
||||
|
||||
// DebugLog
|
||||
// @description: 调试日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
DebugLog(format string, args ...interface{})
|
||||
|
||||
// WarnLog
|
||||
// @description: 警告日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
WarnLog(format string, args ...interface{})
|
||||
|
||||
// ErrorLog
|
||||
// @description: 错误日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
ErrorLog(format string, args ...interface{})
|
||||
|
||||
// FatalLog
|
||||
// @description: 致命错误日志记录
|
||||
// parameter:
|
||||
// @format:日志格式
|
||||
// @args:参数列表
|
||||
// return:
|
||||
FatalLog(format string, args ...interface{})
|
||||
|
||||
// CloseLog
|
||||
// @description: 关闭日志
|
||||
// parameter:
|
||||
// @waitFinish:是否等待日志
|
||||
// return:
|
||||
CloseLog(waitFinish bool)
|
||||
}
|
||||
57
trunk/goutil/logUtil/log.go
Normal file
57
trunk/goutil/logUtil/log.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package logUtil
|
||||
|
||||
import (
|
||||
"goutil/logUtil/impl-localfile"
|
||||
)
|
||||
|
||||
// 定义一个全局的日志对象
|
||||
var (
|
||||
// 日志列表
|
||||
logs []ILog
|
||||
|
||||
// 文件log
|
||||
fileLog *impl_localfile.Logger
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 提供默认的日志对象
|
||||
fileLog = impl_localfile.NewLogger()
|
||||
logs = append(logs, fileLog)
|
||||
}
|
||||
|
||||
// AddLogger
|
||||
// @description: 添加日志对象
|
||||
// parameter:
|
||||
//
|
||||
// @l:日志实现
|
||||
//
|
||||
// return:
|
||||
func SettingLogs(_logs []ILog) {
|
||||
if _logs == nil || len(_logs) == 0 {
|
||||
panic("_logs不能为nil或者len(_logs)==0")
|
||||
}
|
||||
|
||||
logs = _logs
|
||||
}
|
||||
|
||||
// GetLocalFileLog
|
||||
// @description: 获取文件日志对象
|
||||
// parameter:
|
||||
// return:
|
||||
//
|
||||
// @*log_localfile.Logger:
|
||||
func GetLocalFileLog() *impl_localfile.Logger {
|
||||
return fileLog
|
||||
}
|
||||
|
||||
// SetLogPath
|
||||
// @description: 设置文件日志路径
|
||||
// parameter:
|
||||
//
|
||||
// @_logPath:路径
|
||||
//
|
||||
// return:
|
||||
// Deprecated: use GetLocalFileLog().SetLogPath(_logPath) api instead
|
||||
func SetLogPath(_logPath string) {
|
||||
fileLog.SetLogPath(_logPath)
|
||||
}
|
||||
127
trunk/goutil/logUtil/log_api.go
Normal file
127
trunk/goutil/logUtil/log_api.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package logUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
con_MIN_SKIP = 1
|
||||
con_MAX_SKIP = 10
|
||||
)
|
||||
|
||||
// InfoLog 信息日志记录
|
||||
// format:日志格式
|
||||
// args:参数列表
|
||||
func InfoLog(format string, args ...interface{}) {
|
||||
for _, log := range logs {
|
||||
log.InfoLog(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// WarnLog 警告日志记录
|
||||
// format:日志格式
|
||||
// args:参数列表
|
||||
func WarnLog(format string, args ...interface{}) {
|
||||
for _, log := range logs {
|
||||
log.WarnLog(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// DebugLog 调试日志记录
|
||||
// format:日志格式
|
||||
// args:参数列表
|
||||
func DebugLog(format string, args ...interface{}) {
|
||||
for _, log := range logs {
|
||||
log.DebugLog(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorLog 错误日志记录
|
||||
// format:日志格式
|
||||
// args:参数列表
|
||||
func ErrorLog(format string, args ...interface{}) {
|
||||
for _, log := range logs {
|
||||
log.ErrorLog(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// FatalLog 致命错误日志记录
|
||||
// format:日志格式
|
||||
// args:参数列表
|
||||
func FatalLog(format string, args ...interface{}) {
|
||||
for _, log := range logs {
|
||||
log.FatalLog(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Close
|
||||
// @description: 关闭日志
|
||||
// parameter:
|
||||
// @waitFinish:是否等待关闭完成
|
||||
// return:
|
||||
func Close(waitFinish bool) {
|
||||
for _, log := range logs {
|
||||
log.CloseLog(waitFinish)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------Deprecated methods start----------------------------
|
||||
|
||||
// Log 日志记录
|
||||
// Deprecated: use XXXLog api instead
|
||||
func Log(logInfo string, lv LogType, ifIncludeHour bool) {
|
||||
switch lv {
|
||||
case Info:
|
||||
InfoLog(logInfo)
|
||||
case Warn:
|
||||
WarnLog(logInfo)
|
||||
case Debug:
|
||||
DebugLog(logInfo)
|
||||
case Error:
|
||||
ErrorLog(logInfo)
|
||||
case Fatal:
|
||||
FatalLog(logInfo)
|
||||
}
|
||||
}
|
||||
|
||||
// NormalLog 日志记录
|
||||
// Deprecated: use XXXLog api instead
|
||||
func NormalLog(logInfo string, level LogType) {
|
||||
Log(logInfo, level, true)
|
||||
}
|
||||
|
||||
// LogAndPrint 日志记录
|
||||
// Deprecated: use XXXLog api instead
|
||||
func LogAndPrint(logInfo string, level LogType) {
|
||||
NormalLog(logInfo, level)
|
||||
fmt.Println(logInfo)
|
||||
}
|
||||
|
||||
// LogUnknownError 日志记录
|
||||
func LogUnknownError(r interface{}, args ...string) {
|
||||
buf := strings.Builder{}
|
||||
buf.WriteString(fmt.Sprintf("通过recover捕捉到的未处理异常:%v \n", r))
|
||||
|
||||
// 获取附加信息
|
||||
if len(args) > 0 {
|
||||
buf.WriteString("附加信息:")
|
||||
buf.WriteString(strings.Join(args, "-"))
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
// 获取堆栈信息
|
||||
for skip := con_MIN_SKIP; skip <= con_MAX_SKIP; skip++ {
|
||||
_, file, line, ok := runtime.Caller(skip)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("skip = %d, file = %s, line = %d \n", skip, file, line))
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
|
||||
ErrorLog(buf.String())
|
||||
}
|
||||
|
||||
//--------------------------Deprecated methods end----------------------------
|
||||
67
trunk/goutil/logUtil/log_test.go
Normal file
67
trunk/goutil/logUtil/log_test.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package logUtil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
impl_console "goutil/logUtil/impl-console"
|
||||
impl_es "goutil/logUtil/impl-es"
|
||||
impl_localfile "goutil/logUtil/impl-localfile"
|
||||
)
|
||||
|
||||
func TestAllLog(t *testing.T) {
|
||||
file, _ := exec.LookPath(os.Args[0])
|
||||
path, _ := filepath.Abs(file)
|
||||
logPath := filepath.Dir(path)
|
||||
|
||||
GetLocalFileLog().SetLogPath(logPath)
|
||||
|
||||
//添加控制台日志
|
||||
consoleLog := impl_console.NewLogger()
|
||||
|
||||
//添加es日志
|
||||
urls := []string{"http://10.1.0.71:9101/"}
|
||||
eslog, err := impl_es.NewLogger(urls, "", "", "es_log_test", "les_log_test_innerid", nil)
|
||||
if err != nil {
|
||||
t.Error("esLog 创建失败")
|
||||
}
|
||||
SettingLogs([]ILog{consoleLog, eslog, impl_localfile.NewLogger()})
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
InfoLog("Info记录")
|
||||
InfoLog("Info记录2:%v %v", i, time.Now())
|
||||
|
||||
DebugLog("Debug记录")
|
||||
DebugLog("Debug记录2:%v %v", i, time.Now())
|
||||
|
||||
WarnLog("Warn记录")
|
||||
WarnLog("Warn记录2:%v %v", i, time.Now())
|
||||
|
||||
ErrorLog("Error记录")
|
||||
ErrorLog("ErrorLog记录2:%v %v", i, time.Now())
|
||||
|
||||
FatalLog("Fatal记录")
|
||||
FatalLog("Fatal记录2:%v %v", i, time.Now())
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 5)
|
||||
|
||||
Close(true)
|
||||
}
|
||||
|
||||
func BenchmarkInfoLog(b *testing.B) {
|
||||
file, _ := exec.LookPath(os.Args[0])
|
||||
path, _ := filepath.Abs(file)
|
||||
logPath := filepath.Dir(path)
|
||||
|
||||
GetLocalFileLog().SetLogPath(logPath)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
DebugLog("Debug 记录")
|
||||
InfoLog("info记录 :%v", time.Now())
|
||||
}
|
||||
Close(true)
|
||||
}
|
||||
44
trunk/goutil/logUtil/log_type.go
Normal file
44
trunk/goutil/logUtil/log_type.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package logUtil
|
||||
|
||||
type LogType int
|
||||
|
||||
// 日志等级
|
||||
const (
|
||||
// Info 信息
|
||||
Info LogType = iota
|
||||
|
||||
// Warn 警告
|
||||
Warn
|
||||
|
||||
// Debug 调试
|
||||
Debug
|
||||
|
||||
// Error 错误
|
||||
Error
|
||||
|
||||
// Fatal 致命
|
||||
Fatal
|
||||
)
|
||||
|
||||
// String
|
||||
// @description: 类型转化为字符串
|
||||
// parameter:
|
||||
// @receiver t:
|
||||
// return:
|
||||
// @string:
|
||||
func (t LogType) String() string {
|
||||
switch t {
|
||||
case Info:
|
||||
return "Info"
|
||||
case Warn:
|
||||
return "Warn"
|
||||
case Debug:
|
||||
return "Debug"
|
||||
case Error:
|
||||
return "Error"
|
||||
case Fatal:
|
||||
return "Fatal"
|
||||
}
|
||||
|
||||
return "LogTypeDefault"
|
||||
}
|
||||
50
trunk/goutil/logUtil/readme.md
Normal file
50
trunk/goutil/logUtil/readme.md
Normal file
@@ -0,0 +1,50 @@
|
||||
### 日志帮助类,默认实现 文本文件,控制台,elasticsearch(简写es) 三种记录方式。
|
||||
|
||||
1.在调用设置参数方法(SettingLogs)之前,会开启文本文件记录方式.
|
||||
2.在调用设置参数方法(SettingLogs)之后,默认记录方式关闭,根据参数配置决定开启哪些日志记录方式.
|
||||
3.注意:由于日志采用了缓存,关闭程序可能会导致未写入的日志丢失.
|
||||
4.日志帮助类内部错误日志默认路径为程序执行目录下Log子目录下,可以帮助排除日志帮助类内部异常.
|
||||
|
||||
#### =======================>注意事项<=========================
|
||||
|
||||
1.生产环境禁止开始控制台输出,频繁的控制台输出造成性能瓶颈。
|
||||
|
||||
#### =======================>使用方法说明<=========================
|
||||
|
||||
1.引入包
|
||||
2.配置日志输出,如果采用默认输出,可以跳过这一步
|
||||
3.调用方法输出日志
|
||||
|
||||
```go
|
||||
import (
|
||||
"goutil/logUtil"
|
||||
impl_console "goutil/logUtil/impl-console"
|
||||
impl_es "goutil/logUtil/impl-es"
|
||||
impl_localfile "goutil/logUtil/impl-localfile"
|
||||
)
|
||||
|
||||
func init(){
|
||||
//添加控制台日志
|
||||
consoleLog := impl_console.NewLogger()
|
||||
|
||||
//添加es日志
|
||||
urls := []string{"http://10.1.0.71:9101/"}
|
||||
eslog, err := impl_es.NewLogger(urls, "", "", "es_log_test", "les_log_test_innerid", nil)
|
||||
if err != nil {
|
||||
panic("esLog 创建失败")
|
||||
}
|
||||
|
||||
// 设置程序日志
|
||||
logUtil.SettingLogs([]ILog{consoleLog, eslog, impl_localfile.NewLogger()})
|
||||
}
|
||||
```
|
||||
|
||||
3.调用输出方法输出
|
||||
|
||||
```go
|
||||
logUtil.DebugLog("加载游戏配置start");
|
||||
logUtil.InfoLog("加载游戏配置start");
|
||||
logUtil.WarnLog("加载游戏配置start");
|
||||
logUtil.ErrorLog("加载游戏配置start");
|
||||
logUtil.FatalLog("加载游戏配置start");
|
||||
```
|
||||
Reference in New Issue
Block a user