wip: default writer tested
This commit is contained in:
parent
d406fe698f
commit
f482eb8631
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
|||||||
103
log/log.go
103
log/log.go
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
package log
|
|
||||||
|
|
||||||
func Struct(v any) (*Payload, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
29
log/wrapped/wrapped_test.go
Normal file
29
log/wrapped/wrapped_test.go
Normal 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)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user