Skip to content

Commit ec1ba16

Browse files
authored
prom: Fix leak when a call fails with the prometheus endpoint (#2456)
1 parent 7a57245 commit ec1ba16

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

restapi/admin_info.go

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"net/url"
2626
"regexp"
2727
"strings"
28+
"sync"
2829
"time"
2930

3031
"github.com/go-openapi/runtime/middleware"
@@ -977,20 +978,28 @@ func getUsageWidgetsForDeployment(ctx context.Context, prometheusURL string, mAd
977978

978979
func unmarshalPrometheus(ctx context.Context, endpoint string, data interface{}) bool {
979980
httpClnt := GetConsoleHTTPClient(endpoint)
980-
resp, err := httpClnt.Get(endpoint)
981+
982+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
983+
if err != nil {
984+
ErrorWithContext(ctx, fmt.Errorf("Unable to create the request to fetch labels from prometheus: %w", err))
985+
return true
986+
}
987+
988+
resp, err := httpClnt.Do(req)
981989
if err != nil {
982-
ErrorWithContext(ctx, fmt.Errorf("Unable to fetch labels from prometheus (%s)", resp.Status))
990+
ErrorWithContext(ctx, fmt.Errorf("Unable to fetch labels from prometheus: %w", err))
983991
return true
984992
}
993+
985994
defer resp.Body.Close()
986995

987-
if resp.StatusCode != 200 {
988-
ErrorWithContext(ctx, fmt.Errorf("Unexpected errors from prometheus (%s)", resp.Status))
996+
if resp.StatusCode != http.StatusOK {
997+
ErrorWithContext(ctx, fmt.Errorf("Unexpected status code from prometheus (%s)", resp.Status))
989998
return true
990999
}
9911000

9921001
if err = json.NewDecoder(resp.Body).Decode(data); err != nil {
993-
ErrorWithContext(ctx, fmt.Errorf("Unexpected errors from prometheus (%s)", resp.Status))
1002+
ErrorWithContext(ctx, fmt.Errorf("Unexpected error from prometheus: %w", err))
9941003
return true
9951004
}
9961005

@@ -1081,10 +1090,17 @@ LabelsWaitLoop:
10811090
continue
10821091
}
10831092

1084-
targetResults := make(chan *models.ResultTarget)
1093+
var (
1094+
wg sync.WaitGroup
1095+
targetResults = make([]*models.ResultTarget, len(m.Targets))
1096+
)
1097+
10851098
// for each target we will launch another goroutine to fetch the values
1086-
for _, target := range m.Targets {
1087-
go func(target Target, inStep *int32, inStart *int64, inEnd *int64) {
1099+
for idx, target := range m.Targets {
1100+
wg.Add(1)
1101+
go func(idx int, target Target, inStep *int32, inStart *int64, inEnd *int64) {
1102+
defer wg.Done()
1103+
10881104
apiType := "query_range"
10891105
now := time.Now()
10901106

@@ -1145,10 +1161,12 @@ LabelsWaitLoop:
11451161
})
11461162
}
11471163

1148-
targetResults <- &targetResult
1149-
}(target, step, start, end)
1164+
targetResults[idx] = &targetResult
1165+
}(idx, target, step, start, end)
11501166
}
11511167

1168+
wg.Wait()
1169+
11521170
wdgtResult := models.WidgetDetails{
11531171
ID: m.ID,
11541172
Title: m.Title,
@@ -1161,15 +1179,10 @@ LabelsWaitLoop:
11611179
},
11621180
}
11631181
}
1164-
// count how many targets we have received
1165-
targetsReceived := 0
1166-
1167-
for res := range targetResults {
1168-
wdgtResult.Targets = append(wdgtResult.Targets, res)
1169-
targetsReceived++
1170-
// upon receiving the total number of targets needed, we can close the channel to not lock the goroutine
1171-
if targetsReceived >= len(m.Targets) {
1172-
close(targetResults)
1182+
1183+
for _, res := range targetResults {
1184+
if res != nil {
1185+
wdgtResult.Targets = append(wdgtResult.Targets, res)
11731186
}
11741187
}
11751188
return &wdgtResult, nil

0 commit comments

Comments
 (0)