Skip to content

Commit 696861e

Browse files
committed
events-saving is also product-aware
1 parent 6d3ae91 commit 696861e

File tree

1 file changed

+67
-24
lines changed

1 file changed

+67
-24
lines changed

framework/tracking/dx.go

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func (t *NoOpTracker) Track(event string, metadata map[string]any) error {
5151
type DxTracker struct {
5252
mode Mode
5353
testMode bool
54+
product Product
5455

5556
logger zerolog.Logger
5657

@@ -61,7 +62,7 @@ type DxTracker struct {
6162
// NewDxTracker initializes a tracker with automatic GitHub CLI integration for authentication.
6263
// APITokenVariableName is the name of the GitHub repository variable containing the DX API token.
6364
// Each DX project has its own token for tracking purposes.
64-
func NewDxTracker(APITokenVariableName, product string) (Tracker, error) {
65+
func NewDxTracker(APITokenVariableName string, product Product) (Tracker, error) {
6566
t := &DxTracker{}
6667

6768
lvlStr := os.Getenv(EnvVarLogLevel)
@@ -77,7 +78,6 @@ func NewDxTracker(APITokenVariableName, product string) (Tracker, error) {
7778

7879
if os.Getenv(EnvVarDisableTracking) == "true" {
7980
t.logger.Debug().Msg("Tracking disabled by environment variable")
80-
8181
return &NoOpTracker{}, nil
8282
}
8383

@@ -94,6 +94,7 @@ func NewDxTracker(APITokenVariableName, product string) (Tracker, error) {
9494
return nil, errors.New("product is required. Each DX project has its own token for tracking purposes")
9595
}
9696
product = strings.ToLower(product)
97+
t.product = product
9798

9899
c, isConfigAvailable, configErr := openConfig()
99100
if configErr != nil {
@@ -374,7 +375,7 @@ func openConfig() (*config, bool, error) {
374375
GithubUsername: legacyConfig.GithubUsername,
375376
APITokens: map[Product]string{
376377
// it is the only product that uses tracking at the moment
377-
"local_CRE": legacyConfig.DxAPIToken,
378+
"local_cre": legacyConfig.DxAPIToken,
378379
},
379380
}
380381

@@ -407,7 +408,7 @@ func saveConfig(c *config) error {
407408
return errors.Wrap(pathErr, "failed to get config path")
408409
}
409410

410-
mkdirErr := os.MkdirAll(filepath.Dir(configPath), 0755)
411+
mkdirErr := os.MkdirAll(filepath.Dir(configPath), 0o755)
411412
if mkdirErr != nil {
412413
return errors.Wrap(mkdirErr, "failed to create config directory")
413414
}
@@ -442,12 +443,12 @@ type event struct {
442443
func (t *DxTracker) saveEvent(name string, timestamp int64, metadata map[string]any) error {
443444
t.logger.Debug().Msgf("Saving event. Name: %s, Timestamp: %d, Metadata: %v", name, timestamp, metadata)
444445

445-
storagePath, pathErr := storagePath()
446+
storagePath, pathErr := storagePath(t.product)
446447
if pathErr != nil {
447448
return errors.Wrap(pathErr, "failed to get storage path")
448449
}
449450

450-
mkdirErr := os.MkdirAll(filepath.Dir(storagePath), 0755)
451+
mkdirErr := os.MkdirAll(filepath.Dir(storagePath), 0o755)
451452
if mkdirErr != nil {
452453
return errors.Wrap(mkdirErr, "failed to create storage directory")
453454
}
@@ -476,7 +477,7 @@ func (t *DxTracker) saveEvent(name string, timestamp int64, metadata map[string]
476477
return errors.Wrap(err, "failed to marshal events to JSON")
477478
}
478479

479-
if err := os.WriteFile(storagePath, jsonData, 0600); err != nil {
480+
if err := os.WriteFile(storagePath, jsonData, 0o600); err != nil {
480481
return errors.Wrap(err, "failed to write event to storage file")
481482
}
482483

@@ -485,31 +486,62 @@ func (t *DxTracker) saveEvent(name string, timestamp int64, metadata map[string]
485486

486487
// sendSavedEvents attempts to send all queued events and clears the queue on success.
487488
func (t *DxTracker) sendSavedEvents() error {
488-
storagePath, pathErr := storagePath()
489+
storagePath, pathErr := storagePath(t.product)
489490
if pathErr != nil {
490491
return errors.Wrap(pathErr, "failed to get storage path")
491492
}
492493

493-
stats, statErr := os.Stat(storagePath)
494-
if os.IsNotExist(statErr) {
495-
return nil
496-
}
494+
var readEvents = func(path string) ([]event, error) {
495+
stats, statErr := os.Stat(path)
496+
if os.IsNotExist(statErr) {
497+
return nil, nil
498+
}
497499

498-
if stats.Size() == 0 {
499-
return nil
500+
if stats.Size() == 0 {
501+
return nil, nil
502+
}
503+
504+
storageFile, storageErr := os.OpenFile(path, os.O_RDONLY, 0644)
505+
if storageErr != nil {
506+
return nil, errors.Wrap(storageErr, "failed to open storage file")
507+
}
508+
defer storageFile.Close()
509+
510+
var events []event
511+
512+
decoderErr := json.NewDecoder(storageFile).Decode(&events)
513+
if decoderErr != nil {
514+
return nil, errors.Wrap(decoderErr, "failed to decode events from storage file")
515+
}
516+
517+
return events, nil
500518
}
501519

502-
storageFile, storageErr := os.OpenFile(storagePath, os.O_RDONLY, 0644)
503-
if storageErr != nil {
504-
return errors.Wrap(storageErr, "failed to open storage file")
520+
events, readErr := readEvents(storagePath)
521+
if readErr != nil {
522+
return errors.Wrap(readErr, "failed to read saved events")
505523
}
506-
defer storageFile.Close()
507524

508-
var events []event
525+
// read from legacy storage path if product is local_CRE
526+
if t.product == "local_cre" {
527+
t.logger.Debug().Msg("Checking for legacy saved events")
509528

510-
decoderErr := json.NewDecoder(storageFile).Decode(&events)
511-
if decoderErr != nil {
512-
return errors.Wrap(decoderErr, "failed to decode events from storage file")
529+
legacyPath, legacyErr := legacyStoragePath()
530+
if legacyErr != nil {
531+
return errors.Wrap(legacyErr, "failed to get legacy storage path")
532+
}
533+
534+
legacyEvents, legacyReadErr := readEvents(legacyPath)
535+
if legacyReadErr != nil {
536+
return errors.Wrap(legacyReadErr, "failed to read legacy saved events")
537+
}
538+
539+
events = append(events, legacyEvents...)
540+
}
541+
542+
if len(events) == 0 {
543+
t.logger.Debug().Msg("No saved events to send")
544+
return nil
513545
}
514546

515547
t.logger.Debug().Msgf("Sending %d saved events", len(events))
@@ -547,7 +579,7 @@ func (t *DxTracker) sendSavedEvents() error {
547579

548580
// clearSavedEvents removes all queued events after successful transmission.
549581
func (t *DxTracker) clearSavedEvents() error {
550-
storagePath, pathErr := storagePath()
582+
storagePath, pathErr := storagePath(t.product)
551583
if pathErr != nil {
552584
return errors.Wrap(pathErr, "failed to get storage path")
553585
}
@@ -579,7 +611,18 @@ func validateEvent(event string, timestamp int64, metadata map[string]any) error
579611
}
580612

581613
// storagePath returns the path to the events queue file in the user's home directory.
582-
func storagePath() (string, error) {
614+
func storagePath(product Product) (string, error) {
615+
homeDir, err := os.UserHomeDir()
616+
if err != nil {
617+
return "", errors.Wrap(err, "failed to get user home directory")
618+
}
619+
620+
return filepath.Join(homeDir, ".local", "share", "dx", product+"_events.json"), nil
621+
}
622+
623+
// legacyStoragePath returns the path to the events queue file in the user's home directory.
624+
// deprecated: legacyStoragePath is used to read old storage files and migrate them to the new format. Use storagePath instead.
625+
func legacyStoragePath() (string, error) {
583626
homeDir, err := os.UserHomeDir()
584627
if err != nil {
585628
return "", errors.Wrap(err, "failed to get user home directory")

0 commit comments

Comments
 (0)