Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'internal/middleware/errorhandler/errorhandler.go')
-rw-r--r--internal/middleware/errorhandler/errorhandler.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/internal/middleware/errorhandler/errorhandler.go b/internal/middleware/errorhandler/errorhandler.go
new file mode 100644
index 000000000..ea00510d0
--- /dev/null
+++ b/internal/middleware/errorhandler/errorhandler.go
@@ -0,0 +1,98 @@
+package errorhandler
+
+import (
+ "context"
+ "fmt"
+ "sync"
+ "time"
+
+ "gitlab.com/gitlab-org/gitaly/internal/praefect/protoregistry"
+
+ "google.golang.org/grpc"
+)
+
+func UnaryErrorHandler(errorTracker *Errors, registry *protoregistry.Registry) grpc.UnaryServerInterceptor {
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ resp, err := handler(ctx, req)
+ if err != nil {
+ mi, lookupErr := registry.LookupMethod(info.FullMethod)
+ if err != nil {
+ return resp, fmt.Errorf("error when looking up method :%w %w", err, lookupErr)
+ }
+ switch mi.Operation {
+ case protoregistry.OpAccessor:
+ errorTracker.IncrReadErr()
+ case protoregistry.OpMutator:
+ errorTracker.IncrWriteErr()
+ }
+ }
+ return resp, err
+ }
+}
+
+func StreamErrorHandler(errorTracker *Errors, registry *protoregistry.Registry) grpc.StreamServerInterceptor {
+ return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ err := handler(srv, stream)
+ if err != nil {
+ mi, lookupErr := registry.LookupMethod(info.FullMethod)
+ if err != nil {
+ return fmt.Errorf("error when looking up method :%w %w", err, lookupErr)
+ }
+ switch mi.Operation {
+ case protoregistry.OpAccessor:
+ errorTracker.IncrReadErr()
+ case protoregistry.OpMutator:
+ errorTracker.IncrWriteErr()
+ }
+ }
+
+ return err
+ }
+}
+
+type Errors struct {
+ m sync.RWMutex
+ readErrors, writeErrors int64
+}
+
+func (e *Errors) IncrReadErr() {
+ e.m.Lock()
+ defer e.m.Unlock()
+
+ e.readErrors++
+}
+
+func (e *Errors) IncrWriteErr() {
+ e.m.Lock()
+ defer e.m.Unlock()
+
+ e.writeErrors++
+}
+
+func (e *Errors) ReadErrs() int64 {
+ e.m.RLock()
+ defer e.m.RUnlock()
+
+ return e.readErrors
+}
+
+func (e *Errors) WriteErrs() int64 {
+ e.m.RLock()
+ defer e.m.RUnlock()
+
+ return e.writeErrors
+}
+
+func (e *Errors) PeriodicallyClear() {
+ ticker := time.NewTicker(10 * time.Second)
+ for {
+ <-ticker.C
+ }
+}
+
+func (e *Errors) clear() {
+ e.m.Lock()
+ defer e.m.Unlock()
+ e.readErrors = 0
+ e.writeErrors = 0
+}