diff --git a/collector/fibrechannel_linux.go b/collector/fibrechannel_linux.go index 13a3b5dc16..782ad33ee0 100644 --- a/collector/fibrechannel_linux.go +++ b/collector/fibrechannel_linux.go @@ -23,6 +23,7 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/node_exporter/collector/utils" "github.com/prometheus/procfs/sysfs" ) @@ -114,23 +115,36 @@ func (c *fibrechannelCollector) Update(ch chan<- prometheus.Metric) error { 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) + ch <- prometheus.MustNewConstMetric(infoDesc, prometheus.GaugeValue, infoValue, utils.SafeDereference( + 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) + // Note: `procfs` guarantees these a safe dereference for these 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/mountstats_linux.go b/collector/mountstats_linux.go index 9dea6fad71..cdd84ea16c 100644 --- a/collector/mountstats_linux.go +++ b/collector/mountstats_linux.go @@ -538,15 +538,16 @@ func (c *mountStatsCollector) Update(ch chan<- prometheus.Metric) error { mountAddress = miStats.SuperOptions["addr"] } - deviceIdentifier := nfsDeviceIdentifier{m.Device, stats.Transport.Protocol, mountAddress} - i := deviceList[deviceIdentifier] - if i { - level.Debug(c.logger).Log("msg", "Skipping duplicate device entry", "device", deviceIdentifier) - continue + for k := range stats.Transport { + deviceIdentifier := nfsDeviceIdentifier{m.Device, stats.Transport[k].Protocol, mountAddress} + i := deviceList[deviceIdentifier] + if i { + level.Debug(c.logger).Log("msg", "Skipping duplicate device entry", "device", deviceIdentifier) + break + } + deviceList[deviceIdentifier] = true + c.updateNFSStats(ch, stats, m.Device, stats.Transport[k].Protocol, mountAddress) } - - deviceList[deviceIdentifier] = true - c.updateNFSStats(ch, stats, m.Device, stats.Transport.Protocol, mountAddress) } return nil @@ -617,75 +618,77 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, s *pro labelValues..., ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportBindTotal, - prometheus.CounterValue, - float64(s.Transport.Bind), - labelValues..., - ) + for i := range s.Transport { + ch <- prometheus.MustNewConstMetric( + c.NFSTransportBindTotal, + prometheus.CounterValue, + float64(s.Transport[i].Bind), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportConnectTotal, - prometheus.CounterValue, - float64(s.Transport.Connect), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportConnectTotal, + prometheus.CounterValue, + float64(s.Transport[i].Connect), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportIdleTimeSeconds, - prometheus.GaugeValue, - float64(s.Transport.IdleTimeSeconds%float64Mantissa), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportIdleTimeSeconds, + prometheus.GaugeValue, + float64(s.Transport[i].IdleTimeSeconds%float64Mantissa), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportSendsTotal, - prometheus.CounterValue, - float64(s.Transport.Sends), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportSendsTotal, + prometheus.CounterValue, + float64(s.Transport[i].Sends), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportReceivesTotal, - prometheus.CounterValue, - float64(s.Transport.Receives), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportReceivesTotal, + prometheus.CounterValue, + float64(s.Transport[i].Receives), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportBadTransactionIDsTotal, - prometheus.CounterValue, - float64(s.Transport.BadTransactionIDs), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportBadTransactionIDsTotal, + prometheus.CounterValue, + float64(s.Transport[i].BadTransactionIDs), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportBacklogQueueTotal, - prometheus.CounterValue, - float64(s.Transport.CumulativeBacklog), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportBacklogQueueTotal, + prometheus.CounterValue, + float64(s.Transport[i].CumulativeBacklog), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportMaximumRPCSlots, - prometheus.GaugeValue, - float64(s.Transport.MaximumRPCSlotsUsed), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportMaximumRPCSlots, + prometheus.GaugeValue, + float64(s.Transport[i].MaximumRPCSlotsUsed), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportSendingQueueTotal, - prometheus.CounterValue, - float64(s.Transport.CumulativeSendingQueue), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportSendingQueueTotal, + prometheus.CounterValue, + float64(s.Transport[i].CumulativeSendingQueue), + labelValues..., + ) - ch <- prometheus.MustNewConstMetric( - c.NFSTransportPendingQueueTotal, - prometheus.CounterValue, - float64(s.Transport.CumulativePendingQueue), - labelValues..., - ) + ch <- prometheus.MustNewConstMetric( + c.NFSTransportPendingQueueTotal, + prometheus.CounterValue, + float64(s.Transport[i].CumulativePendingQueue), + labelValues..., + ) + } for _, op := range s.Operations { opLabelValues := []string{export, protocol, mountAddress, op.Operation} diff --git a/collector/utils/utils.go b/collector/utils/utils.go new file mode 100644 index 0000000000..aa5b7540f0 --- /dev/null +++ b/collector/utils/utils.go @@ -0,0 +1,27 @@ +// Copyright 2024 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. + +package utils + +func SafeDereference[T any](s ...*T) []T { + var resolved []T + for _, v := range s { + if v != nil { + resolved = append(resolved, *v) + } else { + var zeroValue T + resolved = append(resolved, zeroValue) + } + } + return resolved +} diff --git a/go.mod b/go.mod index ee979cd611..5591668764 100644 --- a/go.mod +++ b/go.mod @@ -26,8 +26,8 @@ require ( github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.53.0 github.com/prometheus/exporter-toolkit v0.11.0 - github.com/prometheus/procfs v0.14.0 - github.com/safchain/ethtool v0.4.1 + github.com/prometheus/procfs v0.15.1 + github.com/safchain/ethtool v0.3.0 golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f golang.org/x/sys v0.21.0 howett.net/plist v1.0.1 diff --git a/go.sum b/go.sum index 5f9265e264..874066bdd0 100644 --- a/go.sum +++ b/go.sum @@ -82,11 +82,12 @@ github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+a github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= -github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s= -github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/safchain/ethtool v0.4.1 h1:S6mEleTADqgynileXoiapt/nKnatyR6bmIHoF+h2ADo= +github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0= +github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs= github.com/safchain/ethtool v0.4.1/go.mod h1:XLLnZmy4OCRTkksP/UiMjij96YmIsBfmBQcs7H6tA48= github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973 h1:GfSdC6wKfTGcgCS7BtzF5694Amne1pGCSTY252WhlEY= github.com/siebenmann/go-kstat v0.0.0-20210513183136-173c9b0a9973/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8= @@ -115,6 +116,7 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=