Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: unify pipeline trigger chart endpoint with credit chart #228

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1
github.com/iancoleman/strcase v0.2.0
github.com/influxdata/influxdb-client-go/v2 v2.12.3
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20240725032116-214c51b2e3bc
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20240725140016-18f3ff64c952
github.com/instill-ai/usage-client v0.2.4-alpha.0.20240123081026-6c78d9a5197a
github.com/instill-ai/x v0.4.0-alpha
github.com/knadh/koanf v1.5.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1090,8 +1090,8 @@ github.com/influxdata/influxdb-client-go/v2 v2.12.3 h1:28nRlNMRIV4QbtIUvxhWqaxn0
github.com/influxdata/influxdb-client-go/v2 v2.12.3/go.mod h1:IrrLUbCjjfkmRuaCiGQg4m2GbkaeJDcuWoxiWdQEbA0=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20240725032116-214c51b2e3bc h1:Lqeu0CKe/XZiK8RxHQXcBGKqtz+e3ITpPkyq1WwQvOQ=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20240725032116-214c51b2e3bc/go.mod h1:2blmpUwiTwxIDnrjIqT6FhR5ewshZZF554wzjXFvKpQ=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20240725140016-18f3ff64c952 h1:gtc9vYwc5sEWIs5H1bdu0vx5IgZb0CKcvBa0VWtU8VE=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20240725140016-18f3ff64c952/go.mod h1:2blmpUwiTwxIDnrjIqT6FhR5ewshZZF554wzjXFvKpQ=
github.com/instill-ai/usage-client v0.2.4-alpha.0.20240123081026-6c78d9a5197a h1:gmy8BcCFDZQan40c/D3f62DwTYtlCwi0VrSax+pKffw=
github.com/instill-ai/usage-client v0.2.4-alpha.0.20240123081026-6c78d9a5197a/go.mod h1:EpX3Yr661uWULtZf5UnJHfr5rw2PDyX8ku4Kx0UtYFw=
github.com/instill-ai/x v0.4.0-alpha h1:zQV2VLbSHjMv6gyBN/2mwwrvWk0/mJM6ZKS12AzjfQg=
Expand Down
21 changes: 21 additions & 0 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// package errors contains domain errors that different layers can use to add
// meaning to an error and that middleware can transform to a status code or
// retry policy. This is implemented as a separate package in order to avoid
// cycle import errors.
//
// TODO jvallesm: when transforming domain errors to response codes, the
// middleware package should eventually use these errors only.
package errors

import (
"fmt"
)

var (
// ErrInvalidArgument is used when the provided argument is incorrect (e.g.
// format, reserved).
ErrInvalidArgument = fmt.Errorf("invalid argument")
// ErrUnauthorized is used when a request can't be performed due to
// insufficient permissions.
ErrUnauthorized = fmt.Errorf("unauthorized")
)
66 changes: 66 additions & 0 deletions pkg/handler/publichandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,72 @@ func (h *PublicHandler) ValidateToken(ctx context.Context, req *mgmtPB.ValidateT
return &mgmtPB.ValidateTokenResponse{UserUid: userUID}, nil
}

// GetPipelineTriggerCount returns the pipeline trigger count of a given
// requester within a timespan. Results are grouped by trigger status.
func (h *PublicHandler) GetPipelineTriggerCount(ctx context.Context, req *mgmtPB.GetPipelineTriggerCountRequest) (*mgmtPB.GetPipelineTriggerCountResponse, error) {
eventName := "GetPipelineTriggerCount"
ctx, span := tracer.Start(ctx, eventName,
trace.WithSpanKind(trace.SpanKindServer))
defer span.End()

logUUID, _ := uuid.NewV4()
logger, _ := logger.GetZapLogger(ctx)

ctxUserUID, err := h.Service.ExtractCtxUser(ctx, false)
if err != nil {
span.SetStatus(1, err.Error())
return nil, err
}

resp, err := h.Service.GetPipelineTriggerCount(ctx, req, ctxUserUID)
if err != nil {
span.SetStatus(1, err.Error())
return nil, fmt.Errorf("fetching credit chart records: %w", err)
}

logger.Info(string(custom_otel.NewLogMessage(
span,
logUUID.String(),
ctxUserUID,
eventName,
)))

return resp, nil
}

// ListPipelineTriggerChartRecords returns a timeline of a requester's pipeline
// trigger count.
func (h *PublicHandler) ListPipelineTriggerChartRecords(ctx context.Context, req *mgmtPB.ListPipelineTriggerChartRecordsRequest) (*mgmtPB.ListPipelineTriggerChartRecordsResponse, error) {
eventName := "ListPipelineTriggerChartRecords"
ctx, span := tracer.Start(ctx, eventName,
trace.WithSpanKind(trace.SpanKindServer))
defer span.End()

logUUID, _ := uuid.NewV4()
logger, _ := logger.GetZapLogger(ctx)

ctxUserUID, err := h.Service.ExtractCtxUser(ctx, false)
if err != nil {
span.SetStatus(1, err.Error())
return nil, err
}

resp, err := h.Service.ListPipelineTriggerChartRecords(ctx, req, ctxUserUID)
if err != nil {
span.SetStatus(1, err.Error())
return nil, fmt.Errorf("fetching credit chart records: %w", err)
}

logger.Info(string(custom_otel.NewLogMessage(
span,
logUUID.String(),
ctxUserUID,
eventName,
)))

return resp, nil
}

func (h *PublicHandler) ListUserMemberships(ctx context.Context, req *mgmtPB.ListUserMembershipsRequest) (*mgmtPB.ListUserMembershipsResponse, error) {

eventName := "ListUserMemberships"
Expand Down
35 changes: 20 additions & 15 deletions pkg/middleware/interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ import (
"google.golang.org/grpc/status"
"gorm.io/gorm"

grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpcrecovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"

"github.com/instill-ai/mgmt-backend/pkg/acl"
"github.com/instill-ai/mgmt-backend/pkg/handler"
"github.com/instill-ai/mgmt-backend/pkg/repository"
"github.com/instill-ai/mgmt-backend/pkg/service"

errdomain "github.com/instill-ai/mgmt-backend/pkg/errors"
)

// RecoveryInterceptor - panic handler
func RecoveryInterceptorOpt() grpc_recovery.Option {
return grpc_recovery.WithRecoveryHandler(func(p interface{}) (err error) {
func RecoveryInterceptorOpt() grpcrecovery.Option {
return grpcrecovery.WithRecoveryHandler(func(p interface{}) (err error) {
return status.Errorf(codes.Unknown, "panic triggered: %v", p)
})
}
Expand All @@ -47,7 +50,7 @@ func StreamAppendMetadataInterceptor(srv interface{}, stream grpc.ServerStream,
}

newCtx := metadata.NewIncomingContext(stream.Context(), md)
wrapped := grpc_middleware.WrapServerStream(stream)
wrapped := grpcmiddleware.WrapServerStream(stream)
wrapped.WrappedContext = newCtx

err := handler(srv, wrapped)
Expand All @@ -64,55 +67,57 @@ func InjectErrCode(err error) error {

case
errors.Is(err, gorm.ErrDuplicatedKey):

return status.Error(codes.AlreadyExists, err.Error())
case
errors.Is(err, gorm.ErrRecordNotFound):
return status.Error(codes.NotFound, err.Error())

return status.Error(codes.NotFound, err.Error())
case
errors.Is(err, repository.ErrNoDataDeleted):
return status.Error(codes.NotFound, err.Error())

return status.Error(codes.NotFound, err.Error())
case
errors.Is(err, repository.ErrOwnerTypeNotMatch),
errors.Is(err, repository.ErrPageTokenDecode):
return status.Error(codes.InvalidArgument, err.Error())

return status.Error(codes.InvalidArgument, err.Error())
case
errors.Is(err, errdomain.ErrInvalidArgument),
errors.Is(err, service.ErrCanNotRemoveOwnerFromOrganization),
errors.Is(err, service.ErrCanNotSetAnotherOwner),
errors.Is(err, service.ErrInvalidRole),
errors.Is(err, service.ErrInvalidTokenTTL),
errors.Is(err, service.ErrStateCanOnlyBeActive),
errors.Is(err, service.ErrPasswordNotMatch),
errors.Is(err, service.ErrInvalidOwnerNamespace):
return status.Error(codes.InvalidArgument, err.Error())

return status.Error(codes.InvalidArgument, err.Error())
case
errors.Is(err, service.ErrNoPermission):
return status.Error(codes.PermissionDenied, err.Error())
errors.Is(err, errdomain.ErrUnauthorized):

return status.Error(codes.PermissionDenied, err.Error())
case
errors.Is(err, service.ErrUnauthenticated):
return status.Error(codes.Unauthenticated, err.Error())

return status.Error(codes.Unauthenticated, err.Error())
case
errors.Is(err, acl.ErrMembershipNotFound):
return status.Error(codes.NotFound, err.Error())

return status.Error(codes.NotFound, err.Error())
case
errors.Is(err, bcrypt.ErrMismatchedHashAndPassword):
return status.Error(codes.InvalidArgument, err.Error())

return status.Error(codes.InvalidArgument, err.Error())
case
errors.Is(err, handler.ErrCheckUpdateImmutableFields),
errors.Is(err, handler.ErrCheckOutputOnlyFields),
errors.Is(err, handler.ErrCheckRequiredFields),
errors.Is(err, handler.ErrFieldMask),
errors.Is(err, handler.ErrResourceID),
errors.Is(err, handler.ErrUpdateMask):
return status.Error(codes.InvalidArgument, err.Error())

return status.Error(codes.InvalidArgument, err.Error())
default:
return err
}
Expand Down
Loading
Loading