usage_alerts.go raw

   1  package alerting
   2  
   3  import (
   4  	"encoding/json"
   5  	"fmt"
   6  )
   7  
   8  // ValidationError creates a formatted validation error
   9  func ValidationError(msg string) error {
  10  	return fmt.Errorf("validation error: %s", msg)
  11  }
  12  
  13  // AlertTypeAccount is the alert type for account-scoped alerts
  14  const AlertTypeAccount = "account"
  15  
  16  // UsageSubtypes defines all supported usage alert subtypes
  17  var UsageSubtypes = struct {
  18  	QueryUsage       string
  19  	RecordUsage      string
  20  	ChinaQueryUsage  string
  21  	RumDecisionUsage string
  22  	FilterChainUsage string
  23  	MonitorUsage     string
  24  }{
  25  	QueryUsage:       "query_usage",
  26  	RecordUsage:      "record_usage",
  27  	ChinaQueryUsage:  "china_query_usage",
  28  	RumDecisionUsage: "rum_decision_usage",
  29  	FilterChainUsage: "filter_chain_usage",
  30  	MonitorUsage:     "monitor_usage",
  31  }
  32  
  33  // AllowedUsageSubtypes is a map of valid usage alert subtypes
  34  var AllowedUsageSubtypes = map[string]bool{
  35  	UsageSubtypes.QueryUsage:       true,
  36  	UsageSubtypes.RecordUsage:      true,
  37  	UsageSubtypes.ChinaQueryUsage:  true,
  38  	UsageSubtypes.RumDecisionUsage: true,
  39  	UsageSubtypes.FilterChainUsage: true,
  40  	UsageSubtypes.MonitorUsage:     true,
  41  }
  42  
  43  // UsageAlertData contains the threshold percentage for usage alerts
  44  type UsageAlertData struct {
  45  	AlertAtPercent int `json:"alert_at_percent"`
  46  }
  47  
  48  // NewUsageAlert creates a new account usage alert
  49  func NewUsageAlert(name string, subtype string, alertAtPercent int, notifierListIds []string) *Alert {
  50  	accountType := AlertTypeAccount
  51  	return &Alert{
  52  		Name:            &name,
  53  		Type:            &accountType,
  54  		Subtype:         &subtype,
  55  		Data:            MarshalUsageAlertData(UsageAlertData{AlertAtPercent: alertAtPercent}),
  56  		NotifierListIds: notifierListIds,
  57  		ZoneNames:       []string{},
  58  	}
  59  }
  60  
  61  // MarshalUsageAlertData converts UsageAlertData to JSON for the Alert.Data field
  62  func MarshalUsageAlertData(data UsageAlertData) json.RawMessage {
  63  	jsonData, _ := json.Marshal(data)
  64  	return jsonData
  65  }
  66  
  67  // UnmarshalUsageAlertData extracts UsageAlertData from an Alert
  68  func UnmarshalUsageAlertData(alert *Alert) (UsageAlertData, error) {
  69  	if alert.Data == nil {
  70  		return UsageAlertData{}, fmt.Errorf("alert data is nil")
  71  	}
  72  
  73  	var data UsageAlertData
  74  	err := json.Unmarshal(alert.Data, &data)
  75  	return data, err
  76  }
  77  
  78  // ValidateUsageAlert validates a usage alert configuration
  79  func ValidateUsageAlert(alert *Alert) error {
  80  	if alert.Type == nil || *alert.Type != AlertTypeAccount {
  81  		return fmt.Errorf("type must be 'account'")
  82  	}
  83  
  84  	if alert.Subtype == nil {
  85  		return fmt.Errorf("subtype is required")
  86  	}
  87  
  88  	if _, ok := AllowedUsageSubtypes[*alert.Subtype]; !ok {
  89  		return fmt.Errorf("invalid subtype %q", *alert.Subtype)
  90  	}
  91  
  92  	data, err := UnmarshalUsageAlertData(alert)
  93  	if err != nil {
  94  		return fmt.Errorf("invalid data format: %v", err)
  95  	}
  96  
  97  	if data.AlertAtPercent < 1 || data.AlertAtPercent > 100 {
  98  		return fmt.Errorf("data.alert_at_percent must be between 1 and 100")
  99  	}
 100  
 101  	if alert.Name == nil || *alert.Name == "" {
 102  		return fmt.Errorf("name is required")
 103  	}
 104  
 105  	return nil
 106  }
 107