From 6698ffc2243ee903778ef156367cc746a03f276c Mon Sep 17 00:00:00 2001 From: dc7303 Date: Sat, 12 Jun 2021 10:11:31 +0900 Subject: [PATCH] Improve error handling using pkg/errors In the case of zap currently in use, the place where the log is output is shown as the error occurrence point in the stack trace. Introduced pkg/errors to allow log output to be processed at the end of the logic. --- api/converter/from_bytes.go | 7 ++- api/converter/from_pb.go | 16 +++--- api/converter/to_bytes.go | 8 ++- api/converter/to_pb.go | 13 ++--- client/client.go | 38 ++++++++------ go.mod | 1 + internal/cli/agent.go | 2 + internal/log/log.go | 2 +- pkg/document/document.go | 3 +- pkg/document/key/key.go | 3 +- pkg/document/operation/add.go | 4 +- pkg/document/operation/edit.go | 4 +- pkg/document/operation/increase.go | 4 +- pkg/document/operation/move.go | 4 +- pkg/document/operation/remove.go | 4 +- pkg/document/operation/rich_edit.go | 4 +- pkg/document/operation/select.go | 4 +- pkg/document/operation/set.go | 4 +- pkg/document/operation/style.go | 4 +- pkg/document/time/actor_id.go | 13 ++--- pkg/types/auth_webhook.go | 13 ++--- yorkie/auth/webhook.go | 15 +++--- yorkie/backend/db/change_info.go | 7 +-- yorkie/backend/db/client_info.go | 24 +++++---- yorkie/backend/db/db.go | 1 + yorkie/backend/db/mongo/client.go | 69 +++++++++---------------- yorkie/backend/db/mongo/decoder.go | 32 ++++-------- yorkie/backend/db/mongo/encoder.go | 7 +-- yorkie/backend/db/mongo/index.go | 18 +++---- yorkie/backend/sync/etcd/client.go | 4 +- yorkie/backend/sync/etcd/client_test.go | 3 +- yorkie/backend/sync/etcd/locker.go | 13 ++--- yorkie/backend/sync/etcd/membermap.go | 13 ++--- yorkie/backend/sync/etcd/pubsub.go | 5 +- yorkie/backend/sync/memory/locker.go | 6 +-- yorkie/backend/sync/memory/pubsub.go | 4 +- yorkie/config.go | 9 ++-- yorkie/packs/packs.go | 26 +++++----- yorkie/rpc/cluster.go | 4 +- yorkie/rpc/interceptors/default.go | 8 +-- yorkie/rpc/server.go | 53 ++++++++++++++----- yorkie/yorkie.go | 2 - 42 files changed, 247 insertions(+), 231 deletions(-) diff --git a/api/converter/from_bytes.go b/api/converter/from_bytes.go index 785123f92..844cfe47f 100644 --- a/api/converter/from_bytes.go +++ b/api/converter/from_bytes.go @@ -17,9 +17,8 @@ package converter import ( - "fmt" - "github.com/gogo/protobuf/proto" + "github.com/pkg/errors" "github.com/yorkie-team/yorkie/api" "github.com/yorkie-team/yorkie/internal/log" @@ -35,7 +34,7 @@ func BytesToObject(snapshot []byte) (*json.Object, error) { pbElem := &api.JSONElement{} if err := proto.Unmarshal(snapshot, pbElem); err != nil { - return nil, err + return nil, errors.WithStack(err) } obj, err := fromJSONObject(pbElem.GetJsonObject()) @@ -61,7 +60,7 @@ func fromJSONElement(pbElem *api.JSONElement) (json.Element, error) { case *api.JSONElement_Counter_: return fromJSONCounter(decoded.Counter) default: - return nil, fmt.Errorf("%s: %w", decoded, ErrUnsupportedElement) + return nil, errors.Wrapf(ErrUnsupportedElement, "decoded: %s", decoded) } } diff --git a/api/converter/from_pb.go b/api/converter/from_pb.go index 863771795..6330a46f8 100644 --- a/api/converter/from_pb.go +++ b/api/converter/from_pb.go @@ -17,7 +17,7 @@ package converter import ( - "fmt" + "github.com/pkg/errors" "github.com/yorkie-team/yorkie/api" "github.com/yorkie-team/yorkie/pkg/document/change" @@ -46,10 +46,10 @@ func FromClient(pbClient *api.Client) (*types.Client, error) { // FromChangePack converts the given Protobuf format to model format. func FromChangePack(pbPack *api.ChangePack) (*change.Pack, error) { if pbPack == nil { - return nil, ErrPackRequired + return nil, errors.WithStack(ErrPackRequired) } if pbPack.Checkpoint == nil { - return nil, ErrCheckpointRequired + return nil, errors.WithStack(ErrCheckpointRequired) } changes, err := fromChanges(pbPack.Changes) @@ -137,7 +137,7 @@ func FromEventType(pbDocEventType api.DocEventType) (types.DocEventType, error) case api.DocEventType_DOCUMENTS_UNWATCHED: return types.DocumentsUnwatchedEvent, nil } - return "", fmt.Errorf("%v: %w", pbDocEventType, ErrUnsupportedEventType) + return "", errors.Wrapf(ErrUnsupportedEventType, "document event type: %v", pbDocEventType) } // FromDocEvent converts the given Protobuf format to model format. @@ -185,7 +185,7 @@ func FromOperations(pbOps []*api.Operation) ([]operation.Operation, error) { case *api.Operation_Increase_: op, err = fromIncrease(decoded.Increase) default: - return nil, ErrUnsupportedOperation + return nil, errors.WithStack(ErrUnsupportedOperation) } if err != nil { return nil, err @@ -553,7 +553,7 @@ func fromElement(pbElement *api.JSONElementSimple) (json.Element, error) { ), nil } - return nil, fmt.Errorf("%d, %w", pbElement.Type, ErrUnsupportedElement) + return nil, errors.Wrapf(ErrUnsupportedElement, "element type: %d", pbElement.Type) } func fromPrimitiveValueType(valueType api.ValueType) (json.ValueType, error) { @@ -576,7 +576,7 @@ func fromPrimitiveValueType(valueType api.ValueType) (json.ValueType, error) { return json.Date, nil } - return 0, fmt.Errorf("%d, %w", valueType, ErrUnsupportedValueType) + return 0, errors.Wrapf(ErrUnsupportedValueType, "value type: %d", valueType) } func fromCounterType(valueType api.ValueType) (json.CounterType, error) { @@ -589,5 +589,5 @@ func fromCounterType(valueType api.ValueType) (json.CounterType, error) { return json.DoubleCnt, nil } - return 0, fmt.Errorf("%d, %w", valueType, ErrUnsupportedCounterType) + return 0, errors.Wrapf(ErrUnsupportedCounterType, "value type: %d", valueType) } diff --git a/api/converter/to_bytes.go b/api/converter/to_bytes.go index f39ad4ba0..c657817af 100644 --- a/api/converter/to_bytes.go +++ b/api/converter/to_bytes.go @@ -17,13 +17,12 @@ package converter import ( - "fmt" "reflect" "github.com/gogo/protobuf/proto" + "github.com/pkg/errors" "github.com/yorkie-team/yorkie/api" - "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/pkg/document/json" ) @@ -36,8 +35,7 @@ func ObjectToBytes(obj *json.Object) ([]byte, error) { bytes, err := proto.Marshal(pbElem) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } return bytes, nil } @@ -57,7 +55,7 @@ func toJSONElement(elem json.Element) (*api.JSONElement, error) { case *json.Counter: return toCounter(elem) default: - return nil, fmt.Errorf("%v: %w", reflect.TypeOf(elem), ErrUnsupportedElement) + return nil, errors.Wrapf(ErrUnsupportedElement, "element type: %v", reflect.TypeOf(elem)) } } diff --git a/api/converter/to_pb.go b/api/converter/to_pb.go index 1212cbe74..e016eb25a 100644 --- a/api/converter/to_pb.go +++ b/api/converter/to_pb.go @@ -17,9 +17,10 @@ package converter import ( - "fmt" "reflect" + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/api" "github.com/yorkie-team/yorkie/pkg/document/change" "github.com/yorkie-team/yorkie/pkg/document/checkpoint" @@ -133,7 +134,7 @@ func ToDocEventType(eventType types.DocEventType) (api.DocEventType, error) { case types.DocumentsUnwatchedEvent: return api.DocEventType_DOCUMENTS_UNWATCHED, nil default: - return 0, fmt.Errorf("%s: %w", eventType, ErrUnsupportedEventType) + return 0, errors.Wrapf(ErrUnsupportedEventType, "document event type: %s", eventType) } } @@ -178,7 +179,7 @@ func ToOperations(operations []operation.Operation) ([]*api.Operation, error) { case *operation.Increase: pbOperation.Body, err = toIncrease(op) default: - return nil, ErrUnsupportedOperation + return nil, errors.WithStack(ErrUnsupportedOperation) } if err != nil { return nil, err @@ -353,7 +354,7 @@ func toJSONElementSimple(elem json.Element) (*api.JSONElementSimple, error) { }, nil } - return nil, fmt.Errorf("%v, %w", reflect.TypeOf(elem), ErrUnsupportedElement) + return nil, errors.Wrapf(ErrUnsupportedElement, "element type: %v", reflect.TypeOf(elem)) } func toTextNodePos(pos *json.RGATreeSplitNodePos) *api.TextNodePos { @@ -406,7 +407,7 @@ func toValueType(valueType json.ValueType) (api.ValueType, error) { return api.ValueType_DATE, nil } - return 0, fmt.Errorf("%d, %w", valueType, ErrUnsupportedValueType) + return 0, errors.Wrapf(ErrUnsupportedValueType, "value type: %d", valueType) } func toCounterType(valueType json.CounterType) (api.ValueType, error) { @@ -419,5 +420,5 @@ func toCounterType(valueType json.CounterType) (api.ValueType, error) { return api.ValueType_DOUBLE_CNT, nil } - return 0, fmt.Errorf("%d, %w", valueType, ErrUnsupportedCounterType) + return 0, errors.Wrapf(ErrUnsupportedCounterType, "value type: %d", valueType) } diff --git a/client/client.go b/client/client.go index c7fac7891..1d0bb7d32 100644 --- a/client/client.go +++ b/client/client.go @@ -18,9 +18,10 @@ package client import ( "context" - "errors" + goerrors "errors" "github.com/google/uuid" + "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -43,11 +44,11 @@ const ( var ( // ErrClientNotActivated occurs when an inactive client executes a function // that can only be executed when activated. - ErrClientNotActivated = errors.New("client is not activated") + ErrClientNotActivated = goerrors.New("client is not activated") // ErrDocumentNotAttached occurs when the given document is not attached to // this client. - ErrDocumentNotAttached = errors.New("document is not attached") + ErrDocumentNotAttached = goerrors.New("document is not attached") ) // Client is a normal client that can communicate with the agent. @@ -105,8 +106,7 @@ func NewClient(opts ...Option) (*Client, error) { serverNameOverride, ) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } dialOptions = append(dialOptions, grpc.WithTransportCredentials(creds)) } else { @@ -150,8 +150,7 @@ func Dial(rpcAddr string, opts ...Option) (*Client, error) { func (c *Client) Dial(rpcAddr string) error { conn, err := grpc.Dial(rpcAddr, c.dialOptions...) if err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } c.conn = conn @@ -163,6 +162,7 @@ func (c *Client) Dial(rpcAddr string) error { // Close closes all resources of this client. func (c *Client) Close() error { if err := c.Deactivate(context.Background()); err != nil { + log.Logger.Errorf("%+v", err) return err } @@ -185,7 +185,6 @@ func (c *Client) Activate(ctx context.Context) error { response, err := c.client.ActivateClient(ctx, &api.ActivateClientRequest{ ClientKey: c.key, }) - if err != nil { log.Logger.Error(err) return err @@ -193,6 +192,7 @@ func (c *Client) Activate(ctx context.Context) error { clientID, err := time.ActorIDFromBytes(response.ClientId) if err != nil { + log.Logger.Errorf("%+v", err) return err } @@ -212,8 +212,7 @@ func (c *Client) Deactivate(ctx context.Context) error { ClientId: c.id.Bytes(), }) if err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } c.status = deactivated @@ -232,6 +231,7 @@ func (c *Client) Attach(ctx context.Context, doc *document.Document) error { pbChangePack, err := converter.ToChangePack(doc.CreateChangePack()) if err != nil { + log.Logger.Errorf("%+v", err) return err } @@ -246,11 +246,12 @@ func (c *Client) Attach(ctx context.Context, doc *document.Document) error { pack, err := converter.FromChangePack(res.ChangePack) if err != nil { + log.Logger.Errorf("%+v", err) return err } if err := doc.ApplyChangePack(pack); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return err } @@ -268,15 +269,18 @@ func (c *Client) Attach(ctx context.Context, doc *document.Document) error { // document is no longer used by this client, it should be detached. func (c *Client) Detach(ctx context.Context, doc *document.Document) error { if c.status != activated { + log.Logger.Error(ErrClientNotActivated) return ErrClientNotActivated } if _, ok := c.attachedDocs[doc.Key().BSONKey()]; !ok { + log.Logger.Error(ErrClientNotActivated) return ErrDocumentNotAttached } pbChangePack, err := converter.ToChangePack(doc.CreateChangePack()) if err != nil { + log.Logger.Errorf("%+v", err) return err } @@ -291,11 +295,12 @@ func (c *Client) Detach(ctx context.Context, doc *document.Document) error { pack, err := converter.FromChangePack(res.ChangePack) if err != nil { + log.Logger.Errorf("%+v", err) return err } if err := doc.ApplyChangePack(pack); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return err } @@ -317,6 +322,7 @@ func (c *Client) Sync(ctx context.Context, keys ...*key.Key) error { for _, k := range keys { if err := c.sync(ctx, k); err != nil { + log.Logger.Errorf("%+v", err) return err } } @@ -423,12 +429,12 @@ func (c *Client) IsActive() bool { func (c *Client) sync(ctx context.Context, key *key.Key) error { if c.status != activated { - return ErrClientNotActivated + return errors.WithStack(ErrClientNotActivated) } doc, ok := c.attachedDocs[key.BSONKey()] if !ok { - return ErrDocumentNotAttached + return errors.WithStack(ErrDocumentNotAttached) } pbChangePack, err := converter.ToChangePack(doc.CreateChangePack()) @@ -441,8 +447,7 @@ func (c *Client) sync(ctx context.Context, key *key.Key) error { ChangePack: pbChangePack, }) if err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } pack, err := converter.FromChangePack(res.ChangePack) @@ -451,7 +456,6 @@ func (c *Client) sync(ctx context.Context, key *key.Key) error { } if err := doc.ApplyChangePack(pack); err != nil { - log.Logger.Error(err) return err } diff --git a/go.mod b/go.mod index fd967242e..75faff793 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/moby/locker v1.0.1 + github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.10.0 github.com/rs/xid v1.2.1 github.com/spf13/cobra v1.1.1 diff --git a/internal/cli/agent.go b/internal/cli/agent.go index 045634d49..4d9363135 100644 --- a/internal/cli/agent.go +++ b/internal/cli/agent.go @@ -68,10 +68,12 @@ func newAgentCmd() *cobra.Command { r, err := yorkie.New(conf) if err != nil { + log.Logger.Errorf("%+v", err) return err } if err := r.Start(); err != nil { + log.Logger.Errorf("%+v", err) return err } diff --git a/internal/log/log.go b/internal/log/log.go index a64cea37c..e904d8f84 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -58,7 +58,7 @@ func init() { zapcore.AddSync(os.Stdout), zap.InfoLevel, ), - ), zap.AddStacktrace(zap.ErrorLevel)) + )) Logger = rawLogger.Sugar() } diff --git a/pkg/document/document.go b/pkg/document/document.go index 174f952fe..879c15c4a 100644 --- a/pkg/document/document.go +++ b/pkg/document/document.go @@ -67,13 +67,14 @@ func (d *Document) Update( if err := updater(proxy.NewObjectProxy(ctx, d.clone.Object())); err != nil { // drop clone because it is contaminated. d.clone = nil - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return err } if ctx.HasOperations() { c := ctx.ToChange() if err := c.Execute(d.doc.root); err != nil { + log.Logger.Errorf("%+v", err) return err } diff --git a/pkg/document/key/key.go b/pkg/document/key/key.go index ff4e6d1a3..bf6d17134 100644 --- a/pkg/document/key/key.go +++ b/pkg/document/key/key.go @@ -17,8 +17,9 @@ package key import ( - "errors" "strings" + + "github.com/pkg/errors" ) const ( diff --git a/pkg/document/operation/add.go b/pkg/document/operation/add.go index c49091690..f77ad2af2 100644 --- a/pkg/document/operation/add.go +++ b/pkg/document/operation/add.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -57,7 +59,7 @@ func (o *Add) Execute(root *json.Root) error { obj, ok := parent.(*json.Array) if !ok { - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } value := o.value.DeepCopy() diff --git a/pkg/document/operation/edit.go b/pkg/document/operation/edit.go index 31c170c9e..1e5abcc91 100644 --- a/pkg/document/operation/edit.go +++ b/pkg/document/operation/edit.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -73,7 +75,7 @@ func (e *Edit) Execute(root *json.Root) error { root.RegisterRemovedNodeTextElement(obj) } default: - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } return nil diff --git a/pkg/document/operation/increase.go b/pkg/document/operation/increase.go index 10644faee..48049b902 100644 --- a/pkg/document/operation/increase.go +++ b/pkg/document/operation/increase.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -47,7 +49,7 @@ func (o *Increase) Execute(root *json.Root) error { parent := root.FindByCreatedAt(o.parentCreatedAt) cnt, ok := parent.(*json.Counter) if !ok { - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } value := o.value.(*json.Primitive) diff --git a/pkg/document/operation/move.go b/pkg/document/operation/move.go index b29ffbdc6..4aaec03d1 100644 --- a/pkg/document/operation/move.go +++ b/pkg/document/operation/move.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -57,7 +59,7 @@ func (o *Move) Execute(root *json.Root) error { obj, ok := parent.(*json.Array) if !ok { - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } obj.MoveAfter(o.prevCreatedAt, o.createdAt, o.executedAt) diff --git a/pkg/document/operation/remove.go b/pkg/document/operation/remove.go index 18fd62731..9f8cd6aca 100644 --- a/pkg/document/operation/remove.go +++ b/pkg/document/operation/remove.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -56,7 +58,7 @@ func (o *Remove) Execute(root *json.Root) error { elem := parent.DeleteByCreatedAt(o.createdAt, o.executedAt) root.RegisterRemovedElementPair(parent, elem) default: - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } return nil diff --git a/pkg/document/operation/rich_edit.go b/pkg/document/operation/rich_edit.go index a8a1e5a43..26f490e20 100644 --- a/pkg/document/operation/rich_edit.go +++ b/pkg/document/operation/rich_edit.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -80,7 +82,7 @@ func (e *RichEdit) Execute(root *json.Root) error { root.RegisterRemovedNodeTextElement(obj) } default: - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } return nil diff --git a/pkg/document/operation/select.go b/pkg/document/operation/select.go index 5abb6fd68..b863e335f 100644 --- a/pkg/document/operation/select.go +++ b/pkg/document/operation/select.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -61,7 +63,7 @@ func (s *Select) Execute(root *json.Root) error { case *json.RichText: obj.Select(s.from, s.to, s.executedAt) default: - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } return nil diff --git a/pkg/document/operation/set.go b/pkg/document/operation/set.go index f14048bde..fec0cb9f1 100644 --- a/pkg/document/operation/set.go +++ b/pkg/document/operation/set.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -58,7 +60,7 @@ func (o *Set) Execute(root *json.Root) error { obj, ok := parent.(*json.Object) if !ok { - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } value := o.value.DeepCopy() diff --git a/pkg/document/operation/style.go b/pkg/document/operation/style.go index ac08a55ca..79c8a1b54 100644 --- a/pkg/document/operation/style.go +++ b/pkg/document/operation/style.go @@ -17,6 +17,8 @@ package operation import ( + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/json" "github.com/yorkie-team/yorkie/pkg/document/time" ) @@ -61,7 +63,7 @@ func (e *Style) Execute(root *json.Root) error { parent := root.FindByCreatedAt(e.parentCreatedAt) obj, ok := parent.(*json.RichText) if !ok { - return ErrNotApplicableDataType + return errors.WithStack(ErrNotApplicableDataType) } obj.SetStyle(e.from, e.to, e.attributes, e.executedAt) diff --git a/pkg/document/time/actor_id.go b/pkg/document/time/actor_id.go index aa63fc838..5a419b44b 100644 --- a/pkg/document/time/actor_id.go +++ b/pkg/document/time/actor_id.go @@ -19,9 +19,10 @@ package time import ( "bytes" "encoding/hex" - "errors" - "fmt" + goerrors "errors" "math" + + "github.com/pkg/errors" ) const actorIDSize = 12 @@ -47,7 +48,7 @@ var ( } // ErrInvalidHexString is returned when the given string is not valid hex. - ErrInvalidHexString = errors.New("invalid hex string") + ErrInvalidHexString = goerrors.New("invalid hex string") ) // ActorID is bytes represented by the hexadecimal string. @@ -63,11 +64,11 @@ func ActorIDFromHex(str string) (*ActorID, error) { actorID := ActorID{} decoded, err := hex.DecodeString(str) if err != nil { - return nil, fmt.Errorf("%s: %w", str, ErrInvalidHexString) + return nil, errors.Wrapf(ErrInvalidHexString, "string: %s", str) } if len(decoded) != actorIDSize { - return nil, fmt.Errorf("decoded length %d: %w", len(decoded), ErrInvalidHexString) + return nil, errors.Wrapf(ErrInvalidHexString, "decoded length %d", len(decoded)) } copy(actorID[:], decoded[:actorIDSize]) @@ -81,7 +82,7 @@ func ActorIDFromBytes(bytes []byte) (*ActorID, error) { } if len(bytes) != actorIDSize { - return nil, fmt.Errorf("bytes length %d: %w", len(bytes), ErrInvalidHexString) + return nil, errors.Wrapf(ErrInvalidHexString, "bytes length %d", len(bytes)) } actorID := ActorID{} diff --git a/pkg/types/auth_webhook.go b/pkg/types/auth_webhook.go index 6cd69d8e9..690703bcd 100644 --- a/pkg/types/auth_webhook.go +++ b/pkg/types/auth_webhook.go @@ -18,9 +18,10 @@ package types import ( "encoding/json" - "errors" - "fmt" + goerrors "errors" "io" + + "github.com/pkg/errors" ) // VerbType represents an action taken on the document. @@ -37,10 +38,10 @@ const ( var ( // ErrInvalidWebhookRequest is returned when the given webhook request is not valid. - ErrInvalidWebhookRequest = errors.New("invalid authorization webhook request") + ErrInvalidWebhookRequest = goerrors.New("invalid authorization webhook request") // ErrInvalidWebhookResponse is returned when the given webhook response is not valid. - ErrInvalidWebhookResponse = errors.New("invalid authorization webhook response") + ErrInvalidWebhookResponse = goerrors.New("invalid authorization webhook response") ) // Method represents a method name of RPC. @@ -79,7 +80,7 @@ func NewAuthWebhookRequest(reader io.Reader) (*AuthWebhookRequest, error) { req := &AuthWebhookRequest{} if err := json.NewDecoder(reader).Decode(req); err != nil { - return nil, fmt.Errorf("%s: %w", err.Error(), ErrInvalidWebhookRequest) + return nil, errors.Wrapf(ErrInvalidWebhookRequest, "error: %s", err.Error()) } return req, nil @@ -96,7 +97,7 @@ func NewAuthWebhookResponse(reader io.Reader) (*AuthWebhookResponse, error) { resp := &AuthWebhookResponse{} if err := json.NewDecoder(reader).Decode(resp); err != nil { - return nil, fmt.Errorf("%s: %w", err.Error(), ErrInvalidWebhookResponse) + return nil, errors.Wrapf(ErrInvalidWebhookResponse, "error: %s", err.Error()) } return resp, nil diff --git a/yorkie/auth/webhook.go b/yorkie/auth/webhook.go index f3391f1dd..68eef33e7 100644 --- a/yorkie/auth/webhook.go +++ b/yorkie/auth/webhook.go @@ -4,10 +4,11 @@ import ( "bytes" "context" "encoding/json" - "errors" - "fmt" + goerrors "errors" "net/http" + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/pkg/document/change" "github.com/yorkie-team/yorkie/pkg/types" @@ -16,7 +17,7 @@ import ( var ( // ErrNotAllowed is returned when the given user is not allowed for the access. - ErrNotAllowed = errors.New("method is not allowed for this user") + ErrNotAllowed = goerrors.New("method is not allowed for this user") ) // AccessAttributes returns an array of AccessAttribute from the given pack. @@ -46,7 +47,7 @@ func VerifyAccess(ctx context.Context, be *backend.Backend, info *types.AccessIn Attributes: info.Attributes, }) if err != nil { - return err + return errors.WithStack(err) } // TODO(hackerwins): We need to apply retryBackoff in case of failure @@ -56,11 +57,11 @@ func VerifyAccess(ctx context.Context, be *backend.Backend, info *types.AccessIn bytes.NewBuffer(reqBody), ) if err != nil { - return err + return errors.WithStack(err) } defer func() { if err := resp.Body.Close(); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", errors.WithStack(err)) } }() @@ -70,7 +71,7 @@ func VerifyAccess(ctx context.Context, be *backend.Backend, info *types.AccessIn } if !authResp.Allowed { - return fmt.Errorf("%s: %w", authResp.Reason, ErrNotAllowed) + return errors.Wrapf(ErrNotAllowed, "reason: %s", authResp.Reason) } return nil diff --git a/yorkie/backend/db/change_info.go b/yorkie/backend/db/change_info.go index dd7bcee00..c0c8ef808 100644 --- a/yorkie/backend/db/change_info.go +++ b/yorkie/backend/db/change_info.go @@ -17,11 +17,10 @@ package db import ( - "errors" + "github.com/pkg/errors" "github.com/yorkie-team/yorkie/api" "github.com/yorkie-team/yorkie/api/converter" - "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/pkg/document/change" "github.com/yorkie-team/yorkie/pkg/document/operation" "github.com/yorkie-team/yorkie/pkg/document/time" @@ -50,7 +49,6 @@ func EncodeOperations(operations []operation.Operation) ([][]byte, error) { for _, pbOp := range changes { encodedOp, err := pbOp.Marshal() if err != nil { - log.Logger.Error(err) return nil, errors.New("fail to encode operation") } encodedOps = append(encodedOps, encodedOp) @@ -72,8 +70,7 @@ func (i *ChangeInfo) ToChange() (*change.Change, error) { for _, bytesOp := range i.Operations { pbOp := api.Operation{} if err := pbOp.Unmarshal(bytesOp); err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } pbOps = append(pbOps, &pbOp) } diff --git a/yorkie/backend/db/client_info.go b/yorkie/backend/db/client_info.go index 5dbdd459c..8b0bb59f0 100644 --- a/yorkie/backend/db/client_info.go +++ b/yorkie/backend/db/client_info.go @@ -17,18 +17,20 @@ package db import ( - "errors" + goerrors "errors" "time" + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/pkg/document/checkpoint" ) // Below are the errors may occur depending on the document and client status. var ( - ErrClientNotActivated = errors.New("client not activated") - ErrDocumentNotAttached = errors.New("document not attached") - ErrDocumentNeverAttached = errors.New("client has never attached the document") - ErrDocumentAlreadyAttached = errors.New("document already attached") + ErrClientNotActivated = goerrors.New("client not activated") + ErrDocumentNotAttached = goerrors.New("document not attached") + ErrDocumentNeverAttached = goerrors.New("client has never attached the document") + ErrDocumentAlreadyAttached = goerrors.New("document already attached") ) // Below are statuses of the client. @@ -63,7 +65,7 @@ type ClientInfo struct { // AttachDocument attaches the given document to this client. func (i *ClientInfo) AttachDocument(docID ID) error { if i.Status != ClientActivated { - return ErrClientNotActivated + return errors.WithStack(ErrClientNotActivated) } if i.Documents == nil { @@ -71,7 +73,7 @@ func (i *ClientInfo) AttachDocument(docID ID) error { } if i.hasDocument(docID) && i.Documents[docID].Status == documentAttached { - return ErrDocumentAlreadyAttached + return errors.WithStack(ErrDocumentAlreadyAttached) } i.Documents[docID] = &ClientDocInfo{ @@ -101,7 +103,7 @@ func (i *ClientInfo) DetachDocument(docID ID) error { // IsAttached returns whether the given document is attached to this client. func (i *ClientInfo) IsAttached(docID ID) (bool, error) { if !i.hasDocument(docID) { - return false, ErrDocumentNeverAttached + return false, errors.WithStack(ErrDocumentNeverAttached) } return i.Documents[docID].Status == documentAttached, nil @@ -123,7 +125,7 @@ func (i *ClientInfo) UpdateCheckpoint( cp *checkpoint.Checkpoint, ) error { if !i.hasDocument(docID) { - return ErrDocumentNeverAttached + return errors.WithStack(ErrDocumentNeverAttached) } i.Documents[docID].ServerSeq = cp.ServerSeq @@ -136,11 +138,11 @@ func (i *ClientInfo) UpdateCheckpoint( // EnsureDocumentAttached ensures the given document is attached. func (i *ClientInfo) EnsureDocumentAttached(docID ID) error { if i.Status != ClientActivated { - return ErrClientNotActivated + return errors.WithStack(ErrClientNotActivated) } if !i.hasDocument(docID) || i.Documents[docID].Status == documentDetached { - return ErrDocumentNotAttached + return errors.WithStack(ErrDocumentNotAttached) } return nil diff --git a/yorkie/backend/db/db.go b/yorkie/backend/db/db.go index d96cbd792..21814ea3a 100644 --- a/yorkie/backend/db/db.go +++ b/yorkie/backend/db/db.go @@ -3,6 +3,7 @@ package db import ( "context" "encoding/hex" + "errors" "github.com/yorkie-team/yorkie/pkg/document" diff --git a/yorkie/backend/db/mongo/client.go b/yorkie/backend/db/mongo/client.go index a25a32e2a..a7bec4cc8 100644 --- a/yorkie/backend/db/mongo/client.go +++ b/yorkie/backend/db/mongo/client.go @@ -18,9 +18,9 @@ package mongo import ( "context" - "fmt" gotime "time" + "github.com/pkg/errors" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" @@ -61,20 +61,17 @@ func Dial(conf *Config) (*Client, error) { options.Client().ApplyURI(conf.ConnectionURI), ) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } ctxPing, cancel := context.WithTimeout(ctx, conf.PingTimeoutSec*gotime.Second) defer cancel() if err := client.Ping(ctxPing, readpref.Primary()); err != nil { - log.Logger.Errorf("fail to connect to %s in %d sec", conf.ConnectionURI, conf.PingTimeoutSec) - return nil, err + return nil, errors.Wrapf(err, "fail to connect to %s in %d sec", conf.ConnectionURI, conf.PingTimeoutSec) } if err := ensureIndexes(ctx, client.Database(conf.YorkieDatabase)); err != nil { - log.Logger.Error(err) return nil, err } @@ -90,8 +87,7 @@ func Dial(conf *Config) (*Client, error) { // Close all resources of this client. func (c *Client) Close() error { if err := c.client.Disconnect(context.Background()); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } return nil @@ -111,8 +107,7 @@ func (c *Client) ActivateClient(ctx context.Context, key string) (*db.ClientInfo }, }, options.Update().SetUpsert(true)) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } var result *mongo.SingleResult @@ -155,8 +150,8 @@ func (c *Client) DeactivateClient(ctx context.Context, clientID db.ID) (*db.Clie }) if err := decodeClientInfo(res, &clientInfo); err != nil { - if err == mongo.ErrNoDocuments { - return nil, fmt.Errorf("%s: %w", clientID, db.ErrClientNotFound) + if errors.Is(err, mongo.ErrNoDocuments) { + return nil, errors.Wrapf(db.ErrClientNotFound, "clientID: %s", clientID) } return nil, err } @@ -176,8 +171,8 @@ func (c *Client) FindClientInfoByID(ctx context.Context, clientID db.ID) (*db.Cl "_id": encodedClientID, }) if err := decodeClientInfo(result, &clientInfo); err != nil { - if err == mongo.ErrNoDocuments { - return nil, fmt.Errorf("%s: %w", clientID, db.ErrClientNotFound) + if errors.Is(err, mongo.ErrNoDocuments) { + return nil, errors.Wrapf(db.ErrClientNotFound, "clientID: %s", clientID) } } @@ -227,9 +222,8 @@ func (c *Client) UpdateClientInfoAfterPushPull( if result.Err() != nil { if result.Err() == mongo.ErrNoDocuments { - return fmt.Errorf("%s: %w", clientInfo.Key, db.ErrClientNotFound) + return errors.Wrapf(db.ErrClientNotFound, "clientKey: %s", clientInfo.Key) } - log.Logger.Error(result.Err()) return result.Err() } @@ -260,8 +254,7 @@ func (c *Client) FindDocInfoByKey( }, }, options.Update().SetUpsert(createDocIfNotExist)) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } var result *mongo.SingleResult @@ -280,12 +273,10 @@ func (c *Client) FindDocInfoByKey( "key": bsonDocKey, }) if result.Err() == mongo.ErrNoDocuments { - log.Logger.Error(result.Err()) - return nil, fmt.Errorf("%s: %w", bsonDocKey, db.ErrDocumentNotFound) + return nil, errors.Wrapf(db.ErrDocumentNotFound, "bson document key: %s", bsonDocKey) } if result.Err() != nil { - log.Logger.Error(result.Err()) - return nil, result.Err() + return nil, errors.WithStack(result.Err()) } } if err := decodeDocInfo(result, &docInfo); err != nil { @@ -333,8 +324,7 @@ func (c *Client) StoreChangeInfos( models, options.BulkWrite().SetOrdered(true), ); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } res, err := c.collection(ColDocuments).UpdateOne(ctx, bson.M{ @@ -347,11 +337,10 @@ func (c *Client) StoreChangeInfos( }, }) if err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if res.MatchedCount == 0 { - return fmt.Errorf("%s: %w", docInfo.ID, db.ErrConflictOnUpdate) + return errors.Wrapf(db.ErrConflictOnUpdate, "docID: %s", docInfo.ID) } return nil @@ -378,8 +367,7 @@ func (c *Client) CreateSnapshotInfo( "snapshot": snapshot, "created_at": gotime.Now(), }); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } return nil @@ -406,8 +394,7 @@ func (c *Client) FindChangeInfosBetweenServerSeqs( }, }, options.Find()) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } defer func() { @@ -429,8 +416,7 @@ func (c *Client) FindChangeInfosBetweenServerSeqs( } if cursor.Err() != nil { - log.Logger.Error(cursor.Err()) - return nil, cursor.Err() + return nil, errors.WithStack(cursor.Err()) } return changes, nil @@ -468,16 +454,14 @@ func (c *Client) UpdateAndFindMinSyncedTicket( "server_seq": serverSeq, }, }, options.Update().SetUpsert(true)); err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } } else { if _, err = c.collection(ColSyncedSeqs).DeleteOne(ctx, bson.M{ "doc_id": encodedDocID, "client_id": encodedClientID, }, options.Delete()); err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } } @@ -492,8 +476,7 @@ func (c *Client) UpdateAndFindMinSyncedTicket( return time.InitialTicket, nil } if result.Err() != nil { - log.Logger.Error(result.Err()) - return nil, result.Err() + return nil, errors.WithStack(result.Err()) } if err := decodeSyncedSeqInfo(result, &syncedSeqInfo); err != nil { return nil, err @@ -535,8 +518,7 @@ func (c *Client) FindLastSnapshotInfo( } if result.Err() != nil { - log.Logger.Error(result.Err()) - return nil, result.Err() + return nil, errors.WithStack(result.Err()) } if err := decodeSnapshotInfo(result, snapshotInfo); err != nil { @@ -562,12 +544,11 @@ func (c *Client) findTicketByServerSeq( "server_seq": serverSeq, }) if result.Err() == mongo.ErrNoDocuments { - return nil, fmt.Errorf("%s: %w", docID.String(), db.ErrDocumentNotFound) + return nil, errors.Wrapf(db.ErrDocumentNotFound, "docID: %s", docID.String()) } if result.Err() != nil { - log.Logger.Error(result.Err()) - return nil, result.Err() + return nil, errors.WithStack(result.Err()) } if err := decodeChangeInfo(result, &changeInfo); err != nil { diff --git a/yorkie/backend/db/mongo/decoder.go b/yorkie/backend/db/mongo/decoder.go index 7a81fb5fc..1036009c1 100644 --- a/yorkie/backend/db/mongo/decoder.go +++ b/yorkie/backend/db/mongo/decoder.go @@ -1,9 +1,9 @@ package mongo import ( + "github.com/pkg/errors" "go.mongodb.org/mongo-driver/bson/primitive" - "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/yorkie/backend/db" ) @@ -19,12 +19,10 @@ func decodeClientInfo( ID primitive.ObjectID `bson:"_id"` }{} if err := result.Decode(&idHolder); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if err := result.Decode(clientInfo); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } clientInfo.ID = decodeID(idHolder.ID) return nil @@ -39,12 +37,10 @@ func decodeDocInfo( Owner primitive.ObjectID `bson:"owner"` }{} if err := result.Decode(&idHolder); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if err := result.Decode(&docInfo); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } docInfo.ID = decodeID(idHolder.ID) docInfo.Owner = decodeID(idHolder.Owner) @@ -60,12 +56,10 @@ func decodeChangeInfo( Actor primitive.ObjectID `bson:"actor"` }{} if err := cursor.Decode(&idHolder); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if err := cursor.Decode(&changeInfo); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } changeInfo.DocID = decodeID(idHolder.DocID) changeInfo.Actor = decodeID(idHolder.Actor) @@ -81,12 +75,10 @@ func decodeSyncedSeqInfo( ClientID primitive.ObjectID `bson:"client_id"` }{} if err := result.Decode(&idHolder); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if err := result.Decode(&syncedSeqInfo); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } syncedSeqInfo.DocID = decodeID(idHolder.DocID) syncedSeqInfo.ClientID = decodeID(idHolder.ClientID) @@ -102,12 +94,10 @@ func decodeSnapshotInfo( DocID primitive.ObjectID `bson:"doc_id"` }{} if err := result.Decode(&idHolder); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if err := result.Decode(&snapshotInfo); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } snapshotInfo.ID = decodeID(idHolder.ID) snapshotInfo.DocID = decodeID(idHolder.DocID) diff --git a/yorkie/backend/db/mongo/encoder.go b/yorkie/backend/db/mongo/encoder.go index ea8f142bd..88a92e180 100644 --- a/yorkie/backend/db/mongo/encoder.go +++ b/yorkie/backend/db/mongo/encoder.go @@ -1,11 +1,9 @@ package mongo import ( - "fmt" - + "github.com/pkg/errors" "go.mongodb.org/mongo-driver/bson/primitive" - "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/pkg/document/time" "github.com/yorkie-team/yorkie/yorkie/backend/db" ) @@ -19,8 +17,7 @@ func encodeActorID(id *time.ActorID) primitive.ObjectID { func encodeID(id db.ID) (primitive.ObjectID, error) { objectID, err := primitive.ObjectIDFromHex(id.String()) if err != nil { - log.Logger.Error(err) - return objectID, fmt.Errorf("%s: %w", id, db.ErrInvalidID) + return objectID, errors.Wrapf(db.ErrInvalidID, "ID: %s", id) } return objectID, nil } diff --git a/yorkie/backend/db/mongo/index.go b/yorkie/backend/db/mongo/index.go index 547cb4565..29a0f1084 100644 --- a/yorkie/backend/db/mongo/index.go +++ b/yorkie/backend/db/mongo/index.go @@ -19,11 +19,10 @@ package mongo import ( "context" + "github.com/pkg/errors" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/x/bsonx" - - "github.com/yorkie-team/yorkie/internal/log" ) // Below are names and indexes information of collections that stores Yorkie data. @@ -78,40 +77,35 @@ func ensureIndexes(ctx context.Context, db *mongo.Database) error { ctx, idxClientInfos, ); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if _, err := db.Collection(ColDocuments).Indexes().CreateMany( ctx, idxDocInfos, ); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if _, err := db.Collection(ColChanges).Indexes().CreateMany( ctx, idxChanges, ); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if _, err := db.Collection(ColSnapshots).Indexes().CreateMany( ctx, idxSnapshots, ); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if _, err := db.Collection(ColSyncedSeqs).Indexes().CreateMany( ctx, idxSyncedSeqs, ); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } return nil diff --git a/yorkie/backend/sync/etcd/client.go b/yorkie/backend/sync/etcd/client.go index c896f0bd9..d03a51e85 100644 --- a/yorkie/backend/sync/etcd/client.go +++ b/yorkie/backend/sync/etcd/client.go @@ -21,6 +21,7 @@ import ( gosync "sync" "time" + "github.com/pkg/errors" "go.etcd.io/etcd/clientv3" "google.golang.org/grpc" @@ -120,8 +121,7 @@ func (c *Client) Dial() error { Password: c.config.Password, }) if err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } log.Logger.Infof("etcd connected, URI: %s", c.config.Endpoints) diff --git a/yorkie/backend/sync/etcd/client_test.go b/yorkie/backend/sync/etcd/client_test.go index 5190991e4..eae95b05b 100644 --- a/yorkie/backend/sync/etcd/client_test.go +++ b/yorkie/backend/sync/etcd/client_test.go @@ -18,6 +18,7 @@ package etcd_test import ( "context" + "errors" "sync" "testing" @@ -41,6 +42,6 @@ func TestClient(t *testing.T) { }() wg.Wait() - assert.ErrorIs(t, context.DeadlineExceeded, err) + assert.ErrorIs(t, context.DeadlineExceeded, errors.Unwrap(err)) }) } diff --git a/yorkie/backend/sync/etcd/locker.go b/yorkie/backend/sync/etcd/locker.go index 96ca68c50..12b4fd1c7 100644 --- a/yorkie/backend/sync/etcd/locker.go +++ b/yorkie/backend/sync/etcd/locker.go @@ -19,9 +19,9 @@ package etcd import ( "context" + "github.com/pkg/errors" "go.etcd.io/etcd/clientv3/concurrency" - "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/yorkie/backend/sync" ) @@ -36,8 +36,7 @@ func (c *Client) NewLocker( concurrency.WithTTL(c.config.LockLeaseTimeSec), ) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } return &internalLocker{ @@ -54,8 +53,7 @@ type internalLocker struct { // Lock locks a mutex. func (il *internalLocker) Lock(ctx context.Context) error { if err := il.mu.Lock(ctx); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } return nil @@ -64,11 +62,10 @@ func (il *internalLocker) Lock(ctx context.Context) error { // Unlock unlocks the mutex. func (il *internalLocker) Unlock(ctx context.Context) error { if err := il.mu.Unlock(ctx); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } if err := il.session.Close(); err != nil { - return err + return errors.WithStack(err) } return nil diff --git a/yorkie/backend/sync/etcd/membermap.go b/yorkie/backend/sync/etcd/membermap.go index 3c35aae04..b12771e55 100644 --- a/yorkie/backend/sync/etcd/membermap.go +++ b/yorkie/backend/sync/etcd/membermap.go @@ -20,6 +20,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/pkg/errors" "time" "go.etcd.io/etcd/clientv3" @@ -73,13 +74,13 @@ func (c *Client) Members() map[string]*sync.AgentInfo { func (c *Client) initializeMemberMap(ctx context.Context) error { getResponse, err := c.client.Get(ctx, agentsPath, clientv3.WithPrefix()) if err != nil { - return err + return errors.WithStack(err) } for _, kv := range getResponse.Kvs { var info sync.AgentInfo if err := json.Unmarshal(kv.Value, &info); err != nil { - return err + return errors.WithStack(err) } c.setAgentInfo(string(kv.Key), info) @@ -106,20 +107,20 @@ func (c *Client) putAgentPeriodically() { func (c *Client) putAgent(ctx context.Context) error { grantResponse, err := c.client.Grant(ctx, int64(agentValueTTL.Seconds())) if err != nil { - return fmt.Errorf("grant %s: %w", c.agentInfo.ID, err) + return errors.Wrapf(err, "grant %s", c.agentInfo.ID) } agentInfo := *c.agentInfo agentInfo.UpdatedAt = time.Now() bytes, err := json.Marshal(agentInfo) if err != nil { - return fmt.Errorf("marshal %s: %w", c.agentInfo.ID, err) + return errors.Wrapf(err, "marshal %s", c.agentInfo.ID) } key := fmt.Sprintf("%s/%s", agentsPath, c.agentInfo.ID) _, err = c.client.Put(ctx, key, string(bytes), clientv3.WithLease(grantResponse.ID)) if err != nil { - return fmt.Errorf("put %s: %w", key, err) + return errors.Wrapf(err, "put %s", key) } return nil } @@ -129,7 +130,7 @@ func (c *Client) removeAgent(ctx context.Context) error { key := fmt.Sprintf("%s/%s", agentsPath, c.agentInfo.ID) _, err := c.client.Delete(ctx, key) if err != nil { - return fmt.Errorf("remove %s: %w", key, err) + return errors.Wrapf(err, "remove %s", key) } return nil } diff --git a/yorkie/backend/sync/etcd/pubsub.go b/yorkie/backend/sync/etcd/pubsub.go index 7c6efb268..c9b494e05 100644 --- a/yorkie/backend/sync/etcd/pubsub.go +++ b/yorkie/backend/sync/etcd/pubsub.go @@ -19,6 +19,7 @@ package etcd import ( "context" + "github.com/pkg/errors" "google.golang.org/grpc" "github.com/yorkie-team/yorkie/api" @@ -127,7 +128,6 @@ func (c *Client) publishToMember( ) error { docEvent, err := converter.ToDocEvent(event) if err != nil { - log.Logger.Error(err) return err } @@ -135,8 +135,7 @@ func (c *Client) publishToMember( PublisherId: publisherID.Bytes(), Event: docEvent, }); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } return nil diff --git a/yorkie/backend/sync/memory/locker.go b/yorkie/backend/sync/memory/locker.go index 2f7037c04..f81d703b3 100644 --- a/yorkie/backend/sync/memory/locker.go +++ b/yorkie/backend/sync/memory/locker.go @@ -18,10 +18,9 @@ package memory import ( "context" + "github.com/pkg/errors" "github.com/moby/locker" - - "github.com/yorkie-team/yorkie/internal/log" ) type internalLocker struct { @@ -39,8 +38,7 @@ func (il *internalLocker) Lock(ctx context.Context) error { // Unlock unlocks the mutex. func (il *internalLocker) Unlock(ctx context.Context) error { if err := il.locks.Unlock(il.key); err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } return nil diff --git a/yorkie/backend/sync/memory/pubsub.go b/yorkie/backend/sync/memory/pubsub.go index ebca49680..4a857e710 100644 --- a/yorkie/backend/sync/memory/pubsub.go +++ b/yorkie/backend/sync/memory/pubsub.go @@ -20,6 +20,8 @@ import ( "context" gosync "sync" + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/pkg/document/key" "github.com/yorkie-team/yorkie/pkg/document/time" @@ -83,7 +85,7 @@ func (m *PubSub) Subscribe( topics []*key.Key, ) (*sync.Subscription, map[string][]types.Client, error) { if len(topics) == 0 { - return nil, nil, sync.ErrEmptyTopics + return nil, nil, errors.WithStack(sync.ErrEmptyTopics) } m.subscriptionsMapMu.Lock() diff --git a/yorkie/config.go b/yorkie/config.go index f5af210c3..4204347df 100644 --- a/yorkie/config.go +++ b/yorkie/config.go @@ -22,7 +22,8 @@ import ( "os" "path/filepath" - "github.com/yorkie-team/yorkie/internal/log" + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/yorkie/backend" "github.com/yorkie-team/yorkie/yorkie/backend/db/mongo" "github.com/yorkie-team/yorkie/yorkie/backend/sync/etcd" @@ -69,13 +70,11 @@ func NewConfigFromFile(path string) (*Config, error) { conf := &Config{} file, err := os.Open(filepath.Clean(path)) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } if err := json.NewDecoder(file).Decode(conf); err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } return conf, nil diff --git a/yorkie/packs/packs.go b/yorkie/packs/packs.go index 7d7ba45e6..df4789a53 100644 --- a/yorkie/packs/packs.go +++ b/yorkie/packs/packs.go @@ -18,10 +18,12 @@ package packs import ( "context" - "errors" + goerrors "errors" "fmt" gotime "time" + "github.com/pkg/errors" + "github.com/yorkie-team/yorkie/api/converter" "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/pkg/document" @@ -38,7 +40,7 @@ import ( var ( // ErrInvalidServerSeq is returned when the given server seq greater than // the initial server seq. - ErrInvalidServerSeq = errors.New("invalid server seq") + ErrInvalidServerSeq = goerrors.New("invalid server seq") ) // NewPushPullKey creates a new sync.Key of PushPull for the given document. @@ -109,7 +111,7 @@ func PushPull( be.AttachGoroutine(func() { publisherID, err := time.ActorIDFromHex(clientInfo.ID.String()) if err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return } @@ -122,17 +124,17 @@ func PushPull( NewSnapshotKey(reqPack.DocumentKey), ) if err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return } if err := locker.Lock(ctx); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return } defer func() { if err := locker.Unlock(ctx); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return } }() @@ -152,7 +154,7 @@ func PushPull( be, docInfo, ); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) } }) } @@ -214,11 +216,11 @@ func pullPack( } if initialServerSeq < requestPack.Checkpoint.ServerSeq { - return nil, fmt.Errorf( - "server seq(initial %d, request pack %d): %w", + return nil, errors.Wrapf( + ErrInvalidServerSeq, + "server seq(initial %d, request pack %d)", initialServerSeq, requestPack.Checkpoint.ServerSeq, - ErrInvalidServerSeq, ) } @@ -227,7 +229,7 @@ func pullPack( if err != nil { return nil, err } - return change.NewPack(docKey, pulledCP, pulledChanges, nil), err + return change.NewPack(docKey, pulledCP, pulledChanges, nil), nil } pulledCP, snapshot, err := pullSnapshot(ctx, be, clientInfo, docInfo, requestPack, pushedCP, initialServerSeq) @@ -237,7 +239,7 @@ func pullPack( be.Metrics.SetPushPullSnapshotBytes(len(snapshot)) - return change.NewPack(docKey, pulledCP, nil, snapshot), err + return change.NewPack(docKey, pulledCP, nil, snapshot), nil } func pullChanges( diff --git a/yorkie/rpc/cluster.go b/yorkie/rpc/cluster.go index 7ba601f6f..1c1d1e5e1 100644 --- a/yorkie/rpc/cluster.go +++ b/yorkie/rpc/cluster.go @@ -16,13 +16,13 @@ func (s *Server) BroadcastEvent( ) (*api.BroadcastEventResponse, error) { actorID, err := time.ActorIDFromBytes(request.PublisherId) if err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return nil, err } docEvent, err := converter.FromDocEvent(request.Event) if err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return nil, err } diff --git a/yorkie/rpc/interceptors/default.go b/yorkie/rpc/interceptors/default.go index 9095c54cc..90af2df1b 100644 --- a/yorkie/rpc/interceptors/default.go +++ b/yorkie/rpc/interceptors/default.go @@ -18,9 +18,9 @@ package interceptors import ( "context" - "errors" gotime "time" + "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -113,9 +113,9 @@ func toStatusError(err error) error { return status.Error(codes.NotFound, err.Error()) } - if err == db.ErrClientNotActivated || - err == db.ErrDocumentNotAttached || - err == db.ErrDocumentAlreadyAttached || + if errors.Is(err, db.ErrClientNotActivated) || + errors.Is(err, db.ErrDocumentNotAttached) || + errors.Is(err, db.ErrDocumentAlreadyAttached) || errors.Is(err, packs.ErrInvalidServerSeq) || errors.Is(err, db.ErrConflictOnUpdate) { return status.Error(codes.FailedPrecondition, err.Error()) diff --git a/yorkie/rpc/server.go b/yorkie/rpc/server.go index 494cc191c..94528e18e 100644 --- a/yorkie/rpc/server.go +++ b/yorkie/rpc/server.go @@ -24,6 +24,7 @@ import ( grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" grpcprometheus "github.com/grpc-ecosystem/go-grpc-prometheus" + "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/health" @@ -77,8 +78,7 @@ func NewServer(conf *Config, be *backend.Backend) (*Server, error) { if conf.CertFile != "" && conf.KeyFile != "" { creds, err := credentials.NewServerTLSFromFile(conf.CertFile, conf.KeyFile) if err != nil { - log.Logger.Error(err) - return nil, err + return nil, errors.WithStack(err) } opts = append(opts, grpc.Creds(creds)) } @@ -119,17 +119,20 @@ func (s *Server) ActivateClient( req *api.ActivateClientRequest, ) (*api.ActivateClientResponse, error) { if req.ClientKey == "" { + log.Logger.Error(clients.ErrInvalidClientKey) return nil, clients.ErrInvalidClientKey } if err := auth.VerifyAccess(ctx, s.backend, &types.AccessInfo{ Method: types.ActivateClient, }); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } client, err := clients.Activate(ctx, s.backend, req.ClientKey) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -151,11 +154,13 @@ func (s *Server) DeactivateClient( if err := auth.VerifyAccess(ctx, s.backend, &types.AccessInfo{ Method: types.DeactivateClient, }); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } client, err := clients.Deactivate(ctx, s.backend, req.ClientId) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -171,6 +176,7 @@ func (s *Server) AttachDocument( ) (*api.AttachDocumentResponse, error) { pack, err := converter.FromChangePack(req.ChangePack) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -178,6 +184,7 @@ func (s *Server) AttachDocument( Method: types.AttachDocument, Attributes: auth.AccessAttributes(pack), }); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -187,15 +194,17 @@ func (s *Server) AttachDocument( packs.NewPushPullKey(pack.DocumentKey), ) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := locker.Lock(ctx); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } defer func() { if err := locker.Unlock(ctx); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) } }() } @@ -208,19 +217,23 @@ func (s *Server) AttachDocument( true, ) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := clientInfo.AttachDocument(docInfo.ID); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } pulled, err := packs.PushPull(ctx, s.backend, clientInfo, docInfo, pack) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } pbChangePack, err := converter.ToChangePack(pulled) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -236,6 +249,7 @@ func (s *Server) DetachDocument( ) (*api.DetachDocumentResponse, error) { pack, err := converter.FromChangePack(req.ChangePack) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -243,6 +257,7 @@ func (s *Server) DetachDocument( Method: types.DetachDocument, Attributes: auth.AccessAttributes(pack), }); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -252,15 +267,17 @@ func (s *Server) DetachDocument( packs.NewPushPullKey(pack.DocumentKey), ) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := locker.Lock(ctx); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } defer func() { if err := locker.Unlock(ctx); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) } }() } @@ -273,22 +290,27 @@ func (s *Server) DetachDocument( false, ) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := clientInfo.EnsureDocumentAttached(docInfo.ID); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := clientInfo.DetachDocument(docInfo.ID); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } pulled, err := packs.PushPull(ctx, s.backend, clientInfo, docInfo, pack) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } pbChangePack, err := converter.ToChangePack(pulled) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -306,6 +328,7 @@ func (s *Server) PushPull( start := gotime.Now() pack, err := converter.FromChangePack(req.ChangePack) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -313,6 +336,7 @@ func (s *Server) PushPull( Method: types.PushPull, Attributes: auth.AccessAttributes(pack), }); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -324,16 +348,17 @@ func (s *Server) PushPull( packs.NewPushPullKey(pack.DocumentKey), ) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := locker.Lock(ctx); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return nil, err } defer func() { if err := locker.Unlock(ctx); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) } }() } @@ -346,19 +371,23 @@ func (s *Server) PushPull( false, ) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } if err := clientInfo.EnsureDocumentAttached(docInfo.ID); err != nil { + log.Logger.Errorf("%+v", err) return nil, err } pulled, err := packs.PushPull(ctx, s.backend, clientInfo, docInfo, pack) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } pbChangePack, err := converter.ToChangePack(pulled) if err != nil { + log.Logger.Errorf("%+v", err) return nil, err } @@ -378,6 +407,7 @@ func (s *Server) WatchDocuments( ) error { client, err := converter.FromClient(req.Client) if err != nil { + log.Logger.Errorf("%+v", err) return err } docKeys := converter.FromDocumentKeys(req.DocumentKeys) @@ -388,7 +418,7 @@ func (s *Server) WatchDocuments( docKeys, ) if err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return err } @@ -399,7 +429,7 @@ func (s *Server) WatchDocuments( }, }, }); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) s.unwatchDocs(docKeys, subscription) return err } @@ -424,7 +454,7 @@ func (s *Server) WatchDocuments( }, }, }); err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) s.unwatchDocs(docKeys, subscription) return err } @@ -435,8 +465,7 @@ func (s *Server) WatchDocuments( func (s *Server) listenAndServeGRPC() error { lis, err := net.Listen("tcp", fmt.Sprintf(":%d", s.conf.Port)) if err != nil { - log.Logger.Error(err) - return err + return errors.WithStack(err) } go func() { @@ -462,7 +491,7 @@ func (s *Server) watchDocs( docKeys, ) if err != nil { - log.Logger.Error(err) + log.Logger.Errorf("%+v", err) return nil, nil, err } diff --git a/yorkie/yorkie.go b/yorkie/yorkie.go index d58f83e49..b7ebc1658 100644 --- a/yorkie/yorkie.go +++ b/yorkie/yorkie.go @@ -19,7 +19,6 @@ package yorkie import ( gosync "sync" - "github.com/yorkie-team/yorkie/internal/log" "github.com/yorkie-team/yorkie/yorkie/backend" "github.com/yorkie-team/yorkie/yorkie/backend/sync" "github.com/yorkie-team/yorkie/yorkie/metrics/prometheus" @@ -84,7 +83,6 @@ func (r *Yorkie) Start() error { if r.metricsServer != nil { err := r.metricsServer.Start() if err != nil { - log.Logger.Error(err) return err } }