diff --git a/ai.go b/ai.go index 74a8fb58..29e7da81 100644 --- a/ai.go +++ b/ai.go @@ -7196,7 +7196,7 @@ func sendAITokenLimitAlert(ctx context.Context, execution WorkflowExecution, ful appRunsLimit := int64(0) orgStats, statsErr := GetOrgStatistics(ctx, billingOrgId) if statsErr == nil && orgStats != nil { - stats := handleGetCorrectedStats(orgStats) + stats := GetCorrectedStats(orgStats) totalAppExecutions = stats.MonthlyAppExecutions + stats.MonthlyChildAppExecutions } if fullOrg != nil { diff --git a/db-connector.go b/db-connector.go index e98b9276..c38b1140 100755 --- a/db-connector.go +++ b/db-connector.go @@ -127,7 +127,7 @@ func SetOrgStatistics(ctx context.Context, stats ExecutionInfo, id string) error } stat.Date = stat.Date.UTC() - statdate := stat.Date.Format("2006-12-30") + statdate := stat.Date.Format("2006-01-02") if !ArrayContains(allDates, statdate) { newDaily = append(newDaily, stat) allDates = append(allDates, statdate) @@ -4807,6 +4807,36 @@ func GetOrgByCreatorId(ctx context.Context, id string) (*Org, error) { return curOrg, nil } +var defaultAlertThresholdPercentages = []int{50, 75, 90, 100} + +func addDefaultAlertThresholds(org *Org) bool { + if org.Billing.DefaultAlertsApplied { + return false + } + + limit := org.SyncFeatures.AppExecutions.Limit + if limit <= 0 { + return false + } + + existingPercentages := map[int]bool{} + for _, threshold := range org.Billing.AlertThreshold { + existingPercentages[threshold.Percentage] = true + } + + for _, percentage := range defaultAlertThresholdPercentages { + if !existingPercentages[percentage] { + org.Billing.AlertThreshold = append(org.Billing.AlertThreshold, AlertThreshold{ + Percentage: percentage, + Count: int(float64(percentage) / 100 * float64(limit)), + }) + } + } + + org.Billing.DefaultAlertsApplied = true + return true +} + // ListBooks returns a list of books, ordered by title. // Handles org grabbing and user / org migrations func GetOrg(ctx context.Context, id string) (*Org, error) { @@ -4843,6 +4873,14 @@ func GetOrg(ctx context.Context, id string) (*Org, error) { if curOrg.Id == "" { return curOrg, errors.New("Org doesn't exist") } else { + billingBackup := curOrg.Billing + if addDefaultAlertThresholds(curOrg) { + err := SetOrg(ctx, *curOrg, curOrg.Id) + if err != nil { + log.Printf("[ERROR] Failed persisting default alert thresholds for org %s: %s", curOrg.Id, err) + curOrg.Billing = billingBackup + } + } return curOrg, nil } } @@ -4995,6 +5033,14 @@ func GetOrg(ctx context.Context, id string) (*Org, error) { } curOrg.Priorities = newPriorities + billingBackup := curOrg.Billing + if addDefaultAlertThresholds(curOrg) { + err := SetOrg(ctx, *curOrg, curOrg.Id) + if err != nil { + log.Printf("[ERROR] Failed persisting default alert thresholds for org %s: %s", curOrg.Id, err) + curOrg.Billing = billingBackup + } + } if project.CacheDb { neworg, err := json.Marshal(curOrg) if err != nil { diff --git a/stats.go b/stats.go index 7a84a62c..e8d6876a 100755 --- a/stats.go +++ b/stats.go @@ -850,7 +850,7 @@ func HandleGetStatistics(resp http.ResponseWriter, request *http.Request) { } } - stats := handleGetCorrectedStats(info) + stats := GetCorrectedStats(info) newjson, err := json.Marshal(stats) if err != nil { @@ -865,7 +865,7 @@ func HandleGetStatistics(resp http.ResponseWriter, request *http.Request) { } // Make sure that we are not calling SetOrgStatistics function after calling this function. This will increase the app runs count in db on every call to this function. -func handleGetCorrectedStats(info *ExecutionInfo) *ExecutionInfo { +func GetCorrectedStats(info *ExecutionInfo) *ExecutionInfo { // 1 Million Input Tokens = 250 app runs // 1 Million Output Tokens = 1500 app runs diff --git a/structs.go b/structs.go index 64a9ce2a..9a611b99 100755 --- a/structs.go +++ b/structs.go @@ -1178,6 +1178,7 @@ type Billing struct { AlertThreshold []AlertThreshold `json:"AlertThreshold" datastore:"AlertThreshold"` Consultation Consultation `json:"Consultation" datastore:"Consultation"` InternalAppRunsHardLimit int64 `json:"internal_app_runs_hard_limit" datastore:"internal_app_runs_hard_limit"` + DefaultAlertsApplied bool `json:"default_alerts_applied" datastore:"default_alerts_applied"` } type AlertThreshold struct {