Correct the logs to use the format key:value

This commit is contained in:
finn
2024-08-20 08:45:43 +07:00
parent 118e51139a
commit b5bb3da9b6
30 changed files with 4800 additions and 799 deletions

View File

@@ -42,7 +42,7 @@ func InitQueue(name string, workers int) error {
if _, ok := jobQueues[name]; ok {
return fmt.Errorf("queue '%s' already existing", name)
}
slog.Info("creating job queue '%s' (%d workers)", name, workers)
slog.Info("creating job queue", "name", name, "workers", workers)
jobQueues[name] = artifex.NewDispatcher(workers, 4096)
jobQueues[name].Start()
return nil

File diff suppressed because it is too large Load Diff

View File

@@ -143,7 +143,7 @@ func main() {
slog.Info("starting with database", "dialect", config.Db.Dialect)
db, err = gorm.Open(config.Db.GetDialector(), &gorm.Config{Logger: gormLogger}, conf.GetWakapiDBOpts(&config.Db))
if err != nil {
slog.Error("could not connect to database", "error", err.Error())
slog.Error("could not connect to database", "error", err)
log.Fatal("could not open database")
}
@@ -152,7 +152,7 @@ func main() {
}
sqlDb, err := db.DB()
if err != nil {
slog.Error("could not connect to database", "error", err.Error())
slog.Error("could not connect to database", "error", err)
log.Fatal("could not connect to database")
}
sqlDb.SetMaxIdleConns(int(config.Db.MaxConn))
@@ -452,4 +452,5 @@ func initLogger() {
}
l := slog.New(handler)
slog.SetDefault(l)
slog.Info("logger initialized", "env", config.Env)
}

View File

@@ -62,7 +62,7 @@ func (m *WakatimeRelayMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Reque
err := m.filterByCache(r)
if err != nil {
slog.Warn("%v", err)
slog.Warn("filter cache error", "error", err)
return
}
@@ -104,7 +104,7 @@ func (m *WakatimeRelayMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Reque
func (m *WakatimeRelayMiddleware) send(method, url string, body io.Reader, headers http.Header, forUser *models.User) {
request, err := http.NewRequest(method, url, body)
if err != nil {
slog.Warn("error constructing relayed request - %v", err)
slog.Warn("error constructing relayed request", "error", err)
return
}
@@ -116,12 +116,12 @@ func (m *WakatimeRelayMiddleware) send(method, url string, body io.Reader, heade
response, err := m.httpClient.Do(request)
if err != nil {
slog.Warn("error executing relayed request - %v", err)
slog.Warn("error executing relayed request", "error", err)
return
}
if response.StatusCode < 200 || response.StatusCode >= 300 {
slog.Warn("failed to relay request for user %s, got status %d", forUser.ID, response.StatusCode)
slog.Warn("failed to relay request for user", "userID", forUser.ID, "statusCode", response.StatusCode)
// TODO: use leaky bucket instead of expiring cache?
if _, found := m.failureCache.Get(forUser.ID); !found {
@@ -133,7 +133,7 @@ func (m *WakatimeRelayMiddleware) send(method, url string, body io.Reader, heade
Fields: map[string]interface{}{config.FieldUser: forUser, config.FieldPayload: n},
})
} else if n%10 == 0 {
slog.Warn("%d / %d failed wakatime heartbeat relaying attempts for user %s within last 24 hours", n, maxFailuresPerDay, forUser.ID)
slog.Warn("failed wakatime heartbeat relaying attempts for user", "failedCount", n, "maxFailures", maxFailuresPerDay, "userID", forUser.ID)
}
}
}
@@ -182,7 +182,7 @@ func (m *WakatimeRelayMiddleware) filterByCache(r *http.Request) error {
if len(newData) != len(heartbeats) {
user := middlewares.GetPrincipal(r)
slog.Warn("only relaying %d of %d heartbeats for user %s", len(newData), len(heartbeats), user.ID)
slog.Warn("only relaying partial heartbeats for user", "relayedCount", len(newData), "totalCount", len(heartbeats), "userID", user.ID)
}
buf := bytes.Buffer{}

View File

@@ -16,12 +16,12 @@ func init() {
oldIndexName, newIndexName := "idx_customrule_user", "idx_language_mapping_user"
if migrator.HasTable(oldTableName) {
slog.Info("renaming '%s' table to '%s'", oldTableName, newTableName)
slog.Info("renaming table", "oldName", oldTableName, "newName", newTableName)
if err := migrator.RenameTable(oldTableName, &models.LanguageMapping{}); err != nil {
return err
}
slog.Info("renaming '%s' index to '%s'", oldIndexName, newIndexName)
slog.Info("renaming index", "oldName", oldIndexName, "newName", newIndexName)
return migrator.RenameIndex(&models.LanguageMapping{}, oldIndexName, newIndexName)
}
return nil

View File

@@ -51,7 +51,7 @@ func init() {
for name, table := range constraints {
if migrator.HasConstraint(table, name) {
slog.Info("dropping constraint '%s'", name)
slog.Info("dropping constraint", "name", name)
if err := migrator.DropConstraint(table, name); err != nil {
return err
}

View File

@@ -31,7 +31,7 @@ func init() {
}
if migrator.HasConstraint(&models.Alias{}, "fk_aliases_user") {
slog.Info("dropping constraint 'fk_aliases_user'")
slog.Info("dropping constraint", "name", "fk_aliases_user")
if err := migrator.DropConstraint(&models.Alias{}, "fk_aliases_user"); err != nil {
return err
}

View File

@@ -38,14 +38,14 @@ func init() {
}
if cfg.Db.Dialect == config.SQLDialectSqlite {
slog.Info("not attempting to drop column 'badges_enabled' on sqlite")
slog.Info("not attempting to drop column on sqlite", "column", "badges_enabled")
return nil
}
if err := migrator.DropColumn(&models.User{}, "badges_enabled"); err != nil {
return err
}
slog.Info("dropped column 'badges_enabled' after substituting it by sharing indicators")
slog.Info("dropped column after substituting it by sharing indicators", "column", "badges_enabled")
return nil
},

View File

@@ -12,7 +12,7 @@ func init() {
name: name,
f: func(db *gorm.DB, cfg *config.Config) error {
if err := db.Migrator().DropTable("gorp_migrations"); err == nil {
slog.Info("dropped table 'gorp_migrations'")
slog.Info("dropped table", "table", "gorp_migrations")
}
return nil
},

View File

@@ -40,7 +40,7 @@ func init() {
} else {
// sqlite doesn't allow for changing column type easily
// https://stackoverflow.com/a/2083562/3112139
slog.Warn("unable to migrate id columns to bigint on %s", cfg.Db.Dialect)
slog.Warn("unable to migrate id columns to bigint", "dialect", cfg.Db.Dialect)
}
setHasRun(name, db)

View File

@@ -45,7 +45,7 @@ func init() {
return err
}
slog.Info("corrected heartbeats counter of %d summaries", result.RowsAffected)
slog.Info("corrected heartbeats counter of summaries", "count", result.RowsAffected)
setHasRun(name, db)
return nil

View File

@@ -19,14 +19,14 @@ func init() {
migrator := db.Migrator()
if migrator.HasColumn(&models.Diagnostics{}, "user_id") {
slog.Info("running migration '%s'", name)
slog.Info("running migration", "name", name)
if err := migrator.DropConstraint(&models.Diagnostics{}, "fk_diagnostics_user"); err != nil {
slog.Warn("failed to drop 'fk_diagnostics_user' constraint (%v)", err)
slog.Warn("failed to drop constraint", "constraint", "fk_diagnostics_user", "error", err)
}
if err := migrator.DropColumn(&models.Diagnostics{}, "user_id"); err != nil {
slog.Warn("failed to drop user_id column of diagnostics (%v)", err)
slog.Warn("failed to drop column", "table", "diagnostics", "column", "user_id", "error", err)
}
}

View File

@@ -25,9 +25,9 @@ func init() {
}
if cfg.Db.IsSQLite() && db.Migrator().HasIndex(&models.Heartbeat{}, idxName) {
slog.Info("running migration '%s'", name)
slog.Info("running migration", "name", name)
if err := db.Migrator().DropIndex(&models.Heartbeat{}, idxName); err != nil {
slog.Warn("failed to drop %s", idxName)
slog.Warn("failed to drop index", "indexName", idxName)
}
}

View File

@@ -19,10 +19,10 @@ func init() {
migrator := db.Migrator()
if migrator.HasTable(&models.LeaderboardItem{}) && migrator.HasColumn(&models.LeaderboardItem{}, "rank") {
slog.Info("running migration '%s'", name)
slog.Info("running migration", "name", name)
if err := migrator.DropColumn(&models.LeaderboardItem{}, "rank"); err != nil {
slog.Warn("failed to drop 'rank' column (%v)", err)
slog.Warn("failed to drop column", "column", "rank", "error", err)
}
}

View File

@@ -15,7 +15,7 @@ func init() {
return nil
}
slog.Info("running migration '%s'", name)
slog.Info("running migration", "name", name)
if err := db.Exec("UPDATE heartbeats SET language = 'Astro' where language = '' and entity like '%.astro'").Error; err != nil {
return err

View File

@@ -19,7 +19,7 @@ func init() {
migrator := db.Migrator()
if migrator.HasColumn(&models.User{}, "subscription_renewal") {
slog.Info("running migration '%s'", name)
slog.Info("running migration", "name", name)
if err := db.Exec("UPDATE users SET subscription_renewal = subscribed_until WHERE subscribed_until is not null").Error; err != nil {
return err

View File

@@ -87,7 +87,7 @@ func RunPreMigrations(db *gorm.DB, cfg *config.Config) {
sort.Sort(preMigrations)
for _, m := range preMigrations {
slog.Info("potentially running migration '%s'", m.name)
slog.Info("potentially running migration", "name", m.name)
if err := m.f(db, cfg); err != nil {
log.Fatalf("migration '%s' failed - %v", m.name, err)
}
@@ -98,7 +98,7 @@ func RunPostMigrations(db *gorm.DB, cfg *config.Config) {
sort.Sort(postMigrations)
for _, m := range postMigrations {
slog.Info("potentially running migration '%s'", m.name)
slog.Info("potentially running migration", "name", m.name)
if err := m.f(db, cfg); err != nil {
log.Fatalf("migration '%s' failed - %v", m.name, err)
}

View File

@@ -349,7 +349,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
// Database metrics
dbSize, err := h.metricsRepo.GetDatabaseSize()
if err != nil {
slog.Warn("failed to get database size (%v)", err)
slog.Warn("failed to get database size", "error", err)
}
metrics = append(metrics, &mm.GaugeMetric{
@@ -383,7 +383,7 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
var metrics mm.Metrics
t0 := time.Now()
slog.Debug("[metrics] start admin metrics calculation")
slog.Debug("start admin metrics calculation")
if !user.IsAdmin {
return nil, errors.New("unauthorized")
@@ -398,14 +398,14 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
totalUsers, _ := h.userSrvc.Count()
totalHeartbeats, _ := h.heartbeatSrvc.Count(true)
slog.Debug("[metrics] finished counting users and heartbeats after %v", time.Now().Sub(t0))
slog.Debug("finished counting users and heartbeats", "duration", time.Since(t0))
activeUsers, err := h.userSrvc.GetActive(false)
if err != nil {
conf.Log().Error("failed to retrieve active users for metric - %v", err)
return nil, err
}
slog.Debug("[metrics] finished getting active users after %v", time.Now().Sub(t0))
slog.Debug("finished getting active users", "duration", time.Since(t0))
metrics = append(metrics, &mm.GaugeMetric{
Name: MetricsPrefix + "_admin_seconds_total",
@@ -451,7 +451,7 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
Labels: []mm.Label{{Key: "user", Value: uc.User}},
})
}
slog.Debug("[metrics] finished counting heartbeats by user after %v", time.Now().Sub(t0))
slog.Debug("finished counting heartbeats by user", "duration", time.Since(t0))
// Get per-user total activity
@@ -480,7 +480,7 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
}
wp.StopAndWait()
slog.Debug("[metrics] finished retrieving total activity time by user after %v", time.Now().Sub(t0))
slog.Debug("finished retrieving total activity time by user", "duration", time.Since(t0))
return &metrics, nil
}

View File

@@ -341,7 +341,7 @@ func (h *LoginHandler) PostResetPassword(w http.ResponseWriter, r *http.Request)
if err := h.mailSrvc.SendPasswordReset(user, link); err != nil {
conf.Log().Request(r).Error("failed to send password reset mail to %s - %v", user.ID, err)
} else {
slog.Info("sent password reset mail to %s", user.ID)
slog.Info("sent password reset mail", "userID", user.ID)
}
}(u)
}

View File

@@ -118,7 +118,7 @@ func (h *SettingsHandler) PostIndex(w http.ResponseWriter, r *http.Request) {
actionFunc := h.dispatchAction(action)
if actionFunc == nil {
slog.Warn("failed to dispatch action '%s'", action)
slog.Warn("failed to dispatch action", "action", action)
w.WriteHeader(http.StatusBadRequest)
templates[conf.SettingsTemplate].Execute(w, h.buildViewModel(r, w, nil).WithError("unknown action requests"))
return
@@ -637,7 +637,7 @@ func (h *SettingsHandler) actionImportWakatime(w http.ResponseWriter, r *http.Re
insert := func(batch []*models.Heartbeat) {
if err := h.heartbeatSrvc.InsertBatch(batch); err != nil {
slog.Warn("failed to insert imported heartbeat, already existing? - %v", err)
slog.Warn("failed to insert imported heartbeat, already existing?", "error", err)
}
}
@@ -655,7 +655,7 @@ func (h *SettingsHandler) actionImportWakatime(w http.ResponseWriter, r *http.Re
}
countAfter, _ := h.heartbeatSrvc.CountByUser(user)
slog.Info("downloaded %d heartbeats for user '%s' (%d actually imported)", count, user.ID, countAfter-countBefore)
slog.Info("downloaded heartbeats for user", "count", count, "userID", user.ID, "importedCount", countAfter-countBefore)
h.regenerateSummaries(user)
@@ -670,7 +670,7 @@ func (h *SettingsHandler) actionImportWakatime(w http.ResponseWriter, r *http.Re
if err := h.mailSrvc.SendImportNotification(user, time.Now().Sub(start), int(countAfter-countBefore)); err != nil {
conf.Log().Request(r).Error("failed to send import notification mail to %s - %v", user.ID, err)
} else {
slog.Info("sent import notification mail to %s", user.ID)
slog.Info("sent import notification mail", "userID", user.ID)
}
}
}(user)
@@ -711,15 +711,15 @@ func (h *SettingsHandler) actionClearData(w http.ResponseWriter, r *http.Request
}
user := middlewares.GetPrincipal(r)
slog.Info("user '%s' requested to delete all data", user.ID)
slog.Info("user requested to delete all data", "userID", user.ID)
go func(user *models.User) {
slog.Info("deleting summaries for user '%s'", user.ID)
slog.Info("deleting summaries for user", "userID", user.ID)
if err := h.summarySrvc.DeleteByUser(user.ID); err != nil {
conf.Log().Request(r).Error("failed to clear summaries: %v", err)
}
slog.Info("deleting heartbeats for user '%s'", user.ID)
slog.Info("deleting heartbeats for user", "userID", user.ID)
if err := h.heartbeatSrvc.DeleteByUser(user); err != nil {
conf.Log().Request(r).Error("failed to clear heartbeats: %v", err)
}
@@ -735,12 +735,12 @@ func (h *SettingsHandler) actionDeleteUser(w http.ResponseWriter, r *http.Reques
user := middlewares.GetPrincipal(r)
go func(user *models.User) {
slog.Info("deleting user '%s' shortly", user.ID)
slog.Info("deleting user shortly", "userID", user.ID)
time.Sleep(5 * time.Minute)
if err := h.userSrvc.Delete(user); err != nil {
conf.Log().Request(r).Error("failed to delete user '%s' - %v", user.ID, err)
} else {
slog.Info("successfully deleted user '%s'", user.ID)
slog.Info("successfully deleted user", "userID", user.ID)
}
}(user)
@@ -806,7 +806,7 @@ func (h *SettingsHandler) validateWakatimeKey(apiKey string, baseUrl string) boo
}
func (h *SettingsHandler) regenerateSummaries(user *models.User) error {
slog.Info("clearing summaries for user '%s'", user.ID)
slog.Info("clearing summaries for user", "userID", user.ID)
if err := h.summarySrvc.DeleteByUser(user.ID); err != nil {
conf.Log().Error("failed to clear summaries: %v", err)
return err

View File

@@ -59,11 +59,11 @@ func NewSubscriptionHandler(
price, err := stripePrice.Get(config.Subscriptions.StandardPriceId, nil)
if err != nil {
log.Fatal("failed to fetch stripe plan details: %v", err)
log.Fatalf("failed to fetch stripe plan details: %v", err)
}
config.Subscriptions.StandardPrice = strings.TrimSpace(fmt.Sprintf("%2.f €", price.UnitAmountDecimal/100.0)) // TODO: respect actual currency
slog.Info("enabling subscriptions with stripe payment for %s / month", config.Subscriptions.StandardPrice)
slog.Info("enabling subscriptions with stripe payment", "price", config.Subscriptions.StandardPrice)
}
handler := &SubscriptionHandler{
@@ -82,9 +82,9 @@ func NewSubscriptionHandler(
continue
}
slog.Info("cancelling subscription for user '%s' (email '%s', stripe customer '%s') upon account deletion", user.ID, user.Email, user.StripeCustomerId)
slog.Info("cancelling subscription for user upon account deletion", "userID", user.ID, "email", user.Email, "stripeCustomerID", user.StripeCustomerId)
if err := handler.cancelUserSubscription(user); err == nil {
slog.Info("successfully cancelled subscription for user '%s' (email '%s', stripe customer '%s')", user.ID, user.Email, user.StripeCustomerId)
slog.Info("successfully cancelled subscription for user", "userID", user.ID, "email", user.Email, "stripeCustomerID", user.StripeCustomerId)
} else {
conf.Log().Error("failed to cancel subscription for user '%s' (email '%s', stripe customer '%s') - %v", user.ID, user.Email, user.StripeCustomerId, err)
}
@@ -223,7 +223,7 @@ func (h *SubscriptionHandler) PostWebhook(w http.ResponseWriter, r *http.Request
if err != nil {
return // status code already written
}
slog.Info("received stripe subscription event of type '%s' for subscription '%s' (customer '%s').", event.Type, subscription.ID, subscription.Customer.ID)
slog.Info("received stripe subscription event", "eventType", event.Type, "subscriptionID", subscription.ID, "customerID", subscription.Customer.ID)
// first, try to get user by associated customer id (requires checkout.session.completed event to have been processed before)
user, err := h.userSrvc.GetUserByStripeCustomerId(subscription.Customer.ID)
@@ -259,7 +259,7 @@ func (h *SubscriptionHandler) PostWebhook(w http.ResponseWriter, r *http.Request
if err != nil {
return // status code already written
}
slog.Info("received stripe checkout session event of type '%s' for session '%s' (customer '%s' with email '%s').", event.Type, checkoutSession.ID, checkoutSession.Customer.ID, checkoutSession.CustomerEmail)
slog.Info("received stripe checkout session event", "eventType", event.Type, "sessionID", checkoutSession.ID, "customerID", checkoutSession.Customer.ID, "customerEmail", checkoutSession.CustomerEmail)
user, err := h.userSrvc.GetUserById(checkoutSession.ClientReferenceID)
if err != nil {
@@ -272,14 +272,14 @@ func (h *SubscriptionHandler) PostWebhook(w http.ResponseWriter, r *http.Request
if _, err := h.userSrvc.Update(user); err != nil {
conf.Log().Request(r).Error("failed to update stripe customer id (%s) for user '%s', %v", checkoutSession.Customer.ID, user.ID, err)
} else {
slog.Info("associated user '%s' with stripe customer '%s'", user.ID, checkoutSession.Customer.ID)
slog.Info("associated user with stripe customer", "userID", user.ID, "stripeCustomerID", checkoutSession.Customer.ID)
}
} else if user.StripeCustomerId != checkoutSession.Customer.ID {
conf.Log().Request(r).Error("invalid state: tried to associate user '%s' with stripe customer '%s', but '%s' already assigned", user.ID, checkoutSession.Customer.ID, user.StripeCustomerId)
}
default:
slog.Warn("got stripe event '%s' with no handler defined", event.Type)
slog.Warn("got stripe event with no handler defined", "eventType", event.Type)
}
w.WriteHeader(http.StatusOK)
@@ -305,19 +305,19 @@ func (h *SubscriptionHandler) handleSubscriptionEvent(subscription *stripe.Subsc
hasSubscribed = true
user.SubscribedUntil = &until
user.SubscriptionRenewal = &until
slog.Info("user %s got active subscription %s until %v", user.ID, subscription.ID, user.SubscribedUntil)
slog.Info("user got active subscription", "userID", user.ID, "subscriptionID", subscription.ID, "subscribedUntil", user.SubscribedUntil)
}
if cancelAt := time.Unix(subscription.CancelAt, 0); !cancelAt.IsZero() && cancelAt.After(time.Now()) {
user.SubscriptionRenewal = nil
slog.Info("user %s chose to cancel subscription %s by %v", user.ID, subscription.ID, cancelAt)
slog.Info("user chose to cancel subscription", "userID", user.ID, "subscriptionID", subscription.ID, "cancelAt", cancelAt)
}
case "canceled", "unpaid", "incomplete_expired":
user.SubscribedUntil = nil
user.SubscriptionRenewal = nil
slog.Info("user %s's subscription %s got canceled, because of status update to '%s'", user.ID, subscription.ID, subscription.Status)
slog.Info("user's subscription got canceled due to status update", "userID", user.ID, "subscriptionID", subscription.ID, "status", subscription.Status)
default:
slog.Info("got subscription (%s) status update to '%s' for user '%s'", subscription.ID, subscription.Status, user.ID)
slog.Info("got subscription status update", "subscriptionID", subscription.ID, "status", subscription.Status, "userID", user.ID)
return nil
}
@@ -399,6 +399,6 @@ func (h *SubscriptionHandler) findCurrentStripeSubscription(customerId string) (
func (h *SubscriptionHandler) clearSubscriptionNotificationStatus(userId string) {
key := fmt.Sprintf("%s_%s", conf.KeySubscriptionNotificationSent, userId)
if err := h.keyValueSrvc.DeleteString(key); err != nil {
slog.Warn("failed to delete '%s', %v", key, err)
slog.Warn("failed to delete", "key", key, "error", err)
}
}

View File

@@ -140,7 +140,7 @@ 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)
} else {
slog.Info("successfully generated summary (%v, %v, %s)", job.From, job.To, job.User.ID)
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)
}

View File

@@ -37,9 +37,9 @@ func (s *HousekeepingService) Schedule() {
}
func (s *HousekeepingService) CleanUserDataBefore(user *models.User, before time.Time) error {
slog.Warn("cleaning up user data for '%s' older than %v", user.ID, before)
slog.Warn("cleaning up user data older than", "userID", user.ID, "date", before)
if s.config.App.DataCleanupDryRun {
slog.Info("skipping actual data deletion for '%v', because this is just a dry run", user.ID)
slog.Info("skipping actual data deletion for dry run", "userID", user.ID)
return nil
}
@@ -49,7 +49,7 @@ func (s *HousekeepingService) CleanUserDataBefore(user *models.User, before time
}
// clear old summaries
slog.Info("clearing summaries for user '%s' older than %v", user.ID, before)
slog.Info("clearing summaries for user older than", "userID", user.ID, "date", before)
if err := s.summarySrvc.DeleteByUserBefore(user.ID, before); err != nil {
return err
}
@@ -58,7 +58,7 @@ func (s *HousekeepingService) CleanUserDataBefore(user *models.User, before time
}
func (s *HousekeepingService) CleanInactiveUsers(before time.Time) error {
slog.Info("cleaning up users inactive since %v", before)
slog.Info("cleaning up users inactive since", "date", before)
users, err := s.userSrvc.GetAll()
if err != nil {
return err
@@ -70,20 +70,20 @@ func (s *HousekeepingService) CleanInactiveUsers(before time.Time) error {
continue
}
slog.Warn("deleting user '%s', because inactive and not having data", u.ID)
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)
} else {
i++
}
}
slog.Info("deleted %d (of %d total) users due to inactivity", i, len(users))
slog.Info("deleted users due to inactivity", "deletedCount", i, "totalCount", len(users))
return nil
}
func (s *HousekeepingService) WarmUserProjectStatsCache(user *models.User) error {
slog.Info("pre-warming project stats cache for '%s'", user.ID)
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)
}

View File

@@ -117,7 +117,7 @@ func (w *WakatimeHeartbeatsImporter) Import(user *models.User, minFrom time.Time
}
if minDataAge := user.MinDataAge(); minFrom.Before(minDataAge) {
slog.Info("wakatime data import for user capped", "userID", user.ID, "capped to", fmt.Sprintf("[%v, %v]", minDataAge, maxTo))
slog.Info("wakatime data import for user capped", "userID", user.ID, "cappedTo", fmt.Sprintf("[%v, %v]", minDataAge, maxTo))
}
slog.Info("scheduling wakatime import for user", "userID", user.ID, "interval", fmt.Sprintf("[%v, %v]", minFrom, maxTo))

View File

@@ -61,10 +61,10 @@ func NewLeaderboardService(leaderboardRepo repositories.ILeaderboardRepository,
}
if user.PublicLeaderboard && !exists {
slog.Info("generating leaderboard for '%s' after settings update", user.ID)
slog.Info("generating leaderboard after settings update", "userID", user.ID)
srv.ComputeLeaderboard([]*models.User{user}, srv.defaultScope, []uint8{models.SummaryLanguage})
} else if !user.PublicLeaderboard && exists {
slog.Info("clearing leaderboard for '%s' after settings update", user.ID)
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)
}
@@ -100,7 +100,7 @@ func (srv *LeaderboardService) Schedule() {
}
func (srv *LeaderboardService) ComputeLeaderboard(users []*models.User, interval *models.IntervalKey, by []uint8) error {
slog.Info("generating leaderboard (%s) for %d users (%d aggregations)", (*interval)[0], len(users), len(by))
slog.Info("generating leaderboard", "interval", (*interval)[0], "userCount", len(users), "aggregationCount", len(by))
for _, user := range users {
if err := srv.repository.DeleteByUserAndInterval(user.ID, interval); err != nil {

View File

@@ -8,6 +8,6 @@ import (
type NoopSendingService struct{}
func (n *NoopSendingService) Send(mail *models.Mail) error {
slog.Info("noop mail service doing nothing instead of sending password reset mail to [%v]", mail.To.Strings())
slog.Info("noop mail service doing nothing instead of sending password reset mail", "to", mail.To.Strings())
return nil
}

View File

@@ -250,7 +250,7 @@ func (srv *MiscService) countUserTotalTime(userId string) time.Duration {
func (srv *MiscService) sendSubscriptionNotificationScheduled(user *models.User, hasExpired bool) {
u := *user
srv.queueMails.Dispatch(func() {
slog.Info("sending subscription expiry notification mail to %s (expired: %v)", u.ID, hasExpired)
slog.Info("sending subscription expiry notification mail", "userID", u.ID, "expired", hasExpired)
defer time.Sleep(10 * time.Second)
if err := srv.mailService.SendSubscriptionNotification(&u, hasExpired); err != nil {

View File

@@ -58,7 +58,7 @@ func (srv *ReportService) Schedule() {
// make the job take at least reportDelay seconds
if diff := reportDelay - time.Now().Sub(t0); diff > 0 {
slog.Debug("waiting for %v before sending next report", diff)
slog.Debug("waiting before sending next report", "duration", diff)
time.Sleep(diff)
}
}); err != nil {
@@ -80,7 +80,7 @@ func (srv *ReportService) Schedule() {
})
// schedule jobs, throttled by one job per x seconds
slog.Info("scheduling report generation for %d users", len(users))
slog.Info("scheduling report generation", "userCount", len(users))
for _, u := range users {
scheduleUserReport(u)
}
@@ -93,11 +93,11 @@ func (srv *ReportService) Schedule() {
func (srv *ReportService) SendReport(user *models.User, duration time.Duration) error {
if user.Email == "" {
slog.Warn("not generating report for '%s' as no e-mail address is set")
slog.Warn("not generating report as no e-mail address is set", "userID", user.ID)
return nil
}
slog.Info("generating report for '%s'", user.ID)
slog.Info("generating report for user", "userID", user.ID)
end := time.Now().In(user.TZ())
start := time.Now().Add(-1 * duration)
@@ -137,6 +137,6 @@ func (srv *ReportService) SendReport(user *models.User, duration time.Duration)
return err
}
slog.Info("sent report to user '%s'", user.ID)
slog.Info("sent report to user", "userID", user.ID)
return nil
}

View File

@@ -335,13 +335,13 @@ func (srv *SummaryService) mergeSummaries(summaries []*models.Summary) (*models.
for i, s := range summaries {
hash := s.FromTime.T()
if _, found := processed[hash]; found {
slog.Warn("summary from %v to %v (user '%s') was attempted to be processed more often than once", s.FromTime, s.ToTime, s.UserID)
slog.Warn("summary was attempted to be processed more often than once", "fromTime", s.FromTime, "toTime", s.ToTime, "userID", s.UserID)
continue
}
if i > 0 {
if prev := summaries[i-1]; s.FromTime.T().Before(prev.ToTime.T()) {
slog.Warn("got overlapping summaries (ids %d, %d) for user '%s' from %v (current.from) to %v (previous.to)", prev.ID, s.ID, s.UserID, s.FromTime, prev.ToTime)
slog.Warn("got overlapping summaries for user", "prevID", prev.ID, "currentID", s.ID, "userID", s.UserID, "fromTime", s.FromTime, "prevToTime", prev.ToTime)
}
}

View File

@@ -39,7 +39,7 @@ func NewUserService(mailService IMailService, userRepo repositories.IUserReposit
user := m.Fields[config.FieldUser].(*models.User)
n := m.Fields[config.FieldPayload].(int)
slog.Warn("resetting wakatime api key for user %s, because of too many failures (%d)", user.ID, n)
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)
@@ -49,7 +49,7 @@ func NewUserService(mailService IMailService, userRepo repositories.IUserReposit
if err := mailService.SendWakatimeFailureNotification(user, n); err != nil {
config.Log().Error("failed to send wakatime failure notification mail to user %s", user.ID)
} else {
slog.Info("sent wakatime connection failure mail to %s", user.ID)
slog.Info("sent wakatime connection failure mail", "userID", user.ID)
}
}
}