diff --git a/internal/engines/cache/cache.go b/internal/engines/cache/cache.go index fbb89bddb..334c0e427 100644 --- a/internal/engines/cache/cache.go +++ b/internal/engines/cache/cache.go @@ -27,7 +27,8 @@ type CheckEngineWithCache struct { cache cache.Cache // Metrics - cacheCounter api.Int64Counter + cacheCounter api.Int64Counter + cacheHitDurationHistogram api.Int64Histogram } // NewCheckEngineWithCache creates a new instance of EngineKeyManager by initializing an EngineKeys @@ -43,11 +44,22 @@ func NewCheckEngineWithCache( panic(err) } + // Cache Hit Duration Histogram + cacheHitDurationHistogram, err := meter.Int64Histogram( + "cache_hit_duration", + api.WithUnit("microseconds"), + api.WithDescription("Duration of cache hits in microseconds"), + ) + if err != nil { + panic(err) + } + return &CheckEngineWithCache{ - schemaReader: schemaReader, - checker: checker, - cache: cache, - cacheCounter: cacheCounter, + schemaReader: schemaReader, + checker: checker, + cache: cache, + cacheCounter: cacheCounter, + cacheHitDurationHistogram: cacheHitDurationHistogram, } } @@ -77,6 +89,7 @@ func (c *CheckEngineWithCache) Check(ctx context.Context, request *base.Permissi // Increase the check count in the metrics. c.cacheCounter.Add(ctx, 1) + // If the request doesn't have the exclusion flag set, return the cached result. return &base.PermissionCheckResponse{ Can: res.GetCan(), @@ -96,11 +109,12 @@ func (c *CheckEngineWithCache) Check(ctx context.Context, request *base.Permissi }, err } + // Add to histogram the response + c.setCheckKey(request, &base.PermissionCheckResponse{ Can: cres.GetCan(), Metadata: &base.PermissionCheckResponseMetadata{}, }, isRelational) - // Return the result of the permission check. return cres, err } diff --git a/internal/invoke/invoke.go b/internal/invoke/invoke.go index 47b6ee892..4816a6ed2 100644 --- a/internal/invoke/invoke.go +++ b/internal/invoke/invoke.go @@ -2,6 +2,7 @@ package invoke import ( "context" + "time" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -73,6 +74,11 @@ type DirectInvoker struct { lookupEntityCounter api.Int64Counter lookupSubjectCounter api.Int64Counter subjectPermissionCounter api.Int64Counter + + checkDurationHistogram api.Int64Histogram + lookupEntityDurationHistogram api.Int64Histogram + lookupSubjectDurationHistogram api.Int64Histogram + subjectPermissionDurationHistogram api.Int64Histogram } // NewDirectInvoker is a constructor for DirectInvoker. @@ -110,17 +116,57 @@ func NewDirectInvoker( panic(err) } + checkDurationHistogram, err := meter.Int64Histogram( + "check_duration", + api.WithUnit("microseconds"), + api.WithDescription("Duration of check duration in microseconds"), + ) + if err != nil { + panic(err) + } + + lookupEntityDurationHistogram, err := meter.Int64Histogram( + "lookup_entity_duration", + api.WithUnit("microseconds"), + api.WithDescription("Duration of lookup entity duration in microseconds"), + ) + if err != nil { + panic(err) + } + + lookupSubjectDurationHistogram, err := meter.Int64Histogram( + "lookup_subject_duration", + api.WithUnit("microseconds"), + api.WithDescription("Duration of lookup subject duration in microseconds"), + ) + if err != nil { + panic(err) + } + + subjectPermissionDurationHistogram, err := meter.Int64Histogram( + "subject_permission_duration", + api.WithUnit("microseconds"), + api.WithDescription("Duration of subject permission duration in microseconds"), + ) + if err != nil { + panic(err) + } + return &DirectInvoker{ - schemaReader: schemaReader, - dataReader: dataReader, - cc: cc, - ec: ec, - lo: lo, - sp: sp, - checkCounter: checkCounter, - lookupEntityCounter: lookupEntityCounter, - lookupSubjectCounter: lookupSubjectCounter, - subjectPermissionCounter: subjectPermissionCounter, + schemaReader: schemaReader, + dataReader: dataReader, + cc: cc, + ec: ec, + lo: lo, + sp: sp, + checkCounter: checkCounter, + lookupEntityCounter: lookupEntityCounter, + lookupSubjectCounter: lookupSubjectCounter, + subjectPermissionCounter: subjectPermissionCounter, + checkDurationHistogram: checkDurationHistogram, + lookupEntityDurationHistogram: lookupEntityDurationHistogram, + lookupSubjectDurationHistogram: lookupSubjectDurationHistogram, + subjectPermissionDurationHistogram: subjectPermissionDurationHistogram, } } @@ -136,6 +182,8 @@ func (invoker *DirectInvoker) Check(ctx context.Context, request *base.Permissio )) defer span.End() + start := time.Now() + // Validate the depth of the request. err = checkDepth(request) if err != nil { @@ -200,6 +248,9 @@ func (invoker *DirectInvoker) Check(ctx context.Context, request *base.Permissio }, }, err } + duration := time.Now().Sub(start) + + invoker.checkDurationHistogram.Record(ctx, duration.Microseconds()) // Increase the check count in the response metadata. response.Metadata = increaseCheckCount(response.Metadata) @@ -257,6 +308,8 @@ func (invoker *DirectInvoker) LookupEntity(ctx context.Context, request *base.Pe )) defer span.End() + start := time.Now() + // Set SnapToken if not provided if request.GetMetadata().GetSnapToken() == "" { // Check if the request has a SnapToken. var st token.SnapToken @@ -279,10 +332,15 @@ func (invoker *DirectInvoker) LookupEntity(ctx context.Context, request *base.Pe } } + resp, err := invoker.lo.LookupEntity(ctx, request) + + duration := time.Now().Sub(start) + invoker.lookupEntityDurationHistogram.Record(ctx, duration.Microseconds()) + // Increase the lookup entity count in the metrics. invoker.lookupEntityCounter.Add(ctx, 1) - return invoker.lo.LookupEntity(ctx, request) + return resp, err } // LookupEntityStream is a method that implements the LookupEntityStream interface. @@ -297,6 +355,8 @@ func (invoker *DirectInvoker) LookupEntityStream(ctx context.Context, request *b )) defer span.End() + start := time.Now() + // Set SnapToken if not provided if request.GetMetadata().GetSnapToken() == "" { // Check if the request has a SnapToken. var st token.SnapToken @@ -319,10 +379,15 @@ func (invoker *DirectInvoker) LookupEntityStream(ctx context.Context, request *b } } + resp := invoker.lo.LookupEntityStream(ctx, request, server) + + duration := time.Now().Sub(start) + invoker.lookupEntityDurationHistogram.Record(ctx, duration.Microseconds()) + // Increase the lookup entity count in the metrics. invoker.lookupEntityCounter.Add(ctx, 1) - return invoker.lo.LookupEntityStream(ctx, request, server) + return resp } // LookupSubject is a method of the DirectInvoker structure. It handles the task of looking up subjects @@ -336,6 +401,8 @@ func (invoker *DirectInvoker) LookupSubject(ctx context.Context, request *base.P )) defer span.End() + start := time.Now() + // Check if the request has a SnapToken. If not, a SnapToken is set. if request.GetMetadata().GetSnapToken() == "" { // Create an instance of SnapToken @@ -364,12 +431,17 @@ func (invoker *DirectInvoker) LookupSubject(ctx context.Context, request *base.P } } + resp, err := invoker.lo.LookupSubject(ctx, request) + + duration := time.Now().Sub(start) + invoker.lookupSubjectDurationHistogram.Record(ctx, duration.Microseconds()) + // Increase the lookup subject count in the metrics. invoker.lookupSubjectCounter.Add(ctx, 1) // Call the LookupSubject function of the ls field in the invoker, pass the context and request, // and return its response and error - return invoker.lo.LookupSubject(ctx, request) + return resp, err } // SubjectPermission is a method of the DirectInvoker structure. It handles the task of subject's permissions @@ -382,6 +454,8 @@ func (invoker *DirectInvoker) SubjectPermission(ctx context.Context, request *ba )) defer span.End() + start := time.Now() + // Check if the request has a SnapToken. If not, a SnapToken is set. if request.GetMetadata().GetSnapToken() == "" { // Create an instance of SnapToken @@ -409,11 +483,15 @@ func (invoker *DirectInvoker) SubjectPermission(ctx context.Context, request *ba return response, err } } + resp, err := invoker.sp.SubjectPermission(ctx, request) + + duration := time.Now().Sub(start) + invoker.subjectPermissionDurationHistogram.Record(ctx, duration.Microseconds()) // Increase the subject permission count in the metrics. invoker.subjectPermissionCounter.Add(ctx, 1) // Call the SubjectPermission function of the ls field in the invoker, pass the context and request, // and return its response and error - return invoker.sp.SubjectPermission(ctx, request) + return resp, err }