Now using a more efficient data structure in the prometheus code for saving the last state to improve efficiency and minimize copying even more.

This commit is contained in:
Erik Brakkee 2024-08-14 23:38:45 +02:00
parent 9a1b78ee63
commit 1a2a3b6ac5

View File

@ -12,10 +12,30 @@ import (
const NAMESPACE = "converge" const NAMESPACE = "converge"
// more efficient state representation for state
type PrometheusState struct {
agents map[string]*models.Agent
clients map[string]*models.Client
}
func NewPrometheusState(state *models.State) *PrometheusState {
res := PrometheusState{
agents: make(map[string]*models.Agent),
clients: make(map[string]*models.Client),
}
for i, _ := range state.Agents {
res.agents[state.Agents[i].Guid] = &state.Agents[i]
}
for i, _ := range state.Clients {
res.clients[state.Clients[i].Guid] = &state.Clients[i]
}
return &res
}
var ( var (
// remember previous values of agent guids and clients so that we can increment // remember previous values of agent guids and clients so that we can increment
// the cumulative counters. // the cumulative counters.
lastState *models.State = &models.State{} lastState *PrometheusState = NewPrometheusState(&models.State{})
cumulativeAgentCount = promauto.NewCounter(prometheus.CounterOpts{ cumulativeAgentCount = promauto.NewCounter(prometheus.CounterOpts{
Namespace: NAMESPACE, Namespace: NAMESPACE,
@ -129,7 +149,7 @@ func clientLabels(client *models.Client) prometheus.Labels {
} }
func agentActive(agent *models.Agent) { func agentActive(agent *models.Agent) {
prevAgent, ok := findAgent(lastState, agent.Guid) prevAgent, ok := lastState.agents[agent.Guid]
if ok && *prevAgent != *agent { if ok && *prevAgent != *agent {
removeAgentInfoMetrics(prevAgent) removeAgentInfoMetrics(prevAgent)
} }
@ -142,26 +162,8 @@ func agentActive(agent *models.Agent) {
Set(float64(time.Now().Sub(agent.StartTime).Seconds())) Set(float64(time.Now().Sub(agent.StartTime).Seconds()))
} }
func findAgent(state *models.State, guid string) (*models.Agent, bool) {
for i := range state.Agents {
if state.Agents[i].Guid == guid {
return &state.Agents[i], true
}
}
return nil, false
}
func findClient(state *models.State, guid string) (*models.Client, bool) {
for i := range state.Clients {
if state.Clients[i].Guid == guid {
return &state.Clients[i], true
}
}
return nil, false
}
func clientActive(client *models.Client) { func clientActive(client *models.Client) {
prevClient, ok := findClient(lastState, client.Guid) prevClient, ok := lastState.clients[client.Guid]
if ok && *prevClient != *client { if ok && *prevClient != *client {
removeClientInfoMetrics(prevClient) removeClientInfoMetrics(prevClient)
} }
@ -214,38 +216,35 @@ var prometheusChannel = make(chan func())
func updateMetrics(state *models.State) { func updateMetrics(state *models.State) {
prometheusChannel <- func() { prometheusChannel <- func() {
updateMetricsImpl(state) updateMetricsImpl(NewPrometheusState(state))
} }
} }
func updateDurations() { func updateDurations() {
for i := range lastState.Agents { for _, agent := range lastState.agents {
agent := &lastState.Agents[i]
agentDuration. agentDuration.
With(prometheus.Labels{"agent_guid": agent.Guid}). With(prometheus.Labels{"agent_guid": agent.Guid}).
Set(float64(time.Now().Sub(agent.StartTime).Seconds())) Set(float64(time.Now().Sub(agent.StartTime).Seconds()))
} }
for i := range lastState.Clients { for _, client := range lastState.clients {
client := &lastState.Clients[i]
clientDuration. clientDuration.
With(prometheus.Labels{"client_guid": client.Guid}). With(prometheus.Labels{"client_guid": client.Guid}).
Set(float64(time.Now().Sub(client.StartTime).Seconds())) Set(float64(time.Now().Sub(client.StartTime).Seconds()))
} }
} }
func updateMetricsImpl(state *models.State) { func updateMetricsImpl(state *PrometheusState) {
agentGuids := make(map[string]*models.Agent) agentGuids := make(map[string]*models.Agent)
clientGuids := make(map[string]*models.Client) clientGuids := make(map[string]*models.Client)
agentCount.Set(float64(len(state.Agents))) agentCount.Set(float64(len(state.agents)))
disconnectedAgents := make(map[string]*models.Agent) disconnectedAgents := make(map[string]*models.Agent)
for i := range lastState.Agents { for _, agent := range lastState.agents {
agent := &lastState.Agents[i]
disconnectedAgents[agent.Guid] = agent disconnectedAgents[agent.Guid] = agent
} }
for i := range state.Agents { for _, agent := range state.agents {
agent := &state.Agents[i] if lastState.agents[agent.Guid] == nil {
if _, ok := findAgent(lastState, agent.Guid); !ok {
cumulativeAgentCount.Inc() cumulativeAgentCount.Inc()
} }
delete(disconnectedAgents, agent.Guid) delete(disconnectedAgents, agent.Guid)
@ -256,17 +255,15 @@ func updateMetricsImpl(state *models.State) {
removeAgentMetrics(agent) removeAgentMetrics(agent)
} }
clientCount.Set(float64(len(state.Clients))) clientCount.Set(float64(len(state.clients)))
// with this app // with this app
disconnectedClients := make(map[string]*models.Client) disconnectedClients := make(map[string]*models.Client)
for i := range lastState.Clients { for _, client := range lastState.clients {
client := &lastState.Clients[i]
disconnectedClients[client.Guid] = client disconnectedClients[client.Guid] = client
} }
for i := range state.Clients { for _, client := range state.clients {
client := &state.Clients[i] if lastState.clients[client.Guid] == nil {
if _, ok := findClient(lastState, client.Guid); !ok {
cumulativeClientCount.Inc() cumulativeClientCount.Inc()
} }
delete(disconnectedClients, client.Guid) delete(disconnectedClients, client.Guid)