func structToFields(i interface{}, namePrefix string) (fields Fields) {
	defer func() {
		if r := recover(); r != nil {
			fields = Fields{"struct_to_fields_panic": r, "type": fmt.Sprintf("%T", i)}
		}
	}()
	v := deref(reflect.ValueOf(i))
	if v.Kind() != reflect.Struct {
		return nil
	}
	t := v.Type()
	fieldCount := v.NumField()
	fields = make(Fields, fieldCount)
	for i := 0; i < fieldCount; i++ {
		name, skip := getName(t.Field(i), namePrefix)
		if skip {
			continue
		}
		var value interface{}
		f := v.Field(i)
		if f.Type().Implements(fmtStringer) && (f.Kind() != reflect.Ptr || !f.IsNil()) {
			value = f.Interface().(fmt.Stringer).String()
		}
		f = deref(f)
		switch f := f.Interface().(type) {  
		case time.Time:
			value = f.Format(time.RFC3339)
		}
		if value != nil {
			fields[name] = value
			continue
		}
		switch f.Kind() {
		case
			reflect.Bool,
			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
			reflect.Float32, reflect.Float64,
			reflect.Complex64, reflect.Complex128,
			reflect.String,
			reflect.Array:
			fields[name] = f.Interface()
		case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface:
			var value interface{} = "<nil>"
			if !f.IsNil() {
				value = f.Interface()
			}
			fields[name] = value
		case reflect.Struct:
			for k, v := range structToFields(f.Interface(), "") {
				fields[name+"."+k] = v
			}
		}
	}
	return fields
}
structToFields maps fields of a passed structure to Fields. It returns empty fields
for a non-structure arguments.
package logger
import (
	"fmt"
	"go/token"
	"reflect"
	"time"
)
var fmtStringer = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()