diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index a5e9b59b7..60e3e64d3 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -237,6 +237,13 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { op.Results.BackupID = model.StableID(uuid.NewString()) + cats, err := op.Selectors.AllHumanPathCategories() + if err != nil { + // No need to exit over this, we'll just be missing a bit of info in the + // log. + logger.CtxErr(ctx, err).Info("getting categories for backup") + } + ctx = clues.Add( ctx, "tenant_id", clues.Hide(op.account.ID()), @@ -244,6 +251,7 @@ func (op *BackupOperation) Run(ctx context.Context) (err error) { "resource_owner_name", clues.Hide(op.ResourceOwner.Name()), "backup_id", op.Results.BackupID, "service", op.Selectors.Service, + "categories", cats, "incremental", op.incremental, "disable_assist_backup", op.disableAssistBackup) diff --git a/src/internal/operations/export.go b/src/internal/operations/export.go index 74fc1a44f..c9be0bbf8 100644 --- a/src/internal/operations/export.go +++ b/src/internal/operations/export.go @@ -137,11 +137,19 @@ func (op *ExportOperation) Run(ctx context.Context) ( ctx, flushMetrics := events.NewMetrics(ctx, logger.Writer{Ctx: ctx}) defer flushMetrics() + cats, err := op.Selectors.AllHumanPathCategories() + if err != nil { + // No need to exit over this, we'll just be missing a bit of info in the + // log. + logger.CtxErr(ctx, err).Info("getting categories for export") + } + ctx = clues.Add( ctx, "tenant_id", clues.Hide(op.acct.ID()), "backup_id", op.BackupID, - "service", op.Selectors.Service) + "service", op.Selectors.Service, + "categories", cats) defer func() { op.bus.Event( diff --git a/src/internal/operations/restore.go b/src/internal/operations/restore.go index c1778912b..08df5e133 100644 --- a/src/internal/operations/restore.go +++ b/src/internal/operations/restore.go @@ -138,11 +138,19 @@ func (op *RestoreOperation) Run(ctx context.Context) (restoreDetails *details.De ctx = count.Embed(ctx, op.Counter) + cats, err := op.Selectors.AllHumanPathCategories() + if err != nil { + // No need to exit over this, we'll just be missing a bit of info in the + // log. + logger.CtxErr(ctx, err).Info("getting categories for restore") + } + ctx = clues.Add( ctx, "tenant_id", clues.Hide(op.acct.ID()), "backup_id", op.BackupID, "service", op.Selectors.Service, + "categories", cats, "destination_container", clues.Hide(op.RestoreCfg.Location)) defer func() { diff --git a/src/pkg/selectors/selectors.go b/src/pkg/selectors/selectors.go index 860fa5572..b1fdb6433 100644 --- a/src/pkg/selectors/selectors.go +++ b/src/pkg/selectors/selectors.go @@ -7,6 +7,7 @@ import ( "github.com/alcionai/clues" "golang.org/x/exp/maps" + "golang.org/x/exp/slices" "github.com/alcionai/corso/src/internal/common/idname" "github.com/alcionai/corso/src/pkg/backup/details" @@ -293,6 +294,32 @@ func (s Selector) PathCategories() (selectorPathCategories, error) { return ro.PathCategories(), nil } +// AllHumanPathCategories returns the sets of include and filter path categories +// across all scope sets. This is good for logging because it returns the +// string version of the categories and sorts the slice so the category set is +// easier to search for or bin across multiple logs. +func (s Selector) AllHumanPathCategories() ([]string, error) { + all, err := s.PathCategories() + if err != nil { + return nil, clues.Stack(err) + } + + allCats := map[path.CategoryType]string{} + + for _, cat := range all.Includes { + allCats[cat] = cat.HumanString() + } + + for _, cat := range all.Filters { + allCats[cat] = cat.HumanString() + } + + res := maps.Values(allCats) + slices.Sort(res) + + return res, nil +} + // Reasons returns a deduplicated set of the backup reasons produced // using the selector's discrete owner and each scopes' service and // category types.