diff --git a/cmd/server/main.go b/cmd/server/main.go index a6459d8..26e2c8e 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -56,7 +56,7 @@ func main() { log.Printf("Got authentication cookie: %s\n", ucsClient.Cookie) // Register prometheus exporters - exporter := exporters.NewUcsmTemperatureCollector(ucsClient, ctx) + exporter := exporters.NewUcsmExporters(ucsClient, ctx) prometheus.MustRegister(exporter) // Start prometheus exporter @@ -64,4 +64,6 @@ func main() { // TODO - run this in a go routine to avoid blocking, as per cbs code log.Fatal(http.ListenAndServe(*listenPort, nil)) + + // TODO - log off from UCS manager } diff --git a/go.mod b/go.mod index c0fa8e5..71b2d95 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21.0 require ( github.com/dnaeon/go-ucs v0.0.0-20180427075322-a04ea35bf5de github.com/prometheus/client_golang v1.16.0 + golang.org/x/sync v0.2.0 ) require ( @@ -20,4 +21,4 @@ require ( google.golang.org/protobuf v1.30.0 // indirect ) -replace github.com/dnaeon/go-ucs => ./local/go-ucs \ No newline at end of file +replace github.com/dnaeon/go-ucs => ./local/go-ucs diff --git a/go.sum b/go.sum index 237f85a..5ad61e3 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-ucs v0.0.0-20180427075322-a04ea35bf5de h1:TPQ2PEbeZy0m8Y/zO+IQx9pUDMqfanACLJqREaLroJU= -github.com/dnaeon/go-ucs v0.0.0-20180427075322-a04ea35bf5de/go.mod h1:CnATpmPv6+QWYn/4O/qrRmxhSvfsiTMB4mVBfsWwKs8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -25,6 +23,8 @@ github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= diff --git a/internal/exporters/UcsmBlade.go b/internal/exporters/UcsmBlade.go deleted file mode 100644 index 9a0c73d..0000000 --- a/internal/exporters/UcsmBlade.go +++ /dev/null @@ -1,77 +0,0 @@ -package exporters - -import ( - "context" - "encoding/xml" - "log" - - "github.com/dnaeon/go-ucs/api" - "github.com/dnaeon/go-ucs/mo" - "github.com/prometheus/client_golang/prometheus" -) - -type UcsmBladeCollector struct { - ucsClient *api.Client - ctx context.Context -} - -/* - type ComputeMbTempStats struct { - XMLName xml.Name `xml:"computeMbTempStats"` - Dn string `xml:"dn,attr,omitempty"` - FmTempSenIo string `xml:"fmTempSenIo,attr,omitempty"` - FmTempSenRear string `xml:"fmTempSenRear,attr,omitempty"` - } -*/ -func NewUcsmBladeCollector(client *api.Client, ctx context.Context) *UcsmTemperaturesCollector { - return &UcsmTemperaturesCollector{ - ucsClient: client, - ctx: ctx, - } -} - -// Describe prometheus describe -func (u *UcsmBladeCollector) Describe(ch chan<- *prometheus.Desc) { - log.Printf("Running Describe for UcsmTemperaturesCollector\n") - ch <- prometheus.NewDesc("ucsm_temperature_sensor", - "UCSM temperature sensor for motherboard/cpu/psu", - []string{"server", "component", "description"}, nil, - ) - ch <- prometheus.NewDesc("ucsm_temperature_sensor", - "UCSM temperature sensor for motherboard/cpu/psu", - []string{"server", "component", "description"}, nil, - ) -} - -// Collect prometheus collect -func (u *UcsmBladeCollector) Collect(ch chan<- prometheus.Metric) { - // The type into which we unmarshal the result data - type blades struct { - XMLName xml.Name - Blades []mo.ComputeBlade `xml:"computeBlade"` - } - - bladeRequest := api.ConfigResolveClassRequest{ - Cookie: u.ucsClient.Cookie, - ClassId: "computeBlade", - InHierarchical: "false", - } - - var bladeList blades - - log.Println("Retrieving managed objects with class `computeBlade`") - - if err := u.ucsClient.ConfigResolveClass(u.ctx, bladeRequest, &bladeList); err != nil { - log.Fatalf("Unable to retrieve `computeBlade` managed object: %s", err) - } - - log.Printf("Retrieved %d compute blades\n", len(bladeList.Blades)) - for _, blade := range bladeList.Blades { - log.Printf("%s:\n", blade.Dn) - log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus) - log.Printf("\tTotal Memory: %d\n", blade.TotalMemory) - log.Printf("\tModel: %s\n", blade.Model) - log.Printf("\tVendor: %s\n", blade.Vendor) - } - -} diff --git a/internal/exporters/UcsmPortStats.go b/internal/exporters/UcsmPortStats.go new file mode 100644 index 0000000..11b08c5 --- /dev/null +++ b/internal/exporters/UcsmPortStats.go @@ -0,0 +1,123 @@ +package exporters + +import ( + "context" + "encoding/xml" + "log" + "strings" + + "github.com/dnaeon/go-ucs/api" + "github.com/dnaeon/go-ucs/mo" +) + +// Define the fields we will send back to the collector +type UcsmVnicPortStats struct { + Server string + Component string + Metrics map[string]uint64 +} + +func (u *UcsExporters) GetUcsmPortStats(ctx context.Context, ucsmPortStatsChannel chan []UcsmVnicPortStats) { + + portStatsResults := make([]UcsmVnicPortStats, 0) + + // The type into which we unmarshal the result data + type vnicStats struct { + XMLName xml.Name + VnicStats []mo.AdaptorVnicStats `xml:"adaptorVnicStats"` + } + + // Define the request we are making to UCS Manager + vnicStatsRequest := api.ConfigResolveClassRequest{ + Cookie: u.ucsClient.Cookie, + ClassId: "adaptorVnicStats", + InHierarchical: "false", + } + + var vnicStatsObject vnicStats + + log.Println("Retrieving managed objects with class `adaptorVnicStats`") + + if err := u.ucsClient.ConfigResolveClass(u.ctx, vnicStatsRequest, &vnicStatsObject); err != nil { + log.Fatalf("Unable to retrieve `computeMbTempStats` managed object: %s", err) + } + + log.Printf("Retrieved port stats for %d vnics\n", len(vnicStatsObject.VnicStats)) + for _, vnic := range vnicStatsObject.VnicStats { + var bladeDn string + + // Extract the bladeDn + startIndex := strings.Index(vnic.Dn, "/adaptor-") + if startIndex != -1 { + bladeDn = vnic.Dn[:startIndex] + } else { + bladeDn = vnic.Dn + } + + log.Printf("Network stats for blade %s and component %s:\n", bladeDn, vnic.Dn) + log.Printf("Bytes Rx: %d, Bytes Tx: %d\n", vnic.BytesRx, vnic.BytesTx) + log.Printf("Packets Rx: %d, Packets Tx: %d\n", vnic.PacketsRx, vnic.PacketsTx) + log.Printf("Dropped Rx: %d, Dropped Tx: %d\n", vnic.DroppedRx, vnic.DroppedTx) + log.Printf("Error Rx: %d, Error Tx: %d\n", vnic.ErrorsRx, vnic.ErrorsTx) + + // Create a map of all the values we care about + portMetrics := make(map[string]uint64) + portMetrics["ucsm_vnic_rx_total_packets"] = vnic.PacketsRx + portMetrics["ucsm_vnic_tx_total_packets"] = vnic.PacketsTx + portMetrics["ucsm_vnic_rx_total_bytes"] = vnic.BytesRx + portMetrics["ucsm_vnic_tx_total_bytes"] = vnic.BytesTx + portMetrics["ucsm_vnic_rx_dropped"] = vnic.DroppedRx + portMetrics["ucsm_vnic_tx_dropped"] = vnic.DroppedTx + portMetrics["ucsm_vnic_rx_error"] = vnic.ErrorsRx + portMetrics["ucsm_vnic_tx_error"] = vnic.ErrorsTx + + // Add the metrics along with the other properties to the results + vnicPortStats := UcsmVnicPortStats{ + Server: bladeDn, + Component: vnic.Dn, + Metrics: portMetrics, + } + + portStatsResults = append(portStatsResults, vnicPortStats) + + /* + // Substring the Dn for the temperatures to get the Dn for the parent blade itself + bladeDn := strings.Replace(temps.Dn, "/board/temp-stats", "", -1) + + log.Printf("Temps for blade %s:\n", bladeDn) + log.Printf("Front Temperature: %v\n", temps.FmTempSenIo) + log.Printf("Rear Temperature: %v\n", temps.FmTempSenRear) + + boardTempFront := UcsmPortStats{ + Server: bladeDn, + Component: temps.Dn, + Description: "motherboard_front_temperature", + Value: temps.FmTempSenIo, + } + + boardTempRear := UcsmPortStats{ + Server: bladeDn, + Component: temps.Dn, + Description: "motherboard_rear_temperature", + Value: temps.FmTempSenRear, + } + + portStatsResults = append(portStatsResults, boardTempFront) + portStatsResults = append(portStatsResults, boardTempRear) + */ + /* + // TODO - work out a better way of running this twice, once for each temperature sensor + + metric1 := prometheus.MustNewConstMetric(u.UcsmTemperatures, prometheus.GaugeValue, temps.FmTempSenIo, bladeDn, temps.Dn, "motherboard_rear_temperature") + // send the data + ch <- metric1 + + // generate the metric + metric2 := prometheus.MustNewConstMetric(u.UcsmTemperatures, prometheus.GaugeValue, temps.FmTempSenRear, bladeDn, temps.Dn, "motherboard_front_temperature") + // send the data + ch <- metric2 + */ + } + log.Printf("GetUcsmPortStats sending results to channel\n") + ucsmPortStatsChannel <- portStatsResults +} diff --git a/internal/exporters/UcsmTemperatures.go b/internal/exporters/UcsmTemperatures.go index 05dcfeb..7c8fd26 100644 --- a/internal/exporters/UcsmTemperatures.go +++ b/internal/exporters/UcsmTemperatures.go @@ -8,9 +8,17 @@ import ( "github.com/dnaeon/go-ucs/api" "github.com/dnaeon/go-ucs/mo" - "github.com/prometheus/client_golang/prometheus" ) +// Define the fields we will send back to the collector +type UcsmTemperatures struct { + Server string + Component string + Description string + Value float64 +} + +/* type UcsmTemperaturesCollector struct { ucsClient *api.Client ctx context.Context @@ -18,6 +26,7 @@ type UcsmTemperaturesCollector struct { } var metrics []prometheus.Desc +*/ //var ucsClient *api.Client //var ctx context.Context @@ -30,64 +39,44 @@ var metrics []prometheus.Desc FmTempSenRear string `xml:"fmTempSenRear,attr,omitempty"` } */ -func NewUcsmTemperatureCollector(client *api.Client, ctx context.Context) *UcsmTemperaturesCollector { +/* +func NewUcsmTemperatureCollector(client *api.Client, ctx context.Context) *UcsExporters { - /* - ucsClient = client - ctx = ctx - */ - /* - return &main.Collector{ - UcsmTemperature: prometheus.NewDesc("ucsm_temperature_sensor", - "UCSM temperature sensor for motherboard/cpu/psu", - []string{"server", "component", "description"}, nil, - ), - } - */ - - return &UcsmTemperaturesCollector{ + return &UcsExporters{ ucsClient: client, ctx: ctx, - metrics: []*prometheus.Desc{ - prometheus.NewDesc( - "ucsm_temperature_sensor", - "UCSM temperature sensor for motherboard/cpu/psu", - []string{"server", "component", "description"}, nil, - ), - }, + UcsmTemperatures: prometheus.NewDesc("ucsm_temperature_sensor", + "UCSM temperature sensor for motherboard/cpu/psu", + []string{"server", "component", "description"}, nil, + ), } } // Describe prometheus describe -func (u *UcsmTemperaturesCollector) Describe(ch chan<- *prometheus.Desc) { +func (u *UcsExporters) Describe(ch chan<- *prometheus.Desc) { log.Printf("Running Describe for UcsmTemperaturesCollector\n") - // Describe the metrics and send them on the channel - for _, desc := range u.metrics { - ch <- desc - } - - /* - metricDesc := prometheus.NewDesc("ucsm_temperature_sensor", - "UCSM temperature sensor for motherboard/cpu/psu", - []string{"server", "component", "description"}, nil) - - fmt.Printf("metricDesc: %v\n", *metricDesc) - - metrics = append(metrics, *metricDesc) - ch <- metricDesc - */ + ch <- u.UcsmTemperatures } +*/ // Collect prometheus collect -func (u *UcsmTemperaturesCollector) Collect(ch chan<- prometheus.Metric) { +func (u *UcsExporters) GetUcsmTemperatures(ctx context.Context, ucsmTempsChannel chan []UcsmTemperatures) { + /* + wg.Add(1) + defer wg.Done() + defer close(ucsmTempsChannel) + */ + temperatureResults := make([]UcsmTemperatures, 0) + // The type into which we unmarshal the result data type temps struct { XMLName xml.Name Temperatures []mo.ComputeMbTempStats `xml:"computeMbTempStats"` } + // Define the request we are making to UCS Manager tempRequest := api.ConfigResolveClassRequest{ Cookie: u.ucsClient.Cookie, ClassId: "computeMbTempStats", @@ -96,6 +85,7 @@ func (u *UcsmTemperaturesCollector) Collect(ch chan<- prometheus.Metric) { var boardTempList temps + //cswg := new(sync.WaitGroup) log.Println("Retrieving managed objects with class `computeMbTempStats`") if err := u.ucsClient.ConfigResolveClass(u.ctx, tempRequest, &boardTempList); err != nil { @@ -111,28 +101,41 @@ func (u *UcsmTemperaturesCollector) Collect(ch chan<- prometheus.Metric) { log.Printf("Front Temperature: %v\n", temps.FmTempSenIo) log.Printf("Rear Temperature: %v\n", temps.FmTempSenRear) - // TODO - work out a better way of running this twice, once for each temperature sensor + boardTempFront := UcsmTemperatures{ + Server: bladeDn, + Component: temps.Dn, + Description: "motherboard_front_temperature", + Value: temps.FmTempSenIo, + } - // Collect the actual metric values and send them on the channel - for _, desc := range u.metrics { + boardTempRear := UcsmTemperatures{ + Server: bladeDn, + Component: temps.Dn, + Description: "motherboard_rear_temperature", + Value: temps.FmTempSenRear, + } - // populate the labels array - //labelValues := []string{bladeDn, temps.Dn, "motherboard_rear_temperature"} + temperatureResults = append(temperatureResults, boardTempFront) + temperatureResults = append(temperatureResults, boardTempRear) - // generate the metric - metric1 := prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, temps.FmTempSenIo, bladeDn, temps.Dn, "motherboard_rear_temperature") + /* + // TODO - work out a better way of running this twice, once for each temperature sensor + + metric1 := prometheus.MustNewConstMetric(u.UcsmTemperatures, prometheus.GaugeValue, temps.FmTempSenIo, bladeDn, temps.Dn, "motherboard_rear_temperature") // send the data ch <- metric1 // generate the metric - metric2 := prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, temps.FmTempSenRear, bladeDn, temps.Dn, "motherboard_front_temperature") + metric2 := prometheus.MustNewConstMetric(u.UcsmTemperatures, prometheus.GaugeValue, temps.FmTempSenRear, bladeDn, temps.Dn, "motherboard_front_temperature") // send the data ch <- metric2 - } - - //ch <- prometheus.MustNewConstMetric() + */ } + //cswg.Wait() + log.Printf("GetUcsmTemperatures sending results to channel\n") + ucsmTempsChannel <- temperatureResults + //return } /* diff --git a/internal/exporters/exporters.go b/internal/exporters/exporters.go new file mode 100644 index 0000000..dcd97ae --- /dev/null +++ b/internal/exporters/exporters.go @@ -0,0 +1,141 @@ +package exporters + +import ( + "context" + "log" + + "github.com/dnaeon/go-ucs/api" + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sync/errgroup" +) + +type UcsExporters struct { + // Define each type of metric here + UcsmTemperatures *prometheus.Desc + UcsmVnicStatsRxTotalPkts *prometheus.Desc + UcsmVnicStatsTxTotalPkts *prometheus.Desc + UcsmVnicStatsRxTotalBytes *prometheus.Desc + UcsmVnicStatsTxTotalBytes *prometheus.Desc + UcsmVnicStatsRxDropped *prometheus.Desc + UcsmVnicStatsTxDropped *prometheus.Desc + UcsmVnicStatsRxError *prometheus.Desc + UcsmVnicStatsTxError *prometheus.Desc + + // Additional properties required + ucsClient *api.Client + ctx context.Context +} + +func NewUcsmExporters(client *api.Client, ctx context.Context) *UcsExporters { + return &UcsExporters{ + ucsClient: client, + ctx: ctx, + // UCS Temperatures + UcsmTemperatures: prometheus.NewDesc("ucsm_temperature_sensor", + "UCSM temperature sensor for motherboard/cpu/psu", + []string{"server", "component", "description"}, nil, + ), + // UCS Network statistics + UcsmVnicStatsRxTotalPkts: prometheus.NewDesc("ucsm_vnic_rx_total_packets", + "UCSM Ethernet RX counter: total_packets", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsTxTotalPkts: prometheus.NewDesc("ucsm_vnic_tx_total_packets", + "UCSM Ethernet TX counter: total_packets", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsRxTotalBytes: prometheus.NewDesc("ucsm_vnic_rx_total_bytes", + "UCSM Ethernet RX counter: total_bytes", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsTxTotalBytes: prometheus.NewDesc("ucsm_vnic_tx_total_bytes", + "UCSM Ethernet TX counter: total_bytes", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsRxDropped: prometheus.NewDesc("ucsm_vnic_rx_dropped", + "UCSM Ethernet Rx Dropped counter: total_count", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsTxDropped: prometheus.NewDesc("ucsm_vnic_tx_dropped", + "UCSM Ethernet Tx Dropped counter: total_count", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsRxError: prometheus.NewDesc("ucsm_vnic_rx_error", + "UCSM Ethernet Rx Error counter: total_count", + []string{"server", "component", "description"}, nil, + ), + UcsmVnicStatsTxError: prometheus.NewDesc("ucsm_vnic_tx_error", + "UCSM Ethernet Tx Error counter: total_count", + []string{"server", "component", "description"}, nil, + ), + } +} + +// Describe prometheus describe +func (u *UcsExporters) Describe(ch chan<- *prometheus.Desc) { + log.Printf("Running Describe for UcsExporters\n") + + // UCS Temperatures + ch <- u.UcsmTemperatures + + // UCS Network statistics + ch <- u.UcsmVnicStatsRxTotalPkts + ch <- u.UcsmVnicStatsTxTotalPkts + ch <- u.UcsmVnicStatsRxTotalBytes + ch <- u.UcsmVnicStatsTxTotalBytes + ch <- u.UcsmVnicStatsRxDropped + ch <- u.UcsmVnicStatsTxDropped + ch <- u.UcsmVnicStatsRxError + ch <- u.UcsmVnicStatsTxError +} + +// Collect prometheus collect +func (u *UcsExporters) Collect(ch chan<- prometheus.Metric) { + + // TODO - refresh UCS Manager login session + + //var wg = sync.WaitGroup{} + g, gCtx := errgroup.WithContext(u.ctx) + + // Create channels to receive values + ucsmTempsChannel := make(chan []UcsmTemperatures) + ucsmPortStatsChannel := make(chan []UcsmVnicPortStats) + + log.Printf("Running Collect for UCS Temperatures\n") + g.Go(func() error { + u.GetUcsmTemperatures(gCtx, ucsmTempsChannel) + return nil + }) + + log.Printf("Running Collect for UCS Network Statistics\n") + g.Go(func() error { + u.GetUcsmPortStats(gCtx, ucsmPortStatsChannel) + return nil + }) + + // Receive results from exporter channels + ucsmTempResults := <-ucsmTempsChannel + ucsmVnicStatsResults := <-ucsmPortStatsChannel + + //wg.Wait() + + // Send results back to prometheus channel + for _, blade := range ucsmTempResults { + log.Printf("Generating constant metric for component %s with value %f\n", blade.Component, blade.Value) + ch <- prometheus.MustNewConstMetric(u.UcsmTemperatures, prometheus.GaugeValue, blade.Value, blade.Server, blade.Component, blade.Description) + } + + for _, vnic := range ucsmVnicStatsResults { + log.Printf("Generating constant metric for component %s\n", vnic.Component) + + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsRxTotalPkts, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_rx_total_packets"]), vnic.Server, vnic.Component, "ucsm_vnic_rx_total_packets") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsTxTotalPkts, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_tx_total_packets"]), vnic.Server, vnic.Component, "ucsm_vnic_tx_total_packets") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsRxTotalBytes, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_rx_total_bytes"]), vnic.Server, vnic.Component, "ucsm_vnic_rx_total_bytes") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsTxTotalBytes, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_tx_total_bytes"]), vnic.Server, vnic.Component, "ucsm_vnic_tx_total_bytes") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsRxDropped, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_rx_dropped"]), vnic.Server, vnic.Component, "ucsm_vnic_rx_dropped") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsTxDropped, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_tx_dropped"]), vnic.Server, vnic.Component, "ucsm_vnic_tx_dropped") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsRxError, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_rx_error"]), vnic.Server, vnic.Component, "ucsm_vnic_rx_error") + ch <- prometheus.MustNewConstMetric(u.UcsmVnicStatsTxError, prometheus.GaugeValue, float64(vnic.Metrics["ucsm_vnic_tx_error"]), vnic.Server, vnic.Component, "ucsm_vnic_tx_error") + } + +} diff --git a/internal/exporters/structs.go b/internal/exporters/structs.go new file mode 100644 index 0000000..f701664 --- /dev/null +++ b/internal/exporters/structs.go @@ -0,0 +1 @@ +package exporters diff --git a/local/go-ucs/mo/mo.go b/local/go-ucs/mo/mo.go index dcebecb..03847b5 100755 --- a/local/go-ucs/mo/mo.go +++ b/local/go-ucs/mo/mo.go @@ -359,6 +359,26 @@ type ProcessorUnit struct { Voltage string `xml:"voltage,attr,omitempty"` } +// AdaptorVnicStats is a managed object representing statistics for a network adaptor +// Added by Nathan. Incomplete representation of all data available +type AdaptorVnicStats struct { + XMLName xml.Name `xml:"adaptorVnicStats"` + Dn string `xml:"dn,attr,omitempty"` + Rn string `xml:"rn,attr,omitempty"` + BytesRx uint64 `xml:"bytesRx,attr,omitempty"` + BytesRxDelta uint64 `xml:"bytesRxDelta,attr,omitempty"` + BytesTx uint64 `xml:"bytesTx,attr,omitempty"` + BytesTxDelta uint64 `xml:"bytesTxDelta,attr,omitempty"` + PacketsRx uint64 `xml:"packetsRx,attr,omitempty"` + PacketsRxDelta uint64 `xml:"packetsRxDelta,attr,omitempty"` + PacketsTx uint64 `xml:"packetsTx,attr,omitempty"` + PacketsTxDelta uint64 `xml:"packetsTxDelta,attr,omitempty"` + DroppedRx uint64 `xml:"droppedRx,attr,omitempty"` + DroppedTx uint64 `xml:"droppedTx,attr,omitempty"` + ErrorsRx uint64 `xml:"errorsRx,attr,omitempty"` + ErrorsTx uint64 `xml:"errorsTx,attr,omitempty"` +} + // AdaptorUnit is a managed object representing a network adaptor unit such as a // card that has NIC and/or HBA, SCSI functionality. type AdaptorUnit struct {