Files
fn-serverless/api/agent/stats.go
Nigel Deakin ac2bfd3462 Change basic stats to use opentracing rather than Prometheus API (#671)
* Change basic stats to use opentracing rather than Prometheus API directly

* Just ran gofmt

* Extract opentracing access for metrics to common/metrics.go

* Replace quotes strings with constants where possible
2018-01-11 17:34:51 +00:00

167 lines
3.7 KiB
Go

package agent
import (
"context"
"github.com/fnproject/fn/api/common"
"sync"
)
// TODO this should expose:
// * hot containers active
// * memory used / available
// global statistics
type stats struct {
mu sync.Mutex
// statistics for all functions combined
queue uint64
running uint64
complete uint64
failed uint64
// statistics for individual functions, keyed by function path
functionStatsMap map[string]*functionStats
}
// statistics for an individual function
type functionStats struct {
queue uint64
running uint64
complete uint64
failed uint64
}
// Stats hold the statistics for all functions combined
// and the statistics for each individual function
type Stats struct {
Queue uint64
Running uint64
Complete uint64
Failed uint64
// statistics for individual functions, keyed by function path
FunctionStatsMap map[string]*FunctionStats
}
// FunctionStats holds the statistics for an individual function
type FunctionStats struct {
Queue uint64
Running uint64
Complete uint64
Failed uint64
}
func (s *stats) getStatsForFunction(path string) *functionStats {
if s.functionStatsMap == nil {
s.functionStatsMap = make(map[string]*functionStats)
}
thisFunctionStats, found := s.functionStatsMap[path]
if !found {
thisFunctionStats = &functionStats{}
s.functionStatsMap[path] = thisFunctionStats
}
return thisFunctionStats
}
func (s *stats) Enqueue(ctx context.Context, app string, path string) {
s.mu.Lock()
s.queue++
s.getStatsForFunction(path).queue++
common.IncrementGauge(ctx, queuedMetricName)
common.IncrementCounter(ctx, callsMetricName)
s.mu.Unlock()
}
// Call when a function has been queued but cannot be started because of an error
func (s *stats) Dequeue(ctx context.Context, app string, path string) {
s.mu.Lock()
s.queue--
s.getStatsForFunction(path).queue--
common.DecrementGauge(ctx, queuedMetricName)
s.mu.Unlock()
}
func (s *stats) DequeueAndStart(ctx context.Context, app string, path string) {
s.mu.Lock()
s.queue--
s.getStatsForFunction(path).queue--
common.DecrementGauge(ctx, queuedMetricName)
s.running++
s.getStatsForFunction(path).running++
common.IncrementGauge(ctx, runningSuffix)
s.mu.Unlock()
}
func (s *stats) Complete(ctx context.Context, app string, path string) {
s.mu.Lock()
s.running--
s.getStatsForFunction(path).running--
common.DecrementGauge(ctx, runningSuffix)
s.complete++
s.getStatsForFunction(path).complete++
common.IncrementCounter(ctx, completedMetricName)
s.mu.Unlock()
}
func (s *stats) Failed(ctx context.Context, app string, path string) {
s.mu.Lock()
s.running--
s.getStatsForFunction(path).running--
common.DecrementGauge(ctx, runningSuffix)
s.failed++
s.getStatsForFunction(path).failed++
common.IncrementCounter(ctx, failedMetricName)
s.mu.Unlock()
}
func (s *stats) DequeueAndFail(ctx context.Context, app string, path string) {
s.mu.Lock()
s.queue--
s.getStatsForFunction(path).queue--
common.DecrementGauge(ctx, queuedMetricName)
s.failed++
s.getStatsForFunction(path).failed++
common.IncrementCounter(ctx, failedMetricName)
s.mu.Unlock()
}
func (s *stats) Stats() Stats {
var stats Stats
s.mu.Lock()
stats.Running = s.running
stats.Complete = s.complete
stats.Queue = s.queue
stats.Failed = s.failed
stats.FunctionStatsMap = make(map[string]*FunctionStats)
for key, value := range s.functionStatsMap {
thisFunctionStats := &FunctionStats{Queue: value.queue, Running: value.running, Complete: value.complete, Failed: value.failed}
stats.FunctionStatsMap[key] = thisFunctionStats
}
s.mu.Unlock()
return stats
}
const (
queuedMetricName = "queued"
callsMetricName = "calls"
runningSuffix = "running"
completedMetricName = "completed"
failedMetricName = "failed"
)