Package Logger:

- Add option to define the buffer size for logger file
- Rework Hashicorp wrapper to not use a standalone pointer of logger and prefer a function to retrieve the logger
- reword some panic recovery message
This commit is contained in:
Nicolas JUHEL
2023-12-14 13:49:14 +01:00
parent eb9f94e916
commit 782f59d0aa
7 changed files with 239 additions and 55 deletions

View File

@@ -27,7 +27,11 @@
package config
import "os"
import (
"os"
libsiz "github.com/nabbar/golib/size"
)
type OptionsFile struct {
// LogLevel define the allowed level of log for this file.
@@ -59,6 +63,9 @@ type OptionsFile struct {
// EnableAccessLog allow to add all message from api router for access log and error log.
EnableAccessLog bool `json:"enableAccessLog,omitempty" yaml:"enableAccessLog,omitempty" toml:"enableAccessLog,omitempty" mapstructure:"enableAccessLog,omitempty"`
// FileBufferSize define the size for buffer size (by default the buffer size is set to 32KB).
FileBufferSize libsiz.Size `json:"file-buffer-size,omitempty" yaml:"file-buffer-size,omitempty" toml:"file-buffer-size,omitempty" mapstructure:"file-buffer-size,omitempty"`
}
type OptionsFiles []OptionsFile

View File

@@ -32,12 +32,12 @@ import (
liblog "github.com/nabbar/golib/logger"
)
func New(logger liblog.Logger) hclog.Logger {
func New(logger liblog.FuncLog) hclog.Logger {
return &_hclog{
l: logger,
}
}
func SetDefault(log liblog.Logger) {
func SetDefault(log liblog.FuncLog) {
hclog.SetDefault(New(log))
}

View File

@@ -30,10 +30,10 @@ package hashicorp
import (
"io"
"log"
"os"
"github.com/hashicorp/go-hclog"
liblog "github.com/nabbar/golib/logger"
logcfg "github.com/nabbar/golib/logger/config"
loglvl "github.com/nabbar/golib/logger/level"
)
@@ -43,74 +43,167 @@ const (
)
type _hclog struct {
l liblog.Logger
l liblog.FuncLog
}
func (o *_hclog) Log(level hclog.Level, msg string, args ...interface{}) {
var lg = o.logger()
if lg == nil {
return
}
switch level {
case hclog.NoLevel, hclog.Off:
return
case hclog.Trace:
o.l.Debug(msg, nil, args...)
lg.Entry(loglvl.DebugLevel, msg, args...).Log()
case hclog.Debug:
o.l.Debug(msg, nil, args...)
lg.Entry(loglvl.DebugLevel, msg, args...).Log()
case hclog.Info:
o.l.Info(msg, nil, args...)
lg.Entry(loglvl.InfoLevel, msg, args...).Log()
case hclog.Warn:
o.l.Warning(msg, nil, args...)
lg.Entry(loglvl.WarnLevel, msg, args...).Log()
case hclog.Error:
o.l.Error(msg, nil, args...)
lg.Entry(loglvl.ErrorLevel, msg, args...).Log()
}
}
func (o *_hclog) logger() liblog.Logger {
if o.l == nil {
return nil
} else if lg := o.l(); lg == nil {
return nil
} else {
return lg
}
}
func (o *_hclog) Trace(msg string, args ...interface{}) {
o.l.Debug(msg, nil, args...)
var lg = o.logger()
if lg == nil {
return
}
lg.Entry(loglvl.DebugLevel, msg, args...).Log()
}
func (o *_hclog) Debug(msg string, args ...interface{}) {
o.l.Debug(msg, nil, args...)
var lg = o.logger()
if lg == nil {
return
}
lg.Entry(loglvl.DebugLevel, msg, args...).Log()
}
func (o *_hclog) Info(msg string, args ...interface{}) {
o.l.Info(msg, nil, args...)
var lg = o.logger()
if lg == nil {
return
}
lg.Entry(loglvl.InfoLevel, msg, args...).Log()
}
func (o *_hclog) Warn(msg string, args ...interface{}) {
o.l.Warning(msg, nil, args...)
var lg = o.logger()
if lg == nil {
return
}
lg.Entry(loglvl.WarnLevel, msg, args...).Log()
}
func (o *_hclog) Error(msg string, args ...interface{}) {
o.l.Error(msg, nil, args...)
var lg = o.logger()
if lg == nil {
return
}
lg.Entry(loglvl.ErrorLevel, msg, args...).Log()
}
func (o *_hclog) IsTrace() bool {
if opt := o.l.GetOptions(); opt == nil {
var lg = o.logger()
if lg == nil {
return false
} else if opt.Stdout == nil {
return false
} else {
return opt.Stdout.EnableTrace
}
if opt := lg.GetOptions(); opt == nil {
return false
} else if opt.Stdout != nil && opt.Stdout.EnableTrace {
return true
} else {
for _, f := range opt.LogFile {
if f.EnableTrace {
return true
}
}
for _, f := range opt.LogSyslog {
if f.EnableTrace {
return true
}
}
}
return false
}
func (o *_hclog) IsDebug() bool {
return o.l.GetLevel() >= loglvl.DebugLevel
var lg = o.logger()
if lg == nil {
return false
}
return lg.GetLevel() >= loglvl.DebugLevel
}
func (o *_hclog) IsInfo() bool {
return o.l.GetLevel() >= loglvl.InfoLevel
var lg = o.logger()
if lg == nil {
return false
}
return lg.GetLevel() >= loglvl.InfoLevel
}
func (o *_hclog) IsWarn() bool {
return o.l.GetLevel() >= loglvl.WarnLevel
var lg = o.logger()
if lg == nil {
return false
}
return lg.GetLevel() >= loglvl.WarnLevel
}
func (o *_hclog) IsError() bool {
return o.l.GetLevel() >= loglvl.ErrorLevel
var lg = o.logger()
if lg == nil {
return false
}
return lg.GetLevel() >= loglvl.ErrorLevel
}
func (o *_hclog) ImpliedArgs() []interface{} {
fields := o.l.GetFields()
var lg = o.logger()
if lg == nil {
return make([]interface{}, 0)
}
fields := lg.GetFields()
if i, l := fields.Load(HCLogArgs); !l {
return make([]interface{}, 0)
@@ -122,12 +215,24 @@ func (o *_hclog) ImpliedArgs() []interface{} {
}
func (o *_hclog) With(args ...interface{}) hclog.Logger {
o.l.SetFields(o.l.GetFields().Add(HCLogArgs, args))
var lg = o.logger()
if lg == nil {
return o
}
lg.SetFields(lg.GetFields().Add(HCLogArgs, args))
return o
}
func (o *_hclog) Name() string {
fields := o.l.GetFields()
var lg = o.logger()
if lg == nil {
return ""
}
fields := lg.GetFields()
if i, l := fields.Load(HCLogName); !l {
return ""
@@ -139,40 +244,77 @@ func (o *_hclog) Name() string {
}
func (o *_hclog) Named(name string) hclog.Logger {
o.l.SetFields(o.l.GetFields().Add(HCLogName, name))
var lg = o.logger()
if lg == nil {
return o
}
lg.SetFields(lg.GetFields().Add(HCLogName, name))
return o
}
func (o *_hclog) ResetNamed(name string) hclog.Logger {
o.l.SetFields(o.l.GetFields().Add(HCLogName, name))
var lg = o.logger()
if lg == nil {
return o
}
lg.SetFields(lg.GetFields().Add(HCLogName, name))
return o
}
func (o *_hclog) SetLevel(level hclog.Level) {
var lg = o.logger()
if lg == nil {
return
}
switch level {
case hclog.NoLevel, hclog.Off:
o.l.SetLevel(loglvl.NilLevel)
lg.SetLevel(loglvl.NilLevel)
case hclog.Trace:
opt := o.l.GetOptions()
if opt.Stdout == nil {
opt.Stdout = &logcfg.OptionsStd{}
opt := lg.GetOptions()
if opt.Stdout != nil {
opt.Stdout.EnableTrace = true
}
opt.Stdout.EnableTrace = true
_ = o.l.SetOptions(opt)
o.l.SetLevel(loglvl.DebugLevel)
if len(opt.LogFile) > 0 {
for i := range opt.LogFile {
opt.LogFile[i].EnableTrace = true
}
}
if len(opt.LogSyslog) > 0 {
for i := range opt.LogSyslog {
opt.LogSyslog[i].EnableTrace = true
}
}
_ = lg.SetOptions(opt)
lg.SetLevel(loglvl.DebugLevel)
case hclog.Debug:
o.l.SetLevel(loglvl.DebugLevel)
lg.SetLevel(loglvl.DebugLevel)
case hclog.Info:
o.l.SetLevel(loglvl.InfoLevel)
lg.SetLevel(loglvl.InfoLevel)
case hclog.Warn:
o.l.SetLevel(loglvl.WarnLevel)
lg.SetLevel(loglvl.WarnLevel)
case hclog.Error:
o.l.SetLevel(loglvl.ErrorLevel)
lg.SetLevel(loglvl.ErrorLevel)
}
}
func (o *_hclog) GetLevel() hclog.Level {
switch o.l.GetLevel() {
var lg = o.logger()
if lg == nil {
return hclog.NoLevel
}
switch lg.GetLevel() {
case loglvl.NilLevel:
return hclog.NoLevel
case loglvl.DebugLevel:
@@ -193,6 +335,12 @@ func (o *_hclog) GetLevel() hclog.Level {
}
func (o *_hclog) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
var lg = o.logger()
if lg == nil {
return log.Default()
}
var lvl loglvl.Level
switch opts.ForceLevel {
case hclog.NoLevel, hclog.Off:
@@ -209,9 +357,15 @@ func (o *_hclog) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
lvl = loglvl.ErrorLevel
}
return o.l.GetStdLogger(lvl, 0)
return lg.GetStdLogger(lvl, 0)
}
func (o *_hclog) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
return o.l
var lg = o.logger()
if lg == nil {
return os.Stdout
}
return lg
}

View File

@@ -36,6 +36,7 @@ import (
logcfg "github.com/nabbar/golib/logger/config"
loglvl "github.com/nabbar/golib/logger/level"
logtps "github.com/nabbar/golib/logger/types"
libsiz "github.com/nabbar/golib/size"
"github.com/sirupsen/logrus"
)
@@ -78,6 +79,7 @@ func New(opt logcfg.OptionsFile, format logrus.Formatter) (HookFile, error) {
n := &hkf{
s: new(atomic.Value),
d: new(atomic.Value),
b: new(atomic.Int64),
o: ohkf{
format: format,
flags: flags,
@@ -93,6 +95,12 @@ func New(opt logcfg.OptionsFile, format logrus.Formatter) (HookFile, error) {
},
}
if opt.FileBufferSize <= libsiz.SizeKilo {
n.b.Store(opt.FileBufferSize.Int64())
} else {
n.b.Store(sizeBuffer)
}
if opt.CreatePath {
if e := libiot.PathCheckCreate(true, opt.Filepath, opt.FileMode, opt.PathMode); e != nil {
return nil, e

View File

@@ -54,6 +54,7 @@ type hkf struct {
s *atomic.Value // channel stop struct{}
d *atomic.Value // channel data []byte
o ohkf // config data
b *atomic.Int64 // buffer size
}
func (o *hkf) Levels() []logrus.Level {

View File

@@ -32,6 +32,7 @@ import (
"context"
"fmt"
"io"
"math"
"os"
"time"
@@ -40,12 +41,26 @@ import (
const sizeBuffer = 32 * 1024
func (o *hkf) getBufferSize() int {
b := o.b.Load()
if b < sizeBuffer {
b = sizeBuffer
}
if b > math.MaxInt {
return math.MaxInt
} else {
return int(b)
}
}
func (o *hkf) newBuffer(size int) *bytes.Buffer {
if size > 0 {
return bytes.NewBuffer(make([]byte, 0, size))
}
return bytes.NewBuffer(make([]byte, 0, sizeBuffer))
return bytes.NewBuffer(make([]byte, 0, o.getBufferSize()))
}
func (o *hkf) writeBuffer(buf *bytes.Buffer) error {
@@ -67,7 +82,7 @@ func (o *hkf) writeBuffer(buf *bytes.Buffer) error {
defer func() {
if rec := recover(); rec != nil {
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on golib/logger/hookfile/system.\nfor log file '%s'\n%v\n", p, rec)
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on writeBuffer function in golib/logger/hookfile/system.\nfor log file '%s'\n%v\n", p, rec)
}
if h != nil {
_ = h.Close()
@@ -95,18 +110,17 @@ func (o *hkf) writeBuffer(buf *bytes.Buffer) error {
func (o *hkf) freeBuffer(buf *bytes.Buffer, size int) *bytes.Buffer {
defer func() {
if rec := recover(); rec != nil {
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on golib/logger/hookfile/system.\nfor log file '%s'\n%v\n", o.getFilepath(), rec)
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on freeBuffer function in golib/logger/hookfile/system.\nfor log file '%s'\n%v\n", o.getFilepath(), rec)
}
}()
if size > buf.Cap() {
size = buf.Cap()
} else {
size = buf.Cap() - size
var a = o.newBuffer(o.getBufferSize())
if size < a.Cap() {
size = a.Cap() - size
a.WriteString(buf.String()[0:size])
}
var a = o.newBuffer(buf.Cap())
a.WriteString(buf.String()[0:size])
return a
}
@@ -120,7 +134,7 @@ func (o *hkf) Run(ctx context.Context) {
defer func() {
if rec := recover(); rec != nil {
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on golib/logger/hookfile/system.\nfor log file '%s'\n%v\n", o.getFilepath(), rec)
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on run function in golib/logger/hookfile/system.\nfor log file '%s'\n%v\n", o.getFilepath(), rec)
}
//flush buffer before exit function
if b.Len() > 0 {

View File

@@ -44,7 +44,7 @@ func (o *hks) Run(ctx context.Context) {
defer func() {
if rec := recover(); rec != nil {
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on golib/logger/hooksyslog/system\n%v\n", rec)
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on run function in golib/logger/hooksyslog/system\n%v\n", rec)
}
if s != nil {
w.Wait()
@@ -84,7 +84,7 @@ func (o *hks) writeWrapper(w Wrapper, d data, done func()) {
defer func() {
if rec := recover(); rec != nil {
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on golib/logger/hooksyslog/system\n%v\n", rec)
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on writeWrapper function in golib/logger/hooksyslog/system\n%v\n", rec)
}
done()
}()