types.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package perfmetrics
  2. import "sync/atomic"
  3. type Store interface {
  4. Record(sample Sample)
  5. Query(params QueryParams) (QueryResult, error)
  6. }
  7. type Sample struct {
  8. Model string
  9. Group string
  10. LatencyMs int64
  11. TtftMs int64
  12. HasTtft bool
  13. Success bool
  14. }
  15. type QueryParams struct {
  16. Model string
  17. Group string
  18. Hours int
  19. }
  20. type BucketPoint struct {
  21. Ts int64 `json:"ts"`
  22. AvgTtftMs int64 `json:"avg_ttft_ms"`
  23. AvgLatencyMs int64 `json:"avg_latency_ms"`
  24. SuccessRate float64 `json:"success_rate"`
  25. Count int64 `json:"count"`
  26. SuccessCount int64 `json:"success_count"`
  27. TtftCount int64 `json:"ttft_count"`
  28. }
  29. type GroupResult struct {
  30. Group string `json:"group"`
  31. AvgTtftMs int64 `json:"avg_ttft_ms"`
  32. AvgLatencyMs int64 `json:"avg_latency_ms"`
  33. SuccessRate float64 `json:"success_rate"`
  34. RequestCount int64 `json:"request_count"`
  35. SuccessCount int64 `json:"success_count"`
  36. TtftCount int64 `json:"ttft_count"`
  37. Series []BucketPoint `json:"series"`
  38. }
  39. type QueryResult struct {
  40. ModelName string `json:"model_name"`
  41. SeriesSchema string `json:"series_schema"`
  42. Groups []GroupResult `json:"groups"`
  43. }
  44. type bucketKey struct {
  45. model string
  46. group string
  47. bucketTs int64
  48. }
  49. type counters struct {
  50. requestCount int64
  51. successCount int64
  52. totalLatencyMs int64
  53. ttftSumMs int64
  54. ttftCount int64
  55. }
  56. type atomicBucket struct {
  57. requestCount atomic.Int64
  58. successCount atomic.Int64
  59. totalLatencyMs atomic.Int64
  60. ttftSumMs atomic.Int64
  61. ttftCount atomic.Int64
  62. }
  63. func (b *atomicBucket) add(sample Sample) {
  64. b.requestCount.Add(1)
  65. if sample.Success {
  66. b.successCount.Add(1)
  67. }
  68. if sample.LatencyMs > 0 {
  69. b.totalLatencyMs.Add(sample.LatencyMs)
  70. }
  71. if sample.HasTtft && sample.TtftMs >= 0 {
  72. b.ttftSumMs.Add(sample.TtftMs)
  73. b.ttftCount.Add(1)
  74. }
  75. }
  76. func (b *atomicBucket) snapshot() counters {
  77. return counters{
  78. requestCount: b.requestCount.Load(),
  79. successCount: b.successCount.Load(),
  80. totalLatencyMs: b.totalLatencyMs.Load(),
  81. ttftSumMs: b.ttftSumMs.Load(),
  82. ttftCount: b.ttftCount.Load(),
  83. }
  84. }
  85. func (b *atomicBucket) drain() counters {
  86. return counters{
  87. requestCount: b.requestCount.Swap(0),
  88. successCount: b.successCount.Swap(0),
  89. totalLatencyMs: b.totalLatencyMs.Swap(0),
  90. ttftSumMs: b.ttftSumMs.Swap(0),
  91. ttftCount: b.ttftCount.Swap(0),
  92. }
  93. }
  94. func (b *atomicBucket) addCounters(c counters) {
  95. if c.requestCount != 0 {
  96. b.requestCount.Add(c.requestCount)
  97. }
  98. if c.successCount != 0 {
  99. b.successCount.Add(c.successCount)
  100. }
  101. if c.totalLatencyMs != 0 {
  102. b.totalLatencyMs.Add(c.totalLatencyMs)
  103. }
  104. if c.ttftSumMs != 0 {
  105. b.ttftSumMs.Add(c.ttftSumMs)
  106. }
  107. if c.ttftCount != 0 {
  108. b.ttftCount.Add(c.ttftCount)
  109. }
  110. }