Compare commits

...

4 Commits

Author SHA1 Message Date
pascal
95365f41c3 limit to 10 open connections 2025-11-03 14:27:34 +01:00
pascal
b50c060bcc update pooling config 2025-11-03 14:16:48 +01:00
pascal
eae4f4be12 add additional logs 2025-11-03 12:50:43 +01:00
pascal
9eb2faef7f Add method timings with conditional logging
- Add timing measurements to key methods
- Only log when duration exceeds 1 second
2025-11-03 11:52:44 +01:00
4 changed files with 54 additions and 2 deletions

View File

@@ -757,6 +757,7 @@ func (am *DefaultAccountManager) AccountExists(ctx context.Context, accountID st
// If the user doesn't have an account, it creates one using the provided domain.
// Returns the account ID or an error if none is found or created.
func (am *DefaultAccountManager) GetAccountIDByUserID(ctx context.Context, userID, domain string) (string, error) {
defer util.TimeTrack(ctx, "GetAccountIDByUserID")()
if userID == "" {
return "", status.Errorf(status.NotFound, "no valid userID provided")
}
@@ -785,6 +786,8 @@ func isNil(i idp.Manager) bool {
// addAccountIDToIDPAppMeta update user's app metadata in idp manager
func (am *DefaultAccountManager) addAccountIDToIDPAppMeta(ctx context.Context, userID string, accountID string) error {
defer util.TimeTrack(ctx, "addAccountIDToIDPAppMeta")()
if !isNil(am.idpManager) {
// user can be nil if it wasn't found (e.g., just created)
user, err := am.lookupUserInCache(ctx, userID, accountID)
@@ -1043,6 +1046,8 @@ func (am *DefaultAccountManager) removeUserFromCache(ctx context.Context, accoun
func (am *DefaultAccountManager) updateAccountDomainAttributesIfNotUpToDate(ctx context.Context, accountID string, userAuth nbcontext.UserAuth,
primaryDomain bool,
) error {
defer util.TimeTrack(ctx, "updateAccountDomainAttributesIfNotUpToDate")()
if userAuth.Domain == "" {
log.WithContext(ctx).Errorf("claims don't contain a valid domain, skipping domain attributes update. Received claims: %v", userAuth)
return nil
@@ -1091,6 +1096,8 @@ func (am *DefaultAccountManager) handleExistingUserAccount(
domainAccountID string,
userAuth nbcontext.UserAuth,
) error {
defer util.TimeTrack(ctx, "handleExistingUserAccount")()
primaryDomain := domainAccountID == "" || userAccountID == domainAccountID
err := am.updateAccountDomainAttributesIfNotUpToDate(ctx, userAccountID, userAuth, primaryDomain)
if err != nil {
@@ -1109,6 +1116,8 @@ func (am *DefaultAccountManager) handleExistingUserAccount(
// addNewPrivateAccount validates if there is an existing primary account for the domain, if so it adds the new user to that account,
// otherwise it will create a new account and make it primary account for the domain.
func (am *DefaultAccountManager) addNewPrivateAccount(ctx context.Context, domainAccountID string, userAuth nbcontext.UserAuth) (string, error) {
defer util.TimeTrack(ctx, "addNewPrivateAccount")()
if userAuth.UserId == "" {
return "", fmt.Errorf("user ID is empty")
}
@@ -1140,6 +1149,8 @@ func (am *DefaultAccountManager) addNewPrivateAccount(ctx context.Context, domai
}
func (am *DefaultAccountManager) addNewUserToDomainAccount(ctx context.Context, domainAccountID string, userAuth nbcontext.UserAuth) (string, error) {
defer util.TimeTrack(ctx, "addNewUserToDomainAccount")()
newUser := types.NewRegularUser(userAuth.UserId)
newUser.AccountID = domainAccountID
@@ -1304,6 +1315,7 @@ func (am *DefaultAccountManager) UpdateAccountOnboarding(ctx context.Context, ac
}
func (am *DefaultAccountManager) GetAccountIDFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) {
defer util.TimeTrack(ctx, "GetAccountIDFromUserAuth")()
if userAuth.UserId == "" {
return "", "", errors.New(emptyUserID)
}
@@ -1348,6 +1360,7 @@ func (am *DefaultAccountManager) GetAccountIDFromUserAuth(ctx context.Context, u
// and propagates changes to peers if group propagation is enabled.
// requires userAuth to have been ValidateAndParseToken and EnsureUserAccessByJWTGroups by the AuthManager
func (am *DefaultAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error {
defer util.TimeTrack(ctx, "SyncUserJWTGroups")()
if userAuth.IsChild || userAuth.IsPAT {
return nil
}
@@ -1506,6 +1519,7 @@ func (am *DefaultAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth
//
// UserAuth IsChild -> checks that account exists
func (am *DefaultAccountManager) getAccountIDWithAuthorizationClaims(ctx context.Context, userAuth nbcontext.UserAuth) (string, error) {
defer util.TimeTrack(ctx, "getAccountIDWithAuthorizationClaims")()
log.WithContext(ctx).Tracef("getting account with authorization claims. User ID: \"%s\", Account ID: \"%s\", Domain: \"%s\", Domain Category: \"%s\"",
userAuth.UserId, userAuth.AccountId, userAuth.Domain, userAuth.DomainCategory)
@@ -1559,6 +1573,8 @@ func (am *DefaultAccountManager) getAccountIDWithAuthorizationClaims(ctx context
return am.addNewPrivateAccount(ctx, domainAccountID, userAuth)
}
func (am *DefaultAccountManager) getPrivateDomainWithGlobalLock(ctx context.Context, domain string) (string, context.CancelFunc, error) {
defer util.TimeTrack(ctx, "getPrivateDomainWithGlobalLock")()
domainAccountID, err := am.Store.GetAccountIDByPrivateDomain(ctx, store.LockingStrengthNone, domain)
if handleNotFound(err) != nil {
@@ -1585,6 +1601,8 @@ func (am *DefaultAccountManager) getPrivateDomainWithGlobalLock(ctx context.Cont
}
func (am *DefaultAccountManager) handlePrivateAccountWithIDFromClaim(ctx context.Context, userAuth nbcontext.UserAuth) (string, error) {
defer util.TimeTrack(ctx, "handlePrivateAccountWithIDFromClaim")()
userAccountID, err := am.Store.GetAccountIDByUserID(ctx, store.LockingStrengthNone, userAuth.UserId)
if err != nil {
log.WithContext(ctx).Errorf("error getting account ID by user ID: %v", err)

View File

@@ -88,9 +88,13 @@ func NewSqlStore(ctx context.Context, db *gorm.DB, storeEngine types.Engine, met
conns = 1
}
sql.SetMaxOpenConns(conns)
sql.SetMaxOpenConns(10)
sql.SetMaxIdleConns(10)
sql.SetConnMaxLifetime(time.Hour)
sql.SetConnMaxIdleTime(3 * time.Minute)
log.WithContext(ctx).Infof("Set max open db connections to %d", conns)
log.WithContext(ctx).Infof("Set max open db connections to %d, max idle to %d, max lifetime to %v, max idle time to %v",
conns, conns, time.Hour, 3*time.Minute)
if skipMigration {
log.WithContext(ctx).Infof("skipping migration")
@@ -500,6 +504,8 @@ func (s *SqlStore) GetAccountByPrivateDomain(ctx context.Context, domain string)
}
func (s *SqlStore) GetAccountIDByPrivateDomain(ctx context.Context, lockStrength LockingStrength, domain string) (string, error) {
defer util.TimeTrack(ctx, "GetAccountIDByPrivateDomain")()
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
@@ -575,6 +581,8 @@ func (s *SqlStore) GetUserByPATID(ctx context.Context, lockStrength LockingStren
}
func (s *SqlStore) GetUserByUserID(ctx context.Context, lockStrength LockingStrength, userID string) (*types.User, error) {
defer util.TimeTrack(ctx, "GetUserByUserID")()
ctx, cancel := getDebuggingCtx(ctx)
defer cancel()
@@ -940,6 +948,8 @@ func (s *SqlStore) GetAccountIDByPeerPubKey(ctx context.Context, peerKey string)
}
func (s *SqlStore) GetAccountIDByUserID(ctx context.Context, lockStrength LockingStrength, userID string) (string, error) {
defer util.TimeTrack(ctx, "GetAccountIDByUserID")()
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
@@ -1127,6 +1137,8 @@ func (s *SqlStore) GetAccountCreatedBy(ctx context.Context, lockStrength Locking
// SaveUserLastLogin stores the last login time for a user in DB.
func (s *SqlStore) SaveUserLastLogin(ctx context.Context, accountID, userID string, lastLogin time.Time) error {
defer util.TimeTrack(ctx, "SyncUserJWTGroups")()
ctx, cancel := getDebuggingCtx(ctx)
defer cancel()
@@ -1784,6 +1796,7 @@ func (s *SqlStore) GetAccountDNSSettings(ctx context.Context, lockStrength Locki
// AccountExists checks whether an account exists by the given ID.
func (s *SqlStore) AccountExists(ctx context.Context, lockStrength LockingStrength, id string) (bool, error) {
defer util.TimeTrack(ctx, "AccountExists")()
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
@@ -1804,6 +1817,8 @@ func (s *SqlStore) AccountExists(ctx context.Context, lockStrength LockingStreng
// GetAccountDomainAndCategory retrieves the Domain and DomainCategory fields for an account based on the given accountID.
func (s *SqlStore) GetAccountDomainAndCategory(ctx context.Context, lockStrength LockingStrength, accountID string) (string, string, error) {
defer util.TimeTrack(ctx, "GetAccountDomainAndCategory")()
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})

View File

@@ -178,6 +178,8 @@ func (am *DefaultAccountManager) GetUserByID(ctx context.Context, id string) (*t
// GetUser looks up a user by provided nbContext.UserAuths.
// Expects account to have been created already.
func (am *DefaultAccountManager) GetUserFromUserAuth(ctx context.Context, userAuth nbContext.UserAuth) (*types.User, error) {
defer util.TimeTrack(ctx, "SyncUserJWTGroups")()
user, err := am.Store.GetUserByUserID(ctx, store.LockingStrengthNone, userAuth.UserId)
if err != nil {
return nil, err

View File

@@ -1,5 +1,12 @@
package util
import (
"context"
"time"
log "github.com/sirupsen/logrus"
)
// Difference returns the elements in `a` that aren't in `b`.
func Difference(a, b []string) []string {
mb := make(map[string]struct{}, len(b))
@@ -50,3 +57,13 @@ func contains[T comparableObject[T]](slice []T, element T) bool {
}
return false
}
func TimeTrack(ctx context.Context, name string) func() {
start := time.Now()
return func() {
elapsed := time.Since(start)
if elapsed > time.Second {
log.WithContext(ctx).Infof("Slow Call: [%s] took %s", name, elapsed)
}
}
}