GetStatistics 获取统计信息
(ctx context.Context, filters *AuditFilters)
| 681 | |
| 682 | // GetStatistics 获取统计信息 |
| 683 | func (al *InMemoryAuditLog) GetStatistics(ctx context.Context, filters *AuditFilters) (*AuditStatistics, error) { |
| 684 | al.mu.RLock() |
| 685 | defer al.mu.RUnlock() |
| 686 | |
| 687 | stats := &AuditStatistics{ |
| 688 | TimeRange: TimeRange{Start: time.Now(), End: time.Now()}, |
| 689 | EventsByType: make(map[AuditType]int64), |
| 690 | EventsByUser: make(map[string]int64), |
| 691 | EventsByHour: make(map[int]int64), |
| 692 | EventsByDay: make(map[string]int64), |
| 693 | GeneratedAt: time.Now(), |
| 694 | } |
| 695 | |
| 696 | var timeRange *TimeRange |
| 697 | if filters != nil && filters.TimeRange != nil { |
| 698 | timeRange = filters.TimeRange |
| 699 | stats.TimeRange = *timeRange |
| 700 | } |
| 701 | |
| 702 | totalEvents := int64(0) |
| 703 | for i := range al.events { |
| 704 | event := &al.events[i] |
| 705 | |
| 706 | // 应用时间过滤 |
| 707 | if timeRange != nil { |
| 708 | if event.Timestamp.Before(timeRange.Start) || event.Timestamp.After(timeRange.End) { |
| 709 | continue |
| 710 | } |
| 711 | } |
| 712 | |
| 713 | // 应用其他过滤条件 |
| 714 | if filters != nil { |
| 715 | if len(filters.Types) > 0 && !containsAuditType(filters.Types, event.Type) { |
| 716 | continue |
| 717 | } |
| 718 | if len(filters.Users) > 0 && !containsString(filters.Users, event.UserID) { |
| 719 | continue |
| 720 | } |
| 721 | } |
| 722 | |
| 723 | totalEvents++ |
| 724 | stats.EventsByType[event.Type]++ |
| 725 | stats.EventsByUser[event.UserID]++ |
| 726 | |
| 727 | // 小时统计 |
| 728 | hour := event.Timestamp.Hour() |
| 729 | stats.EventsByHour[hour]++ |
| 730 | |
| 731 | // 日期统计 |
| 732 | day := event.Timestamp.Format("2006-01-02") |
| 733 | stats.EventsByDay[day]++ |
| 734 | } |
| 735 | |
| 736 | stats.TotalEvents = totalEvents |
| 737 | |
| 738 | return stats, nil |
| 739 | } |
| 740 |
nothing calls this directly
no test coverage detected