Skip to content

Commit e28371d

Browse files
Merge pull request jenningsloy318#67 from xflipped/dev
Add log service metrics for manager, chassis and system
2 parents c8e5308 + 1baf34e commit e28371d

File tree

8 files changed

+323
-670
lines changed

8 files changed

+323
-670
lines changed

collector/chassis_collector.go

Lines changed: 80 additions & 284 deletions
Large diffs are not rendered by default.

collector/common_collector.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package collector
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
7+
"github.com/prometheus/client_golang/prometheus"
8+
"github.com/stmcginnis/gofish/redfish"
9+
)
10+
11+
const (
12+
CommonStateHelp = "1(Enabled),2(Disabled),3(StandbyOffinline),4(StandbySpare),5(InTest),6(Starting),7(Absent),8(UnavailableOffline),9(Deferring),10(Quiesced),11(Updating)"
13+
CommonHealthHelp = "1(OK),2(Warning),3(Critical)"
14+
CommonSeverityHelp = CommonHealthHelp
15+
CommonLinkHelp = "1(LinkUp),2(NoLink),3(LinkDown)"
16+
CommonPortLinkHelp = "1(Up),0(Down)"
17+
CommonIntrusionSensorHelp = "1(Normal),2(TamperingDetected),3(HardwareIntrusion)"
18+
)
19+
20+
type Metric struct {
21+
desc *prometheus.Desc
22+
}
23+
24+
func addToMetricMap(metricMap map[string]Metric, subsystem, name, help string, variableLabels []string) {
25+
metricKey := fmt.Sprintf("%s_%s", subsystem, name)
26+
metricMap[metricKey] = Metric{
27+
desc: prometheus.NewDesc(
28+
prometheus.BuildFQName(namespace, subsystem, name),
29+
help,
30+
variableLabels,
31+
nil,
32+
),
33+
}
34+
}
35+
36+
func parseLogService(ch chan<- prometheus.Metric, metrics map[string]Metric, subsystem, collectorID string, logService *redfish.LogService, wg *sync.WaitGroup) (err error) {
37+
defer wg.Done()
38+
logServiceName := logService.Name
39+
logServiceID := logService.ID
40+
logServiceEnabled := fmt.Sprint(logService.ServiceEnabled)
41+
logServiceOverWritePolicy := string(logService.OverWritePolicy)
42+
logServiceState := logService.Status.State
43+
logServiceHealthState := logService.Status.Health
44+
45+
logServiceLabelValues := []string{collectorID, logServiceName, logServiceID, logServiceEnabled, logServiceOverWritePolicy}
46+
47+
if logServiceStateValue, ok := parseCommonStatusState(logServiceState); ok {
48+
ch <- prometheus.MustNewConstMetric(metrics[fmt.Sprintf("%s_%s", subsystem, "log_service_state")].desc, prometheus.GaugeValue, logServiceStateValue, logServiceLabelValues...)
49+
}
50+
if logServiceHealthStateValue, ok := parseCommonStatusHealth(logServiceHealthState); ok {
51+
ch <- prometheus.MustNewConstMetric(metrics[fmt.Sprintf("%s_%s", subsystem, "log_service_health_state")].desc, prometheus.GaugeValue, logServiceHealthStateValue, logServiceLabelValues...)
52+
}
53+
54+
logEntries, err := logService.Entries()
55+
if err != nil {
56+
return
57+
}
58+
wg2 := &sync.WaitGroup{}
59+
wg2.Add(len(logEntries))
60+
for _, logEntry := range logEntries {
61+
go parseLogEntry(ch, metrics[fmt.Sprintf("%s_%s", subsystem, "log_entry_severity_state")].desc, collectorID, logServiceName, logServiceID, logEntry, wg2)
62+
}
63+
return
64+
}
65+
66+
func parseLogEntry(ch chan<- prometheus.Metric, desc *prometheus.Desc, collectorID, logServiceName, logServiceID string, logEntry *redfish.LogEntry, wg *sync.WaitGroup) {
67+
defer wg.Done()
68+
logEntryName := logEntry.Name
69+
logEntryID := logEntry.ID
70+
logEntryCode := string(logEntry.EntryCode)
71+
logEntryType := string(logEntry.EntryType)
72+
logEntryMessageID := logEntry.MessageID
73+
logEntrySensorNumber := fmt.Sprint(logEntry.SensorNumber)
74+
logEntrySensorType := string(logEntry.SensorType)
75+
logEntrySeverityState := logEntry.Severity
76+
77+
logEntryLabelValues := []string{collectorID, logServiceName, logServiceID, logEntryName, logEntryID, logEntryCode, logEntryType, logEntryMessageID, logEntrySensorNumber, logEntrySensorType}
78+
79+
if logEntrySeverityStateValue, ok := parseCommonSeverityState(logEntrySeverityState); ok {
80+
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, logEntrySeverityStateValue, logEntryLabelValues...)
81+
}
82+
}

collector/manager_collector.go

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,47 @@ package collector
22

33
import (
44
"fmt"
5+
"sync"
56

67
"github.com/apex/log"
78
"github.com/prometheus/client_golang/prometheus"
89
"github.com/stmcginnis/gofish"
910
)
1011

11-
// A ManagerCollector implements the prometheus.Collector.
12-
13-
type managerMetric struct {
14-
desc *prometheus.Desc
15-
}
16-
1712
// ManagerSubmanager is the manager subsystem
1813
var (
1914
ManagerSubmanager = "manager"
2015
ManagerLabelNames = []string{"manager_id", "name", "model", "type"}
21-
managerMetrics = map[string]managerMetric{
22-
"manager_state": {
23-
desc: prometheus.NewDesc(
24-
prometheus.BuildFQName(namespace, ManagerSubmanager, "state"),
25-
"manager state,1(Enabled),2(Disabled),3(StandbyOffinline),4(StandbySpare),5(InTest),6(Starting),7(Absent),8(UnavailableOffline),9(Deferring),10(Quiesced),11(Updating)",
26-
ManagerLabelNames,
27-
nil,
28-
),
29-
},
30-
"manager_health_state": {
31-
desc: prometheus.NewDesc(
32-
prometheus.BuildFQName(namespace, ManagerSubmanager, "health_state"),
33-
"manager health,1(OK),2(Warning),3(Critical)",
34-
ManagerLabelNames,
35-
nil,
36-
),
37-
},
38-
"manager_power_state": {
39-
desc: prometheus.NewDesc(
40-
prometheus.BuildFQName(namespace, ManagerSubmanager, "power_state"),
41-
"manager power state",
42-
ManagerLabelNames,
43-
nil,
44-
),
45-
},
46-
}
16+
17+
ManagerLogServiceLabelNames = []string{"manager_id", "log_service", "log_service_id", "log_service_enabled", "log_service_overwrite_policy"}
18+
ManagerLogEntryLabelNames = []string{"manager_id", "log_service", "log_service_id", "log_entry", "log_entry_id", "log_entry_code", "log_entry_type", "log_entry_message_id", "log_entry_sensor_number", "log_entry_sensor_type"}
19+
20+
managerMetrics = createManagerMetricMap()
4721
)
4822

49-
// ManagerCollector implemented prometheus.Collector
23+
// ManagerCollector implements the prometheus.Collector.
5024
type ManagerCollector struct {
51-
redfishClient *gofish.APIClient
52-
metrics map[string]managerMetric
53-
collectorScrapeStatus *prometheus.GaugeVec
54-
collectorScrapeDuration *prometheus.SummaryVec
55-
Log *log.Entry
25+
redfishClient *gofish.APIClient
26+
metrics map[string]Metric
27+
collectorScrapeStatus *prometheus.GaugeVec
28+
Log *log.Entry
29+
}
30+
31+
func createManagerMetricMap() map[string]Metric {
32+
managerMetrics := make(map[string]Metric)
33+
addToMetricMap(managerMetrics, ManagerSubmanager, "state", fmt.Sprintf("manager state,%s", CommonStateHelp), ManagerLabelNames)
34+
addToMetricMap(managerMetrics, ManagerSubmanager, "health_state", fmt.Sprintf("manager health,%s", CommonHealthHelp), ManagerLabelNames)
35+
addToMetricMap(managerMetrics, ManagerSubmanager, "power_state", "manager power state", ManagerLabelNames)
36+
37+
addToMetricMap(managerMetrics, ManagerSubmanager, "log_service_state", fmt.Sprintf("manager log service state,%s", CommonStateHelp), ManagerLogServiceLabelNames)
38+
addToMetricMap(managerMetrics, ManagerSubmanager, "log_service_health_state", fmt.Sprintf("manager log service health state,%s", CommonHealthHelp), ManagerLogServiceLabelNames)
39+
addToMetricMap(managerMetrics, ManagerSubmanager, "log_entry_severity_state", fmt.Sprintf("manager log entry severity state,%s", CommonSeverityHelp), ManagerLogEntryLabelNames)
40+
41+
return managerMetrics
5642
}
5743

5844
// NewManagerCollector returns a collector that collecting memory statistics
59-
func NewManagerCollector(namespace string, redfishClient *gofish.APIClient, logger *log.Entry) *ManagerCollector {
45+
func NewManagerCollector(redfishClient *gofish.APIClient, logger *log.Entry) *ManagerCollector {
6046
return &ManagerCollector{
6147
redfishClient: redfishClient,
6248
metrics: managerMetrics,
@@ -100,7 +86,7 @@ func (m *ManagerCollector) Collect(ch chan<- prometheus.Metric) {
10086
ManagerID := manager.ID
10187
managerName := manager.Name
10288
managerModel := manager.Model
103-
managerType := fmt.Sprintf("%v", manager.ManagerType)
89+
managerType := fmt.Sprint(manager.ManagerType)
10490
managerPowerState := manager.PowerState
10591
managerState := manager.Status.State
10692
managerHealthState := manager.Status.Health
@@ -115,8 +101,25 @@ func (m *ManagerCollector) Collect(ch chan<- prometheus.Metric) {
115101
}
116102
if managerPowerStateValue, ok := parseCommonPowerState(managerPowerState); ok {
117103
ch <- prometheus.MustNewConstMetric(m.metrics["manager_power_state"].desc, prometheus.GaugeValue, managerPowerStateValue, ManagerLabelValues...)
104+
}
118105

106+
// 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")
119+
}
120+
}
119121
}
122+
120123
managerLogContext.Info("collector scrape completed")
121124
}
122125
m.collectorScrapeStatus.WithLabelValues("manager").Set(float64(1))

collector/redfish_collector.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ func NewRedfishCollector(host string, username string, password string, logger *
4747
if err != nil {
4848
collectorLogCtx.WithError(err).Error("error creating redfish client")
4949
} else {
50-
chassisCollector := NewChassisCollector(namespace, redfishClient, collectorLogCtx)
51-
systemCollector := NewSystemCollector(namespace, redfishClient, collectorLogCtx)
52-
managerCollector := NewManagerCollector(namespace, redfishClient, collectorLogCtx)
50+
chassisCollector := NewChassisCollector(redfishClient, collectorLogCtx)
51+
systemCollector := NewSystemCollector(redfishClient, collectorLogCtx)
52+
managerCollector := NewManagerCollector(redfishClient, collectorLogCtx)
5353

5454
collectors = map[string]prometheus.Collector{"chassis": chassisCollector, "system": systemCollector, "manager": managerCollector}
5555
}
@@ -159,6 +159,17 @@ func parseCommonStatusState(status gofishcommon.State) (float64, bool) {
159159
return float64(0), false
160160
}
161161

162+
func parseCommonSeverityState(severity redfish.EventSeverity) (float64, bool) {
163+
if bytes.Equal([]byte(severity), []byte("OK")) {
164+
return float64(1), true
165+
} else if bytes.Equal([]byte(severity), []byte("Warning")) {
166+
return float64(2), true
167+
} else if bytes.Equal([]byte(severity), []byte("Critical")) {
168+
return float64(3), true
169+
}
170+
return float64(0), false
171+
}
172+
162173
func parseCommonPowerState(status redfish.PowerState) (float64, bool) {
163174
if bytes.Equal([]byte(status), []byte("On")) {
164175
return float64(1), true
@@ -186,7 +197,7 @@ func parseLinkStatus(status redfish.LinkStatus) (float64, bool) {
186197
func parsePortLinkStatus(status redfish.PortLinkStatus) (float64, bool) {
187198
if bytes.Equal([]byte(status), []byte("Up")) {
188199
return float64(1), true
189-
}
200+
}
190201
return float64(0), false
191202
}
192203
func boolToFloat64(data bool) float64 {

0 commit comments

Comments
 (0)