wip: log
This commit is contained in:
parent
8a480acde7
commit
5f7befe02c
@ -7,7 +7,11 @@ type Trace struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Trace) Error() string {
|
func (t *Trace) Error() string {
|
||||||
return "[debug trace available]"
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Trace) Trace() []string {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTraces() error {
|
func GetTraces() error {
|
||||||
|
|||||||
@ -3,5 +3,5 @@ package debugframes
|
|||||||
type PanicTrace []byte
|
type PanicTrace []byte
|
||||||
|
|
||||||
func (p PanicTrace) Error() string {
|
func (p PanicTrace) Error() string {
|
||||||
return "[panic trace available]"
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
27
log/errlog_test.go
Normal file
27
log/errlog_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPrint(t *testing.T) {
|
||||||
|
Print("key", errors.New("hello world"))
|
||||||
|
}
|
||||||
|
|
||||||
|
type testWriter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t testWriter) Write(b []byte) (int, error) {
|
||||||
|
return 0, errors.New("write error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrWrite(t *testing.T) {
|
||||||
|
var (
|
||||||
|
tw testWriter
|
||||||
|
logger zerolog.Logger
|
||||||
|
)
|
||||||
|
logger = zerolog.New(tw)
|
||||||
|
logger.Error().Str("test", "one").Msg("hello")
|
||||||
|
}
|
||||||
@ -7,17 +7,18 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type File struct {
|
type File os.File
|
||||||
path string
|
|
||||||
file *os.File
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
filenameKey = "file"
|
filenameKey = "file"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewLogFile(configKey string) (*File, error) {
|
func NewLogFile(configKey string) (*File, error) {
|
||||||
var err error
|
var (
|
||||||
|
err error
|
||||||
|
path string
|
||||||
|
file *os.File
|
||||||
|
)
|
||||||
if viper.IsSet(configKey) {
|
if viper.IsSet(configKey) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -27,22 +28,23 @@ func NewLogFile(configKey string) (*File, error) {
|
|||||||
return nil, fmt.Errorf("missing file key config %s", fileKey)
|
return nil, fmt.Errorf("missing file key config %s", fileKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := &File{
|
path = viper.GetString(fileKey)
|
||||||
path: viper.GetString(fileKey),
|
if file, err = os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644); err != nil {
|
||||||
}
|
|
||||||
if file.file, err = os.OpenFile(file.path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return file, nil
|
return (*File)(file), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Write(b []byte) (int, error) {
|
func (f *File) Write(b []byte) (int, error) {
|
||||||
return 0, nil
|
var file *os.File
|
||||||
|
file = (*os.File)(f)
|
||||||
|
return file.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Close() error {
|
func (f *File) Close() error {
|
||||||
return f.file.Close()
|
of := (*os.File)(f)
|
||||||
|
return of.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Rotate() error {
|
func (f *File) Rotate() error {
|
||||||
74
log/log.go
74
log/log.go
@ -1,9 +1,10 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"fmt"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Level zerolog.Level
|
type Level zerolog.Level
|
||||||
@ -15,6 +16,11 @@ type ProcessLogConfig interface {
|
|||||||
FileName() string
|
FileName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Traceable interface {
|
||||||
|
error
|
||||||
|
Trace() []string
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Trace Level = Level(zerolog.TraceLevel)
|
Trace Level = Level(zerolog.TraceLevel)
|
||||||
Debug Level = Level(zerolog.DebugLevel)
|
Debug Level = Level(zerolog.DebugLevel)
|
||||||
@ -30,40 +36,39 @@ const (
|
|||||||
var (
|
var (
|
||||||
globalLevel Level = Error
|
globalLevel Level = Error
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
|
onLogWriterError zerolog.Logger
|
||||||
|
writer *Writer
|
||||||
|
DefaultOutlet io.Writer
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
DefaultOutlet = os.Stderr
|
||||||
|
writer = NewWriter()
|
||||||
|
logger = zerolog.New(writer)
|
||||||
|
onLogWriterError = logger.Output(DefaultOutlet)
|
||||||
SetGlobalLevel(globalLevel)
|
SetGlobalLevel(globalLevel)
|
||||||
logger = zerolog.New(os.Stderr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Level) Print(a ...any) {
|
func (l Level) Print(a ...any) {
|
||||||
// var event *zerolog.Event
|
l.Fields(a...).Send()
|
||||||
// for _, i := range a {
|
|
||||||
// if event == nil {
|
|
||||||
// event = logger.WithLevel(zerolog.Level(l))
|
|
||||||
// }
|
|
||||||
// switch v := i.(type) {
|
|
||||||
// case daemon.ProcessLogEntry:
|
|
||||||
// event = event.Str("type", v.Descriptor.InstanceType().String()).Str("origin", "child process").
|
|
||||||
// Str("name", v.Descriptor.Name())
|
|
||||||
// if v.Descriptor.InstanceType() == daemon.Cron {
|
|
||||||
// event = event.Str("instance_name", v.Descriptor.InstanceName())
|
|
||||||
// }
|
|
||||||
// event.Str("entry", v.LogEntry).Send()
|
|
||||||
// event = nil
|
|
||||||
// //TODO: add logic to process cron or service specific log config
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Level) Fields(a ...any) *Payload {
|
func (l Level) PrintTo(outlets []io.Writer, a ...any) {
|
||||||
|
l.Fields(a...).Send(outlets...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Level) Fields(a ...any) (p *Payload) {
|
||||||
|
p = (*Payload)(logger.WithLevel(zerolog.Level(l)).Timestamp())
|
||||||
|
return p.Fields(a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) Fields(a ...any) *Payload {
|
||||||
var (
|
var (
|
||||||
event *zerolog.Event
|
event *zerolog.Event
|
||||||
key string
|
key string
|
||||||
)
|
)
|
||||||
|
|
||||||
event = logger.WithLevel(zerolog.Level(l))
|
event = (*zerolog.Event)(p)
|
||||||
for i, part := range a {
|
for i, part := range a {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
key = part.(string)
|
key = part.(string)
|
||||||
@ -71,16 +76,39 @@ func (l Level) Fields(a ...any) *Payload {
|
|||||||
switch v := part.(type) {
|
switch v := part.(type) {
|
||||||
case string:
|
case string:
|
||||||
event = event.Str(key, v)
|
event = event.Str(key, v)
|
||||||
|
case error:
|
||||||
|
event = event.Err(v)
|
||||||
|
|
||||||
|
default:
|
||||||
|
event = event.Str(key, fmt.Sprintf("[no data type handle] %v", v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return (*Payload)(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Payload) Send(ws ...io.Writer) {
|
||||||
|
event := (*zerolog.Event)(p)
|
||||||
|
|
||||||
|
writer.Lock()
|
||||||
|
defer writer.Unlock()
|
||||||
|
|
||||||
|
if len(ws) == 0 {
|
||||||
|
writer.Writers(DefaultOutlet)
|
||||||
|
} else {
|
||||||
|
writer.Writers(ws...)
|
||||||
|
}
|
||||||
|
event.Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Print(a ...any) {
|
func Print(a ...any) {
|
||||||
globalLevel.Print(a...)
|
globalLevel.Print(a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PrintTo(outlets []io.Writer, a ...any) {
|
||||||
|
globalLevel.PrintTo(outlets, a...)
|
||||||
|
}
|
||||||
|
|
||||||
func SetGlobalLevel(l Level) {
|
func SetGlobalLevel(l Level) {
|
||||||
globalLevel = l
|
globalLevel = l
|
||||||
zerolog.SetGlobalLevel(zerolog.Level(globalLevel))
|
zerolog.SetGlobalLevel(zerolog.Level(globalLevel))
|
||||||
|
|||||||
@ -1,31 +1,90 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Writer struct {
|
var (
|
||||||
writer io.Writer
|
noError = errors.New("no error")
|
||||||
mtx *sync.Mutex
|
ec = make(chan error)
|
||||||
} //TODO: create a writer implementation using this struct, ensure sync and prevent abrupt truncation when stopping
|
)
|
||||||
|
|
||||||
func NewWriter(w io.Writer) *Writer {
|
type Writer struct {
|
||||||
|
writers []io.Writer
|
||||||
|
mtx *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriter() *Writer {
|
||||||
return &Writer{
|
return &Writer{
|
||||||
writer: w,
|
writers: make([]io.Writer, 0),
|
||||||
mtx: &sync.Mutex{},
|
mtx: &sync.Mutex{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Write(b []byte) (int, error) {
|
func (w *Writer) Write(b []byte) (int, error) {
|
||||||
w.mtx.Lock()
|
var (
|
||||||
defer w.mtx.Unlock()
|
ctr int
|
||||||
return w.writer.Write(b)
|
sw io.Writer
|
||||||
}
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
func (w *Writer) Close() {
|
for _, ww := range w.writers {
|
||||||
if wc, ok := w.writer.(io.WriteCloser); ok {
|
if ww == DefaultOutlet {
|
||||||
_ = wc.Close()
|
sw = ww
|
||||||
|
} else {
|
||||||
|
ctr++
|
||||||
|
go subWriter(ww, b, ec)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sw != nil {
|
||||||
|
_, _ = sw.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < ctr; i++ {
|
||||||
|
if err = <-ec; err != noError {
|
||||||
|
onLogWriterError.Error().Err(err).Msg("subWriter error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Lock() {
|
||||||
|
w.mtx.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Unlock() {
|
||||||
|
w.writers[0] = DefaultOutlet
|
||||||
|
w.writers = w.writers[:1]
|
||||||
|
w.mtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) Writers(ws ...io.Writer) {
|
||||||
|
if len(ws) == 0 {
|
||||||
|
w.writers[0] = DefaultOutlet
|
||||||
|
w.writers = w.writers[:1]
|
||||||
|
} else {
|
||||||
|
w.writers = append(w.writers, ws...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func subWriter(w io.Writer, b []byte, errchan chan<- error) {
|
||||||
|
defer func() {
|
||||||
|
if o := recover(); o != nil {
|
||||||
|
errchan <- fmt.Errorf("subWriter panic: %v", o)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if _, err := w.Write(b); err != nil {
|
||||||
|
errchan <- err
|
||||||
|
} else {
|
||||||
|
errchan <- noError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (w *Writer) Close() {
|
||||||
|
//}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user