diff --git a/internal/metrics/period/entries.go b/internal/metrics/period/entries.go index d9a5554f..1c9c17e8 100644 --- a/internal/metrics/period/entries.go +++ b/internal/metrics/period/entries.go @@ -6,7 +6,7 @@ import ( ) type Entries[T any] struct { - entries [maxEntries]*T + entries [maxEntries]T index int count int interval time.Duration @@ -16,17 +16,14 @@ type Entries[T any] struct { const maxEntries = 100 func newEntries[T any](duration time.Duration) *Entries[T] { - interval := duration / maxEntries - if interval < time.Second { - interval = time.Second - } + interval := max(duration/maxEntries, time.Second) return &Entries[T]{ interval: interval, lastAdd: time.Now(), } } -func (e *Entries[T]) Add(now time.Time, info *T) { +func (e *Entries[T]) Add(now time.Time, info T) { if now.Sub(e.lastAdd) < e.interval { return } @@ -38,11 +35,11 @@ func (e *Entries[T]) Add(now time.Time, info *T) { e.lastAdd = now } -func (e *Entries[T]) Get() []*T { +func (e *Entries[T]) Get() []T { if e.count < maxEntries { return e.entries[:e.count] } - res := make([]*T, maxEntries) + res := make([]T, maxEntries) copy(res, e.entries[e.index:]) copy(res[maxEntries-e.index:], e.entries[:e.index]) return res @@ -57,7 +54,7 @@ func (e *Entries[T]) MarshalJSON() ([]byte, error) { func (e *Entries[T]) UnmarshalJSON(data []byte) error { var v struct { - Entries []*T `json:"entries"` + Entries []T `json:"entries"` Interval time.Duration `json:"interval"` } if err := json.Unmarshal(data, &v); err != nil { diff --git a/internal/metrics/period/handler.go b/internal/metrics/period/handler.go index 23f8066f..4dc091c9 100644 --- a/internal/metrics/period/handler.go +++ b/internal/metrics/period/handler.go @@ -3,6 +3,7 @@ package period import ( "errors" "net/http" + "net/url" "time" "github.com/gin-gonic/gin" @@ -29,6 +30,7 @@ type ResponseType[AggregateT any] struct { // // If the request is a websocket request, it serves the data for the given period for every interval. func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) { + period := Filter(c.Query("period")) query := c.Request.URL.Query() if httpheaders.IsWebsocket(c.Request.Header) { @@ -42,10 +44,10 @@ func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) { interval = minInterval } websocket.PeriodicWrite(c, interval, func() (any, error) { - return p.getRespData(c.Request) + return p.getRespData(period, query) }) } else { - data, err := p.getRespData(c.Request) + data, err := p.getRespData(period, query) if err != nil { c.Error(apitypes.InternalServerError(err, "failed to get response data")) return @@ -58,13 +60,11 @@ func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) { } } -func (p *Poller[T, AggregateT]) getRespData(r *http.Request) (any, error) { - query := r.URL.Query() - period := query.Get("period") +func (p *Poller[T, AggregateT]) getRespData(period Filter, query url.Values) (any, error) { if period == "" { return p.GetLastResult(), nil } - rangeData, ok := p.Get(Filter(period)) + rangeData, ok := p.Get(period) if !ok { return nil, errors.New("invalid period") } diff --git a/internal/metrics/period/period.go b/internal/metrics/period/period.go index 601a6df2..3800ff4b 100644 --- a/internal/metrics/period/period.go +++ b/internal/metrics/period/period.go @@ -32,7 +32,7 @@ func NewPeriod[T any]() *Period[T] { } } -func (p *Period[T]) Add(info *T) { +func (p *Period[T]) Add(info T) { p.mu.Lock() defer p.mu.Unlock() now := time.Now() @@ -41,7 +41,7 @@ func (p *Period[T]) Add(info *T) { } } -func (p *Period[T]) Get(filter Filter) ([]*T, bool) { +func (p *Period[T]) Get(filter Filter) ([]T, bool) { p.mu.RLock() defer p.mu.RUnlock() period, ok := p.Entries[filter] diff --git a/internal/metrics/period/poller.go b/internal/metrics/period/poller.go index b881a6ca..95f6be5b 100644 --- a/internal/metrics/period/poller.go +++ b/internal/metrics/period/poller.go @@ -17,16 +17,16 @@ import ( ) type ( - PollFunc[T any] func(ctx context.Context, lastResult *T) (*T, error) - AggregateFunc[T any, AggregateT json.Marshaler] func(entries []*T, query url.Values) (total int, result AggregateT) - FilterFunc[T any] func(entries []*T, keyword string) (filtered []*T) + PollFunc[T any] func(ctx context.Context, lastResult T) (T, error) + AggregateFunc[T any, AggregateT json.Marshaler] func(entries []T, query url.Values) (total int, result AggregateT) + FilterFunc[T any] func(entries []T, keyword string) (filtered []T) Poller[T any, AggregateT json.Marshaler] struct { name string poll PollFunc[T] aggregate AggregateFunc[T, AggregateT] resultFilter FilterFunc[T] period *Period[T] - lastResult atomic.Value[*T] + lastResult atomic.Value[T] errs []pollErr } pollErr struct { @@ -188,10 +188,10 @@ func (p *Poller[T, AggregateT]) Start() { }() } -func (p *Poller[T, AggregateT]) Get(filter Filter) ([]*T, bool) { +func (p *Poller[T, AggregateT]) Get(filter Filter) ([]T, bool) { return p.period.Get(filter) } -func (p *Poller[T, AggregateT]) GetLastResult() *T { +func (p *Poller[T, AggregateT]) GetLastResult() T { return p.lastResult.Load() }