// computeAgentsStats computes and stores statistics about agents and endpoints func computeAgentsStats(ctx Context) (err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("computeAgentsStats() -> %v", e) } ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: "leaving computeAgentsStats()"}.Debug() }() var ( stats mig.AgentsStats wg sync.WaitGroup ) wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.OnlineAgentsByVersion, err = ctx.DB.SumOnlineAgentsByVersion() if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("SumOnlineAgentsByVersion() took %v to run", d)}.Debug() }() wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.IdleAgentsByVersion, err = ctx.DB.SumIdleAgentsByVersion() if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("SumIdleAgentsByVersion() took %v to run", d)}.Debug() }() wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.OnlineEndpoints, err = ctx.DB.CountOnlineEndpoints() if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountOnlineEndpoints() took %v to run", d)}.Debug() }() wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.IdleEndpoints, err = ctx.DB.CountIdleEndpoints() if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountIdleEndpoints() took %v to run", d)}.Debug() }() wg.Add(1) go func() { defer wg.Done() // only run that one once every hour if time.Now().Add(-time.Hour).After(countNewEndpointsHourly) { start := time.Now() // detect new endpoints from last 24 hours against endpoints from last 7 days stats.NewEndpoints, err = ctx.DB.CountNewEndpoints(time.Now().Add(-24*time.Hour), time.Now().Add(-7*24*time.Hour)) if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountNewEndpoints() took %v to run", d)}.Debug() countNewEndpointsHourly = time.Now() } }() wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.MultiAgentsEndpoints, err = ctx.DB.CountDoubleAgents() if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountDoubleAgents() took %v to run", d)}.Debug() }() wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.DisappearedEndpoints, err = ctx.DB.CountDisappearedEndpoints(time.Now().Add(-7 * 24 * time.Hour)) if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountDisappearedEndpoints() took %v to run", d)}.Debug() }() wg.Add(1) go func() { defer wg.Done() start := time.Now() stats.FlappingEndpoints, err = ctx.DB.CountFlappingEndpoints() if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountFlappingEndpoints() took %v to run", d)}.Debug() }() wg.Wait() for _, asum := range stats.OnlineAgentsByVersion { stats.OnlineAgents += asum.Count } for _, asum := range stats.IdleAgentsByVersion { stats.IdleAgents += asum.Count } err = ctx.DB.StoreAgentsStats(stats) if err != nil { panic(err) } return }
// computeAgentsStats computes and stores statistics about agents and endpoints func computeAgentsStats(ctx Context) (err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("computeAgentsStats() -> %v", e) } ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: "leaving computeAgentsStats()"}.Debug() }() var stats mig.AgentsStats done := make(chan bool) routines := 0 go func() { routines++ start := time.Now() stats.OnlineAgentsByVersion, err = ctx.DB.SumOnlineAgentsByVersion() if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("SumOnlineAgentsByVersion() took %v to run", d)}.Debug() }() go func() { routines++ start := time.Now() stats.IdleAgentsByVersion, err = ctx.DB.SumIdleAgentsByVersion() if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("SumIdleAgentsByVersion() took %v to run", d)}.Debug() }() go func() { routines++ start := time.Now() stats.OnlineEndpoints, err = ctx.DB.CountOnlineEndpoints() if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountOnlineEndpoints() took %v to run", d)}.Debug() }() go func() { routines++ start := time.Now() stats.IdleEndpoints, err = ctx.DB.CountIdleEndpoints() if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountIdleEndpoints() took %v to run", d)}.Debug() }() go func() { // only run that one once every hour if time.Now().Add(-time.Hour).After(countNewEndpointsHourly) { routines++ start := time.Now() // detect new endpoints from last 24 hours against endpoints from last 7 days stats.NewEndpoints, err = ctx.DB.CountNewEndpoints(time.Now().Add(-24*time.Hour), time.Now().Add(-7*24*time.Hour)) if err != nil { panic(err) } d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountNewEndpoints() took %v to run", d)}.Debug() countNewEndpointsHourly = time.Now() done <- true } }() go func() { routines++ start := time.Now() stats.MultiAgentsEndpoints, err = ctx.DB.CountDoubleAgents() if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountDoubleAgents() took %v to run", d)}.Debug() }() go func() { routines++ start := time.Now() stats.DisappearedEndpoints, err = ctx.DB.CountDisappearedEndpoints(time.Now().Add(-7 * 24 * time.Hour)) if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountDisappearedEndpoints() took %v to run", d)}.Debug() }() go func() { routines++ start := time.Now() stats.FlappingEndpoints, err = ctx.DB.CountFlappingEndpoints() if err != nil { panic(err) } done <- true d := time.Since(start) ctx.Channels.Log <- mig.Log{OpID: ctx.OpID, Desc: fmt.Sprintf("CountFlappingEndpoints() took %v to run", d)}.Debug() }() // each query is ran in parallel and return a boolean in the done channel // so when we have received 4 messages in the channel, all queries are done time.Sleep(100 * time.Millisecond) completed := 0 for <-done { completed++ if completed == routines { break } } for _, asum := range stats.OnlineAgentsByVersion { stats.OnlineAgents += asum.Count } for _, asum := range stats.IdleAgentsByVersion { stats.IdleAgents += asum.Count } err = ctx.DB.StoreAgentsStats(stats) if err != nil { panic(err) } return }