From f0a3a6be9e2cb5d7d6518a80e013c5a73886a0b2 Mon Sep 17 00:00:00 2001 From: Andrew Wilkins Date: Mon, 25 Feb 2019 09:14:05 +0800 Subject: [PATCH] module/apmmongo: mongo.CommandError ErrorDetailer Register an ErrorDetailer for mongo.CommandError, extract the error code and labels. --- error.go | 6 +++++- module/apmmongo/monitor.go | 13 +++++++++++++ module/apmmongo/monitor_integration_test.go | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/error.go b/error.go index 8ad23ed45..b1aca7090 100644 --- a/error.go +++ b/error.go @@ -557,7 +557,8 @@ var ( ) // ErrorDetails holds details of an error, which can be altered or -// extended by registering an ErrorDetailer with RegisterErrorDetailer. +// extended by registering an ErrorDetailer with RegisterErrorDetailer +// or RegisterTypeErrorDetailer. type ErrorDetails struct { attrs map[string]interface{} @@ -604,6 +605,9 @@ func (d *ErrorDetails) SetAttr(k string, v interface{}) { } // ErrorDetailer defines an interface for altering or extending the ErrorDetails for an error. +// +// ErrorDetailers can be registered using the package-level functions RegisterErrorDetailer and +// RegisterTypeErrorDetailer. type ErrorDetailer interface { // ErrorDetails is called to update or alter details for err. ErrorDetails(err error, details *ErrorDetails) diff --git a/module/apmmongo/monitor.go b/module/apmmongo/monitor.go index e3357c222..7fe36fb97 100644 --- a/module/apmmongo/monitor.go +++ b/module/apmmongo/monitor.go @@ -19,6 +19,7 @@ package apmmongo import ( "context" + "reflect" "sync" "time" @@ -26,6 +27,7 @@ import ( "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/event" + "go.mongodb.org/mongo-driver/mongo" "go.elastic.co/apm" ) @@ -39,6 +41,17 @@ var ( } ) +func init() { + apm.RegisterTypeErrorDetailer( + reflect.TypeOf(mongo.CommandError{}), + apm.ErrorDetailerFunc(func(err error, details *apm.ErrorDetails) { + commandErr := err.(mongo.CommandError) + details.Code.String = commandErr.Name + details.SetAttr("labels", commandErr.Labels) + }), + ) +} + // CommandMonitor returns a new event.CommandMonitor which will report a span // for each command executed within a context containing a sampled transaction. func CommandMonitor(opts ...Option) *event.CommandMonitor { diff --git a/module/apmmongo/monitor_integration_test.go b/module/apmmongo/monitor_integration_test.go index 091865a76..e90ece91e 100644 --- a/module/apmmongo/monitor_integration_test.go +++ b/module/apmmongo/monitor_integration_test.go @@ -110,5 +110,5 @@ func (suite *IntegrationSuite) TestCommandMonitor() { suite.Require().Len(errs, 1) suite.Equal(tx.ID, errs[0].ParentID) suite.Equal("(UserNotFound) User 'bob@test_db' not found", errs[0].Exception.Message) - suite.Equal(model.ExceptionCode{}, errs[0].Exception.Code) // BUG(axw) https://github.com/elastic/apm-agent-go/issues/447 + suite.Equal(model.ExceptionCode{String: "UserNotFound"}, errs[0].Exception.Code) }