2015-05-12 11:06:41 +00:00
// +build !nofilesystem
2014-06-05 19:44:44 +00:00
package collector
import (
"bufio"
"flag"
"fmt"
"os"
"regexp"
"strings"
"syscall"
"github.com/prometheus/client_golang/prometheus"
2015-05-28 19:21:44 +00:00
"github.com/prometheus/log"
2014-06-05 19:44:44 +00:00
)
const (
2014-06-26 17:20:36 +00:00
procMounts = "/proc/mounts"
filesystemSubsystem = "filesystem"
2014-06-05 19:44:44 +00:00
)
var (
2015-02-18 17:15:57 +00:00
ignoredMountPoints = flag . String ( "collector.filesystem.ignored-mount-points" , "^/(sys|proc|dev)($|/)" , "Regexp of mount points to ignore for filesystem collector." )
2014-06-05 19:44:44 +00:00
)
2015-07-02 23:20:49 +00:00
type filesystemDetails struct {
device string
mountPoint string
fsType string
}
2014-06-05 19:44:44 +00:00
type filesystemCollector struct {
ignoredMountPointsPattern * regexp . Regexp
2014-11-25 02:00:17 +00:00
size , free , avail , files , filesFree * prometheus . GaugeVec
2014-06-05 19:44:44 +00:00
}
func init ( ) {
Factories [ "filesystem" ] = NewFilesystemCollector
}
2015-05-20 18:04:49 +00:00
// Takes a prometheus registry and returns a new Collector exposing
2014-06-05 19:44:44 +00:00
// network device filesystems.
2015-05-20 18:04:49 +00:00
func NewFilesystemCollector ( ) ( Collector , error ) {
2015-07-06 16:40:19 +00:00
var filesystemLabelNames = [ ] string { "device" , "mountpoint" , "fstype" }
2014-11-25 02:00:17 +00:00
return & filesystemCollector {
2014-06-05 19:44:44 +00:00
ignoredMountPointsPattern : regexp . MustCompile ( * ignoredMountPoints ) ,
2014-11-25 02:00:17 +00:00
size : prometheus . NewGaugeVec (
prometheus . GaugeOpts {
Namespace : Namespace ,
Subsystem : filesystemSubsystem ,
Name : "size" ,
Help : "Filesystem size in bytes." ,
} ,
filesystemLabelNames ,
) ,
free : prometheus . NewGaugeVec (
prometheus . GaugeOpts {
Namespace : Namespace ,
Subsystem : filesystemSubsystem ,
Name : "free" ,
Help : "Filesystem free space in bytes." ,
} ,
filesystemLabelNames ,
) ,
avail : prometheus . NewGaugeVec (
prometheus . GaugeOpts {
Namespace : Namespace ,
Subsystem : filesystemSubsystem ,
Name : "avail" ,
Help : "Filesystem space available to non-root users in bytes." ,
} ,
filesystemLabelNames ,
) ,
files : prometheus . NewGaugeVec (
prometheus . GaugeOpts {
Namespace : Namespace ,
Subsystem : filesystemSubsystem ,
Name : "files" ,
Help : "Filesystem total file nodes." ,
} ,
filesystemLabelNames ,
) ,
filesFree : prometheus . NewGaugeVec (
prometheus . GaugeOpts {
Namespace : Namespace ,
Subsystem : filesystemSubsystem ,
Name : "files_free" ,
Help : "Filesystem total free file nodes." ,
} ,
filesystemLabelNames ,
) ,
} , nil
2014-06-05 19:44:44 +00:00
}
// Expose filesystem fullness.
2014-10-29 14:16:43 +00:00
func ( c * filesystemCollector ) Update ( ch chan <- prometheus . Metric ) ( err error ) {
2015-07-02 23:20:49 +00:00
mpds , err := mountPointDetails ( )
2014-06-05 19:44:44 +00:00
if err != nil {
2014-10-29 14:16:43 +00:00
return err
2014-06-05 19:44:44 +00:00
}
2015-07-02 23:20:49 +00:00
for _ , mpd := range mpds {
if c . ignoredMountPointsPattern . MatchString ( mpd . mountPoint ) {
log . Debugf ( "Ignoring mount point: %s" , mpd . mountPoint )
2014-06-05 19:44:44 +00:00
continue
}
buf := new ( syscall . Statfs_t )
2015-07-02 23:20:49 +00:00
err := syscall . Statfs ( mpd . mountPoint , buf )
2014-06-05 19:44:44 +00:00
if err != nil {
2015-07-02 23:20:49 +00:00
return fmt . Errorf ( "Statfs on %s returned %s" , mpd . mountPoint , err )
2014-06-05 19:44:44 +00:00
}
2015-07-02 23:20:49 +00:00
c . size . WithLabelValues ( mpd . device , mpd . mountPoint , mpd . fsType ) . Set ( float64 ( buf . Blocks ) * float64 ( buf . Bsize ) )
c . free . WithLabelValues ( mpd . device , mpd . mountPoint , mpd . fsType ) . Set ( float64 ( buf . Bfree ) * float64 ( buf . Bsize ) )
c . avail . WithLabelValues ( mpd . device , mpd . mountPoint , mpd . fsType ) . Set ( float64 ( buf . Bavail ) * float64 ( buf . Bsize ) )
c . files . WithLabelValues ( mpd . device , mpd . mountPoint , mpd . fsType ) . Set ( float64 ( buf . Files ) )
c . filesFree . WithLabelValues ( mpd . device , mpd . mountPoint , mpd . fsType ) . Set ( float64 ( buf . Ffree ) )
2014-06-05 19:44:44 +00:00
}
2014-11-25 02:00:17 +00:00
c . size . Collect ( ch )
c . free . Collect ( ch )
c . avail . Collect ( ch )
c . files . Collect ( ch )
c . filesFree . Collect ( ch )
2014-10-29 14:16:43 +00:00
return err
2014-06-05 19:44:44 +00:00
}
2015-07-02 23:20:49 +00:00
func mountPointDetails ( ) ( [ ] filesystemDetails , error ) {
2014-06-05 19:44:44 +00:00
file , err := os . Open ( procMounts )
if err != nil {
return nil , err
}
defer file . Close ( )
2015-07-02 23:20:49 +00:00
filesystems := [ ] filesystemDetails { }
2014-06-05 19:44:44 +00:00
scanner := bufio . NewScanner ( file )
for scanner . Scan ( ) {
parts := strings . Fields ( scanner . Text ( ) )
2015-07-02 23:20:49 +00:00
filesystems = append ( filesystems , filesystemDetails { parts [ 0 ] , parts [ 1 ] , parts [ 2 ] } )
2014-06-05 19:44:44 +00:00
}
2015-07-02 23:20:49 +00:00
return filesystems , nil
2014-06-05 19:44:44 +00:00
}