Add metrics to count the number of service-mesh config entries

This commit is contained in:
Connor Kelly 2021-10-01 13:22:30 -05:00
parent 9c487389cf
commit ed5693b537
No known key found for this signature in database
GPG Key ID: 588D34E7812BC0B7
6 changed files with 541 additions and 0 deletions

View File

@ -70,6 +70,11 @@ type KVUsage struct {
EnterpriseKVUsage
}
type ConfigUsage struct {
ConfigByKind map[string]int
EnterpriseConfigUsage
}
type uniqueServiceState int
const (
@ -117,6 +122,10 @@ func updateUsage(tx WriteTxn, changes Changes) error {
case "kvs":
usageDeltas[change.Table] += delta
addEnterpriseKVUsage(usageDeltas, change)
case tableConfigEntries:
entry := changeObject(change).(structs.ConfigEntry)
usageDeltas[entry.GetKind()] += delta
addEnterpriseConfigUsage(usageDeltas, change)
}
}
@ -360,6 +369,33 @@ func (s *Store) KVUsage() (uint64, KVUsage, error) {
return kvs.Index, results, nil
}
func (s *Store) ConfigUsage() (uint64, ConfigUsage, error) {
tx := s.db.ReadTxn()
defer tx.Abort()
configEntries := make(map[string]int)
var maxIdx uint64
for _, kind := range structs.AllConfigEntryKinds {
configEntry, err := firstUsageEntry(tx, kind)
if configEntry.Index > maxIdx {
maxIdx = configEntry.Index
}
if err != nil {
return 0, ConfigUsage{}, fmt.Errorf("failed config entry usage lookup: %s", err)
}
configEntries[kind] = configEntry.Count
}
usage := ConfigUsage{
ConfigByKind: configEntries,
}
results, err := compileEnterpriseConfigUsage(tx, usage)
if err != nil {
return 0, ConfigUsage{}, fmt.Errorf("failed config entry usage lookup: %s", err)
}
return maxIdx, results, nil
}
func firstUsageEntry(tx ReadTxn, id string) (*UsageEntry, error) {
usage, err := tx.First(tableUsage, indexID, id)
if err != nil {

View File

@ -11,6 +11,7 @@ import (
type EnterpriseServiceUsage struct{}
type EnterpriseNodeUsage struct{}
type EnterpriseKVUsage struct{}
type EnterpriseConfigUsage struct{}
func addEnterpriseNodeUsage(map[string]int, memdb.Change) {}
@ -22,6 +23,8 @@ func addEnterpriseConnectServiceInstanceUsage(map[string]int, *structs.ServiceNo
func addEnterpriseKVUsage(map[string]int, memdb.Change) {}
func addEnterpriseConfigUsage(map[string]int, memdb.Change) {}
func compileEnterpriseServiceUsage(tx ReadTxn, usage ServiceUsage) (ServiceUsage, error) {
return usage, nil
}
@ -33,3 +36,7 @@ func compileEnterpriseNodeUsage(tx ReadTxn, usage NodeUsage) (NodeUsage, error)
func compileEnterpriseKVUsage(tx ReadTxn, usage KVUsage) (KVUsage, error) {
return usage, nil
}
func compileEnterpriseConfigUsage(tx ReadTxn, usage ConfigUsage) (ConfigUsage, error) {
return usage, nil
}

View File

@ -457,3 +457,47 @@ func TestStateStore_Usage_ServiceUsage_updatingConnectProxy(t *testing.T) {
require.Equal(t, 1, usage.ConnectServiceInstances[string(structs.ServiceKindConnectProxy)])
})
}
func TestStateStore_Usage_ConfigEntries(t *testing.T) {
s := testStateStore(t)
t.Run("empty store", func(t *testing.T) {
i, usage, err := s.ConfigUsage()
require.NoError(t, err)
require.Equal(t, uint64(0), i)
for _, kind := range structs.AllConfigEntryKinds {
require.Equal(t, 0, usage.ConfigByKind[kind])
}
})
t.Run("with config entries", func(t *testing.T) {
require.NoError(t, s.EnsureConfigEntry(1, &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "web",
Protocol: "http",
}))
require.NoError(t, s.EnsureConfigEntry(2, &structs.ServiceResolverConfigEntry{
Kind: structs.ServiceResolver,
Name: "web",
DefaultSubset: "v1",
Subsets: map[string]structs.ServiceResolverSubset{
"v1": {
Filter: "Service.Meta.version == v1",
},
"v2": {
Filter: "Service.Meta.version == v2",
},
},
}))
require.NoError(t, s.EnsureConfigEntry(3, &structs.ServiceIntentionsConfigEntry{
Kind: structs.ServiceIntentions,
Name: "web",
}))
i, usage, err := s.ConfigUsage()
require.NoError(t, err)
require.Equal(t, uint64(3), i)
require.Equal(t, 1, usage.ConfigByKind[structs.ServiceDefaults])
require.Equal(t, 1, usage.ConfigByKind[structs.ServiceResolver])
require.Equal(t, 1, usage.ConfigByKind[structs.ServiceIntentions])
})
}

View File

@ -176,6 +176,12 @@ func (u *UsageMetricsReporter) runOnce() {
u.emitKVUsage(kvUsage)
_, configUsage, err := state.ConfigUsage()
if err != nil {
u.logger.Warn("failed to retrieve config usage from state store", "error", err)
}
u.emitConfigUsage(configUsage)
}
func (u *UsageMetricsReporter) memberUsage() []serf.Member {

View File

@ -74,3 +74,13 @@ func (u *UsageMetricsReporter) emitKVUsage(kvUsage state.KVUsage) {
u.metricLabels,
)
}
func (u *UsageMetricsReporter) emitConfigUsage(configUsage state.ConfigUsage) {
for k, i := range configUsage.ConfigByKind {
metrics.SetGaugeWithLabels(
[]string{"consul", "state", "config_entries"},
float32(i),
append(u.metricLabels, metrics.Label{Name: "kind", Value: k}),
)
}
}

View File

@ -104,6 +104,79 @@ func TestUsageReporter_emitNodeUsage_OSS(t *testing.T) {
Value: 0,
Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}},
},
// --- config entries ---
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-intentions"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-resolver"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-router"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "ingress-gateway"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-splitter"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "mesh"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "proxy-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "terminating-gateway"},
},
},
},
getMembersFunc: func() []serf.Member { return []serf.Member{} },
},
@ -208,6 +281,79 @@ func TestUsageReporter_emitNodeUsage_OSS(t *testing.T) {
Value: 0,
Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}},
},
// --- config entries ---
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-intentions"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-resolver"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-router"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "ingress-gateway"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-splitter"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "mesh"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "proxy-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "terminating-gateway"},
},
},
},
},
}
@ -340,6 +486,79 @@ func TestUsageReporter_emitServiceUsage_OSS(t *testing.T) {
Value: 0,
Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}},
},
// --- config entries ---
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-intentions"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-resolver"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-router"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "ingress-gateway"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-splitter"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "mesh"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "proxy-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "terminating-gateway"},
},
},
},
getMembersFunc: func() []serf.Member { return []serf.Member{} },
},
@ -474,6 +693,79 @@ func TestUsageReporter_emitServiceUsage_OSS(t *testing.T) {
Value: 0,
Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}},
},
// --- config entries ---
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-intentions"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-resolver"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-router"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 1,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "ingress-gateway"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-splitter"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "mesh"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "proxy-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 1,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "terminating-gateway"},
},
},
},
},
}
@ -597,6 +889,79 @@ func TestUsageReporter_emitKVUsage_OSS(t *testing.T) {
Value: 0,
Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}},
},
// --- config entries ---
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-intentions"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-resolver"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-router"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "ingress-gateway"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-splitter"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "mesh"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "proxy-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "terminating-gateway"},
},
},
},
getMembersFunc: func() []serf.Member { return []serf.Member{} },
},
@ -710,6 +1075,79 @@ func TestUsageReporter_emitKVUsage_OSS(t *testing.T) {
Value: 4,
Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}},
},
// --- config entries ---
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-intentions": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-intentions"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-resolver": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-resolver"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-router": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-router"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=ingress-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "ingress-gateway"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=service-splitter": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "service-splitter"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=mesh": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "mesh"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=proxy-defaults": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "proxy-defaults"},
},
},
"consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=terminating-gateway": {
Name: "consul.usage.test.consul.state.config_entries",
Value: 0,
Labels: []metrics.Label{
{Name: "datacenter", Value: "dc1"},
{Name: "kind", Value: "terminating-gateway"},
},
},
},
},
}