feat: implement V2 alert center and scoped alert governance
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kra/internal/biz/business"
|
||||
"kra/internal/service/dto"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AlertGovernanceUsecase interface {
|
||||
Candidates(context.Context, string, int) ([]*business.AlertChannelOption, error)
|
||||
Gap(context.Context) (*business.AlertGap, error)
|
||||
SaveGap(context.Context, bool, int) error
|
||||
List(context.Context, business.AlertExemptionFilter, ...business.ListOption) ([]*business.AlertExemption, int64, error)
|
||||
Add(context.Context, business.ChannelKey, string) error
|
||||
Remove(context.Context, uint64) error
|
||||
}
|
||||
|
||||
func (s *AlertGovernanceService) Candidates(ctx context.Context, keyword string) ([]*dto.AlertChannelOption, error) {
|
||||
if len([]rune(keyword)) > 100 {
|
||||
return nil, business.ErrAlertRecordInput
|
||||
}
|
||||
rows, err := s.uc.Candidates(ctx, keyword, 30)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]*dto.AlertChannelOption, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
result = append(result, &dto.AlertChannelOption{ID: row.ID, SourceDB: row.SourceDB, Account: row.Name})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type AlertGovernanceService struct{ uc AlertGovernanceUsecase }
|
||||
|
||||
func NewAlertGovernanceService(uc *business.AlertGovernanceUsecase) *AlertGovernanceService {
|
||||
return &AlertGovernanceService{uc}
|
||||
}
|
||||
func (s *AlertGovernanceService) Gap(ctx context.Context) (*dto.AlertGapRequest, error) {
|
||||
v, err := s.uc.Gap(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.AlertGapRequest{Enabled: v.Enabled, Days: v.Days}, nil
|
||||
}
|
||||
func (s *AlertGovernanceService) SaveGap(ctx context.Context, req *dto.AlertGapRequest) error {
|
||||
if req == nil || req.Days < 1 || req.Days > 2147483647 {
|
||||
return business.ErrAlertRuleInput
|
||||
}
|
||||
return s.uc.SaveGap(ctx, req.Enabled, req.Days)
|
||||
}
|
||||
func (s *AlertGovernanceService) List(ctx context.Context, req *dto.AlertExemptionQuery) (*dto.AlertExemptionPage, error) {
|
||||
if req == nil {
|
||||
return nil, business.ErrAlertRecordInput
|
||||
}
|
||||
page, size := max(req.Page, 1), req.PageSize
|
||||
if size < 1 {
|
||||
size = 10
|
||||
}
|
||||
size = min(size, 500)
|
||||
if page > int(^uint(0)>>1)/size {
|
||||
return nil, business.ErrAlertRecordInput
|
||||
}
|
||||
rows, total, err := s.uc.List(ctx, business.AlertExemptionFilter{Name: strings.TrimSpace(req.Name), Active: req.Active}, business.ListOffset((page-1)*size), business.ListLimit(size))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := &dto.AlertExemptionPage{Total: total, Rows: make([]*dto.AlertExemptionResponse, 0, len(rows))}
|
||||
for _, r := range rows {
|
||||
out.Rows = append(out.Rows, &dto.AlertExemptionResponse{ID: r.ID, SourceDB: r.SourceDB, PromoteID: r.ChannelKey.ID, ChannelName: r.ChannelName, AddedName: r.AddedName, AddedAt: localTime(&r.AddedAt), Reason: r.Reason, Active: r.RemovedAt == nil, RemovedName: r.RemovedName, RemovedAt: localTime(r.RemovedAt), RemoveReason: r.RemoveReason})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
func (s *AlertGovernanceService) Add(ctx context.Context, req *dto.AlertExemptionRequest) error {
|
||||
if req == nil || len([]rune(req.Reason)) > 500 {
|
||||
return business.ErrAlertRecordInput
|
||||
}
|
||||
id, err := strconv.ParseUint(req.PromoteID.String(), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
return business.ErrAlertRecordInput
|
||||
}
|
||||
return s.uc.Add(ctx, business.ChannelKey{SourceDB: req.SourceDB, ID: id}, req.Reason)
|
||||
}
|
||||
func (s *AlertGovernanceService) Remove(ctx context.Context, id uint64) error {
|
||||
if id == 0 {
|
||||
return business.ErrAlertRecordInput
|
||||
}
|
||||
return s.uc.Remove(ctx, id)
|
||||
}
|
||||
|
||||
func (s *AlertRecordService) Ignore(ctx context.Context, req *dto.AlertIgnoreRequest) error {
|
||||
if req == nil || len(req.IDs) == 0 || len(req.IDs) > 500 {
|
||||
return business.ErrAlertRecordInput
|
||||
}
|
||||
ids := make([]uint64, 0, len(req.IDs))
|
||||
seen := map[uint64]bool{}
|
||||
for _, n := range req.IDs {
|
||||
id, err := strconv.ParseUint(n.String(), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
return business.ErrAlertRecordInput
|
||||
}
|
||||
if !seen[id] {
|
||||
ids = append(ids, id)
|
||||
seen[id] = true
|
||||
}
|
||||
}
|
||||
return s.uc.Ignore(ctx, ids)
|
||||
}
|
||||
@@ -11,12 +11,18 @@ import (
|
||||
)
|
||||
|
||||
type AlertRecordUsecase interface {
|
||||
Platforms(context.Context) ([]string, error)
|
||||
Ignore(context.Context, []uint64) error
|
||||
List(context.Context, business.AlertRecordFilter, ...business.ListOption) (*business.AlertRecordPage, error)
|
||||
Detail(context.Context, uint64) (*business.AlertRecordDetail, error)
|
||||
Process(context.Context, uint64, business.AlertAction, string) error
|
||||
AddNote(context.Context, uint64, string, []string) error
|
||||
}
|
||||
|
||||
func (s *AlertRecordService) Platforms(ctx context.Context) ([]string, error) {
|
||||
return s.uc.Platforms(ctx)
|
||||
}
|
||||
|
||||
type AlertRecordService struct{ uc AlertRecordUsecase }
|
||||
|
||||
func NewAlertRecordService(uc *business.AlertRecordUsecase) *AlertRecordService {
|
||||
@@ -28,7 +34,7 @@ func alertRecordResponse(r *business.AlertRecord) *dto.AlertRecordResponse {
|
||||
if r.MonitorMetric != nil {
|
||||
metricLabel = business.AlertMetricLabel(*r.MonitorMetric)
|
||||
}
|
||||
return &dto.AlertRecordResponse{ID: r.ID, RuleID: r.RuleID, PlatformCode: r.PlatformCode, PlatformName: r.PlatformName, RuleName: r.RuleName, RuleType: r.RuleType, RuleTypeLabel: business.AlertRuleTypeLabel(r.RuleType), MonitorMetric: r.MonitorMetric, MonitorMetricLabel: metricLabel, TargetPromoteID: r.TargetPromoteID, TargetPromoteName: r.TargetPromoteName, BusinessID: r.BusinessID, BusinessName: r.BusinessName, AlertContent: r.AlertContent, Status: r.Status, StatusLabel: business.AlertStatusLabel(r.Status), CreatedAt: localTime(&r.CreatedAt), UpdatedAt: localTime(&r.UpdatedAt)}
|
||||
return &dto.AlertRecordResponse{ID: r.ID, TotalPlayers: r.TotalPlayers, TotalPay: r.TotalPay, WarningColor: r.WarningColor, Lost: r.Lost, RuleID: r.RuleID, PlatformCode: r.PlatformCode, PlatformName: r.PlatformName, RuleName: r.RuleName, RuleType: r.RuleType, RuleTypeLabel: business.AlertRuleTypeLabel(r.RuleType), MonitorMetric: r.MonitorMetric, MonitorMetricLabel: metricLabel, TargetPromoteID: r.TargetPromoteID, TargetPromoteName: r.TargetPromoteName, BusinessID: r.BusinessID, BusinessName: r.BusinessName, AlertContent: r.AlertContent, Status: r.Status, StatusLabel: business.AlertStatusLabel(r.Status), CreatedAt: localTime(&r.CreatedAt), UpdatedAt: localTime(&r.UpdatedAt)}
|
||||
}
|
||||
|
||||
func (s *AlertRecordService) List(ctx context.Context, req *dto.AlertRecordQuery) (*dto.AlertRecordPage, error) {
|
||||
@@ -41,7 +47,7 @@ func (s *AlertRecordService) List(ctx context.Context, req *dto.AlertRecordQuery
|
||||
if req.MonitorMetric != nil && (*req.MonitorMetric < 1 || *req.MonitorMetric > 3) {
|
||||
return nil, business.ErrAlertRecordInput
|
||||
}
|
||||
if req.Status != nil && (*req.Status < 1 || *req.Status > 5) {
|
||||
if req.Status != nil && (*req.Status < 1 || *req.Status > 6) {
|
||||
return nil, business.ErrAlertRecordInput
|
||||
}
|
||||
page, size := req.Page, req.PageSize
|
||||
@@ -57,7 +63,7 @@ func (s *AlertRecordService) List(ctx context.Context, req *dto.AlertRecordQuery
|
||||
if page > int(^uint(0)>>1)/size {
|
||||
return nil, business.ErrAlertRecordInput
|
||||
}
|
||||
filter := business.AlertRecordFilter{TargetPromoteID: req.TargetPromoteID, BusinessID: req.BusinessID, TargetPromoteName: strings.TrimSpace(req.TargetPromoteName), RuleName: strings.TrimSpace(req.RuleName), RuleType: strings.TrimSpace(req.RuleType), BusinessName: strings.TrimSpace(req.BusinessName), MonitorMetric: req.MonitorMetric, Status: req.Status}
|
||||
filter := business.AlertRecordFilter{AlertContent: strings.TrimSpace(req.AlertContent), Lost: req.Lost, TargetPromoteID: req.TargetPromoteID, BusinessID: req.BusinessID, TargetPromoteName: strings.TrimSpace(req.TargetPromoteName), RuleName: strings.TrimSpace(req.RuleName), RuleType: strings.TrimSpace(req.RuleType), BusinessName: strings.TrimSpace(req.BusinessName), MonitorMetric: req.MonitorMetric, Status: req.Status}
|
||||
seen := map[string]bool{}
|
||||
filter.PlatformBusierID = req.PlatformBusierID
|
||||
for _, code := range strings.Split(req.PlatformCodes, ",") {
|
||||
|
||||
@@ -30,13 +30,13 @@ func alertRuleResponse(r *business.AlertRule) *dto.AlertRuleResponse {
|
||||
n := json.Number(*r.MomThreshold)
|
||||
threshold = &n
|
||||
}
|
||||
return &dto.AlertRuleResponse{ID: r.ID, RuleName: r.Name, RuleType: r.Type, RuleTypeLabel: business.AlertRuleTypeLabel(r.Type), MonitorMetric: r.Metric, MonitorMetricLabel: business.AlertMetricLabel(r.Metric), StatPeriodDays: r.StatPeriodDays, MomDirection: r.MomDirection, MomDirectionLabel: business.AlertDirectionLabel(r.MomDirection), MomThreshold: threshold, UnloginDays: r.UnloginDays, MonitorScope: r.MonitorScope, WarningColor: r.WarningColor, CreatorID: r.CreatorID, CreatorName: r.CreatorName, Enabled: r.Enabled, CreatedAt: localTime(&r.CreatedAt), UpdatedAt: localTime(&r.UpdatedAt), RuleDescription: r.Description()}
|
||||
return &dto.AlertRuleResponse{ID: r.ID, ConditionMode: r.ConditionMode, AmountDirection: r.AmountDirection, AmountThreshold: r.AmountThreshold, RuleName: r.Name, RuleType: r.Type, RuleTypeLabel: business.AlertRuleTypeLabel(r.Type), MonitorMetric: r.Metric, MonitorMetricLabel: business.AlertMetricLabel(r.Metric), StatPeriodDays: r.StatPeriodDays, MomDirection: r.MomDirection, MomDirectionLabel: business.AlertDirectionLabel(r.MomDirection), MomThreshold: threshold, UnloginDays: r.UnloginDays, MonitorScope: r.MonitorScope, WarningColor: r.WarningColor, CreatorID: r.CreatorID, CreatorName: r.CreatorName, Enabled: r.Enabled, CreatedAt: localTime(&r.CreatedAt), UpdatedAt: localTime(&r.UpdatedAt), RuleDescription: r.Description()}
|
||||
}
|
||||
func (s *AlertRuleService) List(ctx context.Context, req *dto.AlertRuleQuery) (*dto.AlertRulePage, error) {
|
||||
if req == nil {
|
||||
return nil, business.ErrAlertRuleInput
|
||||
}
|
||||
filter := business.AlertRuleFilter{Name: req.RuleName, Type: req.RuleType}
|
||||
filter := business.AlertRuleFilter{Name: strings.TrimSpace(req.RuleName), Type: strings.TrimSpace(req.RuleType)}
|
||||
if req.MonitorMetric != "" {
|
||||
n, err := strconv.Atoi(req.MonitorMetric)
|
||||
if err != nil || n < 1 || n > 3 {
|
||||
@@ -87,11 +87,23 @@ func (s *AlertRuleService) Save(ctx context.Context, req *dto.AlertRuleRequest)
|
||||
return 0, business.ErrAlertRuleInput
|
||||
}
|
||||
}
|
||||
rule := &business.AlertRule{ID: req.ID, Name: req.RuleName, Type: req.RuleType, Metric: req.MonitorMetric, StatPeriodDays: req.StatPeriodDays, MomDirection: req.MomDirection, UnloginDays: req.UnloginDays, WarningColor: req.WarningColor}
|
||||
var id uint64
|
||||
if req.ID != "" {
|
||||
var err error
|
||||
id, err = strconv.ParseUint(req.ID.String(), 10, 64)
|
||||
if err != nil {
|
||||
return 0, business.ErrAlertRuleInput
|
||||
}
|
||||
}
|
||||
rule := &business.AlertRule{ID: id, ConditionMode: req.ConditionMode, AmountDirection: req.AmountDirection, Name: strings.TrimSpace(req.RuleName), Type: req.RuleType, Metric: req.MonitorMetric, StatPeriodDays: req.StatPeriodDays, MomDirection: req.MomDirection, UnloginDays: req.UnloginDays, WarningColor: strings.TrimSpace(req.WarningColor)}
|
||||
if req.MomThreshold != nil {
|
||||
value := req.MomThreshold.String()
|
||||
rule.MomThreshold = &value
|
||||
}
|
||||
if req.AmountThreshold != nil {
|
||||
value := req.AmountThreshold.String()
|
||||
rule.AmountThreshold = &value
|
||||
}
|
||||
return s.uc.Save(ctx, rule)
|
||||
}
|
||||
func (s *AlertRuleService) Delete(ctx context.Context, id uint64) error {
|
||||
|
||||
Reference in New Issue
Block a user