如何对最近24小时的时间戳按小时分组并统计日志总数与成功数?
Solution for Hourly Log Aggregation Over the Last 24 Hours
Got it, let's break down how to solve this efficiently given your sorted log slice. Here's a step-by-step implementation that handles old logs, ensures you get exactly 24 hourly buckets (even with zero logs), and leverages the sorted nature of your slice for performance.
First, let's define a struct to hold our hourly stats (this will make it easy to serialize for your chart later):
// HourlyStats represents the aggregated data for a single hour type HourlyStats struct { Hour time.Time `json:"hour"` // The start time of the hour interval TotalLogs int `json:"total"` // Total logs in the hour SuccessLogs int `json:"success"` // Number of successful logs in the hour }
Next, the core logic to generate the stats:
func GenerateHourlyStats(logs []Log) []HourlyStats { now := time.Now() // Calculate the start time of the first hour bucket (24 hours ago, truncated to the hour) firstHour := now.Add(-24 * time.Hour).Truncate(time.Hour) // Initialize 24 empty stats buckets (one for each hour in the last 24) stats := make([]HourlyStats, 24) for i := 0; i < 24; i++ { stats[i] = HourlyStats{ Hour: firstHour.Add(time.Duration(i) * time.Hour), } } // Iterate through logs (leverage sorted order to optimize) for _, log := range logs { // Skip logs older than 24 hours if log.Timestamp.Before(firstHour) { continue } // Since logs are sorted ascending, we can break early if we hit future logs if log.Timestamp.After(now) { break } // Calculate which hour bucket this log belongs to hourOffset := int(log.Timestamp.Sub(firstHour) / time.Hour) // Ensure we only count logs within our 24-hour window if hourOffset < 24 { stats[hourOffset].TotalLogs++ if log.Success { stats[hourOffset].SuccessLogs++ } } } return stats }
Key Details & Optimizations:
- Sorted Slice Advantage: Since your logs are already in ascending order, we can skip old logs quickly and even break early if we encounter logs from the future (though that's unlikely if your logs are generated in real-time).
- Guaranteed 24 Buckets: We initialize all 24 hour buckets upfront, so even hours with no logs will show
TotalLogs: 0andSuccessLogs: 0—perfect for your chart that needs exactly 24 bars. - Efficient Time Grouping: Using
Truncate(time.Hour)ensures we align each bucket to the top of the hour, and calculating thehourOffsetlets us map each log directly to its bucket with simple arithmetic. - Handling Edge Cases: Logs that fall exactly on the hour boundary are correctly grouped, and any logs outside the 24-hour window are ignored completely.
Example Usage:
// Sample logs slice (sorted ascending) logs := []Log{ {Success: true, Latency: 100, Timestamp: time.Now().Add(-23*time.Hour - 30*time.Minute)}, {Success: false, Latency: 200, Timestamp: time.Now().Add(-1*time.Hour - 15*time.Minute)}, // ... more logs } stats := GenerateHourlyStats(logs) // stats will have 24 entries, each with the hour start time and aggregated counts
This implementation is lightweight (even with 4000 logs, it's a single pass) and aligns perfectly with your use case for generating a 24-hour chart.
内容的提问来源于stack exchange,提问作者jz22
相关产品推荐
相关产品推荐

