Metrics and logs - MongoDB Submission (#43)

Adds MongoDB-backed submission for survey statistics/metrics and introduces MongoDB ObjectID-based participant/task identifiers to support upserts and linking metrics to a participant.

It introduces breaking changes to the exsisting json stat and metric files. Delete the old ones

Changes:

Add internal/storage/MongoStorage and wire pm survey submit / pm start to submit local .pm/*.json files to MongoDB.
Extend stats/metrics models to include MongoDB _id / participant_id fields and add participant ID propagation into task metrics.
Update app initialization to generate ObjectIDs for new participants and expose GetParticipantID() via StatsService.
This commit is contained in:
Robin Olsen
2026-03-10 06:09:31 -07:00
committed by GitHub
parent 549415135c
commit 72a2e8acf5
17 changed files with 426 additions and 197 deletions

View File

@@ -7,6 +7,7 @@ import (
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/storage"
"github.com/steveyegge/beads"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type App = models.App
@@ -22,13 +23,13 @@ func New(ctx context.Context, config Config, opts ...Option) (*App, func(), erro
}
if !config.AutoInit {
if err := b.initializer.Init(config.BeadsDBPath); err != nil {
if err := b.initializer.Init(config.AppDir + "db.db"); err != nil {
return nil, nil, err
}
}
if b.issueService == nil {
sqliteStore, err := beads.NewSQLiteStorage(b.ctx, config.BeadsDBPath)
sqliteStore, err := beads.NewSQLiteStorage(b.ctx, config.AppDir+"db.db")
if err != nil {
return nil, nil, err
}
@@ -42,7 +43,7 @@ func New(ctx context.Context, config Config, opts ...Option) (*App, func(), erro
if b.statsService == nil {
statStore := storage.NewJsonStorage(config.StatisticsStoragePath, &models.Statistics{
ID: 0,
ID: primitive.NewObjectID(),
StartTime: time.Now(),
})

View File

@@ -9,6 +9,7 @@ import (
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/storage"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type StatisticsService struct {
@@ -42,6 +43,16 @@ func (s *StatisticsService) GetStatistics() (models.Statistics, error) {
return *s.storage.Data, nil
}
func (s *StatisticsService) GetParticipantID() primitive.ObjectID {
s.mu.Lock()
defer s.mu.Unlock()
if s.storage.Data == nil {
return primitive.NilObjectID
}
return s.storage.Data.ID
}
func (s *StatisticsService) RecordTaskRun(ctx context.Context, run models.TaskRunMetrics) error {
_ = ctx
@@ -63,8 +74,8 @@ func (s *StatisticsService) RecordTaskRun(ctx context.Context, run models.TaskRu
}
stats.EndTime = now
stats.Duration = stats.EndTime.Sub(stats.StartTime)
stats.InterfaceType = run.InterfaceType
stats.DurationMs = stats.EndTime.Sub(stats.StartTime).Milliseconds()
stats.LastInterfaceType = run.InterfaceType
stats.TaskRuns++
stats.LastTaskName = run.TaskName