Skip to content

Conversation

@hampusohlsson
Copy link

@hampusohlsson hampusohlsson commented May 8, 2019

This PR adds an option to provide a custom error handler for panics.

By giving more control over the panic error creation, it's possible for the consumer of this library to capture the panics and format the message, add extenstions and send to 3rd party error reporting services.

I opted for keeping existing log.LogPanic functionality to not make breaking changes. But you can write your own panic handler that implements both interfaces. Here's an example of how I'm using a custom panic handler.

// main.go
...
panicHandler := &myerrorlib.PanicHandler{}
rootSchema := graphql.MustParseSchema(
	schema.GetRootSchema(),
	resolvers.NewRootResolver(),
	graphql.Logger(panicHandler),
	graphql.PanicHandler(panicHandler),
)
...

and then in my case I'll provide a custom PanicHandler like so:

package myerrorlib

import (
	"context"
	"github.com/graph-gophers/graphql-go/errors"
)

type PanicHandler struct{}

// LogPanic is a no-op to silence the default panic logging.
// Implements the Logger interface from `graph-gophers/graphql-go/log` 
func (p *PanicHandler) LogPanic(ctx context.Context, value interface{}) {
	return
}

// MakePanicError logs and reports the error using the common error library.
// Implements the PanicHandler interface from `graph-gophers/graphql-go/errors` 
func (p *PanicHandler) MakePanicError(
	ctx context.Context,
	value interface{},
) *errors.QueryError {
	// create and report custom error for 3rd party logging
	err := createAndReportErrorf(ctx, "panic: %s", value)
	return &errors.QueryError{
		Message:    err.Error(),
		// Decorate error with status code, trace id etc...
		Extensions: err.Extensions(),
	}
}

@hampusohlsson hampusohlsson force-pushed the custom-panic-handler branch from bd6123f to cfa4e9f Compare May 8, 2019 13:25
Copy link
Member

@pavelnikolov pavelnikolov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, move the interface, where it is used and not where you declare an implementation of it.

// PanicHandler is the interface used to create custom panic errors that occur during query execution
type PanicHandler interface {
MakePanicError(ctx context.Context, value interface{}) *QueryError
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface needs to be declared where it is used, not where you declare implementations of that interface. Please, move the interface, where it is used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I followed the existing pattern for log.Logger which has the interface defined in the same file as the default logger. But thanks for the pointer, will move the PanicHandler interface to the exec.go file.

Limiter chan struct{}
Tracer trace.Tracer
Logger log.Logger
PanicHandler errors.PanicHandler
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface needs to be declared in this file.

@pavelnikolov
Copy link
Member

Please, add unit tests.

@pavelnikolov
Copy link
Member

@hampusohlsson are you still interested in this change? The code seems to have conflicts. I'm closing this PR. Please, feel free to reopen it later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants