wip: default writer tested

This commit is contained in:
Suyono 2023-09-11 13:56:38 +10:00
parent d406fe698f
commit f482eb8631
5 changed files with 103 additions and 58 deletions

View File

@ -13,19 +13,8 @@ func (t *Trace) Error() string {
return "" return ""
} }
func (t *Trace) Trace() []string {
return nil
}
func (t *Trace) AppendFields(h log.FieldsHandler) log.FieldsHandler { func (t *Trace) AppendFields(h log.FieldsHandler) log.FieldsHandler {
//var slice []string return h.HandleFields("trace", t.Frames)
//
//for _, f := range t.Frames {
// slice = append(slice, fmt.Sprintf("", f.))
//}
//
//
return nil
} }
func GetTraces() error { func GetTraces() error {

View File

@ -1,7 +1,18 @@
package debugframes package debugframes
import "gitea.suyono.dev/suyono/wingmate/log"
type PanicTrace []byte type PanicTrace []byte
func (p PanicTrace) Error() string { func (p PanicTrace) Error() string {
return "" return ""
} }
func (p PanicTrace) AppendFields(h log.FieldsHandler) log.FieldsHandler {
return h.HandleFields("panic_stacktrace", p.String())
}
func (p PanicTrace) String() string {
b := []byte(p)
return string(b)
}

View File

@ -6,6 +6,7 @@ import (
"io" "io"
"os" "os"
"reflect" "reflect"
"runtime/debug"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )
@ -74,32 +75,50 @@ func (l Level) PrintTo(outlets []io.Writer, a ...any) {
} }
func (l Level) Fields(a ...any) (p *Payload) { func (l Level) Fields(a ...any) (p *Payload) {
p = (*Payload)(logger.WithLevel(zerolog.Level(l)).Timestamp()) return payload(logger.WithLevel(zerolog.Level(l)).Timestamp()).Fields(a...)
return p.Fields(a...)
} }
func (p *Payload) HandleFields(a ...any) FieldsHandler { func (p *Payload) HandleFields(a ...any) FieldsHandler {
return p.Fields(a...) return p.Fields(a...)
} }
func (p *Payload) Fields(a ...any) *Payload { func (p *Payload) Fields(a ...any) (result *Payload) {
var ( var (
event *zerolog.Event event *zerolog.Event
sub *zerolog.Event sub *zerolog.Event
key string key string
val reflect.Value val reflect.Value
typ reflect.Type typ reflect.Type
arr *zerolog.Array arr *zerolog.Array
err error err error
errVal error
elf ErrorLogFields
) )
event = (*zerolog.Event)(p) event = p.event()
defer func() {
if o := recover(); o != nil {
// in case there is mishandling reflect
result = payload(event.Str("logger_panic", string(debug.Stack())))
}
}()
enumerateFields:
for i, part := range a { for i, part := range a {
if i%2 == 0 { if i%2 == 0 {
key = part.(string) key = part.(string)
} else { } else {
val = reflect.ValueOf(part) val = reflect.ValueOf(part)
typ = val.Type() typ = val.Type()
if typ.Implements(errType) {
errVal = val.Interface().(error)
event = event.Err(errVal)
if errors.As(errVal, &elf) {
event = elf.AppendFields(payload(event)).(*Payload).event()
}
continue enumerateFields
}
switch typ.Kind() { switch typ.Kind() {
case reflect.String: case reflect.String:
event = event.Str(key, val.String()) event = event.Str(key, val.String())
@ -148,15 +167,11 @@ func (p *Payload) Fields(a ...any) *Payload {
case reflect.Uint64: case reflect.Uint64:
event = event.Uint64(key, val.Uint()) event = event.Uint64(key, val.Uint())
default: default:
if typ.Implements(errType) { event = payload(event).unhandledField(key, part)
} else {
event = payload(event).unhandledField(key, part)
}
} }
} }
} }
return (*Payload)(event) return payload(event)
} }
func (p *Payload) Send(ws ...io.Writer) { func (p *Payload) Send(ws ...io.Writer) {
@ -184,47 +199,49 @@ func (p *Payload) slice(val reflect.Value) (*zerolog.Array, error) {
i int i int
rval *zerolog.Array rval *zerolog.Array
event *zerolog.Event event *zerolog.Event
item reflect.Value
err error err error
) )
vlen = val.Len() vlen = val.Len()
rval = zerolog.Arr() rval = zerolog.Arr()
for i = 0; i < vlen; i++ { for i = 0; i < vlen; i++ {
switch val.Index(i).Kind() { item = val.Index(i)
switch item.Kind() {
//TODO: handle more cases //TODO: handle more cases
case reflect.String: case reflect.String:
rval = rval.Str(val.String()) rval = rval.Str(item.String())
case reflect.Struct: case reflect.Struct:
if event, err = p.structType(val); err != nil { if event, err = p.structType(item); err != nil {
return nil, err return nil, err
} }
rval = rval.Dict(event) rval = rval.Dict(event)
case reflect.Int: case reflect.Int:
rval = rval.Int(int(val.Int())) rval = rval.Int(int(item.Int()))
case reflect.Int8: case reflect.Int8:
rval = rval.Int8(int8(val.Int())) rval = rval.Int8(int8(item.Int()))
case reflect.Int16: case reflect.Int16:
rval = rval.Int16(int16(val.Int())) rval = rval.Int16(int16(item.Int()))
case reflect.Int32: case reflect.Int32:
rval = rval.Int32(int32(val.Int())) rval = rval.Int32(int32(item.Int()))
case reflect.Int64: case reflect.Int64:
rval = rval.Int64(val.Int()) rval = rval.Int64(item.Int())
case reflect.Float32: case reflect.Float32:
rval = rval.Float32(float32(val.Float())) rval = rval.Float32(float32(item.Float()))
case reflect.Float64: case reflect.Float64:
rval = rval.Float64(val.Float()) rval = rval.Float64(item.Float())
case reflect.Uint: case reflect.Uint:
rval = rval.Uint(uint(val.Uint())) rval = rval.Uint(uint(item.Uint()))
case reflect.Uint8: case reflect.Uint8:
rval = rval.Uint8(uint8(val.Uint())) rval = rval.Uint8(uint8(item.Uint()))
case reflect.Uint16: case reflect.Uint16:
rval = rval.Uint16(uint16(val.Uint())) rval = rval.Uint16(uint16(item.Uint()))
case reflect.Uint32: case reflect.Uint32:
rval = rval.Uint32(uint32(val.Uint())) rval = rval.Uint32(uint32(item.Uint()))
case reflect.Uint64: case reflect.Uint64:
rval = rval.Uint64(val.Uint()) rval = rval.Uint64(item.Uint())
default: default:
rval = rval.Str(fmt.Sprintf("[unhandled data type / invalid] %+v", val.Interface())) rval = rval.Str(fmt.Sprintf("[unhandled data type / invalid] %+v", item.Interface()))
} }
} }
return rval, nil return rval, nil
@ -242,21 +259,25 @@ func (p *Payload) pointer(val reflect.Value) (*zerolog.Event, error) {
func (p *Payload) structType(val reflect.Value) (*zerolog.Event, error) { func (p *Payload) structType(val reflect.Value) (*zerolog.Event, error) {
var ( var (
typ reflect.Type typ reflect.Type
event *zerolog.Event event *zerolog.Event
gotValidField bool
) )
typ = val.Type() typ = val.Type()
event = zerolog.Dict()
for _, sf := range reflect.VisibleFields(typ) { for _, sf := range reflect.VisibleFields(typ) {
if sf.Type.Kind() == reflect.String { switch sf.Type.Kind() {
if event == nil { case reflect.String:
event = zerolog.Dict() event = event.Str(sf.Name, val.FieldByIndex(sf.Index).String())
} gotValidField = true
event.Str(sf.Name, val.FieldByIndex(sf.Index).String()) case reflect.Int:
event = event.Int64(sf.Name, val.FieldByIndex(sf.Index).Int())
gotValidField = true
} }
} }
if event == nil { if !gotValidField {
return nil, errNoValidField return nil, errNoValidField
} }

View File

@ -1,5 +0,0 @@
package log
func Struct(v any) (*Payload, error) {
return nil, nil
}

View File

@ -0,0 +1,29 @@
package wrapped
import (
"fmt"
"gitea.suyono.dev/suyono/wingmate/debugframes"
"gitea.suyono.dev/suyono/wingmate/log"
"runtime/debug"
"testing"
)
func TestPrintWrappedError(t *testing.T) {
log.Print("test", fmt.Errorf("wrapped error trace%w", debugframes.GetTraces()))
}
func TestPrintWrappedPanic(t *testing.T) {
f := func() (err error) {
defer func() {
if o := recover(); o != nil {
err = fmt.Errorf("panic: %v%w", o, debugframes.PanicTrace(debug.Stack()))
}
}()
panic("test")
return nil
}
err := f()
log.Print("panic_test", err)
}