in internal/graph/graph_scanner.go [149:217]
func (a AprlScanner) Scan(ctx context.Context, cred azcore.TokenCredential) (map[string]map[string]models.AprlRecommendation, []models.AprlResult) {
recommendations := map[string]map[string]models.AprlRecommendation{}
results := []models.AprlResult{}
rules := []models.AprlRecommendation{}
graph := NewGraphQuery(cred)
// get APRL recommendations
aprl := a.GetAprlRecommendations()
for _, s := range a.serviceScanners {
for _, t := range s.ResourceTypes() {
models.LogResourceTypeScan(t)
gr := a.getGraphRules(t, aprl)
for _, r := range gr {
rules = append(rules, r)
}
for i, r := range gr {
if recommendations[strings.ToLower(t)] == nil {
recommendations[strings.ToLower(t)] = map[string]models.AprlRecommendation{}
}
recommendations[strings.ToLower(t)][i] = r
}
}
}
batches := int(math.Ceil(float64(len(rules)) / 12))
jobs := make(chan []models.AprlRecommendation, batches)
ch := make(chan []models.AprlResult, batches)
var wg sync.WaitGroup
// Start workers
numWorkers := 12 // Define the number of workers in the pool
for w := 0; w < numWorkers; w++ {
go a.worker(ctx, graph, a.subscriptions, jobs, ch, &wg)
}
wg.Add(batches)
batchSize := 12
for i := 0; i < len(rules); i += batchSize {
j := i + batchSize
if j > len(rules) {
j = len(rules)
}
jobs <- rules[i:j]
// Staggering queries to avoid throttling. Max 15 queries each 5 seconds.
// https://learn.microsoft.com/en-us/azure/governance/resource-graph/concepts/guidance-for-throttled-requests#staggering-queries
time.Sleep(5 * time.Second)
}
// Wait for all workers to finish
close(jobs)
wg.Wait()
for i := 0; i < batches; i++ {
res := <-ch
for _, r := range res {
if a.filters.Azqr.IsServiceExcluded(r.ResourceID) {
continue
}
results = append(results, r)
}
}
return recommendations, results
}