Skip to content
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
23 changes: 23 additions & 0 deletions internal/core/services/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ import (
"github.com/poyrazk/thecloud/internal/errors"
"github.com/poyrazk/thecloud/internal/platform"
"github.com/poyrazk/thecloud/pkg/util"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

const tracerNameCache = "cache-service"

const (
defaultRedisPort = "6379"
)
Expand Down Expand Up @@ -57,10 +62,20 @@ func NewCacheService(
}

func (s *CacheService) CreateCache(ctx context.Context, name, version string, memoryMB int, vpcID *uuid.UUID) (*domain.Cache, error) {
tracer := otel.Tracer(tracerNameCache)
_, span := tracer.Start(ctx, "CacheService.CreateCache",
trace.WithAttributes(
attribute.String("cache.name", name),
attribute.String("cache.version", version),
attribute.Int("cache.memory_mb", memoryMB),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionCacheCreate, "*"); err != nil {
span.RecordError(err)
return nil, err
}

Expand Down Expand Up @@ -336,10 +351,18 @@ func (s *CacheService) FlushCache(ctx context.Context, idOrName string) error {
}

func (s *CacheService) GetCacheStats(ctx context.Context, idOrName string) (*ports.CacheStats, error) {
tracer := otel.Tracer(tracerNameCache)
_, span := tracer.Start(ctx, "CacheService.GetCacheStats",
trace.WithAttributes(
attribute.String("cache.id_or_name", idOrName),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionCacheRead, idOrName); err != nil {
span.RecordError(err)
return nil, err
}

Expand Down
32 changes: 32 additions & 0 deletions internal/core/services/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ import (
"github.com/poyrazk/thecloud/internal/errors"
"github.com/poyrazk/thecloud/internal/platform"
"github.com/poyrazk/thecloud/pkg/util"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

const tracerNameDatabase = "database-service"

const (
// Default ports for database engines
DefaultPostgresPort = "5432"
Expand Down Expand Up @@ -116,9 +121,19 @@ func NewDatabaseService(params DatabaseServiceParams) *DatabaseService {
}

func (s *DatabaseService) CreateDatabase(ctx context.Context, req ports.CreateDatabaseRequest) (*domain.Database, error) {
tracer := otel.Tracer(tracerNameDatabase)
_, span := tracer.Start(ctx, "DatabaseService.CreateDatabase",
trace.WithAttributes(
attribute.String("db.name", req.Name),
attribute.String("db.engine", req.Engine),
attribute.String("db.version", req.Version),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)
if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionDBCreate, "*"); err != nil {
span.RecordError(err)
return nil, err
}
dbEngine := domain.DatabaseEngine(req.Engine)
Expand Down Expand Up @@ -192,9 +207,19 @@ func (s *DatabaseService) CreateReplica(ctx context.Context, primaryID uuid.UUID
}

func (s *DatabaseService) RestoreDatabase(ctx context.Context, req ports.RestoreDatabaseRequest) (*domain.Database, error) {
tracer := otel.Tracer(tracerNameDatabase)
_, span := tracer.Start(ctx, "DatabaseService.RestoreDatabase",
trace.WithAttributes(
attribute.String("db.new_name", req.NewName),
attribute.String("db.engine", req.Engine),
attribute.String("db.snapshot_id", req.SnapshotID.String()),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)
if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionDBCreate, "*"); err != nil {
span.RecordError(err)
return nil, err
}
snap, err := s.snapshotSvc.GetSnapshot(ctx, req.SnapshotID)
Expand Down Expand Up @@ -810,6 +835,13 @@ func (s *DatabaseService) RotateCredentials(ctx context.Context, id uuid.UUID, i

// doRotateCredentials performs the actual credential rotation
func (s *DatabaseService) doRotateCredentials(ctx context.Context, id uuid.UUID, _ string) error {
tracer := otel.Tracer(tracerNameDatabase)
_, span := tracer.Start(ctx, "DatabaseService.doRotateCredentials",
trace.WithAttributes(
attribute.String("db.id", id.String()),
))
defer span.End()

db, err := s.repo.GetByID(ctx, id)
if err != nil {
return err
Expand Down
47 changes: 45 additions & 2 deletions internal/core/services/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@
"github.com/poyrazk/thecloud/internal/core/domain"
"github.com/poyrazk/thecloud/internal/core/ports"
"github.com/poyrazk/thecloud/internal/errors"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

const tracerNameFunction = "function-service"

const (
// maxLogSize bounds log reading in captureInvocationResults to prevent memory exhaustion.
maxLogSize = 1 * 1024 * 1024 // 1 MB

Check failure on line 33 in internal/core/services/function.go

View workflow job for this annotation

GitHub Actions / lint

const `maxLogSize` is unused (unused)
)

// RuntimeConfig describes how a function runtime is executed.
Expand Down Expand Up @@ -63,10 +73,20 @@
}

func (s *FunctionService) CreateFunction(ctx context.Context, name, runtime, handler string, code []byte) (*domain.Function, error) {
tracer := otel.Tracer(tracerNameFunction)
_, span := tracer.Start(ctx, "FunctionService.CreateFunction",
trace.WithAttributes(
attribute.String("function.name", name),
attribute.String("function.runtime", runtime),
attribute.String("function.handler", handler),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionFunctionCreate, "*"); err != nil {
span.RecordError(err)
return nil, err
}

Expand Down Expand Up @@ -200,25 +220,48 @@
}

func (s *FunctionService) GetFunctionLogs(ctx context.Context, id uuid.UUID, limit int) ([]*domain.Invocation, error) {
tracer := otel.Tracer(tracerNameFunction)
_, span := tracer.Start(ctx, "FunctionService.GetFunctionLogs",
trace.WithAttributes(
attribute.String("function.id", id.String()),
attribute.Int("function.log_limit", limit),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionFunctionRead, id.String()); err != nil {
span.RecordError(err)
return nil, err
}

// Verify existence and tenant scoping
// Verify existence and tenant scoping (use original ctx to avoid mock context mismatch)
if _, err := s.repo.GetByID(ctx, id); err != nil {
span.RecordError(err)
return nil, err
}

return s.repo.GetInvocations(ctx, id, limit)
invocations, err := s.repo.GetInvocations(ctx, id, limit)
if err != nil {
span.RecordError(err)
}
return invocations, err
}
func (s *FunctionService) InvokeFunction(ctx context.Context, id uuid.UUID, payload []byte, async bool) (*domain.Invocation, error) {
tracer := otel.Tracer(tracerNameFunction)
_, span := tracer.Start(ctx, "FunctionService.InvokeFunction",
trace.WithAttributes(
attribute.String("function.id", id.String()),
attribute.Bool("function.async", async),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionFunctionInvoke, id.String()); err != nil {
span.RecordError(err)
return nil, err
}

Expand Down
41 changes: 41 additions & 0 deletions internal/core/services/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ import (
"github.com/poyrazk/thecloud/internal/errors"
"github.com/poyrazk/thecloud/internal/platform"
"github.com/poyrazk/thecloud/pkg/crypto"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

const tracerNameStorage = "storage-service"

const (
errMultipartNotFound = "multipart upload not found"
partPathFormat = ".uploads/%s/part-%d"
Expand Down Expand Up @@ -82,10 +87,19 @@ func NewStorageService(params StorageServiceParams) *StorageService {
}

func (s *StorageService) Upload(ctx context.Context, bucketName, key string, r io.Reader, providedChecksum string) (*domain.Object, error) {
tracer := otel.Tracer(tracerNameStorage)
_, span := tracer.Start(ctx, "StorageService.Upload",
trace.WithAttributes(
attribute.String("storage.bucket", bucketName),
attribute.String("storage.key", key),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionStorageWrite, "*"); err != nil {
span.RecordError(err)
return nil, err
}

Expand Down Expand Up @@ -202,10 +216,19 @@ func (s *StorageService) Upload(ctx context.Context, bucketName, key string, r i
}

func (s *StorageService) Download(ctx context.Context, bucket, key string) (io.ReadCloser, *domain.Object, error) {
tracer := otel.Tracer(tracerNameStorage)
_, span := tracer.Start(ctx, "StorageService.Download",
trace.WithAttributes(
attribute.String("storage.bucket", bucket),
attribute.String("storage.key", key),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionStorageRead, bucket); err != nil {
span.RecordError(err)
return nil, nil, err
}

Expand Down Expand Up @@ -366,10 +389,19 @@ func (s *StorageService) DeleteObject(ctx context.Context, bucket, key string) e

// CreateBucket creates a new storage bucket.
func (s *StorageService) CreateBucket(ctx context.Context, name string, isPublic bool) (*domain.Bucket, error) {
tracer := otel.Tracer(tracerNameStorage)
_, span := tracer.Start(ctx, "StorageService.CreateBucket",
trace.WithAttributes(
attribute.String("storage.bucket", name),
attribute.Bool("storage.is_public", isPublic),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionStorageWrite, "*"); err != nil {
span.RecordError(err)
return nil, err
}

Expand Down Expand Up @@ -426,10 +458,19 @@ func (s *StorageService) GetBucket(ctx context.Context, name string) (*domain.Bu
}

func (s *StorageService) DeleteBucket(ctx context.Context, name string, force bool) error {
tracer := otel.Tracer(tracerNameStorage)
_, span := tracer.Start(ctx, "StorageService.DeleteBucket",
trace.WithAttributes(
attribute.String("storage.bucket", name),
attribute.Bool("storage.force", force),
))
defer span.End()

userID := appcontext.UserIDFromContext(ctx)
tenantID := appcontext.TenantIDFromContext(ctx)

if err := s.rbacSvc.Authorize(ctx, userID, tenantID, domain.PermissionStorageDelete, name); err != nil {
span.RecordError(err)
return err
}

Expand Down
Loading