Correct the sentry logs to use the format key:value

This commit is contained in:
finn
2024-08-20 09:20:58 +07:00
parent b5bb3da9b6
commit 79f4c03d72
15 changed files with 1316 additions and 1315 deletions

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ config*.yml
pkged.go
package-lock.json
node_modules
.DS_Store

View File

@@ -41,7 +41,7 @@ func Log() *SentryWrapperLogger {
// Create a custom handler that writes to both output and error writers
handler := slog.NewTextHandler(io.MultiWriter(ow, ew), &slog.HandlerOptions{
Level: slog.LevelDebug, // Adjust this level as needed
Level: slog.LevelDebug,
})
return &SentryWrapperLogger{

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,6 @@ func RespondJSON(w http.ResponseWriter, r *http.Request, status int, object inte
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if err := json.NewEncoder(w).Encode(object); err != nil {
config.Log().Request(r).Error("error while writing json response: %v", err)
config.Log().Request(r).Error("error while writing json response", "error", err)
}
}

View File

@@ -87,7 +87,7 @@ func (s *ActivityService) getChartPastYear(user *models.User, darkTheme, hideAtt
wp.Submit(func() {
summary, err := s.summaryService.Retrieve(interval[0], interval[1], user, nil)
if err != nil {
config.Log().Warn("failed to retrieve summary for '%s' between %v and %v for activity chart", user.ID, from, to)
config.Log().Warn("failed to retrieve summary for activity chart", "userID", user.ID, "from", from, "to", to)
summary = models.NewEmptySummary()
summary.FromTime = models.CustomTime(from)
summary.ToTime = models.CustomTime(to)

View File

@@ -52,10 +52,10 @@ func (srv *AggregationService) Schedule() {
if _, err := srv.queueDefault.DispatchCron(func() {
if err := srv.AggregateSummaries(datastructure.New[string]()); err != nil {
config.Log().Error("failed to generate summaries, %v", err)
config.Log().Error("failed to generate summaries", "error", err)
}
}, srv.config.App.GetAggregationTimeCron()); err != nil {
config.Log().Error("failed to schedule summary generation, %v", err)
config.Log().Error("failed to schedule summary generation", "error", err)
}
}
@@ -70,14 +70,14 @@ func (srv *AggregationService) AggregateSummaries(userIds datastructure.Set[stri
// Get a map from user ids to the time of their latest summary or nil if none exists yet
lastUserSummaryTimes, err := srv.summaryService.GetLatestByUser()
if err != nil {
config.Log().Error(err.Error())
config.Log().Error("error occurred", "error", err)
return err
}
// Get a map from user ids to the time of their earliest heartbeats or nil if none exists yet
firstUserHeartbeatTimes, err := srv.heartbeatService.GetFirstByUsers()
if err != nil {
config.Log().Error(err.Error())
config.Log().Error("error occurred", "error", err)
return err
}
@@ -96,7 +96,7 @@ func (srv *AggregationService) AggregateSummaries(userIds datastructure.Set[stri
if err := srv.queueWorkers.Dispatch(func() {
srv.process(job)
}); err != nil {
config.Log().Error("failed to dispatch summary generation job for user '%s'", job.User.ID)
config.Log().Error("failed to dispatch summary generation job", "userID", job.User.ID)
}
}
}()
@@ -138,11 +138,11 @@ func (srv *AggregationService) AggregateSummaries(userIds datastructure.Set[stri
func (srv *AggregationService) process(job AggregationJob) {
if summary, err := srv.summaryService.Summarize(job.From, job.To, job.User, nil); err != nil {
config.Log().Error("failed to generate summary (%v, %v, %s) - %v", job.From, job.To, job.User.ID, err)
config.Log().Error("failed to generate summary", "from", job.From, "to", job.To, "userID", job.User.ID, "error", err)
} else {
slog.Info("successfully generated summary", "from", job.From, "to", job.To, "userID", job.User.ID)
if err := srv.summaryService.Insert(summary); err != nil {
config.Log().Error("failed to save summary (%v, %v, %s) - %v", summary.UserID, summary.FromTime, summary.ToTime, err)
config.Log().Error("failed to save summary", "userID", summary.UserID, "fromTime", summary.FromTime, "toTime", summary.ToTime, "error", err)
}
}
}

View File

@@ -41,7 +41,7 @@ func (srv *AliasService) InitializeUser(userId string) error {
func (srv *AliasService) MayInitializeUser(userId string) {
if err := srv.InitializeUser(userId); err != nil {
config.Log().Error("failed to initialize user alias map for user %s", userId)
config.Log().Error("failed to initialize user alias map", "userID", userId)
}
}

View File

@@ -72,7 +72,7 @@ func (s *HousekeepingService) CleanInactiveUsers(before time.Time) error {
slog.Warn("deleting user due to inactivity and no data", "userID", u.ID)
if err := s.userSrvc.Delete(u); err != nil {
config.Log().Error("failed to delete user '%s'", u.ID)
config.Log().Error("failed to delete user", "userID", u.ID)
} else {
i++
}
@@ -85,7 +85,7 @@ func (s *HousekeepingService) CleanInactiveUsers(before time.Time) error {
func (s *HousekeepingService) WarmUserProjectStatsCache(user *models.User) error {
slog.Info("pre-warming project stats cache for user", "userID", user.ID)
if _, err := s.heartbeatSrvc.GetUserProjectStats(user, time.Time{}, utils.BeginOfToday(time.Local), nil, true); err != nil {
config.Log().Error("failed to pre-warm project stats cache for '%s', %v", user.ID, err)
config.Log().Error("failed to pre-warm project stats cache", "userID", user.ID, "error", err)
}
return nil
}
@@ -94,14 +94,14 @@ func (s *HousekeepingService) runWarmProjectStatsCache() {
// fetch active users
users, err := s.userSrvc.GetActive(false)
if err != nil {
config.Log().Error("failed to get active users for project stats cache warming, %v\n", err)
config.Log().Error("failed to get active users for project stats cache warming", "error", err)
return
}
// fetch user heartbeat counts
userHeartbeatCounts, err := s.heartbeatSrvc.CountByUsers(users)
if err != nil {
config.Log().Error("failed to count user heartbeats for project stats cache warming, %v\n", err)
config.Log().Error("failed to count user heartbeats for project stats cache warming", "error", err)
return
}
@@ -117,7 +117,7 @@ func (s *HousekeepingService) runWarmProjectStatsCache() {
})
s.queueWorkers.Dispatch(func() {
if err := s.WarmUserProjectStatsCache(user); err != nil {
config.Log().Error("failed to pre-warm project stats cache for '%s'", user.ID)
config.Log().Error("failed to pre-warm project stats cache", "userID", user.ID)
}
})
}
@@ -127,7 +127,7 @@ func (s *HousekeepingService) runCleanData() {
// fetch all users
users, err := s.userSrvc.GetAll()
if err != nil {
config.Log().Error("failed to get users for data cleanup, %v", err)
config.Log().Error("failed to get users for data cleanup", "error", err)
return
}
@@ -141,7 +141,7 @@ func (s *HousekeepingService) runCleanData() {
user := *u
s.queueWorkers.Dispatch(func() {
if err := s.CleanUserDataBefore(&user, user.MinDataAge()); err != nil {
config.Log().Error("failed to clear old user data for '%s'", user.ID)
config.Log().Error("failed to clear old user data", "userID", user.ID)
}
})
}
@@ -153,7 +153,7 @@ func (s *HousekeepingService) runCleanInactiveUsers() {
return
}
if err := s.CleanInactiveUsers(time.Now().AddDate(0, -s.config.App.MaxInactiveMonths, 0)); err != nil {
config.Log().Error("failed to clean up inactive users, %v", err)
config.Log().Error("failed to clean up inactive users", "error", err)
}
})
}
@@ -169,7 +169,7 @@ func (s *HousekeepingService) scheduleDataCleanups() {
_, err := s.queueDefault.DispatchCron(s.runCleanData, s.config.App.DataCleanupTime)
if err != nil {
config.Log().Error("failed to dispatch data cleanup jobs, %v", err)
config.Log().Error("failed to dispatch data cleanup jobs", "error", err)
}
}
@@ -182,7 +182,7 @@ func (s *HousekeepingService) scheduleInactiveUsersCleanup() {
_, err := s.queueDefault.DispatchCron(s.runCleanInactiveUsers, s.config.App.DataCleanupTime)
if err != nil {
config.Log().Error("failed to dispatch inactive users cleanup job, %v", err)
config.Log().Error("failed to dispatch inactive users cleanup job", "error", err)
}
}
@@ -191,13 +191,13 @@ func (s *HousekeepingService) scheduleProjectStatsCacheWarming() {
_, err := s.queueDefault.DispatchEvery(s.runWarmProjectStatsCache, 12*time.Hour)
if err != nil {
config.Log().Error("failed to dispatch pre-warming project stats cache, %v", err)
config.Log().Error("failed to dispatch pre-warming project stats cache", "error", err)
}
// run once initially, 1 min after start
if !s.config.QuickStart {
if err := s.queueDefault.DispatchIn(s.runWarmProjectStatsCache, 1*time.Minute); err != nil {
config.Log().Error("failed to dispatch pre-warming project stats cache, %v", err)
config.Log().Error("failed to dispatch pre-warming project stats cache", "error", err)
}
}
}

View File

@@ -83,13 +83,13 @@ func (w *WakatimeDumpImporter) Import(user *models.User, minFrom time.Time, maxT
}
onDumpFailed := func(err error, user *models.User) {
config.Log().Error("fetching data dump for user '%s' failed - %v", user.ID, err)
config.Log().Error("fetching data dump for user failed", "userID", user.ID, "error", err)
readyPollTimer.Stop()
close(out)
}
onDumpReady := func(dump *wakatime.DataDumpData, user *models.User, out chan *models.Heartbeat) {
config.Log().Info("data dump for user '%s' is available for download", user.ID)
config.Log().Info("data dump for user is available for download", "userID", user.ID)
readyPollTimer.Stop()
defer close(out)
@@ -97,7 +97,7 @@ func (w *WakatimeDumpImporter) Import(user *models.User, minFrom time.Time, maxT
req, _ := http.NewRequest(http.MethodGet, dump.DownloadUrl, nil)
res, err := utils.RaiseForStatus((&http.Client{Timeout: 5 * time.Minute}).Do(req))
if err != nil {
config.Log().Error("failed to download %s - %v", dump.DownloadUrl, err)
config.Log().Error("failed to download data dump", "url", dump.DownloadUrl, "error", err)
return
}
defer res.Body.Close()
@@ -107,19 +107,19 @@ func (w *WakatimeDumpImporter) Import(user *models.User, minFrom time.Time, maxT
// decode
var data wakatime.JsonExportViewModel
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
config.Log().Error("failed to decode data dump for user '%s' ('%s') - %v", user.ID, dump.DownloadUrl, err)
config.Log().Error("failed to decode data dump for user", "userID", user.ID, "url", dump.DownloadUrl, "error", err)
return
}
// fetch user agents and machine names
var userAgents map[string]*wakatime.UserAgentEntry
if userAgents, err = fetchUserAgents(config.WakatimeApiUrl, w.apiKey); err != nil {
config.Log().Error("failed to fetch user agents while importing wakatime heartbeats for user '%s' - %v", user.ID, err)
config.Log().Error("failed to fetch user agents while importing wakatime heartbeats", "userID", user.ID, "error", err)
return
}
var machinesNames map[string]*wakatime.MachineEntry
if machinesNames, err = fetchMachineNames(config.WakatimeApiUrl, w.apiKey); err != nil {
config.Log().Error("failed to fetch machine names while importing wakatime heartbeats for user '%s' - %v", user.ID, err)
config.Log().Error("failed to fetch machine names while importing wakatime heartbeats", "userID", user.ID, "error", err)
return
}

View File

@@ -53,7 +53,7 @@ func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time
startDate, endDate, err := w.fetchRange(baseUrl)
if err != nil {
config.Log().Error("failed to fetch date range while importing wakatime heartbeats for user '%s' - %v", user.ID, err)
config.Log().Error("failed to fetch date range while importing wakatime heartbeats", "userID", user.ID, "error", err)
return
}
@@ -69,7 +69,7 @@ func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time
userAgents = data
} else if strings.Contains(baseUrl, "wakatime.com") {
// when importing from wakatime, resolving user agents is mandatorily required
config.Log().Error("failed to fetch user agents while importing wakatime heartbeats for user '%s' - %v", user.ID, err)
config.Log().Error("failed to fetch user agents while importing wakatime heartbeats", "userID", user.ID, "error", err)
return
}
@@ -78,7 +78,7 @@ func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time
machinesNames = data
} else if strings.Contains(baseUrl, "wakatime.com") {
// when importing from wakatime, resolving machine names is mandatorily required
config.Log().Error("failed to fetch machine names while importing wakatime heartbeats for user '%s' - %v", user.ID, err)
config.Log().Error("failed to fetch machine names while importing wakatime heartbeats", "userID", user.ID, "error", err)
return
}
@@ -96,7 +96,7 @@ func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time
d := d.Format(config.SimpleDateFormat)
heartbeats, err := w.fetchHeartbeats(d, baseUrl)
if err != nil {
config.Log().Error("failed to fetch heartbeats for day '%s' and user '%s' - %v", d, user.ID, err)
config.Log().Error("failed to fetch heartbeats for day and user", "day", d, "userID", user.ID, "error", err)
}
for _, h := range heartbeats {
@@ -124,7 +124,7 @@ func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time
if err := w.queue.Dispatch(func() {
process(user, minFrom, maxTo, out)
}); err != nil {
config.Log().Error("failed to dispatch wakatime import job for user '%s', %v", user.ID, err)
config.Log().Error("failed to dispatch wakatime import job for user", "userID", user.ID, "error", err)
}
return out, nil

View File

@@ -57,7 +57,7 @@ func NewLeaderboardService(leaderboardRepo repositories.ILeaderboardRepository,
exists, err := srv.ExistsAnyByUser(user.ID)
if err != nil {
config.Log().Error("failed to check existing leaderboards upon user update - %v", err)
config.Log().Error("failed to check existing leaderboards upon user update", "error", err)
}
if user.PublicLeaderboard && !exists {
@@ -66,7 +66,7 @@ func NewLeaderboardService(leaderboardRepo repositories.ILeaderboardRepository,
} else if !user.PublicLeaderboard && exists {
slog.Info("clearing leaderboard after settings update", "userID", user.ID)
if err := srv.repository.DeleteByUser(user.ID); err != nil {
config.Log().Error("failed to clear leaderboard for user '%s' - %v", user.ID, err)
config.Log().Error("failed to clear leaderboard for user", "userID", user.ID, "error", err)
}
srv.cache.Flush()
}
@@ -86,7 +86,7 @@ func (srv *LeaderboardService) Schedule() {
generate := func() {
users, err := srv.userService.GetAllByLeaderboard(true)
if err != nil {
config.Log().Error("failed to get users for leaderboard generation - %v", err)
config.Log().Error("failed to get users for leaderboard generation", "error", err)
return
}
srv.ComputeLeaderboard(users, srv.defaultScope, []uint8{models.SummaryLanguage})
@@ -94,7 +94,7 @@ func (srv *LeaderboardService) Schedule() {
for _, cronExp := range srv.config.App.GetLeaderboardGenerationTimeCron() {
if _, err := srv.queueDefault.DispatchCron(generate, cronExp); err != nil {
config.Log().Error("failed to schedule leaderboard generation (%s), %v", cronExp, err)
config.Log().Error("failed to schedule leaderboard generation", "cronExpression", cronExp, "error", err)
}
}
}
@@ -104,25 +104,25 @@ func (srv *LeaderboardService) ComputeLeaderboard(users []*models.User, interval
for _, user := range users {
if err := srv.repository.DeleteByUserAndInterval(user.ID, interval); err != nil {
config.Log().Error("failed to delete leaderboard items for user %s (interval %s) - %v", user.ID, (*interval)[0], err)
config.Log().Error("failed to delete leaderboard items for user", "userID", user.ID, "interval", (*interval)[0], "error", err)
continue
}
item, err := srv.GenerateByUser(user, interval)
if err != nil {
config.Log().Error("failed to generate general leaderboard for user %s - %v", user.ID, err)
config.Log().Error("failed to generate general leaderboard for user", "userID", user.ID, "error", err)
continue
}
if err := srv.repository.InsertBatch([]*models.LeaderboardItem{item}); err != nil {
config.Log().Error("failed to persist general leaderboard for user %s - %v", user.ID, err)
config.Log().Error("failed to persist general leaderboard for user", "userID", user.ID, "error", err)
continue
}
for _, by := range by {
items, err := srv.GenerateAggregatedByUser(user, interval, by)
if err != nil {
config.Log().Error("failed to generate aggregated (by %s) leaderboard for user %s - %v", models.GetEntityColumn(by), user.ID, err)
config.Log().Error("failed to generate aggregated leaderboard for user", "aggregatedBy", models.GetEntityColumn(by), "userID", user.ID, "error", err)
continue
}
@@ -131,7 +131,7 @@ func (srv *LeaderboardService) ComputeLeaderboard(users []*models.User, interval
}
if err := srv.repository.InsertBatch(items); err != nil {
config.Log().Error("failed to persist aggregated (by %s) leaderboard for user %s - %v", models.GetEntityColumn(by), user.ID, err)
config.Log().Error("failed to persist aggregated leaderboard for user", "aggregatedBy", models.GetEntityColumn(by), "userID", user.ID, "error", err)
continue
}
}
@@ -184,7 +184,7 @@ func (srv *LeaderboardService) GetAggregatedByInterval(interval *models.Interval
if resolveUsers {
users, err := srv.userService.GetManyMapped(models.Leaderboard(items).UserIDs())
if err != nil {
config.Log().Error("failed to resolve users for leaderboard item - %v", err)
config.Log().Error("failed to resolve users for leaderboard item", "error", err)
} else {
for _, item := range items {
if u, ok := users[item.UserID]; ok {
@@ -213,7 +213,7 @@ func (srv *LeaderboardService) GetAggregatedByIntervalAndUser(interval *models.I
if resolveUser {
u, err := srv.userService.GetUserById(userId)
if err != nil {
config.Log().Error("failed to resolve user for leaderboard item - %v", err)
config.Log().Error("failed to resolve user for leaderboard item", "error", err)
} else {
for _, item := range items {
item.User = u

View File

@@ -58,35 +58,35 @@ func NewMiscService(userService IUserService, heartbeatService IHeartbeatService
func (srv *MiscService) Schedule() {
slog.Info("scheduling total time counting")
if _, err := srv.queueDefault.DispatchEvery(srv.CountTotalTime, countUsersEvery); err != nil {
config.Log().Error("failed to schedule user counting jobs, %v", err)
config.Log().Error("failed to schedule user counting jobs", "error", err)
}
slog.Info("scheduling first data computing")
if _, err := srv.queueDefault.DispatchEvery(srv.ComputeOldestHeartbeats, computeOldestDataEvery); err != nil {
config.Log().Error("failed to schedule first data computing jobs, %v", err)
config.Log().Error("failed to schedule first data computing jobs", "error", err)
}
if srv.config.Subscriptions.Enabled && srv.config.Subscriptions.ExpiryNotifications && srv.config.App.DataRetentionMonths > 0 {
slog.Info("scheduling subscription notifications")
if _, err := srv.queueDefault.DispatchEvery(srv.NotifyExpiringSubscription, notifyExpiringSubscriptionsEvery); err != nil {
config.Log().Error("failed to schedule subscription notification jobs, %v", err)
config.Log().Error("failed to schedule subscription notification jobs", "error", err)
}
}
// run once initially for a fresh instance
if !srv.existsUsersTotalTime() {
if err := srv.queueDefault.Dispatch(srv.CountTotalTime); err != nil {
config.Log().Error("failed to dispatch user counting jobs, %v", err)
config.Log().Error("failed to dispatch user counting jobs", "error", err)
}
}
if !srv.existsUsersFirstData() {
if err := srv.queueDefault.Dispatch(srv.ComputeOldestHeartbeats); err != nil {
config.Log().Error("failed to dispatch first data computing jobs, %v", err)
config.Log().Error("failed to dispatch first data computing jobs", "error", err)
}
}
if !srv.existsSubscriptionNotifications() && srv.config.Subscriptions.Enabled && srv.config.Subscriptions.ExpiryNotifications && srv.config.App.DataRetentionMonths > 0 {
if err := srv.queueDefault.Dispatch(srv.NotifyExpiringSubscription); err != nil {
config.Log().Error("failed to schedule subscription notification jobs, %v", err)
config.Log().Error("failed to schedule subscription notification jobs", "error", err)
}
}
}
@@ -100,7 +100,7 @@ func (srv *MiscService) CountTotalTime() {
users, err := srv.userService.GetAll()
if err != nil {
config.Log().Error("failed to fetch users for time counting, %v", err)
config.Log().Error("failed to fetch users for time counting", "error", err)
return
}
@@ -114,7 +114,7 @@ func (srv *MiscService) CountTotalTime() {
defer pendingJobs.Done()
totalTime.Add(srv.countUserTotalTime(user.ID))
}); err != nil {
config.Log().Error("failed to enqueue counting job for user '%s'", user.ID)
config.Log().Error("failed to enqueue counting job for user", "userID", user.ID)
pendingJobs.Done()
}
}
@@ -126,14 +126,14 @@ func (srv *MiscService) CountTotalTime() {
Key: config.KeyLatestTotalTime,
Value: totalTime.Load().String(),
}); err != nil {
config.Log().Error("failed to save total time count: %v", err)
config.Log().Error("failed to save total time count", "error", err)
}
if err := srv.keyValueService.PutString(&models.KeyStringValue{
Key: config.KeyLatestTotalUsers,
Value: strconv.Itoa(len(users)),
}); err != nil {
config.Log().Error("failed to save total users count: %v", err)
config.Log().Error("failed to save total users count", "error", err)
}
} else {
config.Log().Error("waiting for user counting jobs timed out")
@@ -153,7 +153,7 @@ func (srv *MiscService) ComputeOldestHeartbeats() {
results, err := srv.heartbeatService.GetFirstByUsers()
if err != nil {
config.Log().Error("failed to compute users' first data, %v", err)
config.Log().Error("failed to compute users' first data", "error", err)
return
}
@@ -167,11 +167,11 @@ func (srv *MiscService) ComputeOldestHeartbeats() {
Key: kvKey,
Value: entry.Time.T().Format(time.RFC822Z),
}); err != nil {
config.Log().Error("failed to save user's first heartbeat time: %v", err)
config.Log().Error("failed to save user's first heartbeat time", "error", err)
}
}
}); err != nil {
config.Log().Error("failed to enqueue computing first data for user, %v", err)
config.Log().Error("failed to enqueue computing first data for user", "error", err)
}
}
@@ -193,7 +193,7 @@ func (srv *MiscService) NotifyExpiringSubscription() {
users, err := srv.userService.GetAll()
if err != nil {
config.Log().Error("failed to fetch users for subscription notifications, %v", err)
config.Log().Error("failed to fetch users for subscription notifications", "error", err)
return
}
@@ -203,13 +203,13 @@ func (srv *MiscService) NotifyExpiringSubscription() {
return strings.Replace(kv.Key, config.KeySubscriptionNotificationSent+"_", "", 1)
})
} else {
config.Log().Error("failed to fetch key-values for subscription notifications, %v", err)
config.Log().Error("failed to fetch key-values for subscription notifications", "error", err)
return
}
for _, u := range users {
if u.HasActiveSubscription() && u.Email == "" {
config.Log().Warn("invalid state: user '%s' has active subscription but no e-mail address set", u.ID)
config.Log().Warn("invalid state: user has active subscription but no e-mail address set", "userID", u.ID)
}
var alreadySent bool
@@ -218,7 +218,7 @@ func (srv *MiscService) NotifyExpiringSubscription() {
if sendDate, err := time.Parse(time.RFC822Z, kvs[0].Value); err == nil && now.Sub(sendDate) <= notifyBeforeSubscriptionExpiry {
alreadySent = true
} else if err != nil {
config.Log().Error("failed to parse date for last sent subscription notification mail for user '%s', %v", u.ID, err)
config.Log().Error("failed to parse date for last sent subscription notification mail", "userID", u.ID, "error", err)
alreadySent = true
}
}
@@ -241,7 +241,7 @@ func (srv *MiscService) NotifyExpiringSubscription() {
func (srv *MiscService) countUserTotalTime(userId string) time.Duration {
result, err := srv.summaryService.Aliased(time.Time{}, time.Now(), &models.User{ID: userId}, srv.summaryService.Retrieve, nil, false)
if err != nil {
config.Log().Error("failed to count total for user %s: %v", userId, err)
config.Log().Error("failed to count total for user", "userID", userId, "error", err)
return 0
}
return result.TotalTime()
@@ -254,7 +254,7 @@ func (srv *MiscService) sendSubscriptionNotificationScheduled(user *models.User,
defer time.Sleep(10 * time.Second)
if err := srv.mailService.SendSubscriptionNotification(&u, hasExpired); err != nil {
config.Log().Error("failed to send subscription notification mail to user '%s', %v", u.ID, err)
config.Log().Error("failed to send subscription notification mail to user", "userID", u.ID, "error", err)
return
}
@@ -262,7 +262,7 @@ func (srv *MiscService) sendSubscriptionNotificationScheduled(user *models.User,
Key: fmt.Sprintf("%s_%s", config.KeySubscriptionNotificationSent, u.ID),
Value: time.Now().Format(time.RFC822Z),
}); err != nil {
config.Log().Error("failed to update subscription notification status key-value for user %s, %v", u.ID, err)
config.Log().Error("failed to update subscription notification status key-value for user", "userID", u.ID, "error", err)
}
})
}
@@ -270,7 +270,7 @@ func (srv *MiscService) sendSubscriptionNotificationScheduled(user *models.User,
func (srv *MiscService) existsUsersTotalTime() bool {
results, err := srv.keyValueService.GetByPrefix(config.KeyLatestTotalTime)
if err != nil {
config.Log().Error("failed to fetch latest time key-values, %v", err)
config.Log().Error("failed to fetch latest time key-values", "error", err)
}
return len(results) > 0
}
@@ -278,7 +278,7 @@ func (srv *MiscService) existsUsersTotalTime() bool {
func (srv *MiscService) existsUsersFirstData() bool {
results, err := srv.keyValueService.GetByPrefix(config.KeyFirstHeartbeat)
if err != nil {
config.Log().Error("failed to fetch first heartbeats key-values, %v", err)
config.Log().Error("failed to fetch first heartbeats key-values", "error", err)
}
return len(results) > 0
}
@@ -286,7 +286,7 @@ func (srv *MiscService) existsUsersFirstData() bool {
func (srv *MiscService) existsSubscriptionNotifications() bool {
results, err := srv.keyValueService.GetByPrefix(config.KeySubscriptionNotificationSent)
if err != nil {
config.Log().Error("failed to fetch notifications key-values, %v", err)
config.Log().Error("failed to fetch notifications key-values", "error", err)
}
return len(results) > 0
}

View File

@@ -53,7 +53,7 @@ func (srv *ReportService) Schedule() {
t0 := time.Now()
if err := srv.SendReport(u, reportRange); err != nil {
config.Log().Error("failed to generate report for '%s', %v", u.ID, err)
config.Log().Error("failed to generate report", "userID", u.ID, "error", err)
}
// make the job take at least reportDelay seconds
@@ -62,7 +62,7 @@ func (srv *ReportService) Schedule() {
time.Sleep(diff)
}
}); err != nil {
config.Log().Error("failed to dispatch report generation job for user '%s', %v", u.ID, err)
config.Log().Error("failed to dispatch report generation job for user", "userID", u.ID, "error", err)
}
}
@@ -70,7 +70,7 @@ func (srv *ReportService) Schedule() {
// fetch all users with reports enabled
users, err := srv.userService.GetAllByReports(true)
if err != nil {
config.Log().Error("failed to get users for report generation, %v", err)
config.Log().Error("failed to get users for report generation", "error", err)
return
}
@@ -87,7 +87,7 @@ func (srv *ReportService) Schedule() {
}, srv.config.App.GetWeeklyReportCron())
if err != nil {
config.Log().Error("failed to dispatch report generation jobs, %v", err)
config.Log().Error("failed to dispatch report generation jobs", "error", err)
}
}
@@ -104,7 +104,7 @@ func (srv *ReportService) SendReport(user *models.User, duration time.Duration)
fullSummary, err := srv.summaryService.Aliased(start, end, user, srv.summaryService.Retrieve, nil, false)
if err != nil {
config.Log().Error("failed to generate report for '%s' - %v", user.ID, err)
config.Log().Error("failed to generate report", "userID", user.ID, "error", err)
return err
}
@@ -116,7 +116,7 @@ func (srv *ReportService) SendReport(user *models.User, duration time.Duration)
from, to := datetime.BeginOfDay(interval[0]), interval[1]
summary, err := srv.summaryService.Aliased(from, to, user, srv.summaryService.Retrieve, nil, false)
if err != nil {
config.Log().Error("failed to generate day summary (%v to %v) for report for '%s' - %v", from, to, user.ID, err)
config.Log().Error("failed to generate day summary for report", "from", from, "to", to, "userID", user.ID, "error", err)
break
}
summary.FromTime = models.CustomTime(from)
@@ -133,7 +133,7 @@ func (srv *ReportService) SendReport(user *models.User, duration time.Duration)
}
if err := srv.mailService.SendReport(user, report); err != nil {
config.Log().Error("failed to send report for '%s', %v", user.ID, err)
config.Log().Error("failed to send report", "userID", user.ID, "error", err)
return err
}

View File

@@ -273,7 +273,7 @@ func (srv *SummaryService) withProjectLabels(summary *models.Summary) *models.Su
allLabels, err := srv.projectLabelService.GetByUser(summary.UserID)
if err != nil {
config.Log().Error("failed to retrieve project labels for user summary ('%s', '%s', '%s')", summary.UserID, summary.FromTime.String(), summary.ToTime.String())
config.Log().Error("failed to retrieve project labels for user summary", "userID", summary.UserID, "fromTime", summary.FromTime.String(), "toTime", summary.ToTime.String())
return summary
}

View File

@@ -42,12 +42,12 @@ func NewUserService(mailService IMailService, userRepo repositories.IUserReposit
slog.Warn("resetting wakatime api key for user due to too many failures", "userID", user.ID, "failureCount", n)
if _, err := srv.SetWakatimeApiCredentials(user, "", ""); err != nil {
config.Log().Error("failed to set wakatime api key for user %s", user.ID)
config.Log().Error("failed to set wakatime api key for user", "userID", user.ID)
}
if user.Email != "" {
if err := mailService.SendWakatimeFailureNotification(user, n); err != nil {
config.Log().Error("failed to send wakatime failure notification mail to user %s", user.ID)
config.Log().Error("failed to send wakatime failure notification mail to user", "userID", user.ID)
} else {
slog.Info("sent wakatime connection failure mail", "userID", user.ID)
}