mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 07:11:51 +08:00
Data sources: Improve error messages for grpc errors (#102372)
* Data sources: Improve error messages for grpc errors * Improve code comments * Fix lint * Update connection issue message * Update name * Update comment * Update, rename and add test * Update, remove POC change * Fix lint
This commit is contained in:
@ -172,6 +172,14 @@ func (c *ClientV2) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
return nil, plugins.ErrMethodNotImplemented
|
return nil, plugins.ErrMethodNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if status.Code(err) == codes.Unavailable {
|
||||||
|
return nil, plugins.ErrPluginGrpcConnectionUnavailableBase.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.Code(err) == codes.ResourceExhausted {
|
||||||
|
return nil, plugins.ErrPluginGrpcResourceExhaustedBase.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if errorSource, ok := backend.ErrorSourceFromGrpcStatusError(ctx, err); ok {
|
if errorSource, ok := backend.ErrorSourceFromGrpcStatusError(ctx, err); ok {
|
||||||
return nil, handleGrpcStatusError(ctx, errorSource, err)
|
return nil, handleGrpcStatusError(ctx, errorSource, err)
|
||||||
}
|
}
|
||||||
|
@ -35,4 +35,16 @@ var (
|
|||||||
// Exposed as a base error to wrap it with plugin cancelled errors.
|
// Exposed as a base error to wrap it with plugin cancelled errors.
|
||||||
ErrPluginRequestCanceledErrorBase = errutil.ClientClosedRequest("plugin.requestCanceled",
|
ErrPluginRequestCanceledErrorBase = errutil.ClientClosedRequest("plugin.requestCanceled",
|
||||||
errutil.WithPublicMessage("Plugin request canceled"))
|
errutil.WithPublicMessage("Plugin request canceled"))
|
||||||
|
|
||||||
|
// ErrPluginGrpcResourceExhaustedBase error returned when a plugin response is larger than the grpc limit.
|
||||||
|
// Exposed as a base error to wrap it with plugin resource exhausted errors.
|
||||||
|
ErrPluginGrpcResourceExhaustedBase = errutil.Internal("plugin.resourceExhausted",
|
||||||
|
errutil.WithPublicMessage("The response is too large. Please try to reduce the time range or narrow down your query to return fewer data points."),
|
||||||
|
errutil.WithDownstream())
|
||||||
|
|
||||||
|
// ErrPluginGrpcConnectionUnavailableBase error returned when a plugin connection issue occurs.
|
||||||
|
// Exposed as a base error to wrap it with plugin connection issue errors.
|
||||||
|
ErrPluginGrpcConnectionUnavailableBase = errutil.Internal("plugin.connectionUnavailable",
|
||||||
|
errutil.WithPublicMessage("Data source became unavailable during request. Please try again."),
|
||||||
|
errutil.WithDownstream())
|
||||||
)
|
)
|
||||||
|
@ -30,6 +30,14 @@ var (
|
|||||||
errNilSender = errors.New("sender cannot be nil")
|
errNilSender = errors.New("sender cannot be nil")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// passthroughErrors contains a list of errors that should be returned directly to the caller without wrapping
|
||||||
|
var passthroughErrors = []error{
|
||||||
|
plugins.ErrPluginUnavailable,
|
||||||
|
plugins.ErrMethodNotImplemented,
|
||||||
|
plugins.ErrPluginGrpcResourceExhaustedBase,
|
||||||
|
plugins.ErrPluginGrpcConnectionUnavailableBase,
|
||||||
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
pluginRegistry registry.Service
|
pluginRegistry registry.Service
|
||||||
}
|
}
|
||||||
@ -52,12 +60,10 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
|
|
||||||
resp, err := p.QueryData(ctx, req)
|
resp, err := p.QueryData(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, plugins.ErrMethodNotImplemented) {
|
for _, e := range passthroughErrors {
|
||||||
|
if errors.Is(err, e) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, plugins.ErrPluginUnavailable) {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
|
@ -27,22 +27,37 @@ func TestQueryData(t *testing.T) {
|
|||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
err error
|
err error
|
||||||
expectedError error
|
expectedError error
|
||||||
|
shouldPassThrough bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
err: plugins.ErrPluginUnavailable,
|
err: plugins.ErrPluginUnavailable,
|
||||||
expectedError: plugins.ErrPluginUnavailable,
|
expectedError: plugins.ErrPluginUnavailable,
|
||||||
|
shouldPassThrough: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
err: plugins.ErrMethodNotImplemented,
|
err: plugins.ErrMethodNotImplemented,
|
||||||
expectedError: plugins.ErrMethodNotImplemented,
|
expectedError: plugins.ErrMethodNotImplemented,
|
||||||
|
shouldPassThrough: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
err: errors.New("surprise surprise"),
|
err: errors.New("surprise surprise"),
|
||||||
expectedError: plugins.ErrPluginRequestFailureErrorBase,
|
expectedError: plugins.ErrPluginRequestFailureErrorBase,
|
||||||
|
shouldPassThrough: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
err: context.Canceled,
|
err: context.Canceled,
|
||||||
expectedError: plugins.ErrPluginRequestCanceledErrorBase,
|
expectedError: plugins.ErrPluginRequestCanceledErrorBase,
|
||||||
|
shouldPassThrough: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err: plugins.ErrPluginGrpcConnectionUnavailableBase.Errorf("unavailable"),
|
||||||
|
expectedError: plugins.ErrPluginGrpcConnectionUnavailableBase.Errorf("unavailable"),
|
||||||
|
shouldPassThrough: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err: plugins.ErrPluginGrpcResourceExhaustedBase.Errorf("exhausted"),
|
||||||
|
expectedError: plugins.ErrPluginGrpcResourceExhaustedBase.Errorf("exhausted"),
|
||||||
|
shouldPassThrough: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +84,11 @@ func TestQueryData(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
if tc.shouldPassThrough {
|
||||||
|
require.Equal(t, tc.err, err)
|
||||||
|
} else {
|
||||||
require.ErrorIs(t, err, tc.expectedError)
|
require.ErrorIs(t, err, tc.expectedError)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user