128 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| // +build linux
 | |
| 
 | |
| package kernel
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/influxdata/telegraf"
 | |
| 	"github.com/influxdata/telegraf/plugins/inputs"
 | |
| )
 | |
| 
 | |
| // /proc/stat file line prefixes to gather stats on:
 | |
| var (
 | |
| 	interrupts       = []byte("intr")
 | |
| 	context_switches = []byte("ctxt")
 | |
| 	processes_forked = []byte("processes")
 | |
| 	disk_pages       = []byte("page")
 | |
| 	boot_time        = []byte("btime")
 | |
| )
 | |
| 
 | |
| type Kernel struct {
 | |
| 	statFile        string
 | |
| 	entropyStatFile string
 | |
| }
 | |
| 
 | |
| func (k *Kernel) Description() string {
 | |
| 	return "Get kernel statistics from /proc/stat"
 | |
| }
 | |
| 
 | |
| func (k *Kernel) SampleConfig() string { return "" }
 | |
| 
 | |
| func (k *Kernel) Gather(acc telegraf.Accumulator) error {
 | |
| 
 | |
| 	data, err := k.getProcStat()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	entropyData, err := ioutil.ReadFile(k.entropyStatFile)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	entropyString := string(entropyData)
 | |
| 	entropyValue, err := strconv.ParseInt(strings.TrimSpace(entropyString), 10, 64)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	fields := make(map[string]interface{})
 | |
| 
 | |
| 	fields["entropy_avail"] = int64(entropyValue)
 | |
| 
 | |
| 	dataFields := bytes.Fields(data)
 | |
| 	for i, field := range dataFields {
 | |
| 		switch {
 | |
| 		case bytes.Equal(field, interrupts):
 | |
| 			m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			fields["interrupts"] = int64(m)
 | |
| 		case bytes.Equal(field, context_switches):
 | |
| 			m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			fields["context_switches"] = int64(m)
 | |
| 		case bytes.Equal(field, processes_forked):
 | |
| 			m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			fields["processes_forked"] = int64(m)
 | |
| 		case bytes.Equal(field, boot_time):
 | |
| 			m, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			fields["boot_time"] = int64(m)
 | |
| 		case bytes.Equal(field, disk_pages):
 | |
| 			in, err := strconv.ParseInt(string(dataFields[i+1]), 10, 64)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			out, err := strconv.ParseInt(string(dataFields[i+2]), 10, 64)
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			fields["disk_pages_in"] = int64(in)
 | |
| 			fields["disk_pages_out"] = int64(out)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	acc.AddCounter("kernel", fields, map[string]string{})
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (k *Kernel) getProcStat() ([]byte, error) {
 | |
| 	if _, err := os.Stat(k.statFile); os.IsNotExist(err) {
 | |
| 		return nil, fmt.Errorf("kernel: %s does not exist!", k.statFile)
 | |
| 	} else if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	data, err := ioutil.ReadFile(k.statFile)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return data, nil
 | |
| }
 | |
| 
 | |
| func init() {
 | |
| 	inputs.Add("kernel", func() telegraf.Input {
 | |
| 		return &Kernel{
 | |
| 			statFile:        "/proc/stat",
 | |
| 			entropyStatFile: "/proc/sys/kernel/random/entropy_avail",
 | |
| 		}
 | |
| 	})
 | |
| }
 |