Git Product home page Git Product logo

weberr's People

Contributors

cben avatar etabak avatar olisakov avatar oriadler avatar vkareh avatar zgalor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

weberr's Issues

should Wrapf(nil, ...) return nil?

The behavior when the wrapped error is nil — weberr.Wrapf(nil, "foo %d", 42) — is undocumented.
Currently it returns a new "foo 42" error:

weberr/errors.go

Lines 182 to 186 in 54d909c

// Wrapf creates a new wrapped error with formatted message
func (errorType ErrorType) Wrapf(err error, msg string, args ...interface{}) error {
if err == nil {
return errorType.Errorf(msg, args...)
}

The upstream errors.Wrapf(nil, "foo %d", 42) returns nil:
https://github.com/pkg/errors/blob/49f8f617296114c890ae0b7ac18c5953d2b1ca0f/errors.go#L200-L204

I propose to align with upstream, which is widely used and understood, even if it breaks compatibility with previous weberr.
Some cons/pros below, none very strong, so IMHO keeping this a drop-in replacement to pkg/errors is the decisive point.
@zgalor @vkareh @etabak @nshneor what do you think?

against

upstream nil behavior was opposed in pkg/errors#174, and while it's closed — they clearly won't break compatiblity for this — I can empatize with some use cases there. They're are solvable by conditionally calling errors.New() vs .Wrapf() but that's annoying.

EDIT: there was more discussion on pkg/errors#90, where Dave did say "if I was doing this again today I would not have put in this convenience" but that he won't break compatibility.

pro

In our non-public codebase, I'm not sure we ever called Wrapf outside an if err != nil { block. But now I have minor a use case where I'd like to:

We have some helpers for conditional error handling, one of which I now tried to rewrite to:

==> helpers.go <==
func Check(ctx context.Context, err error, msg string) {
	if err != nil {
		// with some magic I'm adding, 
		// this will dump err message AND weberr.GetStackTrace(err)!
		log.Ctx(ctx).WithError(err).Fatal(msg)
	}
}

==> some_business_logic.go <==
	helpers.Check(ctx, err, "Service terminated with errors")

An annoyance is that for both logrus file:line detection, and for weberr stack traces, you always see helper.go:100 instead of the specific place that called Check(...) 😖
A trick that I learnt from logrus is to keep the call that captures file:line info in the bussiness logic 💡. So I thought to rewrite to this:

==> some_business_logic.go <==
// Wrapf called here captures `some_business_logic.go:200` into stack trace!
	helpers.Check(ctx, weberr.Wrapf("Service terminated with errors: %s", err))

// in helpers.go
func Check(ctx context.Context, err error) {
	if err != nil {
		log.Ctx(ctx).WithError(err).Fatal("")
	}
}

However, if Wrapf() turns nil into a new error without cause, that won't work as Check() will always receive some error and won't know whether it should exit...

(There are other ways to allow helper functions to work, I know)

Stack trace contains helpers from this package

Stack trace contains helpers from this package e.g.:

...
gitlab.cee.redhat.com/service/uhc-clusters-service/vendor/github.com/zgalor/weberr.Errorf
	/var/lib/jenkins/workspace/service-uhc-clusters-service-gl-build-master/.gopath/src/gitlab.cee.redhat.com/service/uhc-clusters-service/vendor/github.com/zgalor/weberr/errors.go:158
gitlab.cee.redhat.com/service/uhc-clusters-service/cmd/clusters-service/clusterprovisioner.(*HiveProvisioner).getClusterDeployment
	/var/lib/jenkins/workspace/service-uhc-clusters-service-gl-build-master/.gopath/src/gitlab.cee.redhat.com/service/uhc-clusters-service/cmd/clusters-service/clusterprovisioner/hive_provisioner.go:464
...

The 1st line is coming from this helper:

weberr/errors.go

Lines 156 to 159 in 9c45299

// Errorf returns an error with format string
func Errorf(msg string, args ...interface{}) error {
return NoType.Errorf(msg, args...)
}

Would be nice to omit these from the trace, they don't add information.
For example the 2nd line listed in above trace is:

			err = errors.Errorf("No ClusterDeployment matches cluster %s", id)

so the info which exactly wrapper was used from errors package is already there anyway.

@zgalor said:

Regarding the stack trace - this is a bug caused by functions in the errors pkg wrapping other functions.
A fix would be a different implementation of GetStackTrace() - to be done be overriding Format() like done in github.com/pkg/errors.
But that is a low priority for me. You are welcome to submit a PR :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.