node_exporter/collector/mountstats_linux.go

500 lines
13 KiB
Go

// Copyright 2016 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 collector
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
)
type mountStatsCollector struct {
// General statistics
NFSAgeSecondsTotal *prometheus.Desc
// Byte statistics
NFSReadBytesTotal *prometheus.Desc
NFSWriteBytesTotal *prometheus.Desc
NFSDirectReadBytesTotal *prometheus.Desc
NFSDirectWriteBytesTotal *prometheus.Desc
NFSTotalReadBytesTotal *prometheus.Desc
NFSTotalWriteBytesTotal *prometheus.Desc
NFSReadPagesTotal *prometheus.Desc
NFSWritePagesTotal *prometheus.Desc
// Per-operation statistics
NFSOperationsRequestsTotal *prometheus.Desc
NFSOperationsTransmissionsTotal *prometheus.Desc
NFSOperationsMajorTimeoutsTotal *prometheus.Desc
NFSOperationsSentBytesTotal *prometheus.Desc
NFSOperationsReceivedBytesTotal *prometheus.Desc
NFSOperationsQueueTimeSecondsTotal *prometheus.Desc
NFSOperationsResponseTimeSecondsTotal *prometheus.Desc
NFSOperationsRequestTimeSecondsTotal *prometheus.Desc
// Transport statistics
NFSTransportBindTotal *prometheus.Desc
NFSTransportConnectTotal *prometheus.Desc
NFSTransportIdleTimeSeconds *prometheus.Desc
NFSTransportSendsTotal *prometheus.Desc
NFSTransportReceivesTotal *prometheus.Desc
NFSTransportBadTransactionIDsTotal *prometheus.Desc
NFSTransportBacklogQueueTotal *prometheus.Desc
NFSTransportMaximumRPCSlots *prometheus.Desc
NFSTransportSendingQueueTotal *prometheus.Desc
NFSTransportPendingQueueTotal *prometheus.Desc
proc procfs.Proc
}
func init() {
Factories["mountstats"] = NewMountStatsCollector
}
func NewMountStatsCollector() (Collector, error) {
fs, err := procfs.NewFS(*procPath)
if err != nil {
return nil, fmt.Errorf("failed to open procfs: %v", err)
}
proc, err := fs.Self()
if err != nil {
return nil, fmt.Errorf("failed to open /proc/self: %v", err)
}
const (
// For the time being, only NFS statistics are available via this mechanism
subsystem = "mountstats_nfs"
)
var (
labels = []string{"export"}
opLabels = []string{"export", "operation"}
)
return &mountStatsCollector{
NFSAgeSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "age_seconds_total"),
"The age of the NFS mount in seconds.",
labels,
nil,
),
NFSReadBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"),
"Number of bytes read using the read() syscall.",
labels,
nil,
),
NFSWriteBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"),
"Number of bytes written using the write() syscall.",
labels,
nil,
),
NFSDirectReadBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "direct_read_bytes_total"),
"Number of bytes read using the read() syscall in O_DIRECT mode.",
labels,
nil,
),
NFSDirectWriteBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "direct_write_bytes_total"),
"Number of bytes written using the write() syscall in O_DIRECT mode.",
labels,
nil,
),
NFSTotalReadBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "total_read_bytes_total"),
"Number of bytes read from the NFS server, in total.",
labels,
nil,
),
NFSTotalWriteBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "total_write_bytes_total"),
"Number of bytes written to the NFS server, in total.",
labels,
nil,
),
NFSReadPagesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "read_pages_total"),
"Number of pages read directly via mmap()'d files.",
labels,
nil,
),
NFSWritePagesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "write_pages_total"),
"Number of pages written directly via mmap()'d files.",
labels,
nil,
),
NFSTransportBindTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_bind_total"),
"Number of times the client has had to establish a connection from scratch to the NFS server.",
labels,
nil,
),
NFSTransportConnectTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_connect_total"),
"Number of times the client has made a TCP connection to the NFS server.",
labels,
nil,
),
NFSTransportIdleTimeSeconds: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_idle_time_seconds"),
"Duration since the NFS mount last saw any RPC traffic, in seconds.",
labels,
nil,
),
NFSTransportSendsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_sends_total"),
"Number of RPC requests for this mount sent to the NFS server.",
labels,
nil,
),
NFSTransportReceivesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_receives_total"),
"Number of RPC responses for this mount received from the NFS server.",
labels,
nil,
),
NFSTransportBadTransactionIDsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_bad_transaction_ids_total"),
"Number of times the NFS server sent a response with a transaction ID unknown to this client.",
labels,
nil,
),
NFSTransportBacklogQueueTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_backlog_queue_total"),
"Total number of items added to the RPC backlog queue.",
labels,
nil,
),
NFSTransportMaximumRPCSlots: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_maximum_rpc_slots"),
"Maximum number of simultaneously active RPC requests ever used.",
labels,
nil,
),
NFSTransportSendingQueueTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_sending_queue_total"),
"Total number of items added to the RPC transmission sending queue.",
labels,
nil,
),
NFSTransportPendingQueueTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "transport_pending_queue_total"),
"Total number of items added to the RPC transmission pending queue.",
labels,
nil,
),
NFSOperationsRequestsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_requests_total"),
"Number of requests performed for a given operation.",
opLabels,
nil,
),
NFSOperationsTransmissionsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_transmissions_total"),
"Number of times an actual RPC request has been transmitted for a given operation.",
opLabels,
nil,
),
NFSOperationsMajorTimeoutsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_major_timeouts_total"),
"Number of times a request has had a major timeout for a given operation.",
opLabels,
nil,
),
NFSOperationsSentBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_sent_bytes_total"),
"Number of bytes sent for a given operation, including RPC headers and payload.",
opLabels,
nil,
),
NFSOperationsReceivedBytesTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_received_bytes_total"),
"Number of bytes received for a given operation, including RPC headers and payload.",
opLabels,
nil,
),
NFSOperationsQueueTimeSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_queue_time_seconds_total"),
"Duration all requests spent queued for transmission for a given operation before they were sent, in seconds.",
opLabels,
nil,
),
NFSOperationsResponseTimeSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_response_time_seconds_total"),
"Duration all requests took to get a reply back after a request for a given operation was transmitted, in seconds.",
opLabels,
nil,
),
NFSOperationsRequestTimeSecondsTotal: prometheus.NewDesc(
prometheus.BuildFQName(Namespace, subsystem, "operations_request_time_seconds_total"),
"Duration all requests took from when a request was enqueued to when it was completely handled for a given operation, in seconds.",
opLabels,
nil,
),
proc: proc,
}, nil
}
func (c *mountStatsCollector) Update(ch chan<- prometheus.Metric) error {
mounts, err := c.proc.MountStats()
if err != nil {
return fmt.Errorf("failed to parse mountstats: %v", err)
}
for _, m := range mounts {
// For the time being, only NFS statistics are available via this mechanism
stats, ok := m.Stats.(*procfs.MountStatsNFS)
if !ok {
continue
}
c.updateNFSStats(ch, m.Device, stats)
}
return nil
}
func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, export string, s *procfs.MountStatsNFS) {
ch <- prometheus.MustNewConstMetric(
c.NFSAgeSecondsTotal,
prometheus.CounterValue,
s.Age.Seconds(),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSReadBytesTotal,
prometheus.CounterValue,
float64(s.Bytes.Read),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSWriteBytesTotal,
prometheus.CounterValue,
float64(s.Bytes.Write),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSDirectReadBytesTotal,
prometheus.CounterValue,
float64(s.Bytes.DirectRead),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSDirectWriteBytesTotal,
prometheus.CounterValue,
float64(s.Bytes.DirectWrite),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTotalReadBytesTotal,
prometheus.CounterValue,
float64(s.Bytes.ReadTotal),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTotalWriteBytesTotal,
prometheus.CounterValue,
float64(s.Bytes.WriteTotal),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSReadPagesTotal,
prometheus.CounterValue,
float64(s.Bytes.ReadPages),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSWritePagesTotal,
prometheus.CounterValue,
float64(s.Bytes.WritePages),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportBindTotal,
prometheus.CounterValue,
float64(s.Transport.Bind),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportConnectTotal,
prometheus.CounterValue,
float64(s.Transport.Connect),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportIdleTimeSeconds,
prometheus.GaugeValue,
s.Transport.IdleTime.Seconds(),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportSendsTotal,
prometheus.CounterValue,
float64(s.Transport.Sends),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportReceivesTotal,
prometheus.CounterValue,
float64(s.Transport.Receives),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportBadTransactionIDsTotal,
prometheus.CounterValue,
float64(s.Transport.BadTransactionIDs),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportBacklogQueueTotal,
prometheus.CounterValue,
float64(s.Transport.CumulativeBacklog),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportMaximumRPCSlots,
prometheus.GaugeValue,
float64(s.Transport.MaximumRPCSlotsUsed),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportSendingQueueTotal,
prometheus.CounterValue,
float64(s.Transport.CumulativeSendingQueue),
export,
)
ch <- prometheus.MustNewConstMetric(
c.NFSTransportPendingQueueTotal,
prometheus.CounterValue,
float64(s.Transport.CumulativePendingQueue),
export,
)
for _, op := range s.Operations {
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsRequestsTotal,
prometheus.CounterValue,
float64(op.Requests),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsTransmissionsTotal,
prometheus.CounterValue,
float64(op.Transmissions),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsMajorTimeoutsTotal,
prometheus.CounterValue,
float64(op.MajorTimeouts),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsSentBytesTotal,
prometheus.CounterValue,
float64(op.BytesSent),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsReceivedBytesTotal,
prometheus.CounterValue,
float64(op.BytesReceived),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsQueueTimeSecondsTotal,
prometheus.CounterValue,
op.CumulativeQueueTime.Seconds(),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsResponseTimeSecondsTotal,
prometheus.CounterValue,
op.CumulativeTotalResponseTime.Seconds(),
export,
op.Operation,
)
ch <- prometheus.MustNewConstMetric(
c.NFSOperationsRequestTimeSecondsTotal,
prometheus.CounterValue,
op.CumulativeTotalRequestTime.Seconds(),
export,
op.Operation,
)
}
}