mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-20 23:46:23 +01:00
73 lines
1.8 KiB
Go
73 lines
1.8 KiB
Go
|
package tenantmetrics
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sync/atomic"
|
||
|
|
||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/auth"
|
||
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||
|
"github.com/VictoriaMetrics/metrics"
|
||
|
)
|
||
|
|
||
|
// TenantID defines metric tenant.
|
||
|
type TenantID struct {
|
||
|
AccountID uint32
|
||
|
ProjectID uint32
|
||
|
}
|
||
|
|
||
|
// CounterMap is a map of counters keyed by tenant.
|
||
|
type CounterMap struct {
|
||
|
metric string
|
||
|
m atomic.Value
|
||
|
}
|
||
|
|
||
|
// NewCounterMap creates new CounterMap for the given metric.
|
||
|
func NewCounterMap(metric string) *CounterMap {
|
||
|
cm := &CounterMap{
|
||
|
metric: metric,
|
||
|
}
|
||
|
cm.m.Store(make(map[TenantID]*metrics.Counter))
|
||
|
return cm
|
||
|
}
|
||
|
|
||
|
// Get returns counter for the given at
|
||
|
func (cm *CounterMap) Get(at *auth.Token) *metrics.Counter {
|
||
|
key := TenantID{
|
||
|
AccountID: at.AccountID,
|
||
|
ProjectID: at.ProjectID,
|
||
|
}
|
||
|
return cm.GetByTenant(key)
|
||
|
}
|
||
|
|
||
|
// GetByTenant returns counter for the given key.
|
||
|
func (cm *CounterMap) GetByTenant(key TenantID) *metrics.Counter {
|
||
|
m := cm.m.Load().(map[TenantID]*metrics.Counter)
|
||
|
if c := m[key]; c != nil {
|
||
|
// Fast path - the counter for k already exists.
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
// Slow path - create missing counter for k and re-create m.
|
||
|
newM := make(map[TenantID]*metrics.Counter, len(m)+1)
|
||
|
for k, c := range m {
|
||
|
newM[k] = c
|
||
|
}
|
||
|
metricName := createMetricName(cm.metric, key)
|
||
|
c := metrics.GetOrCreateCounter(metricName)
|
||
|
newM[key] = c
|
||
|
cm.m.Store(newM)
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
func createMetricName(metric string, key TenantID) string {
|
||
|
if len(metric) == 0 {
|
||
|
logger.Panicf("BUG: metric cannot be empty")
|
||
|
}
|
||
|
if metric[len(metric)-1] != '}' {
|
||
|
// Metric without labels.
|
||
|
return fmt.Sprintf(`%s{accountID="%d",projectID="%d"}`, metric, key.AccountID, key.ProjectID)
|
||
|
}
|
||
|
// Metric with labels.
|
||
|
return fmt.Sprintf(`%s,accountID="%d",projectID="%d"}`, metric[:len(metric)-1], key.AccountID, key.ProjectID)
|
||
|
}
|