Skip to content

Commit d963088

Browse files
dougszumskim-bull
andauthored
Stackhpc upstream master (#5)
* Add config option to not collect logs Collecting logs from BMCs can be very slow, so you may wish to disable doing so. However, the logs can still be useful. This change adds support for optionally overriding the `collectlogs` config setting. One use case envisaged would be to set collectlogs to false in the config, allowing the BMC to be scraped for data every few minutes. Then every hour or so, the logs could be collected via the `collectlogs` override. --------- Co-authored-by: Matt Anson <[email protected]>
1 parent 0257fcf commit d963088

File tree

8 files changed

+124
-46
lines changed

8 files changed

+124
-46
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,46 @@ groups:
2020
Note that the ```default``` entry is useful as it avoids an error
2121
condition that is discussed in [this issue][2].
2222

23+
## Log collection
24+
25+
One issue you may encounter is slow scrape times when collecting logs from
26+
BMCs. Sometimes these scrapes can take ~10minutes. If this becomes
27+
problematic the collection of logs can be configured as follows:
28+
29+
1) via the the config file
30+
31+
To disable log collection you can set:
32+
33+
```yaml
34+
collectlogs: false
35+
```
36+
37+
2) via the `collectlogs` query parameter
38+
39+
For example:
40+
41+
```sh
42+
curl '127.0.0.1:9123/redfish?target=10.10.12.23&collectlogs=false'
43+
```
44+
45+
3) Via a combination of both options
46+
47+
For example, collect metrics without logs by default:
48+
49+
Set:
50+
51+
```yaml
52+
collectlogs: false
53+
```
54+
55+
Every hour or so, override the config setting and fetch the logs:
56+
57+
```sh
58+
curl '127.0.0.1:9123/redfish?target=10.10.12.23&collectlogs=true'
59+
```
60+
61+
The `collectlogs` query parameter can be included in Prometheus config.
62+
2363
## Building
2464

2565
To build the redfish_exporter executable run the command:

collector/chassis_collector.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
type ChassisCollector struct {
3636
redfishClient *gofish.APIClient
3737
metrics map[string]Metric
38+
collectLogs bool
3839
collectorScrapeStatus *prometheus.GaugeVec
3940
Log *log.Entry
4041
}
@@ -90,12 +91,13 @@ func createChassisMetricMap() map[string]Metric {
9091
}
9192

9293
// NewChassisCollector returns a collector that collecting chassis statistics
93-
func NewChassisCollector(redfishClient *gofish.APIClient, logger *log.Entry) *ChassisCollector {
94+
func NewChassisCollector(redfishClient *gofish.APIClient, collectLogs bool, logger *log.Entry) *ChassisCollector {
9495
// get service from redfish client
9596

9697
return &ChassisCollector{
9798
redfishClient: redfishClient,
9899
metrics: chassisMetrics,
100+
collectLogs: collectLogs,
99101
Log: logger.WithFields(log.Fields{
100102
"collector": "ChassisCollector",
101103
}),
@@ -122,6 +124,7 @@ func (c *ChassisCollector) Describe(ch chan<- *prometheus.Desc) {
122124
// Collect implemented prometheus.Collector
123125
func (c *ChassisCollector) Collect(ch chan<- prometheus.Metric) {
124126
collectorLogContext := c.Log
127+
collectLogs := c.collectLogs
125128
service := c.redfishClient.Service
126129

127130
// get a list of chassis from service
@@ -238,18 +241,20 @@ func (c *ChassisCollector) Collect(ch chan<- prometheus.Metric) {
238241
}
239242

240243
// process log services
241-
logServices, err := chassis.LogServices()
242-
if err != nil {
243-
chassisLogContext.WithField("operation", "chassis.LogServices()").WithError(err).Error("error getting log services from chassis")
244-
} else if logServices == nil {
245-
chassisLogContext.WithField("operation", "chassis.LogServices()").Info("no log services found")
246-
} else {
247-
wg6 := &sync.WaitGroup{}
248-
wg6.Add(len(logServices))
249-
250-
for _, logService := range logServices {
251-
if err = parseLogService(ch, chassisMetrics, ChassisSubsystem, chassisID, logService, wg6); err != nil {
252-
chassisLogContext.WithField("operation", "chassis.LogServices()").WithError(err).Error("error getting log entries from log service")
244+
if collectLogs {
245+
logServices, err := chassis.LogServices()
246+
if err != nil {
247+
chassisLogContext.WithField("operation", "chassis.LogServices()").WithError(err).Error("error getting log services from chassis")
248+
} else if logServices == nil {
249+
chassisLogContext.WithField("operation", "chassis.LogServices()").Info("no log services found")
250+
} else {
251+
wg6 := &sync.WaitGroup{}
252+
wg6.Add(len(logServices))
253+
254+
for _, logService := range logServices {
255+
if err = parseLogService(ch, chassisMetrics, ChassisSubsystem, chassisID, logService, wg6); err != nil {
256+
chassisLogContext.WithField("operation", "chassis.LogServices()").WithError(err).Error("error getting log entries from log service")
257+
}
253258
}
254259
}
255260
}

collector/manager_collector.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var (
2424
type ManagerCollector struct {
2525
redfishClient *gofish.APIClient
2626
metrics map[string]Metric
27+
collectLogs bool
2728
collectorScrapeStatus *prometheus.GaugeVec
2829
Log *log.Entry
2930
}
@@ -42,10 +43,11 @@ func createManagerMetricMap() map[string]Metric {
4243
}
4344

4445
// NewManagerCollector returns a collector that collecting memory statistics
45-
func NewManagerCollector(redfishClient *gofish.APIClient, logger *log.Entry) *ManagerCollector {
46+
func NewManagerCollector(redfishClient *gofish.APIClient, collectLogs bool, logger *log.Entry) *ManagerCollector {
4647
return &ManagerCollector{
4748
redfishClient: redfishClient,
4849
metrics: managerMetrics,
50+
collectLogs: collectLogs,
4951
Log: logger.WithFields(log.Fields{
5052
"collector": "ManagerCollector",
5153
}),
@@ -72,6 +74,7 @@ func (m *ManagerCollector) Describe(ch chan<- *prometheus.Desc) {
7274
// Collect implemented prometheus.Collector
7375
func (m *ManagerCollector) Collect(ch chan<- prometheus.Metric) {
7476
collectorLogContext := m.Log
77+
collectLogs := m.collectLogs
7578
//get service
7679
service := m.redfishClient.Service
7780

@@ -104,18 +107,20 @@ func (m *ManagerCollector) Collect(ch chan<- prometheus.Metric) {
104107
}
105108

106109
// process log services
107-
logServices, err := manager.LogServices()
108-
if err != nil {
109-
managerLogContext.WithField("operation", "manager.LogServices()").WithError(err).Error("error getting log services from manager")
110-
} else if logServices == nil {
111-
managerLogContext.WithField("operation", "manager.LogServices()").Info("no log services found")
112-
} else {
113-
wg := &sync.WaitGroup{}
114-
wg.Add(len(logServices))
115-
116-
for _, logService := range logServices {
117-
if err = parseLogService(ch, managerMetrics, ManagerSubmanager, ManagerID, logService, wg); err != nil {
118-
managerLogContext.WithField("operation", "manager.LogServices()").WithError(err).Error("error getting log entries from log service")
110+
if collectLogs {
111+
logServices, err := manager.LogServices()
112+
if err != nil {
113+
managerLogContext.WithField("operation", "manager.LogServices()").WithError(err).Error("error getting log services from manager")
114+
} else if logServices == nil {
115+
managerLogContext.WithField("operation", "manager.LogServices()").Info("no log services found")
116+
} else {
117+
wg := &sync.WaitGroup{}
118+
wg.Add(len(logServices))
119+
120+
for _, logService := range logServices {
121+
if err = parseLogService(ch, managerMetrics, ManagerSubmanager, ManagerID, logService, wg); err != nil {
122+
managerLogContext.WithField("operation", "manager.LogServices()").WithError(err).Error("error getting log entries from log service")
123+
}
119124
}
120125
}
121126
}

collector/redfish_collector.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ type RedfishCollector struct {
4040
}
4141

4242
// NewRedfishCollector return RedfishCollector
43-
func NewRedfishCollector(host string, username string, password string, logger *log.Entry) *RedfishCollector {
43+
func NewRedfishCollector(host string, username string, password string, collectLogs bool, logger *log.Entry) *RedfishCollector {
4444
var collectors map[string]prometheus.Collector
4545
collectorLogCtx := logger
4646
redfishClient, err := newRedfishClient(host, username, password)
4747
if err != nil {
4848
collectorLogCtx.WithError(err).Error("error creating redfish client")
4949
} else {
50-
chassisCollector := NewChassisCollector(redfishClient, collectorLogCtx)
51-
systemCollector := NewSystemCollector(redfishClient, collectorLogCtx)
52-
managerCollector := NewManagerCollector(redfishClient, collectorLogCtx)
50+
chassisCollector := NewChassisCollector(redfishClient, collectLogs, collectorLogCtx)
51+
systemCollector := NewSystemCollector(redfishClient, collectLogs, collectorLogCtx)
52+
managerCollector := NewManagerCollector(redfishClient, collectLogs, collectorLogCtx)
5353

5454
collectors = map[string]prometheus.Collector{"chassis": chassisCollector, "system": systemCollector, "manager": managerCollector}
5555
}

collector/system_collector.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
type SystemCollector struct {
3636
redfishClient *gofish.APIClient
3737
metrics map[string]Metric
38+
collectLogs bool
3839
prometheus.Collector
3940
collectorScrapeStatus *prometheus.GaugeVec
4041
Log *log.Entry
@@ -100,10 +101,11 @@ func createSystemMetricMap() map[string]Metric {
100101
}
101102

102103
// NewSystemCollector returns a collector that collecting memory statistics
103-
func NewSystemCollector(redfishClient *gofish.APIClient, logger *log.Entry) *SystemCollector {
104+
func NewSystemCollector(redfishClient *gofish.APIClient, collectLogs bool, logger *log.Entry) *SystemCollector {
104105
return &SystemCollector{
105106
redfishClient: redfishClient,
106107
metrics: systemMetrics,
108+
collectLogs: collectLogs,
107109
Log: logger.WithFields(log.Fields{
108110
"collector": "SystemCollector",
109111
}),
@@ -129,6 +131,7 @@ func (s *SystemCollector) Describe(ch chan<- *prometheus.Desc) {
129131
// Collect implements prometheus.Collector.
130132
func (s *SystemCollector) Collect(ch chan<- prometheus.Metric) {
131133
collectorLogContext := s.Log
134+
collectLogs := s.collectLogs
132135
//get service
133136
service := s.redfishClient.Service
134137

@@ -366,17 +369,19 @@ func (s *SystemCollector) Collect(ch chan<- prometheus.Metric) {
366369
}
367370

368371
// process log services
369-
logServices, err := system.LogServices()
370-
if err != nil {
371-
systemLogContext.WithField("operation", "system.LogServices()").WithError(err).Error("error getting log services from system")
372-
} else if logServices == nil {
373-
systemLogContext.WithField("operation", "system.LogServices()").Info("no log services found")
374-
} else {
375-
wg10.Add(len(logServices))
376-
377-
for _, logService := range logServices {
378-
if err = parseLogService(ch, systemMetrics, SystemSubsystem, SystemID, logService, wg10); err != nil {
379-
systemLogContext.WithField("operation", "system.LogServices()").WithError(err).Error("error getting log entries from log service")
372+
if collectLogs {
373+
logServices, err := system.LogServices()
374+
if err != nil {
375+
systemLogContext.WithField("operation", "system.LogServices()").WithError(err).Error("error getting log services from system")
376+
} else if logServices == nil {
377+
systemLogContext.WithField("operation", "system.LogServices()").Info("no log services found")
378+
} else {
379+
wg10.Add(len(logServices))
380+
381+
for _, logService := range logServices {
382+
if err = parseLogService(ch, systemMetrics, SystemSubsystem, SystemID, logService, wg10); err != nil {
383+
systemLogContext.WithField("operation", "system.LogServices()").WithError(err).Error("error getting log entries from log service")
384+
}
380385
}
381386
}
382387
}

config.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import (
99
)
1010

1111
type Config struct {
12-
Hosts map[string]HostConfig `yaml:"hosts"`
13-
Groups map[string]HostConfig `yaml:"groups"`
14-
Loglevel string `yaml:"loglevel"`
12+
Hosts map[string]HostConfig `yaml:"hosts"`
13+
Groups map[string]HostConfig `yaml:"groups"`
14+
Loglevel string `yaml:"loglevel"`
15+
Collectlogs *bool `yaml:"collectlogs,omitempty"`
1516
}
1617

1718
type SafeConfig struct {
@@ -80,3 +81,12 @@ func (sc *SafeConfig) AppLogLevel() string {
8081
}
8182
return "info"
8283
}
84+
85+
func (sc *SafeConfig) CollectLogs() bool {
86+
sc.Lock()
87+
defer sc.Unlock()
88+
if sc.C.Collectlogs == nil {
89+
return true
90+
}
91+
return *sc.C.Collectlogs
92+
}

config.yml.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ groups:
1111
password: group1_pass
1212
# loglevel can be one of "debug", "info", "warn", "error", or "fatal"
1313
# loglevel: info
14+
collectlogs: true

main.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net/http"
66
"os"
77
"os/signal"
8+
"strconv"
89
"syscall"
910

1011
alog "github.com/apex/log"
@@ -118,7 +119,17 @@ func metricsHandler() http.HandlerFunc {
118119
}
119120
}
120121

121-
collector := collector.NewRedfishCollector(target, hostConfig.Username, hostConfig.Password, targetLoggerCtx)
122+
// Support optionally overriding collectlogs setting using a query parameter
123+
collectLogs := sc.CollectLogs()
124+
collectLogsOverride := r.URL.Query().Get("collectlogs")
125+
if collectLogsOverride != "" {
126+
if collectLogs, err = strconv.ParseBool(collectLogsOverride); err != nil {
127+
targetLoggerCtx.WithError(err).Error("error parsing collectlogs query parameter as a boolean")
128+
return
129+
}
130+
}
131+
132+
collector := collector.NewRedfishCollector(target, hostConfig.Username, hostConfig.Password, collectLogs, targetLoggerCtx)
122133
registry.MustRegister(collector)
123134
gatherers := prometheus.Gatherers{
124135
prometheus.DefaultGatherer,
@@ -189,6 +200,7 @@ func main() {
189200
<h1>redfish Exporter</h1>
190201
<form action="/redfish">
191202
<label>Target:</label> <input type="text" name="target" placeholder="X.X.X.X" value="1.2.3.4"><br>
203+
<label>CollectLogs:</label> <input type="text" name="collectlogs" placeholder="collectlogs (optional)" value="bool"><br>
192204
<label>Group:</label> <input type="text" name="group" placeholder="group (optional)" value=""><br>
193205
<input type="submit" value="Submit">
194206
</form>

0 commit comments

Comments
 (0)