master
hans 6 years ago
commit 993d40a7b6
  1. 1
      .gitignore
  2. 15
      README.md
  3. 207
      filelog.go
  4. 3
      go.mod
  5. 181
      gokit.go
  6. 55
      gokit_test.go
  7. 1
      kafka.go
  8. 69
      syslog.go

1
.gitignore vendored

@ -0,0 +1 @@
.idea/

@ -0,0 +1,15 @@
#### Usage
```
import git.qietv.work/public/logkit
logkit.Init(FIlE, "test", logkit.LevelDebug)
defer logkit.Exit()
logkit.Info("this is a log")
logkit.Infof("this is log %s", "arg")
```

@ -0,0 +1,207 @@
package logkit
import (
"bufio"
"bytes"
"fmt"
"os"
"path/filepath"
"sync"
"time"
)
type bufferNode struct {
bytes.Buffer
next *bufferNode
}
type mFileLogger struct {
writer *bufferWriter
mu sync.Mutex
filepath string
name string
freeList *bufferNode
freeListMu sync.Mutex
flushInterval time.Duration
fileSplitSize uint64
bufferSize int
}
type bufferWriter struct {
*bufio.Writer
logPath string
logName string
file *os.File
slot int
startTime time.Time
byteSize uint64 // The number of bytes written to this file
maxFileSize uint64
bufferSize int
}
func (w *mFileLogger) getBuffer() *bufferNode {
w.freeListMu.Lock()
b := w.freeList
if b != nil {
w.freeList = b.next
}
w.freeListMu.Unlock()
if b == nil {
b = new(bufferNode)
} else {
b.next = nil
b.Reset()
}
return b
}
func (w *mFileLogger) putBuffer(b *bufferNode) {
if b.Len() >= 256 {
// Let big buffers die with gc.
return
}
w.freeListMu.Lock()
b.next = w.freeList
w.freeList = b
w.freeListMu.Unlock()
}
func (w *mFileLogger) Exit() {
w.flush()
}
func NewFileLogger(path, name string, flushInterval time.Duration, fileSplitSize uint64, bufferSize int) Writer {
writer := &mFileLogger{
filepath: path,
name: name,
flushInterval: flushInterval,
fileSplitSize: fileSplitSize,
bufferSize: bufferSize,
}
go writer.flushDaemon()
return writer
}
func (w *mFileLogger) flushDaemon() {
//for _ = range time.NewTicker(w.flushInterval).C {
// w.flush()
//}
}
func (w *mFileLogger) flush() {
w.writer.Flush()
w.writer.Sync()
}
func (w *mFileLogger) Write(level Level, msg string) {
buf := w.getBuffer()
buf.WriteString(msg)
w.mu.Lock()
defer w.mu.Unlock()
writer := w.writer
if writer == nil {
w.writer = &bufferWriter{
logPath: w.filepath,
logName: w.name,
maxFileSize: w.fileSplitSize,
bufferSize: w.bufferSize,
}
writer = w.writer
}
if err := writer.checkRotate(time.Now()); err != nil {
fmt.Println("[logkit] check rotate err: " + err.Error())
return
}
writer.Write(buf.Bytes())
w.putBuffer(buf)
}
func (bufferW *bufferWriter) Write(p []byte) (int, error) {
n, err := bufferW.Writer.Write(p)
bufferW.byteSize += uint64(n)
return n, err
}
func (bufferW *bufferWriter) Sync() error {
return bufferW.file.Sync()
}
func (bufferW *bufferWriter) checkRotate(now time.Time) error {
if bufferW.file == nil {
return bufferW.rotate(now, 0)
}
sYear, sMonth, sDay := bufferW.startTime.Date()
year, month, day := now.Date()
if year != sYear || month != sMonth || day != sDay {
return bufferW.rotate(now, 0)
}
if bufferW.byteSize >= bufferW.maxFileSize {
return bufferW.rotate(now, bufferW.slot+1)
}
return nil
}
func (bufferW *bufferWriter) write(p []byte) (int, error) {
n, err := bufferW.Writer.Write(p)
bufferW.byteSize += uint64(n)
return n, err
}
func (bufferW *bufferWriter) rotate(oldTime time.Time, slot int) error {
if bufferW.file != nil {
bufferW.Flush()
bufferW.file.Close()
var newFileName string
year, month, day := oldTime.Date()
if slot > 0 {
newFileName = fmt.Sprintf("%s-%02d%02d%02d.%02d", bufferW.logPath, year, month, day, slot-1)
} else {
newFileName = fmt.Sprintf("%s-%02d%02d%02d", bufferW.logPath, year, month, day)
}
os.Rename(bufferW.logPath, newFileName)
}
if err := bufferW.openFile(bufferW.logPath, bufferW.logName); err != nil {
return fmt.Errorf("rotate file error: %#v", err)
}
fileInfo, _ := bufferW.file.Stat()
bufferW.byteSize = uint64(fileInfo.Size())
bufferW.Writer = bufio.NewWriterSize(bufferW.file, bufferW.bufferSize)
bufferW.slot = slot
bufferW.startTime = time.Now()
bufferW.byteSize = 0
return nil
}
func (bufferW *bufferWriter) openFile(fileName, logName string) error {
var file *os.File
var err error
for {
file, err = os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err == nil {
break
}
// try to create all the parent directories for specified log file
// if it doesn't exist
if os.IsNotExist(err) {
err2 := os.MkdirAll(filepath.Dir(fileName), 0755)
if err2 != nil {
return err
}
continue
}
return err
}
bufferW.file = file
return nil
}

@ -0,0 +1,3 @@
module log-kit
go 1.12

@ -0,0 +1,181 @@
package logkit
import (
"fmt"
"time"
)
var (
inited bool
logWriter Writer
logLevel = LevelInfo
logLevelName string
logName string
alsoStdout bool
levelToNames = map[Level]string{
LevelFatal: "FATAL",
LevelError: "ERROR",
LevelWarn: "WARN",
LevelInfo: "INFO",
LevelDebug: "DEBUG",
LevelTrace: "TRACE",
}
)
//Level 日志等级
type Level byte
const (
Default Level = iota
LevelTrace
LevelDebug
LevelInfo
LevelWarn
LevelError
LevelFatal
)
type Channel byte
const (
FIlE Channel = iota
SYSLOG
KAFKA
)
type Writer interface {
//Write 写日志
Write(Level, string)
//Exit 日志退出
Exit()
}
func Exit() {
logWriter.Exit()
}
func Init(channel Channel,name string, level Level) error {
if inited {
return fmt.Errorf("logkit has been inited")
}
if name != "" {
logName = name
} else {
fmt.Errorf("log name must not be empty")
}
logLevel = level
logLevelName = getLevelName(level)
if logWriter == nil && channel == FIlE {
logWriter = NewFileLogger(logName+".log", logName, time.Second * 5, 1204 * 1024 * 1800, 256 * 1024 )
inited = true
}
if logWriter == nil && channel == SYSLOG {
logWriter ,_ = NewSyslogWriter("", "", level, name)
}
return nil
}
func getLevelName(level Level) string {
levelName, _ := levelToNames[level]
return levelName
}
func format(msg string) string {
return fmt.Sprintf("%s [%s] %s \n", time.Now().Format("2006-01-02 15:04:05.999"), logLevelName, msg)
}
func write(level Level, msg string) {
if !inited {
fmt.Println(time.Now().Format("2006-01-02 15:04:05") + " [" + logLevelName + "] " + msg)
return
}
logWriter.Write(level, format(msg))
if alsoStdout {
fmt.Println(time.Now().Format("2006-01-02 15:04:05") + " [" + logLevelName + "] " + msg)
}
}
func level() Level {
return logLevel
}
func Debug(str string) {
if level() <= LevelDebug {
write(LevelDebug, str)
}
}
func Debugs(args ...interface{}) {
if level() <= LevelDebug {
write(LevelDebug, fmt.Sprintln(args...))
}
}
func Debugf(format string, args ...interface{}) {
if level() <= LevelDebug {
write(LevelDebug, fmt.Sprintf(format, args...))
}
}
func Info(str string) {
if level() <= LevelInfo {
write(LevelInfo, str)
}
}
func Infos(args ...interface{}) {
if level() <= LevelInfo {
write(LevelInfo, fmt.Sprintln(args...))
}
}
func Infof(format string, args ...interface{}) {
if level() <= LevelInfo {
write(LevelInfo, fmt.Sprintf(format, args...))
}
}
func Warn(str string) {
if level() <= LevelWarn {
write(LevelWarn, str)
}
}
func Warns(args ...interface{}) {
if level() <= LevelWarn {
write(LevelWarn, fmt.Sprintln(args...))
}
}
func Warnf(format string, args ...interface{}) {
if level() <= LevelWarn {
write(LevelWarn, fmt.Sprintf(format, args...))
}
}
func Error(str string) {
if level() <= LevelError {
write(LevelError, str)
}
}
func Errors(args ...interface{}) {
if level() <= LevelError {
write(LevelError, fmt.Sprintln(args...))
}
}
func Errorf(format string, args ...interface{}) {
if level() <= LevelError {
write(LevelError, fmt.Sprintf(format, args...))
}
}

@ -0,0 +1,55 @@
package logkit
import (
"fmt"
"strconv"
"testing"
"time"
)
func init() {
Init(SYSLOG,"test", LevelInfo)
}
func TestGoKit(t *testing.T) {
Init(FIlE, "test", LevelDebug)
}
func BenchmarkGoKit(b *testing.B) {
defer Exit()
b.ResetTimer()
for i := 0; i < b.N; i++ {
Info("test " + strconv.FormatInt(int64(i), 10))
}
}
func TestInfo(t *testing.T) {
defer Exit()
fmt.Println("start")
for i := 0; i< 10 ; i++ {
go func(i int) {
Info("test "+ strconv.FormatInt(int64(i), 10))
}(i)
}
fmt.Println("end")
time.Sleep(time.Second * 2)
//
//for i := 0; i< 1000 ; i++ {
// Info("test "+ strconv.FormatInt(int64(i), 10))
//}
time.Sleep(time.Second * 1)
Info("test 2")
time.Sleep(time.Second * 1)
Info("test 3")
}
func TestBuffer(t *testing.T) {
defer Exit()
//for i := 0 ; i < 1024; i++ {
// str += strconv.FormatInt(int64(i),10)
//}
Infof("test %s --- %s", "1", "23")
//Exit()
}

@ -0,0 +1 @@
package logkit

@ -0,0 +1,69 @@
package logkit
import "log/syslog"
type SyslogWriter struct {
network string
raddr string
priority syslog.Priority
tag string
writer *syslog.Writer
}
func NewSyslogWriter(network, raddr string, level Level, tag string) (Writer, error) {
var priority syslog.Priority
switch level {
case LevelDebug:
priority = syslog.LOG_DEBUG
break
case LevelInfo:
priority = syslog.LOG_INFO
break
case LevelWarn:
priority = syslog.LOG_WARNING
break
case LevelError:
priority = syslog.LOG_ERR
break
case LevelFatal:
priority = syslog.LOG_ALERT
break
default:
priority = syslog.LOG_INFO
}
writer, err := syslog.Dial(network, raddr,priority, tag)
if err != nil {
return nil, err
}
object := &SyslogWriter{
network: network,
raddr: raddr,
priority: priority,
tag: tag,
writer: writer,
}
return object, nil
}
func (self *SyslogWriter) Write(level Level, msg string) {
switch level {
case LevelFatal:
self.writer.Crit(msg)
case LevelError:
self.writer.Err(msg)
case LevelWarn:
self.writer.Warning(msg)
case LevelInfo:
self.writer.Info(msg)
case LevelDebug:
self.writer.Debug(msg)
default:
self.writer.Write([]byte(msg))
}
}
func (self *SyslogWriter) Exit() {
// ignore the error return code
self.writer.Close()
}
Loading…
Cancel
Save