ops_repo_histograms.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package repository
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "github.com/Wei-Shaw/sub2api/internal/service"
  7. )
  8. func (r *opsRepository) GetLatencyHistogram(ctx context.Context, filter *service.OpsDashboardFilter) (*service.OpsLatencyHistogramResponse, error) {
  9. if r == nil || r.db == nil {
  10. return nil, fmt.Errorf("nil ops repository")
  11. }
  12. if filter == nil {
  13. return nil, fmt.Errorf("nil filter")
  14. }
  15. if filter.StartTime.IsZero() || filter.EndTime.IsZero() {
  16. return nil, fmt.Errorf("start_time/end_time required")
  17. }
  18. start := filter.StartTime.UTC()
  19. end := filter.EndTime.UTC()
  20. join, where, args, _ := buildUsageWhere(filter, start, end, 1)
  21. rangeExpr := latencyHistogramRangeCaseExpr("ul.duration_ms")
  22. orderExpr := latencyHistogramRangeOrderCaseExpr("ul.duration_ms")
  23. q := `
  24. SELECT
  25. ` + rangeExpr + ` AS range,
  26. COALESCE(COUNT(*), 0) AS count,
  27. ` + orderExpr + ` AS ord
  28. FROM usage_logs ul
  29. ` + join + `
  30. ` + where + `
  31. AND ul.duration_ms IS NOT NULL
  32. GROUP BY 1, 3
  33. ORDER BY 3 ASC`
  34. rows, err := r.db.QueryContext(ctx, q, args...)
  35. if err != nil {
  36. return nil, err
  37. }
  38. defer func() { _ = rows.Close() }()
  39. counts := make(map[string]int64, len(latencyHistogramOrderedRanges))
  40. var total int64
  41. for rows.Next() {
  42. var label string
  43. var count int64
  44. var _ord int
  45. if err := rows.Scan(&label, &count, &_ord); err != nil {
  46. return nil, err
  47. }
  48. counts[label] = count
  49. total += count
  50. }
  51. if err := rows.Err(); err != nil {
  52. return nil, err
  53. }
  54. buckets := make([]*service.OpsLatencyHistogramBucket, 0, len(latencyHistogramOrderedRanges))
  55. for _, label := range latencyHistogramOrderedRanges {
  56. buckets = append(buckets, &service.OpsLatencyHistogramBucket{
  57. Range: label,
  58. Count: counts[label],
  59. })
  60. }
  61. return &service.OpsLatencyHistogramResponse{
  62. StartTime: start,
  63. EndTime: end,
  64. Platform: strings.TrimSpace(filter.Platform),
  65. GroupID: filter.GroupID,
  66. TotalRequests: total,
  67. Buckets: buckets,
  68. }, nil
  69. }