diff --git a/README.md b/README.md index 38ff4edf..4102c91b 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ diskstats | Exposes disk I/O statistics. | Darwin, Linux, OpenBSD edac | Exposes error detection and correction statistics. | Linux entropy | Exposes available entropy. | Linux exec | Exposes execution statistics. | Dragonfly, FreeBSD +fibrechannel | Exposes fibre channel information and statistics from `/sys/class/fc_host/`. | Linux filefd | Exposes file descriptor statistics from `/proc/sys/fs/file-nr`. | Linux filesystem | Exposes filesystem statistics, such as disk space used. | Darwin, Dragonfly, FreeBSD, Linux, OpenBSD hwmon | Expose hardware monitoring and sensor data from `/sys/class/hwmon/`. | Linux diff --git a/collector/fibrechannel_linux.go b/collector/fibrechannel_linux.go new file mode 100644 index 00000000..0f1a1b0c --- /dev/null +++ b/collector/fibrechannel_linux.go @@ -0,0 +1,149 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build linux +// +build !nofibrechannel + +package collector + +import ( + "fmt" + "os" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs/sysfs" +) + +const maxUint64 = ^uint64(0) + +type fibrechannelCollector struct { + fs sysfs.FS + metricDescs map[string]*prometheus.Desc + logger log.Logger + subsystem string +} + +func init() { + registerCollector("fibrechannel", defaultEnabled, NewFibreChannelCollector) +} + +// NewFibreChannelCollector returns a new Collector exposing FibreChannel stats. +func NewFibreChannelCollector(logger log.Logger) (Collector, error) { + var i fibrechannelCollector + var err error + + i.fs, err = sysfs.NewFS(*sysPath) + if err != nil { + return nil, fmt.Errorf("failed to open sysfs: %w", err) + } + i.logger = logger + + // Detailed description for all metrics. + descriptions := map[string]string{ + "dumped_frames_total": "Number of dumped frames", + "loss_of_signal_total": "Number of times signal has been lost", + "loss_of_sync_total": "Number of failures on either bit or transmission word boundaries", + "rx_frames_total": "Number of frames received", + "error_frames_total": "Number of errors in frames", + "invalid_tx_words_total": "Number of invalid words transmitted by host port", + "seconds_since_last_reset_total": "Number of seconds since last host port reset", + "tx_words_total": "Number of words transmitted by host port", + "invalid_crc_total": "Invalid Cyclic Redundancy Check count", + "nos_total": "Number Not_Operational Primitive Sequence received by host port", + "fcp_packet_aborts_total": "Number of aborted packets", + "rx_words_total": "Number of words received by host port", + "tx_frames_total": "Number of frames transmitted by host port", + "link_failure_total": "Number of times the host port link has failed", + "name": "Name of Fibre Channel HBA", + "speed": "Current operating speed", + "port_state": "Current port state", + "port_type": "Port type, what the port is connected to", + "symbolic_name": "Symoblic Name", + "node_name": "Node Name as hexadecimal string", + "port_id": "Port ID as string", + "port_name": "Port Name as hexadecimal string", + "fabric_name": "Fabric Name; 0 if PTP", + "dev_loss_tmo": "Device Loss Timeout in seconds", + "supported_classes": "The FC classes supported", + "supported_speeds": "The FC speeds supported", + } + + i.metricDescs = make(map[string]*prometheus.Desc) + i.subsystem = "fibrechannel" + + for metricName, description := range descriptions { + i.metricDescs[metricName] = prometheus.NewDesc( + prometheus.BuildFQName(namespace, i.subsystem, metricName), + description, + []string{"fc_host"}, + nil, + ) + } + + return &i, nil +} + +func (c *fibrechannelCollector) pushMetric(ch chan<- prometheus.Metric, name string, value uint64, host string, valueType prometheus.ValueType) { + ch <- prometheus.MustNewConstMetric(c.metricDescs[name], valueType, float64(value), host) +} + +func (c *fibrechannelCollector) pushCounter(ch chan<- prometheus.Metric, name string, value uint64, host string) { + // Don't push counters that aren't implemented (a counter equal to maxUint64 is unimplemented by the HBA firmware) + if value != maxUint64 { + c.pushMetric(ch, name, value, host, prometheus.CounterValue) + } +} + +func (c *fibrechannelCollector) Update(ch chan<- prometheus.Metric) error { + hosts, err := c.fs.FibreChannelClass() + if err != nil { + if os.IsNotExist(err) { + level.Debug(c.logger).Log("msg", "fibrechannel statistics not found, skipping") + return ErrNoData + } + return fmt.Errorf("error obtaining FibreChannel class info: %s", err) + } + + for _, host := range hosts { + infoDesc := prometheus.NewDesc( + prometheus.BuildFQName(namespace, c.subsystem, "info"), + "Non-numeric data from /sys/class/fc_host/, value is always 1.", + []string{"fc_host", "speed", "port_state", "port_type", "port_id", "port_name", "fabric_name", "symbolic_name", "supported_classes", "supported_speeds", "dev_loss_tmo"}, + nil, + ) + infoValue := 1.0 + + // First push the Host values + ch <- prometheus.MustNewConstMetric(infoDesc, prometheus.GaugeValue, infoValue, host.Name, host.Speed, host.PortState, host.PortType, host.PortID, host.PortName, host.FabricName, host.SymbolicName, host.SupportedClasses, host.SupportedSpeeds, host.DevLossTMO) + + // Then the counters + c.pushCounter(ch, "dumped_frames_total", host.Counters.DumpedFrames, host.Name) + c.pushCounter(ch, "error_frames_total", host.Counters.ErrorFrames, host.Name) + c.pushCounter(ch, "invalid_crc_total", host.Counters.InvalidCRCCount, host.Name) + c.pushCounter(ch, "rx_frames_total", host.Counters.RXFrames, host.Name) + c.pushCounter(ch, "rx_words_total", host.Counters.RXWords, host.Name) + c.pushCounter(ch, "tx_frames_total", host.Counters.TXFrames, host.Name) + c.pushCounter(ch, "tx_words_total", host.Counters.TXWords, host.Name) + c.pushCounter(ch, "seconds_since_last_reset_total", host.Counters.SecondsSinceLastReset, host.Name) + c.pushCounter(ch, "invalid_tx_words_total", host.Counters.InvalidTXWordCount, host.Name) + c.pushCounter(ch, "link_failure_total", host.Counters.LinkFailureCount, host.Name) + c.pushCounter(ch, "loss_of_sync_total", host.Counters.LossOfSyncCount, host.Name) + c.pushCounter(ch, "loss_of_signal_total", host.Counters.LossOfSignalCount, host.Name) + c.pushCounter(ch, "nos_total", host.Counters.NosCount, host.Name) + c.pushCounter(ch, "fcp_packet_aborts_total", host.Counters.FCPPacketAborts, host.Name) + } + + return nil +} diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index 79e3ca93..6ff9eef9 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -659,6 +659,48 @@ node_entropy_available_bits 1337 node_entropy_pool_size_bits 4096 # HELP node_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which node_exporter was built. # TYPE node_exporter_build_info gauge +# HELP node_fibrechannel_error_frames_total Number of errors in frames +# TYPE node_fibrechannel_error_frames_total counter +node_fibrechannel_error_frames_total{fc_host="host0"} 0 +# HELP node_fibrechannel_fcp_packet_aborts_total Number of aborted packets +# TYPE node_fibrechannel_fcp_packet_aborts_total counter +node_fibrechannel_fcp_packet_aborts_total{fc_host="host0"} 19 +# HELP node_fibrechannel_info Non-numeric data from /sys/class/fc_host/, value is always 1. +# TYPE node_fibrechannel_info gauge +node_fibrechannel_info{dev_loss_tmo="30",fabric_name="0",fc_host="host0",port_id="000002",port_name="1000e0071bce95f2",port_state="Online",port_type="Point-To-Point (direct nport connection)",speed="16 Gbit",supported_classes="Class 3",supported_speeds="4 Gbit, 8 Gbit, 16 Gbit",symbolic_name="Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux"} 1 +# HELP node_fibrechannel_invalid_crc_total Invalid Cyclic Redundancy Check count +# TYPE node_fibrechannel_invalid_crc_total counter +node_fibrechannel_invalid_crc_total{fc_host="host0"} 2 +# HELP node_fibrechannel_invalid_tx_words_total Number of invalid words transmitted by host port +# TYPE node_fibrechannel_invalid_tx_words_total counter +node_fibrechannel_invalid_tx_words_total{fc_host="host0"} 8 +# HELP node_fibrechannel_link_failure_total Number of times the host port link has failed +# TYPE node_fibrechannel_link_failure_total counter +node_fibrechannel_link_failure_total{fc_host="host0"} 9 +# HELP node_fibrechannel_loss_of_signal_total Number of times signal has been lost +# TYPE node_fibrechannel_loss_of_signal_total counter +node_fibrechannel_loss_of_signal_total{fc_host="host0"} 17 +# HELP node_fibrechannel_loss_of_sync_total Number of failures on either bit or transmission word boundaries +# TYPE node_fibrechannel_loss_of_sync_total counter +node_fibrechannel_loss_of_sync_total{fc_host="host0"} 16 +# HELP node_fibrechannel_nos_total Number Not_Operational Primitive Sequence received by host port +# TYPE node_fibrechannel_nos_total counter +node_fibrechannel_nos_total{fc_host="host0"} 18 +# HELP node_fibrechannel_rx_frames_total Number of frames received +# TYPE node_fibrechannel_rx_frames_total counter +node_fibrechannel_rx_frames_total{fc_host="host0"} 3 +# HELP node_fibrechannel_rx_words_total Number of words received by host port +# TYPE node_fibrechannel_rx_words_total counter +node_fibrechannel_rx_words_total{fc_host="host0"} 4 +# HELP node_fibrechannel_seconds_since_last_reset_total Number of seconds since last host port reset +# TYPE node_fibrechannel_seconds_since_last_reset_total counter +node_fibrechannel_seconds_since_last_reset_total{fc_host="host0"} 7 +# HELP node_fibrechannel_tx_frames_total Number of frames transmitted by host port +# TYPE node_fibrechannel_tx_frames_total counter +node_fibrechannel_tx_frames_total{fc_host="host0"} 5 +# HELP node_fibrechannel_tx_words_total Number of words transmitted by host port +# TYPE node_fibrechannel_tx_words_total counter +node_fibrechannel_tx_words_total{fc_host="host0"} 6 # HELP node_filefd_allocated File descriptor statistics: allocated. # TYPE node_filefd_allocated gauge node_filefd_allocated 1024 @@ -2685,6 +2727,7 @@ node_scrape_collector_success{collector="diskstats"} 1 node_scrape_collector_success{collector="drbd"} 1 node_scrape_collector_success{collector="edac"} 1 node_scrape_collector_success{collector="entropy"} 1 +node_scrape_collector_success{collector="fibrechannel"} 1 node_scrape_collector_success{collector="filefd"} 1 node_scrape_collector_success{collector="hwmon"} 1 node_scrape_collector_success{collector="infiniband"} 1 diff --git a/collector/fixtures/sys.ttar b/collector/fixtures/sys.ttar index 3e52c609..0392d205 100644 --- a/collector/fixtures/sys.ttar +++ b/collector/fixtures/sys.ttar @@ -38,6 +38,140 @@ SymlinkTo: ../../../devices/system/node/node1 Directory: sys/class Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/class/fc_host +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/class/fc_host/host0 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/dev_loss_tmo +Lines: 1 +30 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/fabric_name +Lines: 1 +0x0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/node_name +Lines: 1 +0x2000e0071bce95f2 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/port_id +Lines: 1 +0x000002 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/port_name +Lines: 1 +0x1000e0071bce95f2 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/port_state +Lines: 1 +Online +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/port_type +Lines: 1 +Point-To-Point (direct nport connection) +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/speed +Lines: 1 +16 Gbit +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/class/fc_host/host0/statistics +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/dumped_frames +Lines: 1 +0xffffffffffffffff +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/error_frames +Lines: 1 +0x0 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/fcp_packet_aborts +Lines: 1 +0x13 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/invalid_crc_count +Lines: 1 +0x2 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/invalid_tx_word_count +Lines: 1 +0x8 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/link_failure_count +Lines: 1 +0x9 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/loss_of_signal_count +Lines: 1 +0x11 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/loss_of_sync_count +Lines: 1 +0x10 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/nos_count +Lines: 1 +0x12 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/rx_frames +Lines: 1 +0x3 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/rx_words +Lines: 1 +0x4 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/seconds_since_last_reset +Lines: 1 +0x7 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/tx_frames +Lines: 1 +0x5 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/statistics/tx_words +Lines: 1 +0x6 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/supported_classes +Lines: 1 +Class 3 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/supported_speeds +Lines: 1 +4 Gbit, 8 Gbit, 16 Gbit +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/class/fc_host/host0/symbolic_name +Lines: 1 +Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/class/hwmon Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/end-to-end-test.sh b/end-to-end-test.sh index 24060611..ac38e58a 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -14,6 +14,7 @@ enabled_collectors=$(cat << COLLECTORS drbd edac entropy + fibrechannel filefd hwmon infiniband