seguims con los errores

master
DEV 3 years ago
parent 83dad836a2
commit 659c46a58c

@ -81,11 +81,11 @@ func main() {
e4 := &MiCustomErr{}
e5 := &MiCustomErr{}
//me := errs.NewErrTrace(errs.NewErrMulti(e3,e4,e5,ne).WrapWithInfo(errs.ErrInfoWithMessage("Es0")),0)
me := errs.NewErrMulti(e3,e4,e5,ne).WrapWithInfo(errs.ErrInfoWithMessage("Es0"))
fmt.Print(errs.ToFormat(me,nil))

@ -0,0 +1,42 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name string_adapter.go
// Created by DEV
// Modified 31/03/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package astrings
type (
Transformer interface {
Transform (value string) string
}
TransformFnc func (value string) string
)
func (f TransformFnc) Transform (value string) string {
return f(value) }

@ -2,9 +2,9 @@
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name string_adapter.go
// File name transformers.go
// Created by DEV
// Modified 31/03/2024
// Modified 18/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -25,24 +25,24 @@ package astrings
type (
Transform func (string) string
type (
Transformers []Transform
Transformers []Transformer
)
func (a Transformers) Apply (value string) string {
func (a Transformers) Transform (value string) string {
if len(a) == 0 {
return value
}
s := value
for _,f := range a {
s = f(s)
s = f.Transform(s)
}
return s
}

@ -25,7 +25,10 @@ package ftext
import (
"ansi"
"atypes/astrings"
"errs/stack"
"fmt"
"strings"
"sync"
)
@ -44,47 +47,73 @@ func DefaultFormatter () *TextFormatter {
g.buildDefault.Do(func() {
g.formatter = NewTextFormatter(
WithOptions(0,AddFields),
WithNameTransformers(
astrings.TransformFnc(func (s string) string {
return astrings.ToKebab(s) }),
astrings.TransformFnc(func (s string) string {
return astrings.Pad(s,8,' ',true) }),
),
WithSectionsFormat(func(c *Sections){
c.Main.Set(0,
func (b *TextBuilder){
c := ansi.Code(0).SetFgColor(ansi.ColorHRed).SetStyle(ansi.StyleBold)
b.AddText(c.Sprint("# ERROR #####################################################\n"))
},
b.AddTextAnsi("# ERROR #####################################################\n",ansi.Code(0).SetFgColor(ansi.ColorHRed).SetStyle(ansi.StyleBold)) },
nil)
c.Head.Set(ansi.Code(0).SetFgColor(ansi.ColorHRed),nil,nil)
c.Fields.Set(ansi.Code(0).SetFgColor(ansi.ColorGreen),
func(b *TextBuilder) {
},
nil,
nil)
c.Causes.Set(ansi.Code(0).SetFgColor(ansi.ColorCyan),
func(b *TextBuilder){
a := ansi.Code(0).SetStyle(ansi.StyleBold)
b.AddText(a.Sprint("* Prev Causes ***********************************************\n"))
},
func(b *TextBuilder){
a := ansi.Code(0).SetStyle(ansi.StyleBold)
b.AddText(a.Sprint("*************************************************************\n"))
})
b.AddTextAnsi("\n* Prev Causes ***********************************************\n",ansi.Code(0).SetStyle(ansi.StyleBold)) },
nil)
c.Cause.Set(ansi.Code(0).SetFgColor(ansi.ColorCyan),
func(b *TextBuilder) {
b.AddText(fmt.Sprintf("-- %d --------------------------------------------------------\n",b.Level()))
},
b.AddTextAnsi(fmt.Sprintf("-- %d --------------------------------------------------------\n",b.Level()),0) },
nil)
c.Trace.Set(ansi.Code(0).SetFgColor(ansi.ColorHYellow),
c.Trace.Set(ansi.Code(0).SetFgColor(ansi.ColorHYellow).SetBgColor(ansi.ColorBlack),
func(b *TextBuilder){
a := b.ansiC.SetStyle(ansi.StyleBold)
b.AddText(a.Sprint("* Stack Trace ***********************************************\n"))
},
b.AddTextAnsi("\n# Stack Trace ###############################################\n",b.ansiC.SetStyle(ansi.StyleBold).SetFgColor(ansi.ColorHYellow)) },
nil)
}),
)
})
return g.formatter
}
}
func defaultFrameBuilder (builder *TextBuilder, frame stack.Frame, num int) {
if strings.Index(frame.Package,"runtime") != -1 {
return
}
var c1, c2, c3, c4 ansi.Code
if builder.Options().ShowAnsi(){
c1 = c1.SetFgColor(ansi.ColorBlue)//.SetBgColor(ansi.ColorHBlack)
c2 = c2.SetFgColor(ansi.ColorMagenta)
c3 = c3.SetFgColor(ansi.ColorWhite)
c4 = c3.SetFgColor(ansi.ColorHWhite)
}
builder.AddText(c4.Sprintf(" %d %s.%s \n",num,frame.Package, frame.FuncName))
builder.AddText(c2.Sprintf(" %.90s:%d\n", frame.File, frame.LineNumber))
f, e := frame.SourceLine()
if e == nil {
builder.AddTextAnsi(fmt.Sprintf(" %s\n", f),c3)
} else {
builder.AddTextAnsi(fmt.Sprintf(" error %s\n", e.Error()),c3)
}
}

@ -28,6 +28,7 @@ import (
"bytes"
"errors"
"errs/fmtr"
"errs/stack"
"fmt"
"reflect"
"strings"
@ -54,9 +55,9 @@ type (
func newTextBuilder(formatter *TextFormatter) *TextBuilder {
return &TextBuilder{
f : formatter,
}
}
f : formatter,
ansiC: formatter.layout.ansiC }}
func (s *TextBuilder) Indent() string {
@ -68,11 +69,24 @@ func (s *TextBuilder) Level () int {
func (s *TextBuilder) Ansi () ansi.Code {
return s.ansiC }
func (s *TextBuilder) Options () Option {
return s.f.Option
}
func (s *TextBuilder) AddText (text string) {
s.b.WriteString(s.ansiC.String())
s.b.WriteString(text) }
func (s *TextBuilder) AddTextAnsi (text string, ansiC ansi.Code) {
if s.f.ShowAnsi() {
if ansiC == 0 {
ansiC = s.ansiC
}
s.b.WriteString(ansiC.String())
defer s.b.WriteString(ansiC.End())
}
s.b.WriteString(text)
s.b.WriteString(s.ansiC.End())
}
@ -81,34 +95,35 @@ func (s *TextBuilder) AddFieldAny(name string, value any ) {
if value == nil && s.f.NotShowEmpty() {
return
}
s.writeField(name,fmt.Sprintf("%v",value),false)
}
func (s *TextBuilder) AddFieldInt(name string, value int ) {
s.writeField(name,fmt.Sprintf(s.f.layouts.intLayout,value))}
s.writeField(name,fmt.Sprintf(s.f.layout.IntLayout,value),false)}
func (s *TextBuilder) AddFieldBool(name string, value bool ) {
s.writeField(name,fmt.Sprintf(s.f.layouts.boolLayout)) }
s.writeField(name,fmt.Sprintf(s.f.layout.BoolLayout),false) }
func (s *TextBuilder) AddFieldString(name string, value string ) {
if len(value) == 0 && s.f.NotShowEmpty() {
return
}
s.writeField(name,value) }
s.writeField(name,value,false) }
func (s *TextBuilder) AddFieldFloat(name string, value float64) {
s.writeField(name,fmt.Sprintf(s.f.layouts.floatLayout,value)) }
s.writeField(name,fmt.Sprintf(s.f.layout.FloatLayout,value),false) }
func (s *TextBuilder) AddFieldTime(name string, value time.Time) {
if value.IsZero() && s.f.NotShowEmpty() {
return
}
s.writeField(name,value.Format(s.f.layouts.timeLayout)) }
s.writeField(name,value.Format(s.f.layout.TimeLayout),false) }
func (s *TextBuilder) AddFieldDate(name string, value time.Time) {
if value.IsZero() && s.f.NotShowEmpty() {
return
}
s.writeField(name,value.Format(s.f.layouts.dateLayout)) }
s.writeField(name,value.Format(s.f.layout.DateLayout),false) }
@ -118,9 +133,9 @@ func (s *TextBuilder) Build(errCode, errType string, fbuilder fmtr.BuildFieldFnc
if s.level == 0 {
s.f.sections.Head.begin(s)
}
s.writeField(fmtr.FieldNameError,errCode)
if s.f.ShowType() {
s.writeField(fmtr.FieldNameType, errType)
s.writeField(fmtr.FieldNameError,errCode,true)
if s.f.AddType() {
s.writeField(fmtr.FieldNameType, errType,true)
}
if s.level == 0 {
s.f.sections.Head.end(s)
@ -149,17 +164,18 @@ func (s *TextBuilder) format (err error) (fe error) {
s.f.sections.Fields.end(s)
}
if s.f.ShowCause() {
if s.f.AddCause() {
s.f.sections.Causes.begin(s)
if fe = s.addCause(err); fe != nil {
//todo
s.f.onCauseError(s,fe)
}
s.f.sections.Causes.end(s)
}
if s.f.ShowTrace() {
s.f.sections.Trace.begin(s)
s.f.sections.Trace.end(s)
if s.f.AddTrace() {
if fe = s.addTrace(err); fe != nil {
s.f.onTraceError(s,fe)
}
}
s.f.sections.Main.end(s)
@ -186,22 +202,26 @@ func (s *TextBuilder) addError(err error) (fe error) {
eb := fmtr.GetErrorTypeBuilder(rt)
if eb != nil {
eb.BuildError(s,err)
return
} else {
eb = fmtr.MakeErrorTypeBuilder(s, err)
fmtr.SetErrorTypeBuilder(rt, eb)
}
eb = fmtr.MakeErrorTypeBuilder(s,err)
fmtr.SetErrorTypeBuilder(rt,eb)
}
if !s.unwrap {
s.unwrap = true
}
if fe = s.addError(errors.Unwrap(err)); fe != nil {
//todo
return fe
}
s.unwrap = false
if ne := errors.Unwrap(err); ne != nil {
if !s.unwrap {
s.unwrap = true
defer func() {
s.unwrap = false
}()
}
if fe = s.addError(ne); fe != nil {
s.f.onFormatError(s,fe)
return fe
}
}
return fe
}
@ -210,17 +230,21 @@ func (s *TextBuilder) addError(err error) (fe error) {
func (s *TextBuilder) addCause(err error) (fe error) {
if err == nil {
return
}
ls := getCauses(err)
for _,ce := range ls {
s.incLevel()
s.f.sections.Cause.begin(s)
if fe = s.addError(ce); fe != nil {
//todo
continue
}
if fe = s.addCause(ce); fe != nil {
//todo
s.f.onCauseError(s,fe)
} else if fe = s.addCause(ce); fe != nil {
s.f.onCauseError(s,fe)
}
s.f.sections.Cause.end(s)
s.decLevel()
}
@ -229,6 +253,7 @@ func (s *TextBuilder) addCause(err error) (fe error) {
func getCauses (err error) []error {
ne := err
for ne != nil {
@ -251,6 +276,33 @@ func getCauses (err error) []error {
}
func (s *TextBuilder) addTrace (err error) (fe error) {
st := stack.UnwrapTrace(err,true)
if st == nil {
return
}
dn := false
s.f.sections.Trace.begin(s)
defer func(d *bool, e *error){
if !(*d) {
if er := recover(); er != nil {
if ne, is := er.(error); is {
fe = ne
} else {
fe = fmt.Errorf("%#v", er)
}
}
}
s.f.sections.Trace.end(s)
}(&dn,&fe)
for n,f := range st.Frames() {
s.f.frameBuilder(s,f,n)
}
dn = true
return
}
@ -258,24 +310,29 @@ func (s *TextBuilder) setAnsi(ansiC ansi.Code) {
if ansiC != 0 {
s.ansiC = ansiC
} else {
s.ansiC = s.f.ansiC
s.ansiC = s.f.layout.ansiC
}
}
func (s *TextBuilder) writeField (name string, value string) {
s.numFields++
func (s *TextBuilder) writeField (name string, value string, head bool) {
if !head {
if !s.f.AddFields() {
return
}
s.numFields++
}
n := s.f.nameTrans.Apply(name)
v := s.f.valueTrans.Apply(value)
n := s.f.nameTrans.Transform(name)
v := s.f.valueTrans.Transform(value)
if s.ansiC != 0 {
s.b.WriteString(s.ansiC.String())
}
s.b.WriteString(s.indent)
s.b.WriteString(n)
s.b.WriteString(s.f.sep)
s.b.WriteString(s.f.layout.sep)
s.b.WriteString(v)
s.b.WriteByte('\n')
@ -289,15 +346,15 @@ func (s *TextBuilder) writeField (name string, value string) {
func (s *TextBuilder) incLevel () {
s.level++
if s.f.ShowIndent() {
s.indent = strings.Repeat(s.f.indent,s.level)
if s.f.UseIndent() {
s.indent = strings.Repeat(s.f.layout.indent,s.level)
}
}
func (s *TextBuilder) decLevel () {
s.level--
if s.f.ShowIndent() && s.level > 0 {
s.indent = strings.Repeat(s.f.indent,s.level)
if s.f.UseIndent() && s.level > 0 {
s.indent = strings.Repeat(s.f.layout.indent,s.level)
}
}

@ -0,0 +1,31 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name fallback.go
// Created by DEV
// Modified 18/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package ftext
type (
ErrorFallbackFnc func (builder *TextBuilder, err error)
)

@ -24,7 +24,6 @@
package ftext
import (
"ansi"
"atypes/astrings"
"errs/stack"
)
@ -33,18 +32,18 @@ type (
TextFormatter struct {
option
Option
ansiC ansi.Code
indent string
sep string
layouts layouts
layout Layout
sections Sections
nameTrans astrings.Transformers
valueTrans astrings.Transformers
onFormatError ErrorFallbackFnc
onTraceError ErrorFallbackFnc
onCauseError ErrorFallbackFnc
frameBuilder func (builder *TextBuilder, frame stack.Frame, num int)
}
@ -54,10 +53,12 @@ type (
func NewTextFormatter(options ...TextFormatterFnc) *TextFormatter {
fm := &TextFormatter{
option : optionsDefault,
indent : " ",
sep : " : ",
layouts : *newLayouts(),
Option : optionsDefault,
frameBuilder : defaultFrameBuilder,
layout : *newLayouts(),
onFormatError : func(b *TextBuilder, e error) { },
onTraceError : func(b *TextBuilder, e error) { },
onCauseError : func(b *TextBuilder, e error) { },
}
for _,o := range options {
o(fm)
@ -79,9 +80,46 @@ func (f *TextFormatter) FormatError (err error) []byte {
}
func WithErrorFallbacks (format, cause, trace ErrorFallbackFnc) TextFormatterFnc {
return func(f *TextFormatter) {
if format == nil {
f.onFormatError = format
}
if cause == nil {
f.onCauseError = cause
}
if trace == nil {
f.onTraceError = trace
}
}
}
func WithOptions (set, unset Option) TextFormatterFnc {
return func(f *TextFormatter) {
f.Option |= set
f.Option &^= unset } }
func WithNameTransformers(transformer ...astrings.Transformer) TextFormatterFnc {
return func(f *TextFormatter) {
f.nameTrans = append(f.nameTrans, transformer ...) } }
func WithValueTransformers(transformer ...astrings.Transformer) TextFormatterFnc {
return func(f *TextFormatter) {
f.valueTrans = append(f.nameTrans, transformer ...) } }
func WithSectionsFormat(config SectionsFnc) TextFormatterFnc {
return func(f *TextFormatter) {
config(&f.sections) } }
config(&f.sections) } }
func WithLayouts (config LayoutFnc) TextFormatterFnc {
return func(f *TextFormatter) {
config(&f.layout) } }
func WithFrameBuilder (builderFn func (builder *TextBuilder, frame stack.Frame, num int)) TextFormatterFnc {
return func(f *TextFormatter) {
f.frameBuilder = builderFn } }

@ -2,7 +2,7 @@
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name layouts.go
// File name Layout.go
// Created by DEV
// Modified 13/04/2024
//
@ -24,28 +24,38 @@
package ftext
import (
"ansi"
"time"
)
type (
layouts struct {
timeLayout string
dateLayout string
intLayout string
floatLayout string
boolLayout string
Layout struct {
ansiC ansi.Code
indent string
sep string
TimeLayout string
DateLayout string
IntLayout string
FloatLayout string
BoolLayout string
}
LayoutFnc func (layouts *Layout)
)
func newLayouts () *layouts {
return &layouts{
timeLayout : time.RFC822Z,
dateLayout : time.RFC822Z,
intLayout : "%d",
floatLayout : "%-10s: %.2f",
func newLayouts () *Layout {
return &Layout{
indent : " ",
sep : " : ",
TimeLayout: time.RFC822Z,
DateLayout: time.RFC822Z,
IntLayout: "%d",
FloatLayout: "%-10s: %.2f",
}
}

@ -26,51 +26,51 @@ package ftext
const (
ShowWrapped option = 1 << iota
ShowType
AddWrapped Option = 1 << iota
AddType
AddFields
AddCause
AddTrace
ShowAnsi
ShowIndent
ShowFields
ShowCause
ShowTrace
UseIndent
NotShowEmpty
optionsDefault = ShowWrapped | ShowType | ShowAnsi | ShowIndent | ShowFields | ShowCause | ShowTrace | NotShowEmpty
optionsDefault = AddWrapped | AddType | ShowAnsi | UseIndent | AddFields | AddCause | AddTrace | NotShowEmpty
)
type (
option uint8
Option uint8
)
func (s option) SetDefaults () option {
func (s Option) SetDefaults () Option {
return optionsDefault
}
func (s option) ShowWrapped () bool {
return s&ShowWrapped !=0 }
func (s Option) AddWrapped() bool {
return s&AddWrapped !=0 }
func (s option) ShowType () bool {
return s&ShowType !=0 }
func (s Option) AddType() bool {
return s&AddType !=0 }
func (s option) ShowAnsi () bool {
func (s Option) ShowAnsi () bool {
return s&ShowAnsi !=0 }
func (s option) ShowIndent () bool {
return s&ShowIndent !=0 }
func (s Option) UseIndent() bool {
return s&UseIndent !=0 }
func (s option) ShowFields() bool {
return s&ShowFields !=0 }
func (s Option) AddFields() bool {
return s&AddFields !=0 }
func (s option) ShowCause () bool {
return s&ShowCause !=0 }
func (s Option) AddCause() bool {
return s&AddCause !=0 }
func (s option) ShowTrace () bool {
return s&ShowTrace !=0 }
func (s Option) AddTrace() bool {
return s&AddTrace !=0 }
func (s option) NotShowEmpty() bool {
func (s Option) NotShowEmpty() bool {
return s&NotShowEmpty !=0 }

@ -51,8 +51,30 @@ func UnwrapTrace(err error, cause bool) Trace {
if cs, is := e.(interface{ Cause() error }); is {
UnwrapTrace(cs.Cause(), cause)
}
if cs, is := e.(interface{ Causes() []error}); is {
if tc := unwrapTraceMulti(cs.Causes()); tc != nil {
return tc
}
}
if cs, is := e.(interface{ Unwrap() []error}); is {
if tc := unwrapTraceMulti(cs.Unwrap()); tc != nil {
return tc
}
}
e = errors.Unwrap(e)
}
}
return nil
}
func unwrapTraceMulti (ers []error) Trace {
for _,e := range ers {
if tc := UnwrapTrace(e,true); tc != nil {
return tc
}
}
return nil
}
Loading…
Cancel
Save

Powered by TurnKey Linux.