Compare commits

...

6 Commits

Author SHA1 Message Date
rick.chan
7f15eb4e36 整理注释。
Signed-off-by: rick.chan <cy@haoan119.com>
2025-04-07 08:59:43 +08:00
rick.chan
e6de5c461d 修改 README。
Signed-off-by: rick.chan <cy@haoan119.com>
2025-04-07 08:46:04 +08:00
rick.chan
4065555565 简化变量名称。
Signed-off-by: rick.chan <cy@haoan119.com>
2025-04-07 08:46:03 +08:00
rick.chan
f82e6db6f8 提供日志等级类型,修正帮助说明。
Signed-off-by: rick.chan <cy@haoan119.com>
2025-04-07 08:46:03 +08:00
rick.chan
cb55fecbc6 修正 ms 显示格式,File Rotating 模式支持续写,如果文件已存在不对上次内容进行覆盖,而是从文件结尾继续往下写,或直接写下一个文件。
Signed-off-by: rick.chan <cy@haoan119.com>
2025-04-07 08:46:03 +08:00
rick.chan
ac9c772fb6 迁移项目。
Signed-off-by: rick.chan <cy@haoan119.com>
2025-04-07 08:46:03 +08:00
6 changed files with 147 additions and 35 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vscode/settings.json
*.log
*.log.*

44
README.md Normal file
View File

@ -0,0 +1,44 @@
# Simple Log
A very simple log system(golang).
## Install
```bash
go get github.com/lion187chen/simplelog
```
## Example
```go
package main
import (
"time"
"github.com/lion187chen/simplelog"
)
func CreateLog(file string, level simplelog.Level) *simplelog.Log {
switch file {
case "":
return new(simplelog.Log).InitStd(level, simplelog.Ltime|simplelog.Lfile|simplelog.Llevel)
default:
return new(simplelog.Log).InitRotating(file, 1024*10, 10, level)
}
}
func main() {
log := CreateLog("./log/MS.log", simplelog.LevelInfo)
for i := 0; i < 10000000; i++ {
log.Trace("hello world")
log.Debug("hello world")
log.Info("hello world")
log.Warn("hello world")
log.Error("hello world")
log.Fatal("hello world")
time.Sleep(8 * time.Millisecond)
}
}
```

29
demo/main.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"time"
"github.com/lion187chen/simplelog"
)
func CreateLog(file string, level simplelog.Level) *simplelog.Log {
switch file {
case "":
return new(simplelog.Log).InitStd(level, simplelog.Ltime|simplelog.Lfile|simplelog.Llevel)
default:
return new(simplelog.Log).InitRotating(file, 1024*10, 10, level)
}
}
func main() {
log := CreateLog("./log/MS.log", simplelog.LevelInfo)
for i := 0; i < 10000000; i++ {
log.Trace("hello world")
log.Debug("hello world")
log.Info("hello world")
log.Warn("hello world")
log.Error("hello world")
log.Fatal("hello world")
time.Sleep(8 * time.Millisecond)
}
}

View File

@ -2,11 +2,22 @@ package simplelog
import (
"fmt"
"io"
"os"
"path"
"time"
)
func isFileExist(filename string) bool {
info, e := os.Stat(filename)
if e == nil {
return !info.IsDir()
} else {
return os.IsExist(e)
}
}
// FileHandler writes log to a file.
type FileHandler struct {
fd *os.File
@ -48,6 +59,29 @@ type RotatingFileHandler struct {
}
func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCount int) (*RotatingFileHandler, error) {
h.fileName = name
h.maxBytes = maxBytes
h.backupCount = backupCount
if isFileExist(name) {
var err error
h.fd, err = os.OpenFile(name, os.O_CREATE|os.O_RDONLY, 0666)
if err != nil {
return nil, err
}
f, err := h.fd.Stat()
if err != nil {
h.fd.Close()
return nil, err
}
if f.Size() < int64(h.maxBytes) {
h.fd.Seek(0, io.SeekEnd)
} else {
h._doRollover()
}
return h, nil
}
dir := path.Dir(name)
os.MkdirAll(dir, 0777)
@ -55,10 +89,6 @@ func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCoun
return nil, fmt.Errorf("invalid max bytes")
}
h.fileName = name
h.maxBytes = maxBytes
h.backupCount = backupCount
var err error
h.fd, err = os.OpenFile(name, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
@ -106,6 +136,10 @@ func (h *RotatingFileHandler) doRollover() {
return
}
h._doRollover()
}
func (h *RotatingFileHandler) _doRollover() {
if h.backupCount > 0 {
h.fd.Close()

2
go.mod
View File

@ -1,3 +1,3 @@
module blacktea.cpolar.cn/OrgGo/simplelog
module github.com/lion187chen/simplelog
go 1.21.0

View File

@ -28,9 +28,11 @@ import (
"time"
)
type Level int
// log level, from low to high, more higher means more serious
const (
LevelTrace = iota
LevelTrace Level = iota
LevelDebug
LevelInfo
LevelWarn
@ -39,7 +41,7 @@ const (
)
const (
Ltime = 1 << iota //print timestamp format as "2006/01/02 15:04:05.000"
Ltime = 1 << iota // print timestamp format as "2006/01/02 15:04:05.000"
Lfile // print file name and line format as file.go:123
Llevel // print log level format as [Trace|Debug|Info...]
)
@ -60,7 +62,7 @@ func (i *atomicInt32) Get() int {
return int(atomic.LoadInt32((*int32)(i)))
}
type SimpleLog struct {
type Log struct {
level atomicInt32
flag int
@ -91,8 +93,8 @@ type SimpleLog struct {
// log.Lfile
// log.Llevel
// 的组合
func (l *SimpleLog) Init(handler StreamHandler, level, flag int) *SimpleLog {
l.level.Set(level)
func (l *Log) Init(handler StreamHandler, level Level, flag int) *Log {
l.level.Set(int(level))
l.handler = handler
l.flag = flag
@ -103,7 +105,7 @@ func (l *SimpleLog) Init(handler StreamHandler, level, flag int) *SimpleLog {
return l
}
func (l *SimpleLog) InitStd(level, flag int) *SimpleLog {
func (l *Log) InitStd(level Level, flag int) *Log {
handler, e := NewStreamHandle(os.Stdout)
if e != nil {
panic(e)
@ -112,7 +114,7 @@ func (l *SimpleLog) InitStd(level, flag int) *SimpleLog {
return l.Init(handler, level, flag)
}
func (l *SimpleLog) InitFile(name string, level, flag int) *SimpleLog {
func (l *Log) InitFile(name string, level Level, flag int) *Log {
handler, e := new(FileHandler).InitFile(name)
if e != nil {
panic(e)
@ -121,7 +123,7 @@ func (l *SimpleLog) InitFile(name string, level, flag int) *SimpleLog {
return l.Init(handler, level, flag)
}
func (l *SimpleLog) InitRotating(name string, maxBytes, backupCount, level int) *SimpleLog {
func (l *Log) InitRotating(name string, maxBytes, backupCount int, level Level) *Log {
handler, e := new(RotatingFileHandler).InitRotating(name, maxBytes, backupCount)
if e != nil {
panic(e)
@ -130,7 +132,7 @@ func (l *SimpleLog) InitRotating(name string, maxBytes, backupCount, level int)
return l.Init(handler, level, Ltime|Lfile|Llevel)
}
func (l *SimpleLog) InitTimedRotating(name string, when int8, interval, level int) *SimpleLog {
func (l *Log) InitTimedRotating(name string, when int8, interval int, level Level) *Log {
handler, e := new(TimedRotatingFileHandler).InitTimedRotating(name, when, interval)
if e != nil {
panic(e)
@ -139,7 +141,7 @@ func (l *SimpleLog) InitTimedRotating(name string, when int8, interval, level in
return l.Init(handler, level, Ltime|Lfile|Llevel)
}
func (l *SimpleLog) popBuf() []byte {
func (l *Log) popBuf() []byte {
l.bufMutex.Lock()
var buf []byte
if len(l.bufs) == 0 {
@ -153,7 +155,7 @@ func (l *SimpleLog) popBuf() []byte {
return buf
}
func (l *SimpleLog) putBuf(buf []byte) {
func (l *Log) putBuf(buf []byte) {
l.bufMutex.Lock()
if len(l.bufs) < maxBufPoolSize {
buf = buf[0:0]
@ -162,7 +164,7 @@ func (l *SimpleLog) putBuf(buf []byte) {
l.bufMutex.Unlock()
}
func (l *SimpleLog) Close() {
func (l *Log) Close() {
if l.closed.Get() == 1 {
return
}
@ -172,12 +174,12 @@ func (l *SimpleLog) Close() {
}
// set log level, any log level less than it will not log
func (l *SimpleLog) SetLevel(level int) {
l.level.Set(level)
func (l *Log) SetLevel(level Level) {
l.level.Set(int(level))
}
// name can be in ["trace", "debug", "info", "warn", "error", "fatal"]
func (l *SimpleLog) SetLevelByName(name string) {
func (l *Log) SetLevelByName(name string) {
name = strings.ToLower(name)
switch name {
case "trace":
@ -195,7 +197,7 @@ func (l *SimpleLog) SetLevelByName(name string) {
}
}
func (l *SimpleLog) SetHandler(h StreamHandler) {
func (l *Log) SetHandler(h StreamHandler) {
if l.closed.Get() == 1 {
return
}
@ -208,13 +210,13 @@ func (l *SimpleLog) SetHandler(h StreamHandler) {
l.hMutex.Unlock()
}
func (l *SimpleLog) Output(callDepth int, level int, format string, v ...interface{}) {
func (l *Log) Output(callDepth int, level Level, format string, v ...interface{}) {
if l.closed.Get() == 1 {
// closed
return
}
if l.level.Get() > level {
if l.level.Get() > int(level) {
// higher level can be logged
return
}
@ -288,61 +290,61 @@ func (l *SimpleLog) Output(callDepth int, level int, format string, v ...interfa
}
// log with Trace level
func (l *SimpleLog) Trace(v ...interface{}) {
func (l *Log) Trace(v ...interface{}) {
l.Output(2, LevelTrace, "", v...)
}
// log with Debug level
func (l *SimpleLog) Debug(v ...interface{}) {
func (l *Log) Debug(v ...interface{}) {
l.Output(2, LevelDebug, "", v...)
}
// log with info level
func (l *SimpleLog) Info(v ...interface{}) {
func (l *Log) Info(v ...interface{}) {
l.Output(2, LevelInfo, "", v...)
}
// log with warn level
func (l *SimpleLog) Warn(v ...interface{}) {
func (l *Log) Warn(v ...interface{}) {
l.Output(2, LevelWarn, "", v...)
}
// log with error level
func (l *SimpleLog) Error(v ...interface{}) {
func (l *Log) Error(v ...interface{}) {
l.Output(2, LevelError, "", v...)
}
// log with fatal level
func (l *SimpleLog) Fatal(v ...interface{}) {
func (l *Log) Fatal(v ...interface{}) {
l.Output(2, LevelFatal, "", v...)
}
// log with Trace level
func (l *SimpleLog) Tracef(format string, v ...interface{}) {
func (l *Log) Tracef(format string, v ...interface{}) {
l.Output(2, LevelTrace, format, v...)
}
// log with Debug level
func (l *SimpleLog) Debugf(format string, v ...interface{}) {
func (l *Log) Debugf(format string, v ...interface{}) {
l.Output(2, LevelDebug, format, v...)
}
// log with info level
func (l *SimpleLog) Infof(format string, v ...interface{}) {
func (l *Log) Infof(format string, v ...interface{}) {
l.Output(2, LevelInfo, format, v...)
}
// log with warn level
func (l *SimpleLog) Warnf(format string, v ...interface{}) {
func (l *Log) Warnf(format string, v ...interface{}) {
l.Output(2, LevelWarn, format, v...)
}
// log with error level
func (l *SimpleLog) Errorf(format string, v ...interface{}) {
func (l *Log) Errorf(format string, v ...interface{}) {
l.Output(2, LevelError, format, v...)
}
// log with fatal level
func (l *SimpleLog) Fatalf(format string, v ...interface{}) {
func (l *Log) Fatalf(format string, v ...interface{}) {
l.Output(2, LevelFatal, format, v...)
}