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 ""
}
func (t *Trace) Trace() []string {
return nil
}
func (t *Trace) AppendFields(h log.FieldsHandler) log.FieldsHandler {
//var slice []string
//
//for _, f := range t.Frames {
// slice = append(slice, fmt.Sprintf("", f.))
//}
//
//
return nil
return h.HandleFields("trace", t.Frames)
}
func GetTraces() error {

View File

@ -1,7 +1,18 @@
package debugframes
import "gitea.suyono.dev/suyono/wingmate/log"
type PanicTrace []byte
func (p PanicTrace) Error() string {
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"
"os"
"reflect"
"runtime/debug"
"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) {
p = (*Payload)(logger.WithLevel(zerolog.Level(l)).Timestamp())
return p.Fields(a...)
return payload(logger.WithLevel(zerolog.Level(l)).Timestamp()).Fields(a...)
}
func (p *Payload) HandleFields(a ...any) FieldsHandler {
return p.Fields(a...)
}
func (p *Payload) Fields(a ...any) *Payload {
func (p *Payload) Fields(a ...any) (result *Payload) {
var (
event *zerolog.Event
sub *zerolog.Event
key string
val reflect.Value
typ reflect.Type
arr *zerolog.Array
err error
event *zerolog.Event
sub *zerolog.Event
key string
val reflect.Value
typ reflect.Type
arr *zerolog.Array
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 {
if i%2 == 0 {
key = part.(string)
} else {
val = reflect.ValueOf(part)
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() {
case reflect.String:
event = event.Str(key, val.String())
@ -148,15 +167,11 @@ func (p *Payload) Fields(a ...any) *Payload {
case reflect.Uint64:
event = event.Uint64(key, val.Uint())
default:
if typ.Implements(errType) {
} else {
event = payload(event).unhandledField(key, part)
}
event = payload(event).unhandledField(key, part)
}
}
}
return (*Payload)(event)
return payload(event)
}
func (p *Payload) Send(ws ...io.Writer) {
@ -184,47 +199,49 @@ func (p *Payload) slice(val reflect.Value) (*zerolog.Array, error) {
i int
rval *zerolog.Array
event *zerolog.Event
item reflect.Value
err error
)
vlen = val.Len()
rval = zerolog.Arr()
for i = 0; i < vlen; i++ {
switch val.Index(i).Kind() {
item = val.Index(i)
switch item.Kind() {
//TODO: handle more cases
case reflect.String:
rval = rval.Str(val.String())
rval = rval.Str(item.String())
case reflect.Struct:
if event, err = p.structType(val); err != nil {
if event, err = p.structType(item); err != nil {
return nil, err
}
rval = rval.Dict(event)
case reflect.Int:
rval = rval.Int(int(val.Int()))
rval = rval.Int(int(item.Int()))
case reflect.Int8:
rval = rval.Int8(int8(val.Int()))
rval = rval.Int8(int8(item.Int()))
case reflect.Int16:
rval = rval.Int16(int16(val.Int()))
rval = rval.Int16(int16(item.Int()))
case reflect.Int32:
rval = rval.Int32(int32(val.Int()))
rval = rval.Int32(int32(item.Int()))
case reflect.Int64:
rval = rval.Int64(val.Int())
rval = rval.Int64(item.Int())
case reflect.Float32:
rval = rval.Float32(float32(val.Float()))
rval = rval.Float32(float32(item.Float()))
case reflect.Float64:
rval = rval.Float64(val.Float())
rval = rval.Float64(item.Float())
case reflect.Uint:
rval = rval.Uint(uint(val.Uint()))
rval = rval.Uint(uint(item.Uint()))
case reflect.Uint8:
rval = rval.Uint8(uint8(val.Uint()))
rval = rval.Uint8(uint8(item.Uint()))
case reflect.Uint16:
rval = rval.Uint16(uint16(val.Uint()))
rval = rval.Uint16(uint16(item.Uint()))
case reflect.Uint32:
rval = rval.Uint32(uint32(val.Uint()))
rval = rval.Uint32(uint32(item.Uint()))
case reflect.Uint64:
rval = rval.Uint64(val.Uint())
rval = rval.Uint64(item.Uint())
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
@ -242,21 +259,25 @@ func (p *Payload) pointer(val reflect.Value) (*zerolog.Event, error) {
func (p *Payload) structType(val reflect.Value) (*zerolog.Event, error) {
var (
typ reflect.Type
event *zerolog.Event
typ reflect.Type
event *zerolog.Event
gotValidField bool
)
typ = val.Type()
event = zerolog.Dict()
for _, sf := range reflect.VisibleFields(typ) {
if sf.Type.Kind() == reflect.String {
if event == nil {
event = zerolog.Dict()
}
event.Str(sf.Name, val.FieldByIndex(sf.Index).String())
switch sf.Type.Kind() {
case reflect.String:
event = event.Str(sf.Name, val.FieldByIndex(sf.Index).String())
gotValidField = true
case reflect.Int:
event = event.Int64(sf.Name, val.FieldByIndex(sf.Index).Int())
gotValidField = true
}
}
if event == nil {
if !gotValidField {
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)
}