2020-11-29 03:22:39 +05:00
|
|
|
package application
|
|
|
|
|
2020-11-29 05:44:21 +05:00
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Fetches data from remote endpoint, parses it and updates in storage.
|
|
|
|
func (a *Application) fetch() {
|
|
|
|
// Do not do anything if fetching is running.
|
|
|
|
// ToDo: maybe another approach?
|
|
|
|
a.fetchIsRunningMutex.RLock()
|
2021-11-21 14:45:09 +05:00
|
|
|
// This is an optimization to avoid excessive waiting when using Lock().
|
|
|
|
// Most of time application will wait between fetches.
|
|
|
|
// nolint:ifshort
|
2020-11-29 05:44:21 +05:00
|
|
|
isFetching := a.fetchIsRunning
|
|
|
|
a.fetchIsRunningMutex.RUnlock()
|
|
|
|
|
|
|
|
if isFetching {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-29 19:36:04 +05:00
|
|
|
a.fetchIsRunningMutex.Lock()
|
|
|
|
a.fetchIsRunning = true
|
|
|
|
a.fetchIsRunningMutex.Unlock()
|
|
|
|
|
2020-12-23 16:28:57 +05:00
|
|
|
a.logger.Infoln("Fetching data for", a.name)
|
2020-11-29 05:44:21 +05:00
|
|
|
|
|
|
|
req, err := http.NewRequestWithContext(a.ctx, "GET", a.config.Endpoint, nil)
|
|
|
|
if err != nil {
|
2020-12-23 16:28:57 +05:00
|
|
|
a.logger.Infoln("Failed to create request for", a.name, "metrics:", err.Error())
|
2020-11-29 05:44:21 +05:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for header, value := range a.config.Headers {
|
|
|
|
req.Header.Add(header, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := a.httpClient.Do(req)
|
|
|
|
if err != nil {
|
2020-12-23 16:28:57 +05:00
|
|
|
a.logger.Infoln("Failed to execute request for", a.name, "metrics:", err.Error())
|
2020-11-29 05:44:21 +05:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
2021-06-04 13:50:12 +05:00
|
|
|
data, err := a.parse(resp.Body)
|
2020-11-29 05:44:21 +05:00
|
|
|
if err != nil {
|
2021-06-04 13:50:12 +05:00
|
|
|
a.logger.Infoln("Failed to parse response body for", a.name, "metrics:", err.Error())
|
2020-11-29 05:44:21 +05:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
a.storage.Put(data)
|
|
|
|
|
|
|
|
a.fetchIsRunningMutex.Lock()
|
|
|
|
a.fetchIsRunning = false
|
|
|
|
a.fetchIsRunningMutex.Unlock()
|
|
|
|
}
|
|
|
|
|
2020-11-29 03:22:39 +05:00
|
|
|
// Configures and starts Prometheus data fetching goroutine.
|
2020-11-29 05:44:21 +05:00
|
|
|
func (a *Application) startFetcher() {
|
|
|
|
fetchTicker := time.NewTicker(a.config.TimeBetweenRequests)
|
|
|
|
|
2020-11-29 05:52:52 +05:00
|
|
|
// nolint:exhaustivestruct
|
2020-11-29 05:44:21 +05:00
|
|
|
a.httpClient = &http.Client{
|
|
|
|
Timeout: time.Second * 5,
|
|
|
|
}
|
|
|
|
|
2020-12-23 16:28:57 +05:00
|
|
|
defer a.logger.Debugln("Fetcher for", a.name, "completed")
|
2020-11-29 05:44:21 +05:00
|
|
|
|
|
|
|
// First fetch should be executed ASAP.
|
|
|
|
a.fetch()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-a.ctx.Done():
|
|
|
|
return
|
|
|
|
case <-fetchTicker.C:
|
|
|
|
a.fetch()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|