mirror of
https://github.com/prometheus/node_exporter.git
synced 2025-03-05 21:00:12 -08:00
switch to go-kit/log (#1575)
Signed-off-by: yeya24 <yb532204897@gmail.com>
This commit is contained in:
parent
a80b7d0bc5
commit
2477c5c67d
|
@ -22,11 +22,13 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type arpCollector struct {
|
type arpCollector struct {
|
||||||
entries *prometheus.Desc
|
entries *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -34,13 +36,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewARPCollector returns a new Collector exposing ARP stats.
|
// NewARPCollector returns a new Collector exposing ARP stats.
|
||||||
func NewARPCollector() (Collector, error) {
|
func NewARPCollector(logger log.Logger) (Collector, error) {
|
||||||
return &arpCollector{
|
return &arpCollector{
|
||||||
entries: prometheus.NewDesc(
|
entries: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "arp", "entries"),
|
prometheus.BuildFQName(namespace, "arp", "entries"),
|
||||||
"ARP entries by device",
|
"ARP entries by device",
|
||||||
[]string{"device"}, nil,
|
[]string{"device"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/bcache"
|
"github.com/prometheus/procfs/bcache"
|
||||||
)
|
)
|
||||||
|
@ -28,19 +29,21 @@ func init() {
|
||||||
|
|
||||||
// A bcacheCollector is a Collector which gathers metrics from Linux bcache.
|
// A bcacheCollector is a Collector which gathers metrics from Linux bcache.
|
||||||
type bcacheCollector struct {
|
type bcacheCollector struct {
|
||||||
fs bcache.FS
|
fs bcache.FS
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBcacheCollector returns a newly allocated bcacheCollector.
|
// NewBcacheCollector returns a newly allocated bcacheCollector.
|
||||||
// It exposes a number of Linux bcache statistics.
|
// It exposes a number of Linux bcache statistics.
|
||||||
func NewBcacheCollector() (Collector, error) {
|
func NewBcacheCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := bcache.NewFS(*sysPath)
|
fs, err := bcache.NewFS(*sysPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &bcacheCollector{
|
return &bcacheCollector{
|
||||||
fs: fs,
|
fs: fs,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,14 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type bondingCollector struct {
|
type bondingCollector struct {
|
||||||
slaves, active typedDesc
|
slaves, active typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -36,7 +38,7 @@ func init() {
|
||||||
|
|
||||||
// NewBondingCollector returns a newly allocated bondingCollector.
|
// NewBondingCollector returns a newly allocated bondingCollector.
|
||||||
// It exposes the number of configured and active slave of linux bonding interfaces.
|
// It exposes the number of configured and active slave of linux bonding interfaces.
|
||||||
func NewBondingCollector() (Collector, error) {
|
func NewBondingCollector(logger log.Logger) (Collector, error) {
|
||||||
return &bondingCollector{
|
return &bondingCollector{
|
||||||
slaves: typedDesc{prometheus.NewDesc(
|
slaves: typedDesc{prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "bonding", "slaves"),
|
prometheus.BuildFQName(namespace, "bonding", "slaves"),
|
||||||
|
@ -48,6 +50,7 @@ func NewBondingCollector() (Collector, error) {
|
||||||
"Number of active slaves per bonding interface.",
|
"Number of active slaves per bonding interface.",
|
||||||
[]string{"master"}, nil,
|
[]string{"master"}, nil,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +60,7 @@ func (c *bondingCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
bondingStats, err := readBondingStats(statusfile)
|
bondingStats, err := readBondingStats(statusfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("Not collecting bonding, file does not exist: %s", statusfile)
|
level.Debug(c.logger).Log("msg", "Not collecting bonding, file does not exist", "file", statusfile)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -17,17 +17,21 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bootTimeCollector struct{ boottime bsdSysctl }
|
type bootTimeCollector struct {
|
||||||
|
boottime bsdSysctl
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("boottime", defaultEnabled, newBootTimeCollector)
|
registerCollector("boottime", defaultEnabled, newBootTimeCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newBootTimeCollector returns a new Collector exposing system boot time on BSD systems.
|
// newBootTimeCollector returns a new Collector exposing system boot time on BSD systems.
|
||||||
func newBootTimeCollector() (Collector, error) {
|
func newBootTimeCollector(logger log.Logger) (Collector, error) {
|
||||||
return &bootTimeCollector{
|
return &bootTimeCollector{
|
||||||
boottime: bsdSysctl{
|
boottime: bsdSysctl{
|
||||||
name: "boot_time_seconds",
|
name: "boot_time_seconds",
|
||||||
|
@ -35,6 +39,7 @@ func newBootTimeCollector() (Collector, error) {
|
||||||
mib: "kern.boottime",
|
mib: "kern.boottime",
|
||||||
dataType: bsdSysctlTypeStructTimeval,
|
dataType: bsdSysctlTypeStructTimeval,
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,19 +17,21 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/siebenmann/go-kstat"
|
"github.com/siebenmann/go-kstat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bootTimeCollector struct {
|
type bootTimeCollector struct {
|
||||||
boottime typedDesc
|
boottime typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("boottime", defaultEnabled, newBootTimeCollector)
|
registerCollector("boottime", defaultEnabled, newBootTimeCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBootTimeCollector() (Collector, error) {
|
func newBootTimeCollector(logger log.Logger) (Collector, error) {
|
||||||
return &bootTimeCollector{
|
return &bootTimeCollector{
|
||||||
boottime: typedDesc{
|
boottime: typedDesc{
|
||||||
prometheus.NewDesc(
|
prometheus.NewDesc(
|
||||||
|
@ -37,6 +39,7 @@ func newBootTimeCollector() (Collector, error) {
|
||||||
"Unix time of last boot, including microseconds.",
|
"Unix time of last boot, including microseconds.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,8 +31,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type buddyinfoCollector struct {
|
type buddyinfoCollector struct {
|
||||||
fs procfs.FS
|
fs procfs.FS
|
||||||
desc *prometheus.Desc
|
desc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -39,7 +41,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuddyinfoCollector returns a new Collector exposing buddyinfo stats.
|
// NewBuddyinfoCollector returns a new Collector exposing buddyinfo stats.
|
||||||
func NewBuddyinfoCollector() (Collector, error) {
|
func NewBuddyinfoCollector(logger log.Logger) (Collector, error) {
|
||||||
desc := prometheus.NewDesc(
|
desc := prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, buddyInfoSubsystem, "blocks"),
|
prometheus.BuildFQName(namespace, buddyInfoSubsystem, "blocks"),
|
||||||
"Count of free blocks according to size.",
|
"Count of free blocks according to size.",
|
||||||
|
@ -49,7 +51,7 @@ func NewBuddyinfoCollector() (Collector, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
}
|
}
|
||||||
return &buddyinfoCollector{fs, desc}, nil
|
return &buddyinfoCollector{fs, desc, logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update calls (*buddyinfoCollector).getBuddyInfo to get the platform specific
|
// Update calls (*buddyinfoCollector).getBuddyInfo to get the platform specific
|
||||||
|
@ -60,7 +62,7 @@ func (c *buddyinfoCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
return fmt.Errorf("couldn't get buddyinfo: %s", err)
|
return fmt.Errorf("couldn't get buddyinfo: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Set node_buddy: %#v", buddyInfo)
|
level.Debug(c.logger).Log("msg", "Set node_buddy", "buddyInfo", buddyInfo)
|
||||||
for _, entry := range buddyInfo {
|
for _, entry := range buddyInfo {
|
||||||
for size, value := range entry.Sizes {
|
for size, value := range entry.Sizes {
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
|
|
@ -19,8 +19,9 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,11 +49,11 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
factories = make(map[string]func() (Collector, error))
|
factories = make(map[string]func(logger log.Logger) (Collector, error))
|
||||||
collectorState = make(map[string]*bool)
|
collectorState = make(map[string]*bool)
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerCollector(collector string, isDefaultEnabled bool, factory func() (Collector, error)) {
|
func registerCollector(collector string, isDefaultEnabled bool, factory func(logger log.Logger) (Collector, error)) {
|
||||||
var helpDefaultState string
|
var helpDefaultState string
|
||||||
if isDefaultEnabled {
|
if isDefaultEnabled {
|
||||||
helpDefaultState = "enabled"
|
helpDefaultState = "enabled"
|
||||||
|
@ -73,10 +74,11 @@ func registerCollector(collector string, isDefaultEnabled bool, factory func() (
|
||||||
// NodeCollector implements the prometheus.Collector interface.
|
// NodeCollector implements the prometheus.Collector interface.
|
||||||
type NodeCollector struct {
|
type NodeCollector struct {
|
||||||
Collectors map[string]Collector
|
Collectors map[string]Collector
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeCollector creates a new NodeCollector.
|
// NewNodeCollector creates a new NodeCollector.
|
||||||
func NewNodeCollector(filters ...string) (*NodeCollector, error) {
|
func NewNodeCollector(logger log.Logger, filters ...string) (*NodeCollector, error) {
|
||||||
f := make(map[string]bool)
|
f := make(map[string]bool)
|
||||||
for _, filter := range filters {
|
for _, filter := range filters {
|
||||||
enabled, exist := collectorState[filter]
|
enabled, exist := collectorState[filter]
|
||||||
|
@ -91,7 +93,7 @@ func NewNodeCollector(filters ...string) (*NodeCollector, error) {
|
||||||
collectors := make(map[string]Collector)
|
collectors := make(map[string]Collector)
|
||||||
for key, enabled := range collectorState {
|
for key, enabled := range collectorState {
|
||||||
if *enabled {
|
if *enabled {
|
||||||
collector, err := factories[key]()
|
collector, err := factories[key](log.With(logger, "collector", key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -100,7 +102,7 @@ func NewNodeCollector(filters ...string) (*NodeCollector, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &NodeCollector{Collectors: collectors}, nil
|
return &NodeCollector{Collectors: collectors, logger: logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe implements the prometheus.Collector interface.
|
// Describe implements the prometheus.Collector interface.
|
||||||
|
@ -115,24 +117,24 @@ func (n NodeCollector) Collect(ch chan<- prometheus.Metric) {
|
||||||
wg.Add(len(n.Collectors))
|
wg.Add(len(n.Collectors))
|
||||||
for name, c := range n.Collectors {
|
for name, c := range n.Collectors {
|
||||||
go func(name string, c Collector) {
|
go func(name string, c Collector) {
|
||||||
execute(name, c, ch)
|
execute(name, c, ch, n.logger)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(name, c)
|
}(name, c)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func execute(name string, c Collector, ch chan<- prometheus.Metric) {
|
func execute(name string, c Collector, ch chan<- prometheus.Metric, logger log.Logger) {
|
||||||
begin := time.Now()
|
begin := time.Now()
|
||||||
err := c.Update(ch)
|
err := c.Update(ch)
|
||||||
duration := time.Since(begin)
|
duration := time.Since(begin)
|
||||||
var success float64
|
var success float64
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("ERROR: %s collector failed after %fs: %s", name, duration.Seconds(), err)
|
level.Error(logger).Log("msg", "collector failed", "name", name, "duration_seconds", duration.Seconds(), "err", err)
|
||||||
success = 0
|
success = 0
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("OK: %s collector succeeded after %fs.", name, duration.Seconds())
|
level.Debug(logger).Log("msg", "collector succeeded", "name", name, "duration_seconds", duration.Seconds())
|
||||||
success = 1
|
success = 1
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(scrapeDurationDesc, prometheus.GaugeValue, duration.Seconds(), name)
|
ch <- prometheus.MustNewConstMetric(scrapeDurationDesc, prometheus.GaugeValue, duration.Seconds(), name)
|
||||||
|
|
|
@ -16,12 +16,14 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type conntrackCollector struct {
|
type conntrackCollector struct {
|
||||||
current *prometheus.Desc
|
current *prometheus.Desc
|
||||||
limit *prometheus.Desc
|
limit *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -29,7 +31,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConntrackCollector returns a new Collector exposing conntrack stats.
|
// NewConntrackCollector returns a new Collector exposing conntrack stats.
|
||||||
func NewConntrackCollector() (Collector, error) {
|
func NewConntrackCollector(logger log.Logger) (Collector, error) {
|
||||||
return &conntrackCollector{
|
return &conntrackCollector{
|
||||||
current: prometheus.NewDesc(
|
current: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "", "nf_conntrack_entries"),
|
prometheus.BuildFQName(namespace, "", "nf_conntrack_entries"),
|
||||||
|
@ -41,6 +43,7 @@ func NewConntrackCollector() (Collector, error) {
|
||||||
"Maximum size of connection tracking table.",
|
"Maximum size of connection tracking table.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +50,8 @@ import "C"
|
||||||
const ClocksPerSec = float64(C.CLK_TCK)
|
const ClocksPerSec = float64(C.CLK_TCK)
|
||||||
|
|
||||||
type statCollector struct {
|
type statCollector struct {
|
||||||
cpu *prometheus.Desc
|
cpu *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -57,9 +59,10 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCPUCollector returns a new Collector exposing CPU stats.
|
// NewCPUCollector returns a new Collector exposing CPU stats.
|
||||||
func NewCPUCollector() (Collector, error) {
|
func NewCPUCollector(logger log.Logger) (Collector, error) {
|
||||||
return &statCollector{
|
return &statCollector{
|
||||||
cpu: nodeCPUSecondsDesc,
|
cpu: nodeCPUSecondsDesc,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,7 +76,8 @@ import "C"
|
||||||
const maxCPUTimesLen = C.MAXCPU * C.CPUSTATES
|
const maxCPUTimesLen = C.MAXCPU * C.CPUSTATES
|
||||||
|
|
||||||
type statCollector struct {
|
type statCollector struct {
|
||||||
cpu *prometheus.Desc
|
cpu *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -83,9 +85,10 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStatCollector returns a new Collector exposing CPU stats.
|
// NewStatCollector returns a new Collector exposing CPU stats.
|
||||||
func NewStatCollector() (Collector, error) {
|
func NewStatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &statCollector{
|
return &statCollector{
|
||||||
cpu: nodeCPUSecondsDesc,
|
cpu: nodeCPUSecondsDesc,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,8 +82,9 @@ func getCPUTimes() ([]cputime, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type statCollector struct {
|
type statCollector struct {
|
||||||
cpu typedDesc
|
cpu typedDesc
|
||||||
temp typedDesc
|
temp typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -90,7 +92,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStatCollector returns a new Collector exposing CPU stats.
|
// NewStatCollector returns a new Collector exposing CPU stats.
|
||||||
func NewStatCollector() (Collector, error) {
|
func NewStatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &statCollector{
|
return &statCollector{
|
||||||
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
||||||
temp: typedDesc{prometheus.NewDesc(
|
temp: typedDesc{prometheus.NewDesc(
|
||||||
|
@ -98,6 +100,7 @@ func NewStatCollector() (Collector, error) {
|
||||||
"CPU temperature",
|
"CPU temperature",
|
||||||
[]string{"cpu"}, nil,
|
[]string{"cpu"}, nil,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,11 +133,11 @@ func (c *statCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == unix.ENOENT {
|
if err == unix.ENOENT {
|
||||||
// No temperature information for this CPU
|
// No temperature information for this CPU
|
||||||
log.Debugf("no temperature information for CPU %d", cpu)
|
level.Debug(c.logger).Log("msg", "no temperature information for CPU", "cpu", cpu)
|
||||||
} else {
|
} else {
|
||||||
// Unexpected error
|
// Unexpected error
|
||||||
ch <- c.temp.mustNewConstMetric(math.NaN(), lcpu)
|
ch <- c.temp.mustNewConstMetric(math.NaN(), lcpu)
|
||||||
log.Errorf("failed to query CPU temperature for CPU %d: %s", cpu, err)
|
level.Error(c.logger).Log("msg", "failed to query CPU temperature for CPU", "cpu", cpu, "err", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,11 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cpuCollector struct {
|
type cpuCollector struct {
|
||||||
|
@ -33,6 +34,7 @@ type cpuCollector struct {
|
||||||
cpuGuest *prometheus.Desc
|
cpuGuest *prometheus.Desc
|
||||||
cpuCoreThrottle *prometheus.Desc
|
cpuCoreThrottle *prometheus.Desc
|
||||||
cpuPackageThrottle *prometheus.Desc
|
cpuPackageThrottle *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -44,7 +46,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCPUCollector returns a new Collector exposing kernel/system statistics.
|
// NewCPUCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewCPUCollector() (Collector, error) {
|
func NewCPUCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
fs, err := procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -72,6 +74,7 @@ func NewCPUCollector() (Collector, error) {
|
||||||
"Number of times this cpu package has been throttled.",
|
"Number of times this cpu package has been throttled.",
|
||||||
[]string{"package"}, nil,
|
[]string{"package"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,12 +137,12 @@ func (c *cpuCollector) updateThermalThrottle(ch chan<- prometheus.Metric) error
|
||||||
|
|
||||||
// topology/physical_package_id
|
// topology/physical_package_id
|
||||||
if physicalPackageID, err = readUintFromFile(filepath.Join(cpu, "topology", "physical_package_id")); err != nil {
|
if physicalPackageID, err = readUintFromFile(filepath.Join(cpu, "topology", "physical_package_id")); err != nil {
|
||||||
log.Debugf("CPU %v is missing physical_package_id", cpu)
|
level.Debug(c.logger).Log("msg", "CPU is missing physical_package_id", "cpu", cpu)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// topology/core_id
|
// topology/core_id
|
||||||
if coreID, err = readUintFromFile(filepath.Join(cpu, "topology", "core_id")); err != nil {
|
if coreID, err = readUintFromFile(filepath.Join(cpu, "topology", "core_id")); err != nil {
|
||||||
log.Debugf("CPU %v is missing core_id", cpu)
|
level.Debug(c.logger).Log("msg", "CPU is missing core_id", "cpu", cpu)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +160,7 @@ func (c *cpuCollector) updateThermalThrottle(ch chan<- prometheus.Metric) error
|
||||||
if coreThrottleCount, err := readUintFromFile(filepath.Join(cpu, "thermal_throttle", "core_throttle_count")); err == nil {
|
if coreThrottleCount, err := readUintFromFile(filepath.Join(cpu, "thermal_throttle", "core_throttle_count")); err == nil {
|
||||||
packageCoreThrottles[physicalPackageID][coreID] = coreThrottleCount
|
packageCoreThrottles[physicalPackageID][coreID] = coreThrottleCount
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("CPU %v is missing core_throttle_count", cpu)
|
level.Debug(c.logger).Log("msg", "CPU is missing core_throttle_count", "cpu", cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +170,7 @@ func (c *cpuCollector) updateThermalThrottle(ch chan<- prometheus.Metric) error
|
||||||
if packageThrottleCount, err := readUintFromFile(filepath.Join(cpu, "thermal_throttle", "package_throttle_count")); err == nil {
|
if packageThrottleCount, err := readUintFromFile(filepath.Join(cpu, "thermal_throttle", "package_throttle_count")); err == nil {
|
||||||
packageThrottles[physicalPackageID] = packageThrottleCount
|
packageThrottles[physicalPackageID] = packageThrottleCount
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("CPU %v is missing package_throttle_count", cpu)
|
level.Debug(c.logger).Log("msg", "CPU is missing package_throttle_count", "cpu", cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -30,16 +31,18 @@ import (
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
type cpuCollector struct {
|
type cpuCollector struct {
|
||||||
cpu typedDesc
|
cpu typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("cpu", defaultEnabled, NewCPUCollector)
|
registerCollector("cpu", defaultEnabled, NewCPUCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCPUCollector() (Collector, error) {
|
func NewCPUCollector(logger log.Logger) (Collector, error) {
|
||||||
return &cpuCollector{
|
return &cpuCollector{
|
||||||
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
kstat "github.com/siebenmann/go-kstat"
|
kstat "github.com/siebenmann/go-kstat"
|
||||||
)
|
)
|
||||||
|
@ -27,16 +28,18 @@ import (
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
type cpuCollector struct {
|
type cpuCollector struct {
|
||||||
cpu typedDesc
|
cpu typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("cpu", defaultEnabled, NewCpuCollector)
|
registerCollector("cpu", defaultEnabled, NewCpuCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCpuCollector() (Collector, error) {
|
func NewCpuCollector(logger log.Logger) (Collector, error) {
|
||||||
return &cpuCollector{
|
return &cpuCollector{
|
||||||
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/sysfs"
|
"github.com/prometheus/procfs/sysfs"
|
||||||
)
|
)
|
||||||
|
@ -30,6 +31,7 @@ type cpuFreqCollector struct {
|
||||||
scalingFreq *prometheus.Desc
|
scalingFreq *prometheus.Desc
|
||||||
scalingFreqMin *prometheus.Desc
|
scalingFreqMin *prometheus.Desc
|
||||||
scalingFreqMax *prometheus.Desc
|
scalingFreqMax *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -37,7 +39,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCPUFreqCollector returns a new Collector exposing kernel/system statistics.
|
// NewCPUFreqCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewCPUFreqCollector() (Collector, error) {
|
func NewCPUFreqCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := sysfs.NewFS(*sysPath)
|
fs, err := sysfs.NewFS(*sysPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
||||||
|
@ -75,6 +77,7 @@ func NewCPUFreqCollector() (Collector, error) {
|
||||||
"Maximum scaled cpu thread frequency in hertz.",
|
"Maximum scaled cpu thread frequency in hertz.",
|
||||||
[]string{"cpu"}, nil,
|
[]string{"cpu"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
kstat "github.com/siebenmann/go-kstat"
|
kstat "github.com/siebenmann/go-kstat"
|
||||||
)
|
)
|
||||||
|
@ -30,13 +31,14 @@ import "C"
|
||||||
type cpuFreqCollector struct {
|
type cpuFreqCollector struct {
|
||||||
cpuFreq *prometheus.Desc
|
cpuFreq *prometheus.Desc
|
||||||
cpuFreqMax *prometheus.Desc
|
cpuFreqMax *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("cpufreq", defaultEnabled, NewCpuFreqCollector)
|
registerCollector("cpufreq", defaultEnabled, NewCpuFreqCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFreqCpuCollector() (Collector, error) {
|
func NewFreqCpuCollector(logger log.Logger) (Collector, error) {
|
||||||
return &cpuFreqCollector{
|
return &cpuFreqCollector{
|
||||||
cpuFreq: prometheus.NewDesc(
|
cpuFreq: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"),
|
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "frequency_hertz"),
|
||||||
|
@ -48,6 +50,7 @@ func NewFreqCpuCollector() (Collector, error) {
|
||||||
"Maximum cpu thread frequency in hertz.",
|
"Maximum cpu thread frequency in hertz.",
|
||||||
[]string{"cpu"}, nil,
|
[]string{"cpu"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ type devstatCollector struct {
|
||||||
bytesDesc *prometheus.Desc
|
bytesDesc *prometheus.Desc
|
||||||
transfersDesc *prometheus.Desc
|
transfersDesc *prometheus.Desc
|
||||||
blocksDesc *prometheus.Desc
|
blocksDesc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -103,7 +105,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDevstatCollector returns a new Collector exposing Device stats.
|
// NewDevstatCollector returns a new Collector exposing Device stats.
|
||||||
func NewDevstatCollector() (Collector, error) {
|
func NewDevstatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &devstatCollector{
|
return &devstatCollector{
|
||||||
bytesDesc: prometheus.NewDesc(
|
bytesDesc: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, devstatSubsystem, "bytes_total"),
|
prometheus.BuildFQName(namespace, devstatSubsystem, "bytes_total"),
|
||||||
|
@ -120,6 +122,7 @@ func NewDevstatCollector() (Collector, error) {
|
||||||
"The total number of bytes given in terms of the devices blocksize.",
|
"The total number of bytes given in terms of the devices blocksize.",
|
||||||
[]string{"device"}, nil,
|
[]string{"device"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ type devstatCollector struct {
|
||||||
duration typedDesc
|
duration typedDesc
|
||||||
busyTime typedDesc
|
busyTime typedDesc
|
||||||
blocks typedDesc
|
blocks typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -48,7 +50,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDevstatCollector returns a new Collector exposing Device stats.
|
// NewDevstatCollector returns a new Collector exposing Device stats.
|
||||||
func NewDevstatCollector() (Collector, error) {
|
func NewDevstatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &devstatCollector{
|
return &devstatCollector{
|
||||||
devinfo: &C.struct_devinfo{},
|
devinfo: &C.struct_devinfo{},
|
||||||
bytes: typedDesc{prometheus.NewDesc(
|
bytes: typedDesc{prometheus.NewDesc(
|
||||||
|
@ -76,6 +78,7 @@ func NewDevstatCollector() (Collector, error) {
|
||||||
"The total number of blocks transferred.",
|
"The total number of blocks transferred.",
|
||||||
[]string{"device"}, nil,
|
[]string{"device"}, nil,
|
||||||
), prometheus.CounterValue},
|
), prometheus.CounterValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/lufia/iostat"
|
"github.com/lufia/iostat"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
@ -28,7 +29,8 @@ type typedDescFunc struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type diskstatsCollector struct {
|
type diskstatsCollector struct {
|
||||||
descs []typedDescFunc
|
descs []typedDescFunc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -36,7 +38,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
|
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
|
||||||
func NewDiskstatsCollector() (Collector, error) {
|
func NewDiskstatsCollector(logger log.Logger) (Collector, error) {
|
||||||
var diskLabelNames = []string{"device"}
|
var diskLabelNames = []string{"device"}
|
||||||
|
|
||||||
return &diskstatsCollector{
|
return &diskstatsCollector{
|
||||||
|
@ -124,6 +126,7 @@ func NewDiskstatsCollector() (Collector, error) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ func (d *typedFactorDesc) mustNewConstMetric(value float64, labels ...string) pr
|
||||||
type diskstatsCollector struct {
|
type diskstatsCollector struct {
|
||||||
ignoredDevicesPattern *regexp.Regexp
|
ignoredDevicesPattern *regexp.Regexp
|
||||||
descs []typedFactorDesc
|
descs []typedFactorDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -62,7 +64,7 @@ func init() {
|
||||||
|
|
||||||
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
|
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
|
||||||
// Docs from https://www.kernel.org/doc/Documentation/iostats.txt
|
// Docs from https://www.kernel.org/doc/Documentation/iostats.txt
|
||||||
func NewDiskstatsCollector() (Collector, error) {
|
func NewDiskstatsCollector(logger log.Logger) (Collector, error) {
|
||||||
var diskLabelNames = []string{"device"}
|
var diskLabelNames = []string{"device"}
|
||||||
|
|
||||||
return &diskstatsCollector{
|
return &diskstatsCollector{
|
||||||
|
@ -178,6 +180,7 @@ func NewDiskstatsCollector() (Collector, error) {
|
||||||
factor: .001,
|
factor: .001,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +192,7 @@ func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
for dev, stats := range diskStats {
|
for dev, stats := range diskStats {
|
||||||
if c.ignoredDevicesPattern.MatchString(dev) {
|
if c.ignoredDevicesPattern.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(c.logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -34,6 +35,7 @@ type diskstatsCollector struct {
|
||||||
wxfer typedDesc
|
wxfer typedDesc
|
||||||
wbytes typedDesc
|
wbytes typedDesc
|
||||||
time typedDesc
|
time typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -41,13 +43,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
|
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
|
||||||
func NewDiskstatsCollector() (Collector, error) {
|
func NewDiskstatsCollector(logger log.Logger) (Collector, error) {
|
||||||
return &diskstatsCollector{
|
return &diskstatsCollector{
|
||||||
rxfer: typedDesc{readsCompletedDesc, prometheus.CounterValue},
|
rxfer: typedDesc{readsCompletedDesc, prometheus.CounterValue},
|
||||||
rbytes: typedDesc{readBytesDesc, prometheus.CounterValue},
|
rbytes: typedDesc{readBytesDesc, prometheus.CounterValue},
|
||||||
wxfer: typedDesc{writesCompletedDesc, prometheus.CounterValue},
|
wxfer: typedDesc{writesCompletedDesc, prometheus.CounterValue},
|
||||||
wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue},
|
wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue},
|
||||||
time: typedDesc{ioTimeSecondsDesc, prometheus.CounterValue},
|
time: typedDesc{ioTimeSecondsDesc, prometheus.CounterValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Numerical metric provided by /proc/drbd.
|
// Numerical metric provided by /proc/drbd.
|
||||||
|
@ -74,13 +75,14 @@ type drbdCollector struct {
|
||||||
numerical map[string]drbdNumericalMetric
|
numerical map[string]drbdNumericalMetric
|
||||||
stringPair map[string]drbdStringPairMetric
|
stringPair map[string]drbdStringPairMetric
|
||||||
connected *prometheus.Desc
|
connected *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("drbd", defaultDisabled, newDRBDCollector)
|
registerCollector("drbd", defaultDisabled, newDRBDCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDRBDCollector() (Collector, error) {
|
func newDRBDCollector(logger log.Logger) (Collector, error) {
|
||||||
return &drbdCollector{
|
return &drbdCollector{
|
||||||
numerical: map[string]drbdNumericalMetric{
|
numerical: map[string]drbdNumericalMetric{
|
||||||
"ns": newDRBDNumericalMetric(
|
"ns": newDRBDNumericalMetric(
|
||||||
|
@ -176,6 +178,7 @@ func newDRBDCollector() (Collector, error) {
|
||||||
[]string{"device"},
|
[]string{"device"},
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +187,7 @@ func (c *drbdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
file, err := os.Open(statsFile)
|
file, err := os.Open(statsFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("drbd: %s does not exist, skipping: %s", statsFile, err)
|
level.Debug(c.logger).Log("msg", "stats file does not exist, skipping", "file", statsFile, "err", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +204,7 @@ func (c *drbdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
kv := strings.Split(field, ":")
|
kv := strings.Split(field, ":")
|
||||||
if len(kv) != 2 {
|
if len(kv) != 2 {
|
||||||
log.Debugf("drbd: skipping invalid key:value pair %q", field)
|
level.Debug(c.logger).Log("msg", "skipping invalid key:value pair", "field", field)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +270,7 @@ func (c *drbdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("drbd: unhandled key-value pair: [%s: %q]", kv[0], kv[1])
|
level.Debug(c.logger).Log("msg", "unhandled key-value pair", "key", kv[0], "value", kv[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
return scanner.Err()
|
return scanner.Err()
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ type edacCollector struct {
|
||||||
ueCount *prometheus.Desc
|
ueCount *prometheus.Desc
|
||||||
csRowCECount *prometheus.Desc
|
csRowCECount *prometheus.Desc
|
||||||
csRowUECount *prometheus.Desc
|
csRowUECount *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -44,7 +46,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEdacCollector returns a new Collector exposing edac stats.
|
// NewEdacCollector returns a new Collector exposing edac stats.
|
||||||
func NewEdacCollector() (Collector, error) {
|
func NewEdacCollector(logger log.Logger) (Collector, error) {
|
||||||
return &edacCollector{
|
return &edacCollector{
|
||||||
ceCount: prometheus.NewDesc(
|
ceCount: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, edacSubsystem, "correctable_errors_total"),
|
prometheus.BuildFQName(namespace, edacSubsystem, "correctable_errors_total"),
|
||||||
|
@ -66,6 +68,7 @@ func NewEdacCollector() (Collector, error) {
|
||||||
"Total uncorrectable memory errors for this csrow.",
|
"Total uncorrectable memory errors for this csrow.",
|
||||||
[]string{"controller", "csrow"}, nil,
|
[]string{"controller", "csrow"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,13 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type entropyCollector struct {
|
type entropyCollector struct {
|
||||||
entropyAvail *prometheus.Desc
|
entropyAvail *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -30,13 +32,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEntropyCollector returns a new Collector exposing entropy stats.
|
// NewEntropyCollector returns a new Collector exposing entropy stats.
|
||||||
func NewEntropyCollector() (Collector, error) {
|
func NewEntropyCollector(logger log.Logger) (Collector, error) {
|
||||||
return &entropyCollector{
|
return &entropyCollector{
|
||||||
entropyAvail: prometheus.NewDesc(
|
entropyAvail: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "", "entropy_available_bits"),
|
prometheus.BuildFQName(namespace, "", "entropy_available_bits"),
|
||||||
"Bits of available entropy.",
|
"Bits of available entropy.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,13 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type execCollector struct {
|
type execCollector struct {
|
||||||
sysctls []bsdSysctl
|
sysctls []bsdSysctl
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -29,7 +31,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExecCollector returns a new Collector exposing system execution statistics.
|
// NewExecCollector returns a new Collector exposing system execution statistics.
|
||||||
func NewExecCollector() (Collector, error) {
|
func NewExecCollector(logger log.Logger) (Collector, error) {
|
||||||
// From sys/vm/vm_meter.c:
|
// From sys/vm/vm_meter.c:
|
||||||
// All are of type CTLTYPE_UINT.
|
// All are of type CTLTYPE_UINT.
|
||||||
//
|
//
|
||||||
|
@ -73,6 +75,7 @@ func NewExecCollector() (Collector, error) {
|
||||||
mib: "vm.stats.vm.v_forks",
|
mib: "vm.stats.vm.v_forks",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,15 +30,17 @@ const (
|
||||||
fileFDStatSubsystem = "filefd"
|
fileFDStatSubsystem = "filefd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fileFDStatCollector struct{}
|
type fileFDStatCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector(fileFDStatSubsystem, defaultEnabled, NewFileFDStatCollector)
|
registerCollector(fileFDStatSubsystem, defaultEnabled, NewFileFDStatCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFileFDStatCollector returns a new Collector exposing file-nr stats.
|
// NewFileFDStatCollector returns a new Collector exposing file-nr stats.
|
||||||
func NewFileFDStatCollector() (Collector, error) {
|
func NewFileFDStatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &fileFDStatCollector{}, nil
|
return &fileFDStatCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fileFDStatCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *fileFDStatCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log/level"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -50,14 +50,14 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
|
||||||
for i := 0; i < int(count); i++ {
|
for i := 0; i < int(count); i++ {
|
||||||
mountpoint := C.GoString(&mnt[i].f_mntonname[0])
|
mountpoint := C.GoString(&mnt[i].f_mntonname[0])
|
||||||
if c.ignoredMountPointsPattern.MatchString(mountpoint) {
|
if c.ignoredMountPointsPattern.MatchString(mountpoint) {
|
||||||
log.Debugf("Ignoring mount point: %s", mountpoint)
|
level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
device := C.GoString(&mnt[i].f_mntfromname[0])
|
device := C.GoString(&mnt[i].f_mntfromname[0])
|
||||||
fstype := C.GoString(&mnt[i].f_fstypename[0])
|
fstype := C.GoString(&mnt[i].f_fstypename[0])
|
||||||
if c.ignoredFSTypesPattern.MatchString(fstype) {
|
if c.ignoredFSTypesPattern.MatchString(fstype) {
|
||||||
log.Debugf("Ignoring fs type: %s", fstype)
|
level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -48,6 +49,7 @@ type filesystemCollector struct {
|
||||||
sizeDesc, freeDesc, availDesc *prometheus.Desc
|
sizeDesc, freeDesc, availDesc *prometheus.Desc
|
||||||
filesDesc, filesFreeDesc *prometheus.Desc
|
filesDesc, filesFreeDesc *prometheus.Desc
|
||||||
roDesc, deviceErrorDesc *prometheus.Desc
|
roDesc, deviceErrorDesc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type filesystemLabels struct {
|
type filesystemLabels struct {
|
||||||
|
@ -66,7 +68,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFilesystemCollector returns a new Collector exposing filesystems stats.
|
// NewFilesystemCollector returns a new Collector exposing filesystems stats.
|
||||||
func NewFilesystemCollector() (Collector, error) {
|
func NewFilesystemCollector(logger log.Logger) (Collector, error) {
|
||||||
subsystem := "filesystem"
|
subsystem := "filesystem"
|
||||||
mountPointPattern := regexp.MustCompile(*ignoredMountPoints)
|
mountPointPattern := regexp.MustCompile(*ignoredMountPoints)
|
||||||
filesystemsTypesPattern := regexp.MustCompile(*ignoredFSTypes)
|
filesystemsTypesPattern := regexp.MustCompile(*ignoredFSTypes)
|
||||||
|
@ -123,6 +125,7 @@ func NewFilesystemCollector() (Collector, error) {
|
||||||
filesFreeDesc: filesFreeDesc,
|
filesFreeDesc: filesFreeDesc,
|
||||||
roDesc: roDesc,
|
roDesc: roDesc,
|
||||||
deviceErrorDesc: deviceErrorDesc,
|
deviceErrorDesc: deviceErrorDesc,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log/level"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -54,14 +54,14 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
for _, fs := range buf {
|
for _, fs := range buf {
|
||||||
mountpoint := gostring(fs.Mntonname[:])
|
mountpoint := gostring(fs.Mntonname[:])
|
||||||
if c.ignoredMountPointsPattern.MatchString(mountpoint) {
|
if c.ignoredMountPointsPattern.MatchString(mountpoint) {
|
||||||
log.Debugf("Ignoring mount point: %s", mountpoint)
|
level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
device := gostring(fs.Mntfromname[:])
|
device := gostring(fs.Mntfromname[:])
|
||||||
fstype := gostring(fs.Fstypename[:])
|
fstype := gostring(fs.Fstypename[:])
|
||||||
if c.ignoredFSTypesPattern.MatchString(fstype) {
|
if c.ignoredFSTypesPattern.MatchString(fstype) {
|
||||||
log.Debugf("Ignoring fs type: %s", fstype)
|
level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -42,18 +43,18 @@ var stuckMountsMtx = &sync.Mutex{}
|
||||||
|
|
||||||
// GetStats returns filesystem stats.
|
// GetStats returns filesystem stats.
|
||||||
func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
mps, err := mountPointDetails()
|
mps, err := mountPointDetails(c.logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
stats := []filesystemStats{}
|
stats := []filesystemStats{}
|
||||||
for _, labels := range mps {
|
for _, labels := range mps {
|
||||||
if c.ignoredMountPointsPattern.MatchString(labels.mountPoint) {
|
if c.ignoredMountPointsPattern.MatchString(labels.mountPoint) {
|
||||||
log.Debugf("Ignoring mount point: %s", labels.mountPoint)
|
level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", labels.mountPoint)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if c.ignoredFSTypesPattern.MatchString(labels.fsType) {
|
if c.ignoredFSTypesPattern.MatchString(labels.fsType) {
|
||||||
log.Debugf("Ignoring fs type: %s", labels.fsType)
|
level.Debug(c.logger).Log("msg", "Ignoring fs", "type", labels.fsType)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stuckMountsMtx.Lock()
|
stuckMountsMtx.Lock()
|
||||||
|
@ -62,7 +63,7 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
labels: labels,
|
labels: labels,
|
||||||
deviceError: 1,
|
deviceError: 1,
|
||||||
})
|
})
|
||||||
log.Debugf("Mount point %q is in an unresponsive state", labels.mountPoint)
|
level.Debug(c.logger).Log("msg", "Mount point is in an unresponsive state", "mountpoint", labels.mountPoint)
|
||||||
stuckMountsMtx.Unlock()
|
stuckMountsMtx.Unlock()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -71,7 +72,7 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
// The success channel is used do tell the "watcher" that the stat
|
// The success channel is used do tell the "watcher" that the stat
|
||||||
// finished successfully. The channel is closed on success.
|
// finished successfully. The channel is closed on success.
|
||||||
success := make(chan struct{})
|
success := make(chan struct{})
|
||||||
go stuckMountWatcher(labels.mountPoint, success)
|
go stuckMountWatcher(labels.mountPoint, success, c.logger)
|
||||||
|
|
||||||
buf := new(unix.Statfs_t)
|
buf := new(unix.Statfs_t)
|
||||||
err = unix.Statfs(rootfsFilePath(labels.mountPoint), buf)
|
err = unix.Statfs(rootfsFilePath(labels.mountPoint), buf)
|
||||||
|
@ -79,7 +80,7 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
close(success)
|
close(success)
|
||||||
// If the mount has been marked as stuck, unmark it and log it's recovery.
|
// If the mount has been marked as stuck, unmark it and log it's recovery.
|
||||||
if _, ok := stuckMounts[labels.mountPoint]; ok {
|
if _, ok := stuckMounts[labels.mountPoint]; ok {
|
||||||
log.Debugf("Mount point %q has recovered, monitoring will resume", labels.mountPoint)
|
level.Debug(c.logger).Log("msg", "Mount point has recovered, monitoring will resume", "mountpoint", labels.mountPoint)
|
||||||
delete(stuckMounts, labels.mountPoint)
|
delete(stuckMounts, labels.mountPoint)
|
||||||
}
|
}
|
||||||
stuckMountsMtx.Unlock()
|
stuckMountsMtx.Unlock()
|
||||||
|
@ -89,7 +90,8 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
labels: labels,
|
labels: labels,
|
||||||
deviceError: 1,
|
deviceError: 1,
|
||||||
})
|
})
|
||||||
log.Debugf("Error on statfs() system call for %q: %s", rootfsFilePath(labels.mountPoint), err)
|
|
||||||
|
level.Debug(c.logger).Log("msg", "Error on statfs() system call", "rootfs", rootfsFilePath(labels.mountPoint), "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +119,7 @@ func (c *filesystemCollector) GetStats() ([]filesystemStats, error) {
|
||||||
// stuckMountWatcher listens on the given success channel and if the channel closes
|
// stuckMountWatcher listens on the given success channel and if the channel closes
|
||||||
// then the watcher does nothing. If instead the timeout is reached, the
|
// then the watcher does nothing. If instead the timeout is reached, the
|
||||||
// mount point that is being watched is marked as stuck.
|
// mount point that is being watched is marked as stuck.
|
||||||
func stuckMountWatcher(mountPoint string, success chan struct{}) {
|
func stuckMountWatcher(mountPoint string, success chan struct{}, logger log.Logger) {
|
||||||
select {
|
select {
|
||||||
case <-success:
|
case <-success:
|
||||||
// Success
|
// Success
|
||||||
|
@ -128,18 +130,18 @@ func stuckMountWatcher(mountPoint string, success chan struct{}) {
|
||||||
case <-success:
|
case <-success:
|
||||||
// Success came in just after the timeout was reached, don't label the mount as stuck
|
// Success came in just after the timeout was reached, don't label the mount as stuck
|
||||||
default:
|
default:
|
||||||
log.Debugf("Mount point %q timed out, it is being labeled as stuck and will not be monitored", mountPoint)
|
level.Debug(logger).Log("msg", "Mount point timed out, it is being labeled as stuck and will not be monitored", "mountpoint", mountPoint)
|
||||||
stuckMounts[mountPoint] = struct{}{}
|
stuckMounts[mountPoint] = struct{}{}
|
||||||
}
|
}
|
||||||
stuckMountsMtx.Unlock()
|
stuckMountsMtx.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mountPointDetails() ([]filesystemLabels, error) {
|
func mountPointDetails(logger log.Logger) ([]filesystemLabels, error) {
|
||||||
file, err := os.Open(procFilePath("1/mounts"))
|
file, err := os.Open(procFilePath("1/mounts"))
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
// Fallback to `/proc/mounts` if `/proc/1/mounts` is missing due hidepid.
|
// Fallback to `/proc/mounts` if `/proc/1/mounts` is missing due hidepid.
|
||||||
log.Debugf("Got %q reading root mounts, falling back to system mounts", err)
|
level.Debug(logger).Log("msg", "Reading root mounts failed, falling back to system mounts", "err", err)
|
||||||
file, err = os.Open(procFilePath("mounts"))
|
file, err = os.Open(procFilePath("mounts"))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ func TestMountPointDetails(t *testing.T) {
|
||||||
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/[vsanDatastore] bafb9e5a-8856-7e6c-699c-801844e77a4a/kubernetes-dynamic-pvc-3eba5bba-48a3-11e8-89ab-005056b92113.vmdk": "",
|
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/[vsanDatastore] bafb9e5a-8856-7e6c-699c-801844e77a4a/kubernetes-dynamic-pvc-3eba5bba-48a3-11e8-89ab-005056b92113.vmdk": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystems, err := mountPointDetails()
|
filesystems, err := mountPointDetails(log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
|
@ -101,7 +102,7 @@ func TestMountsFallback(t *testing.T) {
|
||||||
"/": "",
|
"/": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystems, err := mountPointDetails()
|
filesystems, err := mountPointDetails(log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
|
@ -129,7 +130,7 @@ func TestPathRootfs(t *testing.T) {
|
||||||
"/sys/fs/cgroup": "",
|
"/sys/fs/cgroup": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystems, err := mountPointDetails()
|
filesystems, err := mountPointDetails(log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,9 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,12 +46,14 @@ func init() {
|
||||||
registerCollector("hwmon", defaultEnabled, NewHwMonCollector)
|
registerCollector("hwmon", defaultEnabled, NewHwMonCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
type hwMonCollector struct{}
|
type hwMonCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
// NewHwMonCollector returns a new Collector exposing /sys/class/hwmon stats
|
// NewHwMonCollector returns a new Collector exposing /sys/class/hwmon stats
|
||||||
// (similar to lm-sensors).
|
// (similar to lm-sensors).
|
||||||
func NewHwMonCollector() (Collector, error) {
|
func NewHwMonCollector(logger log.Logger) (Collector, error) {
|
||||||
return &hwMonCollector{}, nil
|
return &hwMonCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanMetricName(name string) string {
|
func cleanMetricName(name string) string {
|
||||||
|
@ -422,7 +425,7 @@ func (c *hwMonCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
hwmonFiles, err := ioutil.ReadDir(hwmonPathName)
|
hwmonFiles, err := ioutil.ReadDir(hwmonPathName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debug("hwmon collector metrics are not available for this system")
|
level.Debug(c.logger).Log("msg", "hwmon collector metrics are not available for this system")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/sysfs"
|
"github.com/prometheus/procfs/sysfs"
|
||||||
)
|
)
|
||||||
|
@ -27,6 +28,7 @@ import (
|
||||||
type infinibandCollector struct {
|
type infinibandCollector struct {
|
||||||
fs sysfs.FS
|
fs sysfs.FS
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -34,7 +36,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInfiniBandCollector returns a new Collector exposing InfiniBand stats.
|
// NewInfiniBandCollector returns a new Collector exposing InfiniBand stats.
|
||||||
func NewInfiniBandCollector() (Collector, error) {
|
func NewInfiniBandCollector(logger log.Logger) (Collector, error) {
|
||||||
var i infinibandCollector
|
var i infinibandCollector
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -42,6 +44,7 @@ func NewInfiniBandCollector() (Collector, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
||||||
}
|
}
|
||||||
|
i.logger = logger
|
||||||
|
|
||||||
// Detailed description for all metrics.
|
// Detailed description for all metrics.
|
||||||
descriptions := map[string]string{
|
descriptions := map[string]string{
|
||||||
|
|
|
@ -16,10 +16,14 @@
|
||||||
|
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import "github.com/prometheus/client_golang/prometheus"
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
type interruptsCollector struct {
|
type interruptsCollector struct {
|
||||||
desc typedDesc
|
desc typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -27,12 +31,13 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInterruptsCollector returns a new Collector exposing interrupts stats.
|
// NewInterruptsCollector returns a new Collector exposing interrupts stats.
|
||||||
func NewInterruptsCollector() (Collector, error) {
|
func NewInterruptsCollector(logger log.Logger) (Collector, error) {
|
||||||
return &interruptsCollector{
|
return &interruptsCollector{
|
||||||
desc: typedDesc{prometheus.NewDesc(
|
desc: typedDesc{prometheus.NewDesc(
|
||||||
namespace+"_interrupts_total",
|
namespace+"_interrupts_total",
|
||||||
"Interrupt details.",
|
"Interrupt details.",
|
||||||
interruptLabelNames, nil,
|
interruptLabelNames, nil,
|
||||||
), prometheus.CounterValue},
|
), prometheus.CounterValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ type ipvsCollector struct {
|
||||||
fs procfs.FS
|
fs procfs.FS
|
||||||
backendConnectionsActive, backendConnectionsInact, backendWeight typedDesc
|
backendConnectionsActive, backendConnectionsInact, backendWeight typedDesc
|
||||||
connections, incomingPackets, outgoingPackets, incomingBytes, outgoingBytes typedDesc
|
connections, incomingPackets, outgoingPackets, incomingBytes, outgoingBytes typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -38,11 +40,11 @@ func init() {
|
||||||
|
|
||||||
// NewIPVSCollector sets up a new collector for IPVS metrics. It accepts the
|
// NewIPVSCollector sets up a new collector for IPVS metrics. It accepts the
|
||||||
// "procfs" config parameter to override the default proc location (/proc).
|
// "procfs" config parameter to override the default proc location (/proc).
|
||||||
func NewIPVSCollector() (Collector, error) {
|
func NewIPVSCollector(logger log.Logger) (Collector, error) {
|
||||||
return newIPVSCollector()
|
return newIPVSCollector(logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIPVSCollector() (*ipvsCollector, error) {
|
func newIPVSCollector(logger log.Logger) (*ipvsCollector, error) {
|
||||||
var (
|
var (
|
||||||
ipvsBackendLabelNames = []string{
|
ipvsBackendLabelNames = []string{
|
||||||
"local_address",
|
"local_address",
|
||||||
|
@ -57,6 +59,7 @@ func newIPVSCollector() (*ipvsCollector, error) {
|
||||||
subsystem = "ipvs"
|
subsystem = "ipvs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
c.logger = logger
|
||||||
c.fs, err = procfs.NewFS(*procPath)
|
c.fs, err = procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -111,7 +114,7 @@ func (c *ipvsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Cannot access ipvs metrics, report no error.
|
// Cannot access ipvs metrics, report no error.
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debug("ipvs collector metrics are not available for this system")
|
level.Debug(c.logger).Log("msg", "ipvs collector metrics are not available for this system")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("could not get IPVS stats: %s", err)
|
return fmt.Errorf("could not get IPVS stats: %s", err)
|
||||||
|
|
|
@ -15,6 +15,7 @@ package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -30,7 +31,7 @@ func TestIPVSCollector(t *testing.T) {
|
||||||
if _, err := kingpin.CommandLine.Parse([]string{"--path.procfs", "fixtures/proc"}); err != nil {
|
if _, err := kingpin.CommandLine.Parse([]string{"--path.procfs", "fixtures/proc"}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
collector, err := newIPVSCollector()
|
collector, err := newIPVSCollector(log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ func TestIPVSCollectorResponse(t *testing.T) {
|
||||||
if _, err := kingpin.CommandLine.Parse([]string{"--path.procfs", "fixtures/proc"}); err != nil {
|
if _, err := kingpin.CommandLine.Parse([]string{"--path.procfs", "fixtures/proc"}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
collector, err := NewIPVSCollector()
|
collector, err := NewIPVSCollector(log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ var (
|
||||||
|
|
||||||
type ksmdCollector struct {
|
type ksmdCollector struct {
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -47,7 +49,7 @@ func getCanonicalMetricName(filename string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKsmdCollector returns a new Collector exposing kernel/system statistics.
|
// NewKsmdCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewKsmdCollector() (Collector, error) {
|
func NewKsmdCollector(logger log.Logger) (Collector, error) {
|
||||||
subsystem := "ksmd"
|
subsystem := "ksmd"
|
||||||
descs := make(map[string]*prometheus.Desc)
|
descs := make(map[string]*prometheus.Desc)
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ func NewKsmdCollector() (Collector, error) {
|
||||||
prometheus.BuildFQName(namespace, subsystem, getCanonicalMetricName(n)),
|
prometheus.BuildFQName(namespace, subsystem, getCanonicalMetricName(n)),
|
||||||
fmt.Sprintf("ksmd '%s' file.", n), nil, nil)
|
fmt.Sprintf("ksmd '%s' file.", n), nil, nil)
|
||||||
}
|
}
|
||||||
return &ksmdCollector{descs}, nil
|
return &ksmdCollector{descs, logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update implements Collector and exposes kernel and system statistics.
|
// Update implements Collector and exposes kernel and system statistics.
|
||||||
|
|
|
@ -19,12 +19,14 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type loadavgCollector struct {
|
type loadavgCollector struct {
|
||||||
metric []typedDesc
|
metric []typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -32,13 +34,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLoadavgCollector returns a new Collector exposing load average stats.
|
// NewLoadavgCollector returns a new Collector exposing load average stats.
|
||||||
func NewLoadavgCollector() (Collector, error) {
|
func NewLoadavgCollector(logger log.Logger) (Collector, error) {
|
||||||
return &loadavgCollector{
|
return &loadavgCollector{
|
||||||
metric: []typedDesc{
|
metric: []typedDesc{
|
||||||
{prometheus.NewDesc(namespace+"_load1", "1m load average.", nil, nil), prometheus.GaugeValue},
|
{prometheus.NewDesc(namespace+"_load1", "1m load average.", nil, nil), prometheus.GaugeValue},
|
||||||
{prometheus.NewDesc(namespace+"_load5", "5m load average.", nil, nil), prometheus.GaugeValue},
|
{prometheus.NewDesc(namespace+"_load5", "5m load average.", nil, nil), prometheus.GaugeValue},
|
||||||
{prometheus.NewDesc(namespace+"_load15", "15m load average.", nil, nil), prometheus.GaugeValue},
|
{prometheus.NewDesc(namespace+"_load15", "15m load average.", nil, nil), prometheus.GaugeValue},
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +51,7 @@ func (c *loadavgCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
return fmt.Errorf("couldn't get load: %s", err)
|
return fmt.Errorf("couldn't get load: %s", err)
|
||||||
}
|
}
|
||||||
for i, load := range loads {
|
for i, load := range loads {
|
||||||
log.Debugf("return load %d: %f", i, load)
|
level.Debug(c.logger).Log("msg", "return load", "index", i, "load", load)
|
||||||
ch <- c.metric[i].mustNewConstMetric(load)
|
ch <- c.metric[i].mustNewConstMetric(load)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/godbus/dbus"
|
"github.com/godbus/dbus"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
@ -43,7 +44,9 @@ var (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
type logindCollector struct{}
|
type logindCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
type logindDbus struct {
|
type logindDbus struct {
|
||||||
conn *dbus.Conn
|
conn *dbus.Conn
|
||||||
|
@ -82,8 +85,8 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLogindCollector returns a new Collector exposing logind statistics.
|
// NewLogindCollector returns a new Collector exposing logind statistics.
|
||||||
func NewLogindCollector() (Collector, error) {
|
func NewLogindCollector(logger log.Logger) (Collector, error) {
|
||||||
return &logindCollector{}, nil
|
return &logindCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *logindCollector) Update(ch chan<- prometheus.Metric) error {
|
func (lc *logindCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
|
|
@ -19,20 +19,23 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mdadmCollector struct{}
|
type mdadmCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("mdadm", defaultEnabled, NewMdadmCollector)
|
registerCollector("mdadm", defaultEnabled, NewMdadmCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMdadmCollector returns a new Collector exposing raid statistics.
|
// NewMdadmCollector returns a new Collector exposing raid statistics.
|
||||||
func NewMdadmCollector() (Collector, error) {
|
func NewMdadmCollector(logger log.Logger) (Collector, error) {
|
||||||
return &mdadmCollector{}, nil
|
return &mdadmCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -101,7 +104,7 @@ func (c *mdadmCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("Not collecting mdstat, file does not exist: %s", *procPath)
|
level.Debug(c.logger).Log("msg", "Not collecting mdstat, file does not exist", "file", *procPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ func (c *mdadmCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mdStat := range mdStats {
|
for _, mdStat := range mdStats {
|
||||||
log.Debugf("collecting metrics for device %s", mdStat.Name)
|
level.Debug(c.logger).Log("msg", "collecting metrics for device", "device", mdStat.Name)
|
||||||
|
|
||||||
stateVals := make(map[string]float64)
|
stateVals := make(map[string]float64)
|
||||||
stateVals[mdStat.ActivityState] = 1
|
stateVals[mdStat.ActivityState] = 1
|
||||||
|
|
|
@ -20,23 +20,26 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
memInfoSubsystem = "memory"
|
memInfoSubsystem = "memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
type meminfoCollector struct{}
|
type meminfoCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("meminfo", defaultEnabled, NewMeminfoCollector)
|
registerCollector("meminfo", defaultEnabled, NewMeminfoCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMeminfoCollector returns a new Collector exposing memory stats.
|
// NewMeminfoCollector returns a new Collector exposing memory stats.
|
||||||
func NewMeminfoCollector() (Collector, error) {
|
func NewMeminfoCollector(logger log.Logger) (Collector, error) {
|
||||||
return &meminfoCollector{}, nil
|
return &meminfoCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update calls (*meminfoCollector).getMemInfo to get the platform specific
|
// Update calls (*meminfoCollector).getMemInfo to get the platform specific
|
||||||
|
@ -47,7 +50,7 @@ func (c *meminfoCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't get meminfo: %s", err)
|
return fmt.Errorf("couldn't get meminfo: %s", err)
|
||||||
}
|
}
|
||||||
log.Debugf("Set node_mem: %#v", memInfo)
|
level.Debug(c.logger).Log("msg", "Set node_mem", "memInfo", memInfo)
|
||||||
for k, v := range memInfo {
|
for k, v := range memInfo {
|
||||||
if strings.HasSuffix(k, "_total") {
|
if strings.HasSuffix(k, "_total") {
|
||||||
metricType = prometheus.CounterValue
|
metricType = prometheus.CounterValue
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ type meminfoMetric struct {
|
||||||
|
|
||||||
type meminfoNumaCollector struct {
|
type meminfoNumaCollector struct {
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -50,9 +52,10 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMeminfoNumaCollector returns a new Collector exposing memory stats.
|
// NewMeminfoNumaCollector returns a new Collector exposing memory stats.
|
||||||
func NewMeminfoNumaCollector() (Collector, error) {
|
func NewMeminfoNumaCollector(logger log.Logger) (Collector, error) {
|
||||||
return &meminfoNumaCollector{
|
return &meminfoNumaCollector{
|
||||||
metricDescs: map[string]*prometheus.Desc{},
|
metricDescs: map[string]*prometheus.Desc{},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -31,6 +32,7 @@ type memoryCollector struct {
|
||||||
pageSize uint64
|
pageSize uint64
|
||||||
sysctls []bsdSysctl
|
sysctls []bsdSysctl
|
||||||
kvm kvm
|
kvm kvm
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -38,7 +40,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMemoryCollector returns a new Collector exposing memory stats.
|
// NewMemoryCollector returns a new Collector exposing memory stats.
|
||||||
func NewMemoryCollector() (Collector, error) {
|
func NewMemoryCollector(logger log.Logger) (Collector, error) {
|
||||||
tmp32, err := unix.SysctlUint32("vm.stats.vm.v_page_size")
|
tmp32, err := unix.SysctlUint32("vm.stats.vm.v_page_size")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("sysctl(vm.stats.vm.v_page_size) failed: %s", err)
|
return nil, fmt.Errorf("sysctl(vm.stats.vm.v_page_size) failed: %s", err)
|
||||||
|
@ -57,6 +59,7 @@ func NewMemoryCollector() (Collector, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &memoryCollector{
|
return &memoryCollector{
|
||||||
|
logger: logger,
|
||||||
pageSize: uint64(tmp32),
|
pageSize: uint64(tmp32),
|
||||||
sysctls: []bsdSysctl{
|
sysctls: []bsdSysctl{
|
||||||
// Descriptions via: https://wiki.freebsd.org/Memory
|
// Descriptions via: https://wiki.freebsd.org/Memory
|
||||||
|
|
|
@ -16,8 +16,9 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,6 +92,8 @@ type mountStatsCollector struct {
|
||||||
NFSEventPNFSWriteTotal *prometheus.Desc
|
NFSEventPNFSWriteTotal *prometheus.Desc
|
||||||
|
|
||||||
proc procfs.Proc
|
proc procfs.Proc
|
||||||
|
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to uniquely identify an NFS mount to prevent duplicates
|
// used to uniquely identify an NFS mount to prevent duplicates
|
||||||
|
@ -105,7 +108,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMountStatsCollector returns a new Collector exposing NFS statistics.
|
// NewMountStatsCollector returns a new Collector exposing NFS statistics.
|
||||||
func NewMountStatsCollector() (Collector, error) {
|
func NewMountStatsCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
fs, err := procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -498,7 +501,8 @@ func NewMountStatsCollector() (Collector, error) {
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
|
|
||||||
proc: proc,
|
proc: proc,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +538,7 @@ func (c *mountStatsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
deviceIdentifier := nfsDeviceIdentifier{m.Device, stats.Transport.Protocol, mountAddress}
|
deviceIdentifier := nfsDeviceIdentifier{m.Device, stats.Transport.Protocol, mountAddress}
|
||||||
i := deviceList[deviceIdentifier]
|
i := deviceList[deviceIdentifier]
|
||||||
if i {
|
if i {
|
||||||
log.Debugf("Skipping duplicate device entry %q", deviceIdentifier)
|
level.Debug(c.logger).Log("msg", "Skipping duplicate device entry", "device", deviceIdentifier)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/sysfs"
|
"github.com/prometheus/procfs/sysfs"
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -34,6 +35,7 @@ type netClassCollector struct {
|
||||||
subsystem string
|
subsystem string
|
||||||
ignoredDevicesPattern *regexp.Regexp
|
ignoredDevicesPattern *regexp.Regexp
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -41,7 +43,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNetClassCollector returns a new Collector exposing network class stats.
|
// NewNetClassCollector returns a new Collector exposing network class stats.
|
||||||
func NewNetClassCollector() (Collector, error) {
|
func NewNetClassCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := sysfs.NewFS(*sysPath)
|
fs, err := sysfs.NewFS(*sysPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
||||||
|
@ -52,6 +54,7 @@ func NewNetClassCollector() (Collector, error) {
|
||||||
subsystem: "network",
|
subsystem: "network",
|
||||||
ignoredDevicesPattern: pattern,
|
ignoredDevicesPattern: pattern,
|
||||||
metricDescs: map[string]*prometheus.Desc{},
|
metricDescs: map[string]*prometheus.Desc{},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -34,7 +35,7 @@ import (
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
|
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||||
netDev := map[string]map[string]string{}
|
netDev := map[string]map[string]string{}
|
||||||
|
|
||||||
var ifap, ifa *C.struct_ifaddrs
|
var ifap, ifa *C.struct_ifaddrs
|
||||||
|
@ -47,11 +48,11 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]ma
|
||||||
if ifa.ifa_addr.sa_family == C.AF_LINK {
|
if ifa.ifa_addr.sa_family == C.AF_LINK {
|
||||||
dev := C.GoString(ifa.ifa_name)
|
dev := C.GoString(ifa.ifa_name)
|
||||||
if ignore != nil && ignore.MatchString(dev) {
|
if ignore != nil && ignore.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if accept != nil && !accept.MatchString(dev) {
|
if accept != nil && !accept.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -36,6 +37,7 @@ type netDevCollector struct {
|
||||||
ignoredDevicesPattern *regexp.Regexp
|
ignoredDevicesPattern *regexp.Regexp
|
||||||
acceptDevicesPattern *regexp.Regexp
|
acceptDevicesPattern *regexp.Regexp
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -43,7 +45,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNetDevCollector returns a new Collector exposing network device stats.
|
// NewNetDevCollector returns a new Collector exposing network device stats.
|
||||||
func NewNetDevCollector() (Collector, error) {
|
func NewNetDevCollector(logger log.Logger) (Collector, error) {
|
||||||
if *netdevIgnoredDevices != "" && *netdevAcceptDevices != "" {
|
if *netdevIgnoredDevices != "" && *netdevAcceptDevices != "" {
|
||||||
return nil, errors.New("device-blacklist & accept-devices are mutually exclusive")
|
return nil, errors.New("device-blacklist & accept-devices are mutually exclusive")
|
||||||
}
|
}
|
||||||
|
@ -63,11 +65,12 @@ func NewNetDevCollector() (Collector, error) {
|
||||||
ignoredDevicesPattern: ignorePattern,
|
ignoredDevicesPattern: ignorePattern,
|
||||||
acceptDevicesPattern: acceptPattern,
|
acceptDevicesPattern: acceptPattern,
|
||||||
metricDescs: map[string]*prometheus.Desc{},
|
metricDescs: map[string]*prometheus.Desc{},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
netDev, err := getNetDevStats(c.ignoredDevicesPattern, c.acceptDevicesPattern)
|
netDev, err := getNetDevStats(c.ignoredDevicesPattern, c.acceptDevicesPattern, c.logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't get netstats: %s", err)
|
return fmt.Errorf("couldn't get netstats: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,12 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
|
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||||
netDev := map[string]map[string]string{}
|
netDev := map[string]map[string]string{}
|
||||||
|
|
||||||
ifs, err := net.Interfaces()
|
ifs, err := net.Interfaces()
|
||||||
|
@ -38,16 +39,16 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]ma
|
||||||
for _, iface := range ifs {
|
for _, iface := range ifs {
|
||||||
ifaceData, err := getIfaceData(iface.Index)
|
ifaceData, err := getIfaceData(iface.Index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("failed to load data for interface %q: %v", iface.Name, err)
|
level.Debug(logger).Log("msg", "failed to load data for interface", "device", iface.Name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ignore != nil && ignore.MatchString(iface.Name) {
|
if ignore != nil && ignore.MatchString(iface.Name) {
|
||||||
log.Debugf("Ignoring device: %s", iface.Name)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", iface.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if accept != nil && !accept.MatchString(iface.Name) {
|
if accept != nil && !accept.MatchString(iface.Name) {
|
||||||
log.Debugf("Ignoring device: %s", iface.Name)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", iface.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -31,17 +32,17 @@ var (
|
||||||
procNetDevFieldSep = regexp.MustCompile(` +`)
|
procNetDevFieldSep = regexp.MustCompile(` +`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
|
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||||
file, err := os.Open(procFilePath("net/dev"))
|
file, err := os.Open(procFilePath("net/dev"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
return parseNetDevStats(file, ignore, accept)
|
return parseNetDevStats(file, ignore, accept, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
|
func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||||
scanner := bufio.NewScanner(r)
|
scanner := bufio.NewScanner(r)
|
||||||
scanner.Scan() // skip first header
|
scanner.Scan() // skip first header
|
||||||
scanner.Scan()
|
scanner.Scan()
|
||||||
|
@ -65,11 +66,11 @@ func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp)
|
||||||
|
|
||||||
dev := parts[1]
|
dev := parts[1]
|
||||||
if ignore != nil && ignore.MatchString(dev) {
|
if ignore != nil && ignore.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if accept != nil && !accept.MatchString(dev) {
|
if accept != nil && !accept.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -26,7 +27,7 @@ func TestNetDevStatsIgnore(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
netStats, err := parseNetDevStats(file, regexp.MustCompile("^veth"), nil)
|
netStats, err := parseNetDevStats(file, regexp.MustCompile("^veth"), nil, log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@ func TestNetDevStatsAccept(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
netStats, err := parseNetDevStats(file, nil, regexp.MustCompile("^💩0$"))
|
netStats, err := parseNetDevStats(file, nil, regexp.MustCompile("^💩0$"), log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/prometheus/common/log"
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,7 +32,7 @@ import (
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
|
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||||
netDev := map[string]map[string]string{}
|
netDev := map[string]map[string]string{}
|
||||||
|
|
||||||
var ifap, ifa *C.struct_ifaddrs
|
var ifap, ifa *C.struct_ifaddrs
|
||||||
|
@ -44,11 +45,11 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]ma
|
||||||
if ifa.ifa_addr.sa_family == C.AF_LINK {
|
if ifa.ifa_addr.sa_family == C.AF_LINK {
|
||||||
dev := C.GoString(ifa.ifa_name)
|
dev := C.GoString(ifa.ifa_name)
|
||||||
if ignore != nil && ignore.MatchString(dev) {
|
if ignore != nil && ignore.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if accept != nil && !accept.MatchString(dev) {
|
if accept != nil && !accept.MatchString(dev) {
|
||||||
log.Debugf("Ignoring device: %s", dev)
|
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -38,6 +39,7 @@ var (
|
||||||
|
|
||||||
type netStatCollector struct {
|
type netStatCollector struct {
|
||||||
fieldPattern *regexp.Regexp
|
fieldPattern *regexp.Regexp
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -46,10 +48,11 @@ func init() {
|
||||||
|
|
||||||
// NewNetStatCollector takes and returns
|
// NewNetStatCollector takes and returns
|
||||||
// a new Collector exposing network stats.
|
// a new Collector exposing network stats.
|
||||||
func NewNetStatCollector() (Collector, error) {
|
func NewNetStatCollector(logger log.Logger) (Collector, error) {
|
||||||
pattern := regexp.MustCompile(*netStatFields)
|
pattern := regexp.MustCompile(*netStatFields)
|
||||||
return &netStatCollector{
|
return &netStatCollector{
|
||||||
fieldPattern: pattern,
|
fieldPattern: pattern,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs/nfs"
|
"github.com/prometheus/procfs/nfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ type nfsCollector struct {
|
||||||
nfsRPCRetransmissionsDesc *prometheus.Desc
|
nfsRPCRetransmissionsDesc *prometheus.Desc
|
||||||
nfsRPCAuthenticationRefreshesDesc *prometheus.Desc
|
nfsRPCAuthenticationRefreshesDesc *prometheus.Desc
|
||||||
nfsProceduresDesc *prometheus.Desc
|
nfsProceduresDesc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -42,7 +44,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNfsCollector returns a new Collector exposing NFS statistics.
|
// NewNfsCollector returns a new Collector exposing NFS statistics.
|
||||||
func NewNfsCollector() (Collector, error) {
|
func NewNfsCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := nfs.NewFS(*procPath)
|
fs, err := nfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -86,6 +88,7 @@ func NewNfsCollector() (Collector, error) {
|
||||||
[]string{"proto", "method"},
|
[]string{"proto", "method"},
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +96,7 @@ func (c *nfsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
stats, err := c.fs.ClientRPCStats()
|
stats, err := c.fs.ClientRPCStats()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("Not collecting NFS metrics: %s", err)
|
level.Debug(c.logger).Log("msg", "Not collecting NFS metrics", "err", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("failed to retrieve nfs stats: %w", err)
|
return fmt.Errorf("failed to retrieve nfs stats: %w", err)
|
||||||
|
|
|
@ -17,8 +17,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs/nfs"
|
"github.com/prometheus/procfs/nfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ import (
|
||||||
type nfsdCollector struct {
|
type nfsdCollector struct {
|
||||||
fs nfs.FS
|
fs nfs.FS
|
||||||
requestsDesc *prometheus.Desc
|
requestsDesc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -38,7 +40,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewNFSdCollector returns a new Collector exposing /proc/net/rpc/nfsd statistics.
|
// NewNFSdCollector returns a new Collector exposing /proc/net/rpc/nfsd statistics.
|
||||||
func NewNFSdCollector() (Collector, error) {
|
func NewNFSdCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := nfs.NewFS(*procPath)
|
fs, err := nfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -51,6 +53,7 @@ func NewNFSdCollector() (Collector, error) {
|
||||||
"Total number NFSd Requests by method and protocol.",
|
"Total number NFSd Requests by method and protocol.",
|
||||||
[]string{"proto", "method"}, nil,
|
[]string{"proto", "method"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ func (c *nfsdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
stats, err := c.fs.ServerRPCStats()
|
stats, err := c.fs.ServerRPCStats()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("Not collecting NFSd metrics: %s", err)
|
level.Debug(c.logger).Log("msg", "Not collecting NFSd metrics", "err", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("failed to retrieve nfsd stats: %w", err)
|
return fmt.Errorf("failed to retrieve nfsd stats: %w", err)
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beevik/ntp"
|
"github.com/beevik/ntp"
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -47,6 +48,7 @@ var (
|
||||||
|
|
||||||
type ntpCollector struct {
|
type ntpCollector struct {
|
||||||
stratum, leap, rtt, offset, reftime, rootDelay, rootDispersion, sanity typedDesc
|
stratum, leap, rtt, offset, reftime, rootDelay, rootDispersion, sanity typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -57,7 +59,7 @@ func init() {
|
||||||
// Default definition of "local" is:
|
// Default definition of "local" is:
|
||||||
// - collector.ntp.server address is a loopback address (or collector.ntp.server-is-mine flag is turned on)
|
// - collector.ntp.server address is a loopback address (or collector.ntp.server-is-mine flag is turned on)
|
||||||
// - the server is reachable with outgoin IP_TTL = 1
|
// - the server is reachable with outgoin IP_TTL = 1
|
||||||
func NewNtpCollector() (Collector, error) {
|
func NewNtpCollector(logger log.Logger) (Collector, error) {
|
||||||
ipaddr := net.ParseIP(*ntpServer)
|
ipaddr := net.ParseIP(*ntpServer)
|
||||||
if !*ntpServerIsLocal && (ipaddr == nil || !ipaddr.IsLoopback()) {
|
if !*ntpServerIsLocal && (ipaddr == nil || !ipaddr.IsLoopback()) {
|
||||||
return nil, fmt.Errorf("only IP address of local NTP server is valid for --collector.ntp.server")
|
return nil, fmt.Errorf("only IP address of local NTP server is valid for --collector.ntp.server")
|
||||||
|
@ -112,6 +114,7 @@ func NewNtpCollector() (Collector, error) {
|
||||||
"NTPD sanity according to RFC5905 heuristics and configured limits.",
|
"NTPD sanity according to RFC5905 heuristics and configured limits.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
perf "github.com/hodgesds/perf-utils"
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/hodgesds/perf-utils"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ func init() {
|
||||||
registerCollector(perfSubsystem, defaultDisabled, NewPerfCollector)
|
registerCollector(perfSubsystem, defaultDisabled, NewPerfCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// perfCollector is a Collecter that uses the perf subsystem to collect
|
// perfCollector is a Collector that uses the perf subsystem to collect
|
||||||
// metrics. It uses perf_event_open an ioctls for profiling. Due to the fact
|
// metrics. It uses perf_event_open an ioctls for profiling. Due to the fact
|
||||||
// that the perf subsystem is highly dependent on kernel configuration and
|
// that the perf subsystem is highly dependent on kernel configuration and
|
||||||
// settings not all profiler values may be exposed on the target system at any
|
// settings not all profiler values may be exposed on the target system at any
|
||||||
|
@ -39,34 +40,36 @@ type perfCollector struct {
|
||||||
perfSwProfilers map[int]perf.SoftwareProfiler
|
perfSwProfilers map[int]perf.SoftwareProfiler
|
||||||
perfCacheProfilers map[int]perf.CacheProfiler
|
perfCacheProfilers map[int]perf.CacheProfiler
|
||||||
desc map[string]*prometheus.Desc
|
desc map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPerfCollector returns a new perf based collector, it creates a profiler
|
// NewPerfCollector returns a new perf based collector, it creates a profiler
|
||||||
// per CPU.
|
// per CPU.
|
||||||
func NewPerfCollector() (Collector, error) {
|
func NewPerfCollector(logger log.Logger) (Collector, error) {
|
||||||
collector := &perfCollector{
|
c := &perfCollector{
|
||||||
perfHwProfilers: map[int]perf.HardwareProfiler{},
|
perfHwProfilers: map[int]perf.HardwareProfiler{},
|
||||||
perfSwProfilers: map[int]perf.SoftwareProfiler{},
|
perfSwProfilers: map[int]perf.SoftwareProfiler{},
|
||||||
perfCacheProfilers: map[int]perf.CacheProfiler{},
|
perfCacheProfilers: map[int]perf.CacheProfiler{},
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
ncpus := runtime.NumCPU()
|
ncpus := runtime.NumCPU()
|
||||||
for i := 0; i < ncpus; i++ {
|
for i := 0; i < ncpus; i++ {
|
||||||
// Use -1 to profile all processes on the CPU, see:
|
// Use -1 to profile all processes on the CPU, see:
|
||||||
// man perf_event_open
|
// man perf_event_open
|
||||||
collector.perfHwProfilers[i] = perf.NewHardwareProfiler(-1, i)
|
c.perfHwProfilers[i] = perf.NewHardwareProfiler(-1, i)
|
||||||
if err := collector.perfHwProfilers[i].Start(); err != nil {
|
if err := c.perfHwProfilers[i].Start(); err != nil {
|
||||||
return collector, err
|
return c, err
|
||||||
}
|
}
|
||||||
collector.perfSwProfilers[i] = perf.NewSoftwareProfiler(-1, i)
|
c.perfSwProfilers[i] = perf.NewSoftwareProfiler(-1, i)
|
||||||
if err := collector.perfSwProfilers[i].Start(); err != nil {
|
if err := c.perfSwProfilers[i].Start(); err != nil {
|
||||||
return collector, err
|
return c, err
|
||||||
}
|
}
|
||||||
collector.perfCacheProfilers[i] = perf.NewCacheProfiler(-1, i)
|
c.perfCacheProfilers[i] = perf.NewCacheProfiler(-1, i)
|
||||||
if err := collector.perfCacheProfilers[i].Start(); err != nil {
|
if err := c.perfCacheProfilers[i].Start(); err != nil {
|
||||||
return collector, err
|
return c, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
collector.desc = map[string]*prometheus.Desc{
|
c.desc = map[string]*prometheus.Desc{
|
||||||
"cpucycles_total": prometheus.NewDesc(
|
"cpucycles_total": prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(
|
prometheus.BuildFQName(
|
||||||
namespace,
|
namespace,
|
||||||
|
@ -309,7 +312,7 @@ func NewPerfCollector() (Collector, error) {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
return collector, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update implements the Collector interface and will collect metrics per CPU.
|
// Update implements the Collector interface and will collect metrics per CPU.
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -37,7 +38,7 @@ func TestPerfCollector(t *testing.T) {
|
||||||
if paranoid >= 1 {
|
if paranoid >= 1 {
|
||||||
t.Skip("Skipping perf tests, set perf_event_paranoid to 0")
|
t.Skip("Skipping perf tests, set perf_event_paranoid to 0")
|
||||||
}
|
}
|
||||||
collector, err := NewPerfCollector()
|
collector, err := NewPerfCollector(log.NewNopLogger())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/sysfs"
|
"github.com/prometheus/procfs/sysfs"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
|
@ -33,18 +34,20 @@ type powerSupplyClassCollector struct {
|
||||||
subsystem string
|
subsystem string
|
||||||
ignoredPattern *regexp.Regexp
|
ignoredPattern *regexp.Regexp
|
||||||
metricDescs map[string]*prometheus.Desc
|
metricDescs map[string]*prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector("powersupplyclass", defaultEnabled, NewPowerSupplyClassCollector)
|
registerCollector("powersupplyclass", defaultEnabled, NewPowerSupplyClassCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPowerSupplyClassCollector() (Collector, error) {
|
func NewPowerSupplyClassCollector(logger log.Logger) (Collector, error) {
|
||||||
pattern := regexp.MustCompile(*powerSupplyClassIgnoredPowerSupplies)
|
pattern := regexp.MustCompile(*powerSupplyClassIgnoredPowerSupplies)
|
||||||
return &powerSupplyClassCollector{
|
return &powerSupplyClassCollector{
|
||||||
subsystem: "power_supply",
|
subsystem: "power_supply",
|
||||||
ignoredPattern: pattern,
|
ignoredPattern: pattern,
|
||||||
metricDescs: map[string]*prometheus.Desc{},
|
metricDescs: map[string]*prometheus.Desc{},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,9 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,6 +36,8 @@ type pressureStatsCollector struct {
|
||||||
memFull *prometheus.Desc
|
memFull *prometheus.Desc
|
||||||
|
|
||||||
fs procfs.FS
|
fs procfs.FS
|
||||||
|
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -42,7 +45,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPressureStatsCollector returns a Collector exposing pressure stall information
|
// NewPressureStatsCollector returns a Collector exposing pressure stall information
|
||||||
func NewPressureStatsCollector() (Collector, error) {
|
func NewPressureStatsCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
fs, err := procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -74,17 +77,18 @@ func NewPressureStatsCollector() (Collector, error) {
|
||||||
"Total time in seconds no process could make progress due to memory congestion",
|
"Total time in seconds no process could make progress due to memory congestion",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
fs: fs,
|
fs: fs,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update calls procfs.NewPSIStatsForResource for the different resources and updates the values
|
// Update calls procfs.NewPSIStatsForResource for the different resources and updates the values
|
||||||
func (c *pressureStatsCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *pressureStatsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
for _, res := range psiResources {
|
for _, res := range psiResources {
|
||||||
log.Debugf("collecting statistics for resource: %s", res)
|
level.Debug(c.logger).Log("msg", "collecting statistics for resource", "resource", res)
|
||||||
vals, err := c.fs.PSIStatsForResource(res)
|
vals, err := c.fs.PSIStatsForResource(res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("pressure information is unavailable, you need a Linux kernel >= 4.20 and/or CONFIG_PSI enabled for your kernel")
|
level.Debug(c.logger).Log("msg", "pressure information is unavailable, you need a Linux kernel >= 4.20 and/or CONFIG_PSI enabled for your kernel")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch res {
|
switch res {
|
||||||
|
@ -97,7 +101,7 @@ func (c *pressureStatsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
ch <- prometheus.MustNewConstMetric(c.mem, prometheus.CounterValue, float64(vals.Some.Total)/1000.0/1000.0)
|
ch <- prometheus.MustNewConstMetric(c.mem, prometheus.CounterValue, float64(vals.Some.Total)/1000.0/1000.0)
|
||||||
ch <- prometheus.MustNewConstMetric(c.memFull, prometheus.CounterValue, float64(vals.Full.Total)/1000.0/1000.0)
|
ch <- prometheus.MustNewConstMetric(c.memFull, prometheus.CounterValue, float64(vals.Full.Total)/1000.0/1000.0)
|
||||||
default:
|
default:
|
||||||
log.Debugf("did not account for resource: %s", res)
|
level.Debug(c.logger).Log("msg", "did not account for resource", "resource", res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ type processCollector struct {
|
||||||
procsState *prometheus.Desc
|
procsState *prometheus.Desc
|
||||||
pidUsed *prometheus.Desc
|
pidUsed *prometheus.Desc
|
||||||
pidMax *prometheus.Desc
|
pidMax *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -38,7 +40,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProcessStatCollector returns a new Collector exposing process data read from the proc filesystem.
|
// NewProcessStatCollector returns a new Collector exposing process data read from the proc filesystem.
|
||||||
func NewProcessStatCollector() (Collector, error) {
|
func NewProcessStatCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
fs, err := procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -67,6 +69,7 @@ func NewProcessStatCollector() (Collector, error) {
|
||||||
pidMax: prometheus.NewDesc(prometheus.BuildFQName(namespace, subsystem, "max_processes"),
|
pidMax: prometheus.NewDesc(prometheus.BuildFQName(namespace, subsystem, "max_processes"),
|
||||||
"Number of max PIDs limit", nil, nil,
|
"Number of max PIDs limit", nil, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
func (c *processCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *processCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
@ -108,11 +111,11 @@ func (c *processCollector) getAllocatedThreads() (int, map[string]int32, int, er
|
||||||
stat, err := pid.Stat()
|
stat, err := pid.Stat()
|
||||||
// PIDs can vanish between getting the list and getting stats.
|
// PIDs can vanish between getting the list and getting stats.
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debugf("file not found when retrieving stats for pid %v: %q", pid, err)
|
level.Debug(c.logger).Log("msg", "file not found when retrieving stats for pid", "pid", pid, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("error reading stat for pid %v: %q", pid, err)
|
level.Debug(c.logger).Log("msg", "error reading stat for pid", "pid", pid, "err", err)
|
||||||
return 0, nil, 0, err
|
return 0, nil, 0, err
|
||||||
}
|
}
|
||||||
pids++
|
pids++
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
|
@ -31,7 +32,7 @@ func TestReadProcessStatus(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to open procfs: %v", err)
|
t.Errorf("failed to open procfs: %v", err)
|
||||||
}
|
}
|
||||||
c := processCollector{fs: fs}
|
c := processCollector{fs: fs, logger: log.NewNopLogger()}
|
||||||
pids, states, threads, err := c.getAllocatedThreads()
|
pids, states, threads, err := c.getAllocatedThreads()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot retrieve data from procfs getAllocatedThreads function: %v ", err)
|
t.Fatalf("Cannot retrieve data from procfs getAllocatedThreads function: %v ", err)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ema/qdisc"
|
"github.com/ema/qdisc"
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -31,6 +32,7 @@ type qdiscStatCollector struct {
|
||||||
drops typedDesc
|
drops typedDesc
|
||||||
requeues typedDesc
|
requeues typedDesc
|
||||||
overlimits typedDesc
|
overlimits typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -42,7 +44,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQdiscStatCollector returns a new Collector exposing queuing discipline statistics.
|
// NewQdiscStatCollector returns a new Collector exposing queuing discipline statistics.
|
||||||
func NewQdiscStatCollector() (Collector, error) {
|
func NewQdiscStatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &qdiscStatCollector{
|
return &qdiscStatCollector{
|
||||||
bytes: typedDesc{prometheus.NewDesc(
|
bytes: typedDesc{prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "qdisc", "bytes_total"),
|
prometheus.BuildFQName(namespace, "qdisc", "bytes_total"),
|
||||||
|
@ -69,6 +71,7 @@ func NewQdiscStatCollector() (Collector, error) {
|
||||||
"Number of overlimit packets.",
|
"Number of overlimit packets.",
|
||||||
[]string{"device", "kind"}, nil,
|
[]string{"device", "kind"}, nil,
|
||||||
), prometheus.CounterValue},
|
), prometheus.CounterValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,9 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/soundcloud/go-runit/runit"
|
"github.com/soundcloud/go-runit/runit"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -25,7 +26,11 @@ import (
|
||||||
var runitServiceDir = kingpin.Flag("collector.runit.servicedir", "Path to runit service directory.").Default("/etc/service").String()
|
var runitServiceDir = kingpin.Flag("collector.runit.servicedir", "Path to runit service directory.").Default("/etc/service").String()
|
||||||
|
|
||||||
type runitCollector struct {
|
type runitCollector struct {
|
||||||
state, stateDesired, stateNormal, stateTimestamp typedDesc
|
state typedDesc
|
||||||
|
stateDesired typedDesc
|
||||||
|
stateNormal typedDesc
|
||||||
|
stateTimestamp typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -33,7 +38,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRunitCollector returns a new Collector exposing runit statistics.
|
// NewRunitCollector returns a new Collector exposing runit statistics.
|
||||||
func NewRunitCollector() (Collector, error) {
|
func NewRunitCollector(logger log.Logger) (Collector, error) {
|
||||||
var (
|
var (
|
||||||
subsystem = "service"
|
subsystem = "service"
|
||||||
constLabels = prometheus.Labels{"supervisor": "runit"}
|
constLabels = prometheus.Labels{"supervisor": "runit"}
|
||||||
|
@ -61,6 +66,7 @@ func NewRunitCollector() (Collector, error) {
|
||||||
"Unix timestamp of the last runit service state change.",
|
"Unix timestamp of the last runit service state change.",
|
||||||
labelNames, constLabels,
|
labelNames, constLabels,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +79,11 @@ func (c *runitCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
status, err := service.Status()
|
status, err := service.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("Couldn't get status for %s: %s, skipping...", service.Name, err)
|
level.Debug(c.logger).Log("msg", "Couldn't get status", "service", service.Name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("%s is %d on pid %d for %d seconds", service.Name, status.State, status.Pid, status.Duration)
|
level.Debug(c.logger).Log("msg", "duration", "service", service.Name, "status", status.State, "pid", status.Pid, "duration_seconds", status.Duration)
|
||||||
ch <- c.state.mustNewConstMetric(float64(status.State), service.Name)
|
ch <- c.state.mustNewConstMetric(float64(status.State), service.Name)
|
||||||
ch <- c.stateDesired.mustNewConstMetric(float64(status.Want), service.Name)
|
ch <- c.stateDesired.mustNewConstMetric(float64(status.Want), service.Name)
|
||||||
ch <- c.stateTimestamp.mustNewConstMetric(float64(status.Timestamp.Unix()), service.Name)
|
ch <- c.stateTimestamp.mustNewConstMetric(float64(status.Timestamp.Unix()), service.Name)
|
||||||
|
|
|
@ -16,6 +16,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
@ -46,17 +47,18 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSchedstatCollector returns a new Collector exposing task scheduler statistics
|
// NewSchedstatCollector returns a new Collector exposing task scheduler statistics
|
||||||
func NewSchedstatCollector() (Collector, error) {
|
func NewSchedstatCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
fs, err := procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &schedstatCollector{fs: fs}, nil
|
return &schedstatCollector{fs, logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type schedstatCollector struct {
|
type schedstatCollector struct {
|
||||||
fs procfs.FS
|
fs procfs.FS
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -19,8 +19,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,15 +32,17 @@ const (
|
||||||
// Used for calculating the total memory bytes on TCP and UDP.
|
// Used for calculating the total memory bytes on TCP and UDP.
|
||||||
var pageSize = os.Getpagesize()
|
var pageSize = os.Getpagesize()
|
||||||
|
|
||||||
type sockStatCollector struct{}
|
type sockStatCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerCollector(sockStatSubsystem, defaultEnabled, NewSockStatCollector)
|
registerCollector(sockStatSubsystem, defaultEnabled, NewSockStatCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSockStatCollector returns a new Collector exposing socket stats.
|
// NewSockStatCollector returns a new Collector exposing socket stats.
|
||||||
func NewSockStatCollector() (Collector, error) {
|
func NewSockStatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &sockStatCollector{}, nil
|
return &sockStatCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
@ -53,7 +56,7 @@ func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
case os.IsNotExist(err):
|
case os.IsNotExist(err):
|
||||||
log.Debug("IPv4 sockstat statistics not found, skipping")
|
level.Debug(c.logger).Log("msg", "IPv4 sockstat statistics not found, skipping")
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("failed to get IPv4 sockstat data: %w", err)
|
return fmt.Errorf("failed to get IPv4 sockstat data: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +65,7 @@ func (c *sockStatCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
case os.IsNotExist(err):
|
case os.IsNotExist(err):
|
||||||
log.Debug("IPv6 sockstat statistics not found, skipping")
|
level.Debug(c.logger).Log("msg", "IPv6 sockstat statistics not found, skipping")
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("failed to get IPv6 sockstat data: %w", err)
|
return fmt.Errorf("failed to get IPv6 sockstat data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/prometheus/procfs"
|
"github.com/go-kit/kit/log"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/procfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type statCollector struct {
|
type statCollector struct {
|
||||||
|
@ -31,6 +31,7 @@ type statCollector struct {
|
||||||
btime *prometheus.Desc
|
btime *prometheus.Desc
|
||||||
procsRunning *prometheus.Desc
|
procsRunning *prometheus.Desc
|
||||||
procsBlocked *prometheus.Desc
|
procsBlocked *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -38,7 +39,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStatCollector returns a new Collector exposing kernel/system statistics.
|
// NewStatCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewStatCollector() (Collector, error) {
|
func NewStatCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := procfs.NewFS(*procPath)
|
fs, err := procfs.NewFS(*procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
@ -75,6 +76,7 @@ func NewStatCollector() (Collector, error) {
|
||||||
"Number of processes blocked waiting for I/O to complete.",
|
"Number of processes blocked waiting for I/O to complete.",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,10 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/mattn/go-xmlrpc"
|
"github.com/mattn/go-xmlrpc"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,6 +34,7 @@ type supervisordCollector struct {
|
||||||
stateDesc *prometheus.Desc
|
stateDesc *prometheus.Desc
|
||||||
exitStatusDesc *prometheus.Desc
|
exitStatusDesc *prometheus.Desc
|
||||||
startTimeDesc *prometheus.Desc
|
startTimeDesc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -40,7 +42,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSupervisordCollector returns a new Collector exposing supervisord statistics.
|
// NewSupervisordCollector returns a new Collector exposing supervisord statistics.
|
||||||
func NewSupervisordCollector() (Collector, error) {
|
func NewSupervisordCollector(logger log.Logger) (Collector, error) {
|
||||||
var (
|
var (
|
||||||
subsystem = "supervisord"
|
subsystem = "supervisord"
|
||||||
labelNames = []string{"name", "group"}
|
labelNames = []string{"name", "group"}
|
||||||
|
@ -70,6 +72,7 @@ func NewSupervisordCollector() (Collector, error) {
|
||||||
labelNames,
|
labelNames,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +150,7 @@ func (c *supervisordCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
} else {
|
} else {
|
||||||
ch <- prometheus.MustNewConstMetric(c.upDesc, prometheus.GaugeValue, 0, labels...)
|
ch <- prometheus.MustNewConstMetric(c.upDesc, prometheus.GaugeValue, 0, labels...)
|
||||||
}
|
}
|
||||||
log.Debugf("%s:%s is %s on pid %d", info.Group, info.Name, info.StateName, info.PID)
|
level.Debug(c.logger).Log("msg", "process info", "group", info.Group, "name", info.Name, "state", info.StateName, "pid", info.PID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -25,8 +25,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/go-systemd/dbus"
|
"github.com/coreos/go-systemd/dbus"
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ type systemdCollector struct {
|
||||||
systemdVersion int
|
systemdVersion int
|
||||||
unitWhitelistPattern *regexp.Regexp
|
unitWhitelistPattern *regexp.Regexp
|
||||||
unitBlacklistPattern *regexp.Regexp
|
unitBlacklistPattern *regexp.Regexp
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
var unitStatesName = []string{"active", "activating", "deactivating", "inactive", "failed"}
|
var unitStatesName = []string{"active", "activating", "deactivating", "inactive", "failed"}
|
||||||
|
@ -71,7 +73,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSystemdCollector returns a new Collector exposing systemd statistics.
|
// NewSystemdCollector returns a new Collector exposing systemd statistics.
|
||||||
func NewSystemdCollector() (Collector, error) {
|
func NewSystemdCollector(logger log.Logger) (Collector, error) {
|
||||||
const subsystem = "systemd"
|
const subsystem = "systemd"
|
||||||
|
|
||||||
unitDesc := prometheus.NewDesc(
|
unitDesc := prometheus.NewDesc(
|
||||||
|
@ -119,10 +121,10 @@ func NewSystemdCollector() (Collector, error) {
|
||||||
unitWhitelistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitWhitelist))
|
unitWhitelistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitWhitelist))
|
||||||
unitBlacklistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitBlacklist))
|
unitBlacklistPattern := regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *unitBlacklist))
|
||||||
|
|
||||||
systemdVersion := getSystemdVersion()
|
systemdVersion := getSystemdVersion(logger)
|
||||||
if systemdVersion < minSystemdVersionSystemState {
|
if systemdVersion < minSystemdVersionSystemState {
|
||||||
log.Warnf("Detected systemd version %v is lower than minimum %v", systemdVersion, minSystemdVersionSystemState)
|
level.Warn(logger).Log("msg", "Detected systemd version is lower than minimum", "current", systemdVersion, "minimum", minSystemdVersionSystemState)
|
||||||
log.Warn("Some systemd state and timer metrics will not be available")
|
level.Warn(logger).Log("msg", "Some systemd state and timer metrics will not be available")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &systemdCollector{
|
return &systemdCollector{
|
||||||
|
@ -141,6 +143,7 @@ func NewSystemdCollector() (Collector, error) {
|
||||||
systemdVersion: systemdVersion,
|
systemdVersion: systemdVersion,
|
||||||
unitWhitelistPattern: unitWhitelistPattern,
|
unitWhitelistPattern: unitWhitelistPattern,
|
||||||
unitBlacklistPattern: unitBlacklistPattern,
|
unitBlacklistPattern: unitBlacklistPattern,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,16 +161,16 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't get units: %s", err)
|
return fmt.Errorf("couldn't get units: %s", err)
|
||||||
}
|
}
|
||||||
log.Debugf("systemd getAllUnits took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "getAllUnits took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
|
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
summary := summarizeUnits(allUnits)
|
summary := summarizeUnits(allUnits)
|
||||||
c.collectSummaryMetrics(ch, summary)
|
c.collectSummaryMetrics(ch, summary)
|
||||||
log.Debugf("systemd collectSummaryMetrics took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectSummaryMetrics took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
|
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
units := filterUnits(allUnits, c.unitWhitelistPattern, c.unitBlacklistPattern)
|
units := filterUnits(allUnits, c.unitWhitelistPattern, c.unitBlacklistPattern, c.logger)
|
||||||
log.Debugf("systemd filterUnits took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "filterUnits took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
defer wg.Wait()
|
defer wg.Wait()
|
||||||
|
@ -177,7 +180,7 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
c.collectUnitStatusMetrics(conn, ch, units)
|
c.collectUnitStatusMetrics(conn, ch, units)
|
||||||
log.Debugf("systemd collectUnitStatusMetrics took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectUnitStatusMetrics took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if *enableStartTimeMetrics {
|
if *enableStartTimeMetrics {
|
||||||
|
@ -186,7 +189,7 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
c.collectUnitStartTimeMetrics(conn, ch, units)
|
c.collectUnitStartTimeMetrics(conn, ch, units)
|
||||||
log.Debugf("systemd collectUnitStartTimeMetrics took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectUnitStartTimeMetrics took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +199,7 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
c.collectUnitTasksMetrics(conn, ch, units)
|
c.collectUnitTasksMetrics(conn, ch, units)
|
||||||
log.Debugf("systemd collectUnitTasksMetrics took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectUnitTasksMetrics took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +209,7 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
c.collectTimers(conn, ch, units)
|
c.collectTimers(conn, ch, units)
|
||||||
log.Debugf("systemd collectTimers took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectTimers took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,13 +218,13 @@ func (c *systemdCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
c.collectSockets(conn, ch, units)
|
c.collectSockets(conn, ch, units)
|
||||||
log.Debugf("systemd collectSockets took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectSockets took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if c.systemdVersion >= minSystemdVersionSystemState {
|
if c.systemdVersion >= minSystemdVersionSystemState {
|
||||||
begin = time.Now()
|
begin = time.Now()
|
||||||
err = c.collectSystemState(conn, ch)
|
err = c.collectSystemState(conn, ch)
|
||||||
log.Debugf("systemd collectSystemState took %f", time.Since(begin).Seconds())
|
level.Debug(c.logger).Log("msg", "collectSystemState took", "duration_seconds", time.Since(begin).Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
@ -236,14 +239,14 @@ func (c *systemdCollector) collectUnitStatusMetrics(conn *dbus.Conn, ch chan<- p
|
||||||
if strings.HasSuffix(unit.Name, ".service") {
|
if strings.HasSuffix(unit.Name, ".service") {
|
||||||
serviceTypeProperty, err := conn.GetUnitTypeProperty(unit.Name, "Service", "Type")
|
serviceTypeProperty, err := conn.GetUnitTypeProperty(unit.Name, "Service", "Type")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' Type: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit type", "unit", unit.Name, "err", err)
|
||||||
} else {
|
} else {
|
||||||
serviceType = serviceTypeProperty.Value.Value().(string)
|
serviceType = serviceTypeProperty.Value.Value().(string)
|
||||||
}
|
}
|
||||||
} else if strings.HasSuffix(unit.Name, ".mount") {
|
} else if strings.HasSuffix(unit.Name, ".mount") {
|
||||||
serviceTypeProperty, err := conn.GetUnitTypeProperty(unit.Name, "Mount", "Type")
|
serviceTypeProperty, err := conn.GetUnitTypeProperty(unit.Name, "Mount", "Type")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' Type: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit type", "unit", unit.Name, "err", err)
|
||||||
} else {
|
} else {
|
||||||
serviceType = serviceTypeProperty.Value.Value().(string)
|
serviceType = serviceTypeProperty.Value.Value().(string)
|
||||||
}
|
}
|
||||||
|
@ -261,7 +264,7 @@ func (c *systemdCollector) collectUnitStatusMetrics(conn *dbus.Conn, ch chan<- p
|
||||||
// NRestarts wasn't added until systemd 235.
|
// NRestarts wasn't added until systemd 235.
|
||||||
restartsCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "NRestarts")
|
restartsCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "NRestarts")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' NRestarts: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit NRestarts", "unit", unit.Name, "err", err)
|
||||||
} else {
|
} else {
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.nRestartsDesc, prometheus.CounterValue,
|
c.nRestartsDesc, prometheus.CounterValue,
|
||||||
|
@ -279,7 +282,7 @@ func (c *systemdCollector) collectSockets(conn *dbus.Conn, ch chan<- prometheus.
|
||||||
|
|
||||||
acceptedConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NAccepted")
|
acceptedConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NAccepted")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' NAccepted: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit NAccepted", "unit", unit.Name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
@ -288,7 +291,7 @@ func (c *systemdCollector) collectSockets(conn *dbus.Conn, ch chan<- prometheus.
|
||||||
|
|
||||||
currentConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NConnections")
|
currentConnectionCount, err := conn.GetUnitTypeProperty(unit.Name, "Socket", "NConnections")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' NConnections: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit NConnections", "unit", unit.Name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
@ -316,7 +319,7 @@ func (c *systemdCollector) collectUnitStartTimeMetrics(conn *dbus.Conn, ch chan<
|
||||||
} else {
|
} else {
|
||||||
timestampValue, err := conn.GetUnitProperty(unit.Name, "ActiveEnterTimestamp")
|
timestampValue, err := conn.GetUnitProperty(unit.Name, "ActiveEnterTimestamp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' StartTimeUsec: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit StartTimeUsec", "unit", unit.Name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
startTimeUsec = timestampValue.Value.Value().(uint64)
|
startTimeUsec = timestampValue.Value.Value().(uint64)
|
||||||
|
@ -334,7 +337,7 @@ func (c *systemdCollector) collectUnitTasksMetrics(conn *dbus.Conn, ch chan<- pr
|
||||||
if strings.HasSuffix(unit.Name, ".service") {
|
if strings.HasSuffix(unit.Name, ".service") {
|
||||||
tasksCurrentCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "TasksCurrent")
|
tasksCurrentCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "TasksCurrent")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' TasksCurrent: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit TasksCurrent", "unit", unit.Name, "err", err)
|
||||||
} else {
|
} else {
|
||||||
val = tasksCurrentCount.Value.Value().(uint64)
|
val = tasksCurrentCount.Value.Value().(uint64)
|
||||||
// Don't set if tasksCurrent if dbus reports MaxUint64.
|
// Don't set if tasksCurrent if dbus reports MaxUint64.
|
||||||
|
@ -346,7 +349,7 @@ func (c *systemdCollector) collectUnitTasksMetrics(conn *dbus.Conn, ch chan<- pr
|
||||||
}
|
}
|
||||||
tasksMaxCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "TasksMax")
|
tasksMaxCount, err := conn.GetUnitTypeProperty(unit.Name, "Service", "TasksMax")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' TasksMax: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit TasksMax", "unit", unit.Name, "err", err)
|
||||||
} else {
|
} else {
|
||||||
val = tasksMaxCount.Value.Value().(uint64)
|
val = tasksMaxCount.Value.Value().(uint64)
|
||||||
// Don't set if tasksMax if dbus reports MaxUint64.
|
// Don't set if tasksMax if dbus reports MaxUint64.
|
||||||
|
@ -368,7 +371,7 @@ func (c *systemdCollector) collectTimers(conn *dbus.Conn, ch chan<- prometheus.M
|
||||||
|
|
||||||
lastTriggerValue, err := conn.GetUnitTypeProperty(unit.Name, "Timer", "LastTriggerUSec")
|
lastTriggerValue, err := conn.GetUnitTypeProperty(unit.Name, "Timer", "LastTriggerUSec")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("couldn't get unit '%s' LastTriggerUSec: %s", unit.Name, err)
|
level.Debug(c.logger).Log("msg", "couldn't get unit LastTriggerUSec", "unit", unit.Name, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,36 +443,36 @@ func summarizeUnits(units []unit) map[string]float64 {
|
||||||
return summarized
|
return summarized
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterUnits(units []unit, whitelistPattern, blacklistPattern *regexp.Regexp) []unit {
|
func filterUnits(units []unit, whitelistPattern, blacklistPattern *regexp.Regexp, logger log.Logger) []unit {
|
||||||
filtered := make([]unit, 0, len(units))
|
filtered := make([]unit, 0, len(units))
|
||||||
for _, unit := range units {
|
for _, unit := range units {
|
||||||
if whitelistPattern.MatchString(unit.Name) && !blacklistPattern.MatchString(unit.Name) && unit.LoadState == "loaded" {
|
if whitelistPattern.MatchString(unit.Name) && !blacklistPattern.MatchString(unit.Name) && unit.LoadState == "loaded" {
|
||||||
log.Debugf("Adding unit: %s", unit.Name)
|
level.Debug(logger).Log("msg", "Adding unit", "unit", unit.Name)
|
||||||
filtered = append(filtered, unit)
|
filtered = append(filtered, unit)
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("Ignoring unit: %s", unit.Name)
|
level.Debug(logger).Log("msg", "Ignoring unit", "unit", unit.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSystemdVersion() int {
|
func getSystemdVersion(logger log.Logger) int {
|
||||||
conn, err := newSystemdDbusConn()
|
conn, err := newSystemdDbusConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("Unable to get systemd dbus connection, defaulting systemd version to 0: %s", err)
|
level.Warn(logger).Log("msg", "Unable to get systemd dbus connection, defaulting systemd version to 0", "err", err)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
version, err := conn.GetManagerProperty("Version")
|
version, err := conn.GetManagerProperty("Version")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Unable to get systemd version property, defaulting to 0")
|
level.Warn(logger).Log("msg", "Unable to get systemd version property, defaulting to 0")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
version = strings.Replace(version, "\"", "", 2)
|
version = strings.Replace(version, "\"", "", 2)
|
||||||
v, err := strconv.Atoi(version)
|
v, err := strconv.Atoi(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("Got invalid systemd version: %v", version)
|
level.Warn(logger).Log("msg", "Got invalid systemd version", "version", version)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ func TestSystemdIgnoreFilter(t *testing.T) {
|
||||||
fixtures := getUnitListFixtures()
|
fixtures := getUnitListFixtures()
|
||||||
whitelistPattern := regexp.MustCompile("^foo$")
|
whitelistPattern := regexp.MustCompile("^foo$")
|
||||||
blacklistPattern := regexp.MustCompile("^bar$")
|
blacklistPattern := regexp.MustCompile("^bar$")
|
||||||
filtered := filterUnits(fixtures[0], whitelistPattern, blacklistPattern)
|
filtered := filterUnits(fixtures[0], whitelistPattern, blacklistPattern, log.NewNopLogger())
|
||||||
for _, unit := range filtered {
|
for _, unit := range filtered {
|
||||||
if blacklistPattern.MatchString(unit.Name) || !whitelistPattern.MatchString(unit.Name) {
|
if blacklistPattern.MatchString(unit.Name) || !whitelistPattern.MatchString(unit.Name) {
|
||||||
t.Error(unit.Name, "should not be in the filtered list")
|
t.Error(unit.Name, "should not be in the filtered list")
|
||||||
|
@ -98,13 +99,14 @@ func TestSystemdIgnoreFilter(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestSystemdIgnoreFilterDefaultKeepsAll(t *testing.T) {
|
func TestSystemdIgnoreFilterDefaultKeepsAll(t *testing.T) {
|
||||||
c, err := NewSystemdCollector()
|
logger := log.NewNopLogger()
|
||||||
|
c, err := NewSystemdCollector(logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fixtures := getUnitListFixtures()
|
fixtures := getUnitListFixtures()
|
||||||
collector := c.(*systemdCollector)
|
collector := c.(*systemdCollector)
|
||||||
filtered := filterUnits(fixtures[0], collector.unitWhitelistPattern, collector.unitBlacklistPattern)
|
filtered := filterUnits(fixtures[0], collector.unitWhitelistPattern, collector.unitBlacklistPattern, logger)
|
||||||
// Adjust fixtures by 3 "not-found" units.
|
// Adjust fixtures by 3 "not-found" units.
|
||||||
if len(filtered) != len(fixtures[0])-3 {
|
if len(filtered) != len(fixtures[0])-3 {
|
||||||
t.Error("Default filters removed units")
|
t.Error("Default filters removed units")
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -54,7 +55,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type tcpStatCollector struct {
|
type tcpStatCollector struct {
|
||||||
desc typedDesc
|
desc typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -62,13 +64,14 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPStatCollector returns a new Collector exposing network stats.
|
// NewTCPStatCollector returns a new Collector exposing network stats.
|
||||||
func NewTCPStatCollector() (Collector, error) {
|
func NewTCPStatCollector(logger log.Logger) (Collector, error) {
|
||||||
return &tcpStatCollector{
|
return &tcpStatCollector{
|
||||||
desc: typedDesc{prometheus.NewDesc(
|
desc: typedDesc{prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "tcp", "connection_states"),
|
prometheus.BuildFQName(namespace, "tcp", "connection_states"),
|
||||||
"Number of connection states.",
|
"Number of connection states.",
|
||||||
[]string{"state"}, nil,
|
[]string{"state"}, nil,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
"github.com/prometheus/common/expfmt"
|
"github.com/prometheus/common/expfmt"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,7 +45,8 @@ var (
|
||||||
type textFileCollector struct {
|
type textFileCollector struct {
|
||||||
path string
|
path string
|
||||||
// Only set for testing to get predictable output.
|
// Only set for testing to get predictable output.
|
||||||
mtime *float64
|
mtime *float64
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -53,14 +55,15 @@ func init() {
|
||||||
|
|
||||||
// NewTextFileCollector returns a new Collector exposing metrics read from files
|
// NewTextFileCollector returns a new Collector exposing metrics read from files
|
||||||
// in the given textfile directory.
|
// in the given textfile directory.
|
||||||
func NewTextFileCollector() (Collector, error) {
|
func NewTextFileCollector(logger log.Logger) (Collector, error) {
|
||||||
c := &textFileCollector{
|
c := &textFileCollector{
|
||||||
path: *textFileDirectory,
|
path: *textFileDirectory,
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) {
|
func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric, logger log.Logger) {
|
||||||
var valType prometheus.ValueType
|
var valType prometheus.ValueType
|
||||||
var val float64
|
var val float64
|
||||||
|
|
||||||
|
@ -76,7 +79,7 @@ func convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Me
|
||||||
|
|
||||||
for _, metric := range metricFamily.Metric {
|
for _, metric := range metricFamily.Metric {
|
||||||
if metric.TimestampMs != nil {
|
if metric.TimestampMs != nil {
|
||||||
log.Warnf("Ignoring unsupported custom timestamp on textfile collector metric %v", metric)
|
level.Warn(logger).Log("msg", "Ignoring unsupported custom timestamp on textfile collector metric", "metric", metric)
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := metric.GetLabel()
|
labels := metric.GetLabel()
|
||||||
|
@ -191,7 +194,7 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
files, err := ioutil.ReadDir(c.path)
|
files, err := ioutil.ReadDir(c.path)
|
||||||
if err != nil && c.path != "" {
|
if err != nil && c.path != "" {
|
||||||
errored = true
|
errored = true
|
||||||
log.Errorf("failed to read textfile collector directory %q: %v", c.path, err)
|
level.Error(c.logger).Log("msg", "failed to read textfile collector directory", "path", c.path, "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mtimes := make(map[string]time.Time, len(files))
|
mtimes := make(map[string]time.Time, len(files))
|
||||||
|
@ -203,7 +206,7 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
mtime, err := c.processFile(f.Name(), ch)
|
mtime, err := c.processFile(f.Name(), ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errored = true
|
errored = true
|
||||||
log.Errorf("failed to collect textfile data from %q: %v", f.Name(), err)
|
level.Error(c.logger).Log("msg", "failed to collect textfile data", "file", f.Name(), "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +260,7 @@ func (c *textFileCollector) processFile(name string, ch chan<- prometheus.Metric
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mf := range families {
|
for _, mf := range families {
|
||||||
convertMetricFamily(mf, ch)
|
convertMetricFamily(mf, ch, c.logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only stat the file once it has been parsed and validated, so that
|
// Only stat the file once it has been parsed and validated, so that
|
||||||
|
|
|
@ -20,10 +20,12 @@ import (
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/promlog"
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
"github.com/prometheus/common/promlog/flag"
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type collectorAdapter struct {
|
type collectorAdapter struct {
|
||||||
|
@ -39,8 +41,7 @@ func (a collectorAdapter) Describe(ch chan<- *prometheus.Desc) {
|
||||||
|
|
||||||
// Collect implements the prometheus.Collector interface.
|
// Collect implements the prometheus.Collector interface.
|
||||||
func (a collectorAdapter) Collect(ch chan<- prometheus.Metric) {
|
func (a collectorAdapter) Collect(ch chan<- prometheus.Metric) {
|
||||||
err := a.Update(ch)
|
if err := a.Update(ch); err != nil {
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("failed to update collector: %v", err))
|
panic(fmt.Sprintf("failed to update collector: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,15 +96,16 @@ func TestTextfileCollector(t *testing.T) {
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
mtime := 1.0
|
mtime := 1.0
|
||||||
c := &textFileCollector{
|
c := &textFileCollector{
|
||||||
path: test.path,
|
path: test.path,
|
||||||
mtime: &mtime,
|
mtime: &mtime,
|
||||||
|
logger: log.NewNopLogger(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suppress a log message about `nonexistent_path` not existing, this is
|
// Suppress a log message about `nonexistent_path` not existing, this is
|
||||||
// expected and clutters the test output.
|
// expected and clutters the test output.
|
||||||
log.AddFlags(kingpin.CommandLine)
|
promlogConfig := &promlog.Config{}
|
||||||
_, err := kingpin.CommandLine.Parse([]string{"--log.level", "fatal"})
|
flag.AddFlags(kingpin.CommandLine, promlogConfig)
|
||||||
if err != nil {
|
if _, err := kingpin.CommandLine.Parse([]string{"--log.level", "debug"}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/sysfs"
|
"github.com/prometheus/procfs/sysfs"
|
||||||
)
|
)
|
||||||
|
@ -30,6 +31,7 @@ type thermalZoneCollector struct {
|
||||||
coolingDeviceCurState *prometheus.Desc
|
coolingDeviceCurState *prometheus.Desc
|
||||||
coolingDeviceMaxState *prometheus.Desc
|
coolingDeviceMaxState *prometheus.Desc
|
||||||
zoneTemp *prometheus.Desc
|
zoneTemp *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -37,7 +39,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewThermalZoneCollector returns a new Collector exposing kernel/system statistics.
|
// NewThermalZoneCollector returns a new Collector exposing kernel/system statistics.
|
||||||
func NewThermalZoneCollector() (Collector, error) {
|
func NewThermalZoneCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := sysfs.NewFS(*sysPath)
|
fs, err := sysfs.NewFS(*sysPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
||||||
|
@ -60,6 +62,7 @@ func NewThermalZoneCollector() (Collector, error) {
|
||||||
"Maximum throttle state of the cooling device",
|
"Maximum throttle state of the cooling device",
|
||||||
[]string{"name", "type"}, nil,
|
[]string{"name", "type"}, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,14 @@ package collector
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type timeCollector struct {
|
type timeCollector struct {
|
||||||
desc *prometheus.Desc
|
desc *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -32,19 +34,20 @@ func init() {
|
||||||
|
|
||||||
// NewTimeCollector returns a new Collector exposing the current system time in
|
// NewTimeCollector returns a new Collector exposing the current system time in
|
||||||
// seconds since epoch.
|
// seconds since epoch.
|
||||||
func NewTimeCollector() (Collector, error) {
|
func NewTimeCollector(logger log.Logger) (Collector, error) {
|
||||||
return &timeCollector{
|
return &timeCollector{
|
||||||
desc: prometheus.NewDesc(
|
desc: prometheus.NewDesc(
|
||||||
namespace+"_time_seconds",
|
namespace+"_time_seconds",
|
||||||
"System time in seconds since epoch (1970).",
|
"System time in seconds since epoch (1970).",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *timeCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *timeCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
now := float64(time.Now().UnixNano()) / 1e9
|
now := float64(time.Now().UnixNano()) / 1e9
|
||||||
log.Debugf("Return time: %f", now)
|
level.Debug(c.logger).Log("msg", "Return time", "now", now)
|
||||||
ch <- prometheus.MustNewConstMetric(c.desc, prometheus.GaugeValue, now)
|
ch <- prometheus.MustNewConstMetric(c.desc, prometheus.GaugeValue, now)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -54,6 +55,7 @@ type timexCollector struct {
|
||||||
stbcnt,
|
stbcnt,
|
||||||
tai,
|
tai,
|
||||||
syncStatus typedDesc
|
syncStatus typedDesc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -61,7 +63,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTimexCollector returns a new Collector exposing adjtime(3) stats.
|
// NewTimexCollector returns a new Collector exposing adjtime(3) stats.
|
||||||
func NewTimexCollector() (Collector, error) {
|
func NewTimexCollector(logger log.Logger) (Collector, error) {
|
||||||
const subsystem = "timex"
|
const subsystem = "timex"
|
||||||
|
|
||||||
return &timexCollector{
|
return &timexCollector{
|
||||||
|
@ -150,6 +152,7 @@ func NewTimexCollector() (Collector, error) {
|
||||||
"Is clock synchronized to a reliable server (1 = yes, 0 = no).",
|
"Is clock synchronized to a reliable server (1 = yes, 0 = no).",
|
||||||
nil, nil,
|
nil, nil,
|
||||||
), prometheus.GaugeValue},
|
), prometheus.GaugeValue},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,7 +35,9 @@ var unameDesc = prometheus.NewDesc(
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
type unameCollector struct{}
|
type unameCollector struct {
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
type uname struct {
|
type uname struct {
|
||||||
SysName string
|
SysName string
|
||||||
Release string
|
Release string
|
||||||
|
@ -49,8 +52,8 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnameCollector returns new unameCollector.
|
// NewUnameCollector returns new unameCollector.
|
||||||
func newUnameCollector() (Collector, error) {
|
func newUnameCollector(logger log.Logger) (Collector, error) {
|
||||||
return &unameCollector{}, nil
|
return &unameCollector{logger}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *unameCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *unameCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
@ -37,6 +38,7 @@ var (
|
||||||
|
|
||||||
type vmStatCollector struct {
|
type vmStatCollector struct {
|
||||||
fieldPattern *regexp.Regexp
|
fieldPattern *regexp.Regexp
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -44,10 +46,11 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewvmStatCollector returns a new Collector exposing vmstat stats.
|
// NewvmStatCollector returns a new Collector exposing vmstat stats.
|
||||||
func NewvmStatCollector() (Collector, error) {
|
func NewvmStatCollector(logger log.Logger) (Collector, error) {
|
||||||
pattern := regexp.MustCompile(*vmStatFields)
|
pattern := regexp.MustCompile(*vmStatFields)
|
||||||
return &vmStatCollector{
|
return &vmStatCollector{
|
||||||
fieldPattern: pattern,
|
fieldPattern: pattern,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/mdlayher/wifi"
|
"github.com/mdlayher/wifi"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,6 +41,8 @@ type wifiCollector struct {
|
||||||
stationTransmitRetriesTotal *prometheus.Desc
|
stationTransmitRetriesTotal *prometheus.Desc
|
||||||
stationTransmitFailedTotal *prometheus.Desc
|
stationTransmitFailedTotal *prometheus.Desc
|
||||||
stationBeaconLossTotal *prometheus.Desc
|
stationBeaconLossTotal *prometheus.Desc
|
||||||
|
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -61,7 +64,7 @@ type wifiStater interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWifiCollector returns a new Collector exposing Wifi statistics.
|
// NewWifiCollector returns a new Collector exposing Wifi statistics.
|
||||||
func NewWifiCollector() (Collector, error) {
|
func NewWifiCollector(logger log.Logger) (Collector, error) {
|
||||||
const (
|
const (
|
||||||
subsystem = "wifi"
|
subsystem = "wifi"
|
||||||
)
|
)
|
||||||
|
@ -154,6 +157,7 @@ func NewWifiCollector() (Collector, error) {
|
||||||
labels,
|
labels,
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,11 +166,11 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Cannot access wifi metrics, report no error.
|
// Cannot access wifi metrics, report no error.
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Debug("wifi collector metrics are not available for this system")
|
level.Debug(c.logger).Log("msg", "wifi collector metrics are not available for this system")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if os.IsPermission(err) {
|
if os.IsPermission(err) {
|
||||||
log.Debug("wifi collector got permission denied when accessing metrics")
|
level.Debug(c.logger).Log("msg", "wifi collector got permission denied when accessing metrics")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +189,7 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("probing wifi device %q with type %q", ifi.Name, ifi.Type)
|
level.Debug(c.logger).Log("msg", "probing wifi device with type", "wifi", ifi.Name, "type", ifi.Type)
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.interfaceFrequencyHertz,
|
c.interfaceFrequencyHertz,
|
||||||
|
@ -203,7 +207,7 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
c.updateBSSStats(ch, ifi.Name, bss)
|
c.updateBSSStats(ch, ifi.Name, bss)
|
||||||
case os.IsNotExist(err):
|
case os.IsNotExist(err):
|
||||||
log.Debugf("BSS information not found for wifi device %q", ifi.Name)
|
level.Debug(c.logger).Log("msg", "BSS information not found for wifi device", "name", ifi.Name)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("failed to retrieve BSS for device %s: %v",
|
return fmt.Errorf("failed to retrieve BSS for device %s: %v",
|
||||||
ifi.Name, err)
|
ifi.Name, err)
|
||||||
|
@ -216,7 +220,7 @@ func (c *wifiCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
c.updateStationStats(ch, ifi.Name, station)
|
c.updateStationStats(ch, ifi.Name, station)
|
||||||
}
|
}
|
||||||
case os.IsNotExist(err):
|
case os.IsNotExist(err):
|
||||||
log.Debugf("station information not found for wifi device %q", ifi.Name)
|
level.Debug(c.logger).Log("msg", "station information not found for wifi device", "name", ifi.Name)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("failed to retrieve station info for device %q: %v",
|
return fmt.Errorf("failed to retrieve station info for device %q: %v",
|
||||||
ifi.Name, err)
|
ifi.Name, err)
|
||||||
|
|
|
@ -16,13 +16,15 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/procfs/xfs"
|
"github.com/prometheus/procfs/xfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// An xfsCollector is a Collector which gathers metrics from XFS filesystems.
|
// An xfsCollector is a Collector which gathers metrics from XFS filesystems.
|
||||||
type xfsCollector struct {
|
type xfsCollector struct {
|
||||||
fs xfs.FS
|
fs xfs.FS
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -30,14 +32,15 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewXFSCollector returns a new Collector exposing XFS statistics.
|
// NewXFSCollector returns a new Collector exposing XFS statistics.
|
||||||
func NewXFSCollector() (Collector, error) {
|
func NewXFSCollector(logger log.Logger) (Collector, error) {
|
||||||
fs, err := xfs.NewFS(*procPath, *sysPath)
|
fs, err := xfs.NewFS(*procPath, *sysPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
return nil, fmt.Errorf("failed to open sysfs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &xfsCollector{
|
return &xfsCollector{
|
||||||
fs: fs,
|
fs: fs,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var errZFSNotAvailable = errors.New("ZFS / ZFS statistics are not available")
|
var errZFSNotAvailable = errors.New("ZFS / ZFS statistics are not available")
|
||||||
|
@ -36,10 +37,11 @@ type zfsCollector struct {
|
||||||
linuxProcpathBase string
|
linuxProcpathBase string
|
||||||
linuxZpoolIoPath string
|
linuxZpoolIoPath string
|
||||||
linuxPathMap map[string]string
|
linuxPathMap map[string]string
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewZFSCollector returns a new Collector exposing ZFS statistics.
|
// NewZFSCollector returns a new Collector exposing ZFS statistics.
|
||||||
func NewZFSCollector() (Collector, error) {
|
func NewZFSCollector(logger log.Logger) (Collector, error) {
|
||||||
return &zfsCollector{
|
return &zfsCollector{
|
||||||
linuxProcpathBase: "spl/kstat/zfs",
|
linuxProcpathBase: "spl/kstat/zfs",
|
||||||
linuxZpoolIoPath: "/*/io",
|
linuxZpoolIoPath: "/*/io",
|
||||||
|
@ -56,6 +58,7 @@ func NewZFSCollector() (Collector, error) {
|
||||||
"zfs_zfetch": "zfetchstats",
|
"zfs_zfetch": "zfetchstats",
|
||||||
"zfs_zil": "zil",
|
"zfs_zil": "zil",
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +66,7 @@ func (c *zfsCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
for subsystem := range c.linuxPathMap {
|
for subsystem := range c.linuxPathMap {
|
||||||
if err := c.updateZfsStats(subsystem, ch); err != nil {
|
if err := c.updateZfsStats(subsystem, ch); err != nil {
|
||||||
if err == errZFSNotAvailable {
|
if err == errZFSNotAvailable {
|
||||||
log.Debug(err)
|
level.Debug(c.logger).Log("err", err)
|
||||||
// ZFS /proc files are added as new features to ZFS arrive, it is ok to continue
|
// ZFS /proc files are added as new features to ZFS arrive, it is ok to continue
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@ package collector
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type zfsCollector struct {
|
type zfsCollector struct {
|
||||||
sysctls []bsdSysctl
|
sysctls []bsdSysctl
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -31,7 +33,7 @@ func init() {
|
||||||
registerCollector("zfs", defaultEnabled, NewZfsCollector)
|
registerCollector("zfs", defaultEnabled, NewZfsCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewZfsCollector() (Collector, error) {
|
func NewZfsCollector(logger log.Logger) (Collector, error) {
|
||||||
return &zfsCollector{
|
return &zfsCollector{
|
||||||
sysctls: []bsdSysctl{
|
sysctls: []bsdSysctl{
|
||||||
{
|
{
|
||||||
|
@ -238,6 +240,7 @@ func NewZfsCollector() (Collector, error) {
|
||||||
valueType: prometheus.CounterValue,
|
valueType: prometheus.CounterValue,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// constants from https://github.com/zfsonlinux/zfs/blob/master/lib/libspl/include/sys/kstat.h
|
// constants from https://github.com/zfsonlinux/zfs/blob/master/lib/libspl/include/sys/kstat.h
|
||||||
|
@ -45,7 +45,7 @@ func (c *zfsCollector) openProcFile(path string) (*os.File, error) {
|
||||||
// file not found error can occur if:
|
// file not found error can occur if:
|
||||||
// 1. zfs module is not loaded
|
// 1. zfs module is not loaded
|
||||||
// 2. zfs version does not have the feature with metrics -- ok to ignore
|
// 2. zfs version does not have the feature with metrics -- ok to ignore
|
||||||
log.Debugf("Cannot open %q for reading", procFilePath(path))
|
level.Debug(c.logger).Log("msg", "Cannot open file for reading", "path", procFilePath(path))
|
||||||
return nil, errZFSNotAvailable
|
return nil, errZFSNotAvailable
|
||||||
}
|
}
|
||||||
return file, nil
|
return file, nil
|
||||||
|
@ -77,7 +77,7 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
|
||||||
file, err := os.Open(zpoolPath)
|
file, err := os.Open(zpoolPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// this file should exist, but there is a race where an exporting pool can remove the files -- ok to ignore
|
// this file should exist, but there is a race where an exporting pool can remove the files -- ok to ignore
|
||||||
log.Debugf("Cannot open %q for reading", zpoolPath)
|
level.Debug(c.logger).Log("msg", "Cannot open file for reading", "path", zpoolPath)
|
||||||
return errZFSNotAvailable
|
return errZFSNotAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package collector
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/siebenmann/go-kstat"
|
"github.com/siebenmann/go-kstat"
|
||||||
)
|
)
|
||||||
|
@ -52,6 +53,7 @@ type zfsCollector struct {
|
||||||
arcstatsSize *prometheus.Desc
|
arcstatsSize *prometheus.Desc
|
||||||
zfetchstatsHits *prometheus.Desc
|
zfetchstatsHits *prometheus.Desc
|
||||||
zfetchstatsMisses *prometheus.Desc
|
zfetchstatsMisses *prometheus.Desc
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -62,7 +64,7 @@ func init() {
|
||||||
registerCollector("zfs", defaultEnabled, NewZfsCollector)
|
registerCollector("zfs", defaultEnabled, NewZfsCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewZfsCollector() (Collector, error) {
|
func NewZfsCollector(logger log.Logger) (Collector, error) {
|
||||||
return &zfsCollector{
|
return &zfsCollector{
|
||||||
abdstatsLinearCount: prometheus.NewDesc(
|
abdstatsLinearCount: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, zfsCollectorSubsystem, "abdstats_linear_count_total"),
|
prometheus.BuildFQName(namespace, zfsCollectorSubsystem, "abdstats_linear_count_total"),
|
||||||
|
@ -180,6 +182,7 @@ func NewZfsCollector() (Collector, error) {
|
||||||
prometheus.BuildFQName(namespace, zfsCollectorSubsystem, "zfetchstats_misses_total"),
|
prometheus.BuildFQName(namespace, zfsCollectorSubsystem, "zfetchstats_misses_total"),
|
||||||
"ZFS cache fetch misses", nil, nil,
|
"ZFS cache fetch misses", nil, nil,
|
||||||
),
|
),
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,9 +4,9 @@ require (
|
||||||
github.com/beevik/ntp v0.2.0
|
github.com/beevik/ntp v0.2.0
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||||
github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043
|
github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043
|
||||||
|
github.com/go-kit/kit v0.9.0
|
||||||
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968
|
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968
|
||||||
github.com/hodgesds/perf-utils v0.0.7
|
github.com/hodgesds/perf-utils v0.0.7
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
|
||||||
github.com/lufia/iostat v0.0.0-20170605150913-9f7362b77ad3
|
github.com/lufia/iostat v0.0.0-20170605150913-9f7362b77ad3
|
||||||
github.com/mattn/go-xmlrpc v0.0.3
|
github.com/mattn/go-xmlrpc v0.0.3
|
||||||
github.com/mdlayher/genetlink v0.0.0-20190828143517-e35f2bf499b9 // indirect
|
github.com/mdlayher/genetlink v0.0.0-20190828143517-e35f2bf499b9 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -20,9 +20,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||||
github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043 h1:I3hLsM87FSASssIrIOGwJCio31dvLkvpYDKn2+r31ec=
|
github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043 h1:I3hLsM87FSASssIrIOGwJCio31dvLkvpYDKn2+r31ec=
|
||||||
github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE=
|
github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 h1:s+PDl6lozQ+dEUtUtQnO7+A2iPG3sK1pI4liU+jxn90=
|
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968 h1:s+PDl6lozQ+dEUtUtQnO7+A2iPG3sK1pI4liU+jxn90=
|
||||||
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
|
@ -46,8 +49,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/lufia/iostat v0.0.0-20170605150913-9f7362b77ad3 h1:XGhvld9vIpj929Gri5ybjukYZeyZwKkFkqgATqBQiOs=
|
github.com/lufia/iostat v0.0.0-20170605150913-9f7362b77ad3 h1:XGhvld9vIpj929Gri5ybjukYZeyZwKkFkqgATqBQiOs=
|
||||||
github.com/lufia/iostat v0.0.0-20170605150913-9f7362b77ad3/go.mod h1:lRgtFVamD7L7GaXOSwBiuXMwU3Aicfn5h66LVs4u2SA=
|
github.com/lufia/iostat v0.0.0-20170605150913-9f7362b77ad3/go.mod h1:lRgtFVamD7L7GaXOSwBiuXMwU3Aicfn5h66LVs4u2SA=
|
||||||
|
|
|
@ -15,13 +15,17 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/prometheus/common/promlog"
|
||||||
|
"github.com/prometheus/common/promlog/flag"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/prometheus/common/log"
|
|
||||||
"github.com/prometheus/common/version"
|
"github.com/prometheus/common/version"
|
||||||
"github.com/prometheus/node_exporter/collector"
|
"github.com/prometheus/node_exporter/collector"
|
||||||
"github.com/prometheus/node_exporter/https"
|
"github.com/prometheus/node_exporter/https"
|
||||||
|
@ -38,13 +42,15 @@ type handler struct {
|
||||||
exporterMetricsRegistry *prometheus.Registry
|
exporterMetricsRegistry *prometheus.Registry
|
||||||
includeExporterMetrics bool
|
includeExporterMetrics bool
|
||||||
maxRequests int
|
maxRequests int
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHandler(includeExporterMetrics bool, maxRequests int) *handler {
|
func newHandler(includeExporterMetrics bool, maxRequests int, logger log.Logger) *handler {
|
||||||
h := &handler{
|
h := &handler{
|
||||||
exporterMetricsRegistry: prometheus.NewRegistry(),
|
exporterMetricsRegistry: prometheus.NewRegistry(),
|
||||||
includeExporterMetrics: includeExporterMetrics,
|
includeExporterMetrics: includeExporterMetrics,
|
||||||
maxRequests: maxRequests,
|
maxRequests: maxRequests,
|
||||||
|
logger: logger,
|
||||||
}
|
}
|
||||||
if h.includeExporterMetrics {
|
if h.includeExporterMetrics {
|
||||||
h.exporterMetricsRegistry.MustRegister(
|
h.exporterMetricsRegistry.MustRegister(
|
||||||
|
@ -53,7 +59,7 @@ func newHandler(includeExporterMetrics bool, maxRequests int) *handler {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if innerHandler, err := h.innerHandler(); err != nil {
|
if innerHandler, err := h.innerHandler(); err != nil {
|
||||||
log.Fatalf("Couldn't create metrics handler: %s", err)
|
panic(fmt.Sprintf("Couldn't create metrics handler: %s", err))
|
||||||
} else {
|
} else {
|
||||||
h.unfilteredHandler = innerHandler
|
h.unfilteredHandler = innerHandler
|
||||||
}
|
}
|
||||||
|
@ -63,7 +69,7 @@ func newHandler(includeExporterMetrics bool, maxRequests int) *handler {
|
||||||
// ServeHTTP implements http.Handler.
|
// ServeHTTP implements http.Handler.
|
||||||
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
filters := r.URL.Query()["collect[]"]
|
filters := r.URL.Query()["collect[]"]
|
||||||
log.Debugln("collect query:", filters)
|
level.Debug(h.logger).Log("msg", "collect query:", "filters", filters)
|
||||||
|
|
||||||
if len(filters) == 0 {
|
if len(filters) == 0 {
|
||||||
// No filters, use the prepared unfiltered handler.
|
// No filters, use the prepared unfiltered handler.
|
||||||
|
@ -73,7 +79,7 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// To serve filtered metrics, we create a filtering handler on the fly.
|
// To serve filtered metrics, we create a filtering handler on the fly.
|
||||||
filteredHandler, err := h.innerHandler(filters...)
|
filteredHandler, err := h.innerHandler(filters...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln("Couldn't create filtered metrics handler:", err)
|
level.Warn(h.logger).Log("msg", "Couldn't create filtered metrics handler:", "err", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err)))
|
w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err)))
|
||||||
return
|
return
|
||||||
|
@ -81,13 +87,13 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
filteredHandler.ServeHTTP(w, r)
|
filteredHandler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// innerHandler is used to create buth the one unfiltered http.Handler to be
|
// innerHandler is used to create both the one unfiltered http.Handler to be
|
||||||
// wrapped by the outer handler and also the filtered handlers created on the
|
// wrapped by the outer handler and also the filtered handlers created on the
|
||||||
// fly. The former is accomplished by calling innerHandler without any arguments
|
// fly. The former is accomplished by calling innerHandler without any arguments
|
||||||
// (in which case it will log all the collectors enabled via command-line
|
// (in which case it will log all the collectors enabled via command-line
|
||||||
// flags).
|
// flags).
|
||||||
func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
|
func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
|
||||||
nc, err := collector.NewNodeCollector(filters...)
|
nc, err := collector.NewNodeCollector(h.logger, filters...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("couldn't create collector: %s", err)
|
return nil, fmt.Errorf("couldn't create collector: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -95,14 +101,14 @@ func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
|
||||||
// Only log the creation of an unfiltered handler, which should happen
|
// Only log the creation of an unfiltered handler, which should happen
|
||||||
// only once upon startup.
|
// only once upon startup.
|
||||||
if len(filters) == 0 {
|
if len(filters) == 0 {
|
||||||
log.Infof("Enabled collectors:")
|
level.Info(h.logger).Log("msg", "Enabled collectors")
|
||||||
collectors := []string{}
|
collectors := []string{}
|
||||||
for n := range nc.Collectors {
|
for n := range nc.Collectors {
|
||||||
collectors = append(collectors, n)
|
collectors = append(collectors, n)
|
||||||
}
|
}
|
||||||
sort.Strings(collectors)
|
sort.Strings(collectors)
|
||||||
for _, n := range collectors {
|
for _, c := range collectors {
|
||||||
log.Infof(" - %s", n)
|
level.Info(h.logger).Log("collector", c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +120,6 @@ func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
|
||||||
handler := promhttp.HandlerFor(
|
handler := promhttp.HandlerFor(
|
||||||
prometheus.Gatherers{h.exporterMetricsRegistry, r},
|
prometheus.Gatherers{h.exporterMetricsRegistry, r},
|
||||||
promhttp.HandlerOpts{
|
promhttp.HandlerOpts{
|
||||||
ErrorLog: log.NewErrorLogger(),
|
|
||||||
ErrorHandling: promhttp.ContinueOnError,
|
ErrorHandling: promhttp.ContinueOnError,
|
||||||
MaxRequestsInFlight: h.maxRequests,
|
MaxRequestsInFlight: h.maxRequests,
|
||||||
Registry: h.exporterMetricsRegistry,
|
Registry: h.exporterMetricsRegistry,
|
||||||
|
@ -154,15 +159,17 @@ func main() {
|
||||||
).Default("").String()
|
).Default("").String()
|
||||||
)
|
)
|
||||||
|
|
||||||
log.AddFlags(kingpin.CommandLine)
|
promlogConfig := &promlog.Config{}
|
||||||
|
flag.AddFlags(kingpin.CommandLine, promlogConfig)
|
||||||
kingpin.Version(version.Print("node_exporter"))
|
kingpin.Version(version.Print("node_exporter"))
|
||||||
kingpin.HelpFlag.Short('h')
|
kingpin.HelpFlag.Short('h')
|
||||||
kingpin.Parse()
|
kingpin.Parse()
|
||||||
|
logger := promlog.New(promlogConfig)
|
||||||
|
|
||||||
log.Infoln("Starting node_exporter", version.Info())
|
level.Info(logger).Log("msg", "Starting node_exporter", "version", version.Info())
|
||||||
log.Infoln("Build context", version.BuildContext())
|
level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext())
|
||||||
|
|
||||||
http.Handle(*metricsPath, newHandler(!*disableExporterMetrics, *maxRequests))
|
http.Handle(*metricsPath, newHandler(!*disableExporterMetrics, *maxRequests, logger))
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte(`<html>
|
w.Write([]byte(`<html>
|
||||||
<head><title>Node Exporter</title></head>
|
<head><title>Node Exporter</title></head>
|
||||||
|
@ -173,9 +180,10 @@ func main() {
|
||||||
</html>`))
|
</html>`))
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Infoln("Listening on", *listenAddress)
|
level.Info(logger).Log("msg", "Listening on", "address", *listenAddress)
|
||||||
server := &http.Server{Addr: *listenAddress}
|
server := &http.Server{Addr: *listenAddress}
|
||||||
if err := https.Listen(server, *configFile); err != nil {
|
if err := https.Listen(server, *configFile); err != nil {
|
||||||
log.Fatal(err)
|
level.Error(logger).Log("err", err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
// Used in HTTP handlers, any error is handled by the server itself.
|
// Used in HTTP handlers, any error is handled by the server itself.
|
||||||
(net/http.ResponseWriter).Write
|
(net/http.ResponseWriter).Write
|
||||||
|
// Never check for logger errors.
|
||||||
|
(github.com/go-kit/kit/log.Logger).Log
|
11
vendor/github.com/sirupsen/logrus/LICENSE → vendor/github.com/go-kit/kit/LICENSE
generated
vendored
11
vendor/github.com/sirupsen/logrus/LICENSE → vendor/github.com/go-kit/kit/LICENSE
generated
vendored
|
@ -1,6 +1,6 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014 Simon Eskildsen
|
Copyright (c) 2015 Peter Bourgon
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -9,13 +9,14 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in all
|
||||||
all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
THE SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
151
vendor/github.com/go-kit/kit/log/README.md
generated
vendored
Normal file
151
vendor/github.com/go-kit/kit/log/README.md
generated
vendored
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# package log
|
||||||
|
|
||||||
|
`package log` provides a minimal interface for structured logging in services.
|
||||||
|
It may be wrapped to encode conventions, enforce type-safety, provide leveled
|
||||||
|
logging, and so on. It can be used for both typical application log events,
|
||||||
|
and log-structured data streams.
|
||||||
|
|
||||||
|
## Structured logging
|
||||||
|
|
||||||
|
Structured logging is, basically, conceding to the reality that logs are
|
||||||
|
_data_, and warrant some level of schematic rigor. Using a stricter,
|
||||||
|
key/value-oriented message format for our logs, containing contextual and
|
||||||
|
semantic information, makes it much easier to get insight into the
|
||||||
|
operational activity of the systems we build. Consequently, `package log` is
|
||||||
|
of the strong belief that "[the benefits of structured logging outweigh the
|
||||||
|
minimal effort involved](https://www.thoughtworks.com/radar/techniques/structured-logging)".
|
||||||
|
|
||||||
|
Migrating from unstructured to structured logging is probably a lot easier
|
||||||
|
than you'd expect.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Unstructured
|
||||||
|
log.Printf("HTTP server listening on %s", addr)
|
||||||
|
|
||||||
|
// Structured
|
||||||
|
logger.Log("transport", "HTTP", "addr", addr, "msg", "listening")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Typical application logging
|
||||||
|
|
||||||
|
```go
|
||||||
|
w := log.NewSyncWriter(os.Stderr)
|
||||||
|
logger := log.NewLogfmtLogger(w)
|
||||||
|
logger.Log("question", "what is the meaning of life?", "answer", 42)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// question="what is the meaning of life?" answer=42
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contextual Loggers
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
var logger log.Logger
|
||||||
|
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
|
||||||
|
logger = log.With(logger, "instance_id", 123)
|
||||||
|
|
||||||
|
logger.Log("msg", "starting")
|
||||||
|
NewWorker(log.With(logger, "component", "worker")).Run()
|
||||||
|
NewSlacker(log.With(logger, "component", "slacker")).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// instance_id=123 msg=starting
|
||||||
|
// instance_id=123 component=worker msg=running
|
||||||
|
// instance_id=123 component=slacker msg=running
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interact with stdlib logger
|
||||||
|
|
||||||
|
Redirect stdlib logger to Go kit logger.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
stdlog "log"
|
||||||
|
kitlog "github.com/go-kit/kit/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
logger := kitlog.NewJSONLogger(kitlog.NewSyncWriter(os.Stdout))
|
||||||
|
stdlog.SetOutput(kitlog.NewStdlibAdapter(logger))
|
||||||
|
stdlog.Print("I sure like pie")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {"msg":"I sure like pie","ts":"2016/01/01 12:34:56"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if, for legacy reasons, you need to pipe all of your logging through the
|
||||||
|
stdlib log package, you can redirect Go kit logger to the stdlib logger.
|
||||||
|
|
||||||
|
```go
|
||||||
|
logger := kitlog.NewLogfmtLogger(kitlog.StdlibWriter{})
|
||||||
|
logger.Log("legacy", true, "msg", "at least it's something")
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 2016/01/01 12:34:56 legacy=true msg="at least it's something"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Timestamps and callers
|
||||||
|
|
||||||
|
```go
|
||||||
|
var logger log.Logger
|
||||||
|
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
|
||||||
|
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
|
||||||
|
|
||||||
|
logger.Log("msg", "hello")
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ts=2016-01-01T12:34:56Z caller=main.go:15 msg=hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## Levels
|
||||||
|
|
||||||
|
Log levels are supported via the [level package](https://godoc.org/github.com/go-kit/kit/log/level).
|
||||||
|
|
||||||
|
## Supported output formats
|
||||||
|
|
||||||
|
- [Logfmt](https://brandur.org/logfmt) ([see also](https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write))
|
||||||
|
- JSON
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
|
||||||
|
`package log` is centered on the one-method Logger interface.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Logger interface {
|
||||||
|
Log(keyvals ...interface{}) error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This interface, and its supporting code like is the product of much iteration
|
||||||
|
and evaluation. For more details on the evolution of the Logger interface,
|
||||||
|
see [The Hunt for a Logger Interface](http://go-talks.appspot.com/github.com/ChrisHines/talks/structured-logging/structured-logging.slide#1),
|
||||||
|
a talk by [Chris Hines](https://github.com/ChrisHines).
|
||||||
|
Also, please see
|
||||||
|
[#63](https://github.com/go-kit/kit/issues/63),
|
||||||
|
[#76](https://github.com/go-kit/kit/pull/76),
|
||||||
|
[#131](https://github.com/go-kit/kit/issues/131),
|
||||||
|
[#157](https://github.com/go-kit/kit/pull/157),
|
||||||
|
[#164](https://github.com/go-kit/kit/issues/164), and
|
||||||
|
[#252](https://github.com/go-kit/kit/pull/252)
|
||||||
|
to review historical conversations about package log and the Logger interface.
|
||||||
|
|
||||||
|
Value-add packages and suggestions,
|
||||||
|
like improvements to [the leveled logger](https://godoc.org/github.com/go-kit/kit/log/level),
|
||||||
|
are of course welcome. Good proposals should
|
||||||
|
|
||||||
|
- Be composable with [contextual loggers](https://godoc.org/github.com/go-kit/kit/log#With),
|
||||||
|
- Not break the behavior of [log.Caller](https://godoc.org/github.com/go-kit/kit/log#Caller) in any wrapped contextual loggers, and
|
||||||
|
- Be friendly to packages that accept only an unadorned log.Logger.
|
||||||
|
|
||||||
|
## Benchmarks & comparisons
|
||||||
|
|
||||||
|
There are a few Go logging benchmarks and comparisons that include Go kit's package log.
|
||||||
|
|
||||||
|
- [imkira/go-loggers-bench](https://github.com/imkira/go-loggers-bench) includes kit/log
|
||||||
|
- [uber-common/zap](https://github.com/uber-common/zap), a zero-alloc logging library, includes a comparison with kit/log
|
116
vendor/github.com/go-kit/kit/log/doc.go
generated
vendored
Normal file
116
vendor/github.com/go-kit/kit/log/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
// Package log provides a structured logger.
|
||||||
|
//
|
||||||
|
// Structured logging produces logs easily consumed later by humans or
|
||||||
|
// machines. Humans might be interested in debugging errors, or tracing
|
||||||
|
// specific requests. Machines might be interested in counting interesting
|
||||||
|
// events, or aggregating information for off-line processing. In both cases,
|
||||||
|
// it is important that the log messages are structured and actionable.
|
||||||
|
// Package log is designed to encourage both of these best practices.
|
||||||
|
//
|
||||||
|
// Basic Usage
|
||||||
|
//
|
||||||
|
// The fundamental interface is Logger. Loggers create log events from
|
||||||
|
// key/value data. The Logger interface has a single method, Log, which
|
||||||
|
// accepts a sequence of alternating key/value pairs, which this package names
|
||||||
|
// keyvals.
|
||||||
|
//
|
||||||
|
// type Logger interface {
|
||||||
|
// Log(keyvals ...interface{}) error
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Here is an example of a function using a Logger to create log events.
|
||||||
|
//
|
||||||
|
// func RunTask(task Task, logger log.Logger) string {
|
||||||
|
// logger.Log("taskID", task.ID, "event", "starting task")
|
||||||
|
// ...
|
||||||
|
// logger.Log("taskID", task.ID, "event", "task complete")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The keys in the above example are "taskID" and "event". The values are
|
||||||
|
// task.ID, "starting task", and "task complete". Every key is followed
|
||||||
|
// immediately by its value.
|
||||||
|
//
|
||||||
|
// Keys are usually plain strings. Values may be any type that has a sensible
|
||||||
|
// encoding in the chosen log format. With structured logging it is a good
|
||||||
|
// idea to log simple values without formatting them. This practice allows
|
||||||
|
// the chosen logger to encode values in the most appropriate way.
|
||||||
|
//
|
||||||
|
// Contextual Loggers
|
||||||
|
//
|
||||||
|
// A contextual logger stores keyvals that it includes in all log events.
|
||||||
|
// Building appropriate contextual loggers reduces repetition and aids
|
||||||
|
// consistency in the resulting log output. With and WithPrefix add context to
|
||||||
|
// a logger. We can use With to improve the RunTask example.
|
||||||
|
//
|
||||||
|
// func RunTask(task Task, logger log.Logger) string {
|
||||||
|
// logger = log.With(logger, "taskID", task.ID)
|
||||||
|
// logger.Log("event", "starting task")
|
||||||
|
// ...
|
||||||
|
// taskHelper(task.Cmd, logger)
|
||||||
|
// ...
|
||||||
|
// logger.Log("event", "task complete")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The improved version emits the same log events as the original for the
|
||||||
|
// first and last calls to Log. Passing the contextual logger to taskHelper
|
||||||
|
// enables each log event created by taskHelper to include the task.ID even
|
||||||
|
// though taskHelper does not have access to that value. Using contextual
|
||||||
|
// loggers this way simplifies producing log output that enables tracing the
|
||||||
|
// life cycle of individual tasks. (See the Contextual example for the full
|
||||||
|
// code of the above snippet.)
|
||||||
|
//
|
||||||
|
// Dynamic Contextual Values
|
||||||
|
//
|
||||||
|
// A Valuer function stored in a contextual logger generates a new value each
|
||||||
|
// time an event is logged. The Valuer example demonstrates how this feature
|
||||||
|
// works.
|
||||||
|
//
|
||||||
|
// Valuers provide the basis for consistently logging timestamps and source
|
||||||
|
// code location. The log package defines several valuers for that purpose.
|
||||||
|
// See Timestamp, DefaultTimestamp, DefaultTimestampUTC, Caller, and
|
||||||
|
// DefaultCaller. A common logger initialization sequence that ensures all log
|
||||||
|
// entries contain a timestamp and source location looks like this:
|
||||||
|
//
|
||||||
|
// logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
|
||||||
|
// logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
|
||||||
|
//
|
||||||
|
// Concurrent Safety
|
||||||
|
//
|
||||||
|
// Applications with multiple goroutines want each log event written to the
|
||||||
|
// same logger to remain separate from other log events. Package log provides
|
||||||
|
// two simple solutions for concurrent safe logging.
|
||||||
|
//
|
||||||
|
// NewSyncWriter wraps an io.Writer and serializes each call to its Write
|
||||||
|
// method. Using a SyncWriter has the benefit that the smallest practical
|
||||||
|
// portion of the logging logic is performed within a mutex, but it requires
|
||||||
|
// the formatting Logger to make only one call to Write per log event.
|
||||||
|
//
|
||||||
|
// NewSyncLogger wraps any Logger and serializes each call to its Log method.
|
||||||
|
// Using a SyncLogger has the benefit that it guarantees each log event is
|
||||||
|
// handled atomically within the wrapped logger, but it typically serializes
|
||||||
|
// both the formatting and output logic. Use a SyncLogger if the formatting
|
||||||
|
// logger may perform multiple writes per log event.
|
||||||
|
//
|
||||||
|
// Error Handling
|
||||||
|
//
|
||||||
|
// This package relies on the practice of wrapping or decorating loggers with
|
||||||
|
// other loggers to provide composable pieces of functionality. It also means
|
||||||
|
// that Logger.Log must return an error because some
|
||||||
|
// implementations—especially those that output log data to an io.Writer—may
|
||||||
|
// encounter errors that cannot be handled locally. This in turn means that
|
||||||
|
// Loggers that wrap other loggers should return errors from the wrapped
|
||||||
|
// logger up the stack.
|
||||||
|
//
|
||||||
|
// Fortunately, the decorator pattern also provides a way to avoid the
|
||||||
|
// necessity to check for errors every time an application calls Logger.Log.
|
||||||
|
// An application required to panic whenever its Logger encounters
|
||||||
|
// an error could initialize its logger as follows.
|
||||||
|
//
|
||||||
|
// fmtlogger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
|
||||||
|
// logger := log.LoggerFunc(func(keyvals ...interface{}) error {
|
||||||
|
// if err := fmtlogger.Log(keyvals...); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
// })
|
||||||
|
package log
|
89
vendor/github.com/go-kit/kit/log/json_logger.go
generated
vendored
Normal file
89
vendor/github.com/go-kit/kit/log/json_logger.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type jsonLogger struct {
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewJSONLogger returns a Logger that encodes keyvals to the Writer as a
|
||||||
|
// single JSON object. Each log event produces no more than one call to
|
||||||
|
// w.Write. The passed Writer must be safe for concurrent use by multiple
|
||||||
|
// goroutines if the returned Logger will be used concurrently.
|
||||||
|
func NewJSONLogger(w io.Writer) Logger {
|
||||||
|
return &jsonLogger{w}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *jsonLogger) Log(keyvals ...interface{}) error {
|
||||||
|
n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd
|
||||||
|
m := make(map[string]interface{}, n)
|
||||||
|
for i := 0; i < len(keyvals); i += 2 {
|
||||||
|
k := keyvals[i]
|
||||||
|
var v interface{} = ErrMissingValue
|
||||||
|
if i+1 < len(keyvals) {
|
||||||
|
v = keyvals[i+1]
|
||||||
|
}
|
||||||
|
merge(m, k, v)
|
||||||
|
}
|
||||||
|
return json.NewEncoder(l.Writer).Encode(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func merge(dst map[string]interface{}, k, v interface{}) {
|
||||||
|
var key string
|
||||||
|
switch x := k.(type) {
|
||||||
|
case string:
|
||||||
|
key = x
|
||||||
|
case fmt.Stringer:
|
||||||
|
key = safeString(x)
|
||||||
|
default:
|
||||||
|
key = fmt.Sprint(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want json.Marshaler and encoding.TextMarshaller to take priority over
|
||||||
|
// err.Error() and v.String(). But json.Marshall (called later) does that by
|
||||||
|
// default so we force a no-op if it's one of those 2 case.
|
||||||
|
switch x := v.(type) {
|
||||||
|
case json.Marshaler:
|
||||||
|
case encoding.TextMarshaler:
|
||||||
|
case error:
|
||||||
|
v = safeError(x)
|
||||||
|
case fmt.Stringer:
|
||||||
|
v = safeString(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[key] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeString(str fmt.Stringer) (s string) {
|
||||||
|
defer func() {
|
||||||
|
if panicVal := recover(); panicVal != nil {
|
||||||
|
if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
|
||||||
|
s = "NULL"
|
||||||
|
} else {
|
||||||
|
panic(panicVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
s = str.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeError(err error) (s interface{}) {
|
||||||
|
defer func() {
|
||||||
|
if panicVal := recover(); panicVal != nil {
|
||||||
|
if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
|
||||||
|
s = nil
|
||||||
|
} else {
|
||||||
|
panic(panicVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
s = err.Error()
|
||||||
|
return
|
||||||
|
}
|
22
vendor/github.com/go-kit/kit/log/level/doc.go
generated
vendored
Normal file
22
vendor/github.com/go-kit/kit/log/level/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Package level implements leveled logging on top of Go kit's log package. To
|
||||||
|
// use the level package, create a logger as per normal in your func main, and
|
||||||
|
// wrap it with level.NewFilter.
|
||||||
|
//
|
||||||
|
// var logger log.Logger
|
||||||
|
// logger = log.NewLogfmtLogger(os.Stderr)
|
||||||
|
// logger = level.NewFilter(logger, level.AllowInfo()) // <--
|
||||||
|
// logger = log.With(logger, "ts", log.DefaultTimestampUTC)
|
||||||
|
//
|
||||||
|
// Then, at the callsites, use one of the level.Debug, Info, Warn, or Error
|
||||||
|
// helper methods to emit leveled log events.
|
||||||
|
//
|
||||||
|
// logger.Log("foo", "bar") // as normal, no level
|
||||||
|
// level.Debug(logger).Log("request_id", reqID, "trace_data", trace.Get())
|
||||||
|
// if value > 100 {
|
||||||
|
// level.Error(logger).Log("value", value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// NewFilter allows precise control over what happens when a log event is
|
||||||
|
// emitted without a level key, or if a squelched level is used. Check the
|
||||||
|
// Option functions for details.
|
||||||
|
package level
|
205
vendor/github.com/go-kit/kit/log/level/level.go
generated
vendored
Normal file
205
vendor/github.com/go-kit/kit/log/level/level.go
generated
vendored
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
package level
|
||||||
|
|
||||||
|
import "github.com/go-kit/kit/log"
|
||||||
|
|
||||||
|
// Error returns a logger that includes a Key/ErrorValue pair.
|
||||||
|
func Error(logger log.Logger) log.Logger {
|
||||||
|
return log.WithPrefix(logger, Key(), ErrorValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn returns a logger that includes a Key/WarnValue pair.
|
||||||
|
func Warn(logger log.Logger) log.Logger {
|
||||||
|
return log.WithPrefix(logger, Key(), WarnValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info returns a logger that includes a Key/InfoValue pair.
|
||||||
|
func Info(logger log.Logger) log.Logger {
|
||||||
|
return log.WithPrefix(logger, Key(), InfoValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug returns a logger that includes a Key/DebugValue pair.
|
||||||
|
func Debug(logger log.Logger) log.Logger {
|
||||||
|
return log.WithPrefix(logger, Key(), DebugValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFilter wraps next and implements level filtering. See the commentary on
|
||||||
|
// the Option functions for a detailed description of how to configure levels.
|
||||||
|
// If no options are provided, all leveled log events created with Debug,
|
||||||
|
// Info, Warn or Error helper methods are squelched and non-leveled log
|
||||||
|
// events are passed to next unmodified.
|
||||||
|
func NewFilter(next log.Logger, options ...Option) log.Logger {
|
||||||
|
l := &logger{
|
||||||
|
next: next,
|
||||||
|
}
|
||||||
|
for _, option := range options {
|
||||||
|
option(l)
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
type logger struct {
|
||||||
|
next log.Logger
|
||||||
|
allowed level
|
||||||
|
squelchNoLevel bool
|
||||||
|
errNotAllowed error
|
||||||
|
errNoLevel error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) Log(keyvals ...interface{}) error {
|
||||||
|
var hasLevel, levelAllowed bool
|
||||||
|
for i := 1; i < len(keyvals); i += 2 {
|
||||||
|
if v, ok := keyvals[i].(*levelValue); ok {
|
||||||
|
hasLevel = true
|
||||||
|
levelAllowed = l.allowed&v.level != 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasLevel && l.squelchNoLevel {
|
||||||
|
return l.errNoLevel
|
||||||
|
}
|
||||||
|
if hasLevel && !levelAllowed {
|
||||||
|
return l.errNotAllowed
|
||||||
|
}
|
||||||
|
return l.next.Log(keyvals...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option sets a parameter for the leveled logger.
|
||||||
|
type Option func(*logger)
|
||||||
|
|
||||||
|
// AllowAll is an alias for AllowDebug.
|
||||||
|
func AllowAll() Option {
|
||||||
|
return AllowDebug()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowDebug allows error, warn, info and debug level log events to pass.
|
||||||
|
func AllowDebug() Option {
|
||||||
|
return allowed(levelError | levelWarn | levelInfo | levelDebug)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowInfo allows error, warn and info level log events to pass.
|
||||||
|
func AllowInfo() Option {
|
||||||
|
return allowed(levelError | levelWarn | levelInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowWarn allows error and warn level log events to pass.
|
||||||
|
func AllowWarn() Option {
|
||||||
|
return allowed(levelError | levelWarn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowError allows only error level log events to pass.
|
||||||
|
func AllowError() Option {
|
||||||
|
return allowed(levelError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowNone allows no leveled log events to pass.
|
||||||
|
func AllowNone() Option {
|
||||||
|
return allowed(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func allowed(allowed level) Option {
|
||||||
|
return func(l *logger) { l.allowed = allowed }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrNotAllowed sets the error to return from Log when it squelches a log
|
||||||
|
// event disallowed by the configured Allow[Level] option. By default,
|
||||||
|
// ErrNotAllowed is nil; in this case the log event is squelched with no
|
||||||
|
// error.
|
||||||
|
func ErrNotAllowed(err error) Option {
|
||||||
|
return func(l *logger) { l.errNotAllowed = err }
|
||||||
|
}
|
||||||
|
|
||||||
|
// SquelchNoLevel instructs Log to squelch log events with no level, so that
|
||||||
|
// they don't proceed through to the wrapped logger. If SquelchNoLevel is set
|
||||||
|
// to true and a log event is squelched in this way, the error value
|
||||||
|
// configured with ErrNoLevel is returned to the caller.
|
||||||
|
func SquelchNoLevel(squelch bool) Option {
|
||||||
|
return func(l *logger) { l.squelchNoLevel = squelch }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrNoLevel sets the error to return from Log when it squelches a log event
|
||||||
|
// with no level. By default, ErrNoLevel is nil; in this case the log event is
|
||||||
|
// squelched with no error.
|
||||||
|
func ErrNoLevel(err error) Option {
|
||||||
|
return func(l *logger) { l.errNoLevel = err }
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInjector wraps next and returns a logger that adds a Key/level pair to
|
||||||
|
// the beginning of log events that don't already contain a level. In effect,
|
||||||
|
// this gives a default level to logs without a level.
|
||||||
|
func NewInjector(next log.Logger, level Value) log.Logger {
|
||||||
|
return &injector{
|
||||||
|
next: next,
|
||||||
|
level: level,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type injector struct {
|
||||||
|
next log.Logger
|
||||||
|
level interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *injector) Log(keyvals ...interface{}) error {
|
||||||
|
for i := 1; i < len(keyvals); i += 2 {
|
||||||
|
if _, ok := keyvals[i].(*levelValue); ok {
|
||||||
|
return l.next.Log(keyvals...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kvs := make([]interface{}, len(keyvals)+2)
|
||||||
|
kvs[0], kvs[1] = key, l.level
|
||||||
|
copy(kvs[2:], keyvals)
|
||||||
|
return l.next.Log(kvs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value is the interface that each of the canonical level values implement.
|
||||||
|
// It contains unexported methods that prevent types from other packages from
|
||||||
|
// implementing it and guaranteeing that NewFilter can distinguish the levels
|
||||||
|
// defined in this package from all other values.
|
||||||
|
type Value interface {
|
||||||
|
String() string
|
||||||
|
levelVal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the unique key added to log events by the loggers in this
|
||||||
|
// package.
|
||||||
|
func Key() interface{} { return key }
|
||||||
|
|
||||||
|
// ErrorValue returns the unique value added to log events by Error.
|
||||||
|
func ErrorValue() Value { return errorValue }
|
||||||
|
|
||||||
|
// WarnValue returns the unique value added to log events by Warn.
|
||||||
|
func WarnValue() Value { return warnValue }
|
||||||
|
|
||||||
|
// InfoValue returns the unique value added to log events by Info.
|
||||||
|
func InfoValue() Value { return infoValue }
|
||||||
|
|
||||||
|
// DebugValue returns the unique value added to log events by Warn.
|
||||||
|
func DebugValue() Value { return debugValue }
|
||||||
|
|
||||||
|
var (
|
||||||
|
// key is of type interface{} so that it allocates once during package
|
||||||
|
// initialization and avoids allocating every time the value is added to a
|
||||||
|
// []interface{} later.
|
||||||
|
key interface{} = "level"
|
||||||
|
|
||||||
|
errorValue = &levelValue{level: levelError, name: "error"}
|
||||||
|
warnValue = &levelValue{level: levelWarn, name: "warn"}
|
||||||
|
infoValue = &levelValue{level: levelInfo, name: "info"}
|
||||||
|
debugValue = &levelValue{level: levelDebug, name: "debug"}
|
||||||
|
)
|
||||||
|
|
||||||
|
type level byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
levelDebug level = 1 << iota
|
||||||
|
levelInfo
|
||||||
|
levelWarn
|
||||||
|
levelError
|
||||||
|
)
|
||||||
|
|
||||||
|
type levelValue struct {
|
||||||
|
name string
|
||||||
|
level
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *levelValue) String() string { return v.name }
|
||||||
|
func (v *levelValue) levelVal() {}
|
135
vendor/github.com/go-kit/kit/log/log.go
generated
vendored
Normal file
135
vendor/github.com/go-kit/kit/log/log.go
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// Logger is the fundamental interface for all log operations. Log creates a
|
||||||
|
// log event from keyvals, a variadic sequence of alternating keys and values.
|
||||||
|
// Implementations must be safe for concurrent use by multiple goroutines. In
|
||||||
|
// particular, any implementation of Logger that appends to keyvals or
|
||||||
|
// modifies or retains any of its elements must make a copy first.
|
||||||
|
type Logger interface {
|
||||||
|
Log(keyvals ...interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrMissingValue is appended to keyvals slices with odd length to substitute
|
||||||
|
// the missing value.
|
||||||
|
var ErrMissingValue = errors.New("(MISSING)")
|
||||||
|
|
||||||
|
// With returns a new contextual logger with keyvals prepended to those passed
|
||||||
|
// to calls to Log. If logger is also a contextual logger created by With or
|
||||||
|
// WithPrefix, keyvals is appended to the existing context.
|
||||||
|
//
|
||||||
|
// The returned Logger replaces all value elements (odd indexes) containing a
|
||||||
|
// Valuer with their generated value for each call to its Log method.
|
||||||
|
func With(logger Logger, keyvals ...interface{}) Logger {
|
||||||
|
if len(keyvals) == 0 {
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
l := newContext(logger)
|
||||||
|
kvs := append(l.keyvals, keyvals...)
|
||||||
|
if len(kvs)%2 != 0 {
|
||||||
|
kvs = append(kvs, ErrMissingValue)
|
||||||
|
}
|
||||||
|
return &context{
|
||||||
|
logger: l.logger,
|
||||||
|
// Limiting the capacity of the stored keyvals ensures that a new
|
||||||
|
// backing array is created if the slice must grow in Log or With.
|
||||||
|
// Using the extra capacity without copying risks a data race that
|
||||||
|
// would violate the Logger interface contract.
|
||||||
|
keyvals: kvs[:len(kvs):len(kvs)],
|
||||||
|
hasValuer: l.hasValuer || containsValuer(keyvals),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPrefix returns a new contextual logger with keyvals prepended to those
|
||||||
|
// passed to calls to Log. If logger is also a contextual logger created by
|
||||||
|
// With or WithPrefix, keyvals is prepended to the existing context.
|
||||||
|
//
|
||||||
|
// The returned Logger replaces all value elements (odd indexes) containing a
|
||||||
|
// Valuer with their generated value for each call to its Log method.
|
||||||
|
func WithPrefix(logger Logger, keyvals ...interface{}) Logger {
|
||||||
|
if len(keyvals) == 0 {
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
l := newContext(logger)
|
||||||
|
// Limiting the capacity of the stored keyvals ensures that a new
|
||||||
|
// backing array is created if the slice must grow in Log or With.
|
||||||
|
// Using the extra capacity without copying risks a data race that
|
||||||
|
// would violate the Logger interface contract.
|
||||||
|
n := len(l.keyvals) + len(keyvals)
|
||||||
|
if len(keyvals)%2 != 0 {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
kvs := make([]interface{}, 0, n)
|
||||||
|
kvs = append(kvs, keyvals...)
|
||||||
|
if len(kvs)%2 != 0 {
|
||||||
|
kvs = append(kvs, ErrMissingValue)
|
||||||
|
}
|
||||||
|
kvs = append(kvs, l.keyvals...)
|
||||||
|
return &context{
|
||||||
|
logger: l.logger,
|
||||||
|
keyvals: kvs,
|
||||||
|
hasValuer: l.hasValuer || containsValuer(keyvals),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// context is the Logger implementation returned by With and WithPrefix. It
|
||||||
|
// wraps a Logger and holds keyvals that it includes in all log events. Its
|
||||||
|
// Log method calls bindValues to generate values for each Valuer in the
|
||||||
|
// context keyvals.
|
||||||
|
//
|
||||||
|
// A context must always have the same number of stack frames between calls to
|
||||||
|
// its Log method and the eventual binding of Valuers to their value. This
|
||||||
|
// requirement comes from the functional requirement to allow a context to
|
||||||
|
// resolve application call site information for a Caller stored in the
|
||||||
|
// context. To do this we must be able to predict the number of logging
|
||||||
|
// functions on the stack when bindValues is called.
|
||||||
|
//
|
||||||
|
// Two implementation details provide the needed stack depth consistency.
|
||||||
|
//
|
||||||
|
// 1. newContext avoids introducing an additional layer when asked to
|
||||||
|
// wrap another context.
|
||||||
|
// 2. With and WithPrefix avoid introducing an additional layer by
|
||||||
|
// returning a newly constructed context with a merged keyvals rather
|
||||||
|
// than simply wrapping the existing context.
|
||||||
|
type context struct {
|
||||||
|
logger Logger
|
||||||
|
keyvals []interface{}
|
||||||
|
hasValuer bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newContext(logger Logger) *context {
|
||||||
|
if c, ok := logger.(*context); ok {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return &context{logger: logger}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log replaces all value elements (odd indexes) containing a Valuer in the
|
||||||
|
// stored context with their generated value, appends keyvals, and passes the
|
||||||
|
// result to the wrapped Logger.
|
||||||
|
func (l *context) Log(keyvals ...interface{}) error {
|
||||||
|
kvs := append(l.keyvals, keyvals...)
|
||||||
|
if len(kvs)%2 != 0 {
|
||||||
|
kvs = append(kvs, ErrMissingValue)
|
||||||
|
}
|
||||||
|
if l.hasValuer {
|
||||||
|
// If no keyvals were appended above then we must copy l.keyvals so
|
||||||
|
// that future log events will reevaluate the stored Valuers.
|
||||||
|
if len(keyvals) == 0 {
|
||||||
|
kvs = append([]interface{}{}, l.keyvals...)
|
||||||
|
}
|
||||||
|
bindValues(kvs[:len(l.keyvals)])
|
||||||
|
}
|
||||||
|
return l.logger.Log(kvs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoggerFunc is an adapter to allow use of ordinary functions as Loggers. If
|
||||||
|
// f is a function with the appropriate signature, LoggerFunc(f) is a Logger
|
||||||
|
// object that calls f.
|
||||||
|
type LoggerFunc func(...interface{}) error
|
||||||
|
|
||||||
|
// Log implements Logger by calling f(keyvals...).
|
||||||
|
func (f LoggerFunc) Log(keyvals ...interface{}) error {
|
||||||
|
return f(keyvals...)
|
||||||
|
}
|
62
vendor/github.com/go-kit/kit/log/logfmt_logger.go
generated
vendored
Normal file
62
vendor/github.com/go-kit/kit/log/logfmt_logger.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/go-logfmt/logfmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type logfmtEncoder struct {
|
||||||
|
*logfmt.Encoder
|
||||||
|
buf bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logfmtEncoder) Reset() {
|
||||||
|
l.Encoder.Reset()
|
||||||
|
l.buf.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
var logfmtEncoderPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
var enc logfmtEncoder
|
||||||
|
enc.Encoder = logfmt.NewEncoder(&enc.buf)
|
||||||
|
return &enc
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type logfmtLogger struct {
|
||||||
|
w io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLogfmtLogger returns a logger that encodes keyvals to the Writer in
|
||||||
|
// logfmt format. Each log event produces no more than one call to w.Write.
|
||||||
|
// The passed Writer must be safe for concurrent use by multiple goroutines if
|
||||||
|
// the returned Logger will be used concurrently.
|
||||||
|
func NewLogfmtLogger(w io.Writer) Logger {
|
||||||
|
return &logfmtLogger{w}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l logfmtLogger) Log(keyvals ...interface{}) error {
|
||||||
|
enc := logfmtEncoderPool.Get().(*logfmtEncoder)
|
||||||
|
enc.Reset()
|
||||||
|
defer logfmtEncoderPool.Put(enc)
|
||||||
|
|
||||||
|
if err := enc.EncodeKeyvals(keyvals...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add newline to the end of the buffer
|
||||||
|
if err := enc.EndRecord(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Logger interface requires implementations to be safe for concurrent
|
||||||
|
// use by multiple goroutines. For this implementation that means making
|
||||||
|
// only one call to l.w.Write() for each call to Log.
|
||||||
|
if _, err := l.w.Write(enc.buf.Bytes()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
8
vendor/github.com/go-kit/kit/log/nop_logger.go
generated
vendored
Normal file
8
vendor/github.com/go-kit/kit/log/nop_logger.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
type nopLogger struct{}
|
||||||
|
|
||||||
|
// NewNopLogger returns a logger that doesn't do anything.
|
||||||
|
func NewNopLogger() Logger { return nopLogger{} }
|
||||||
|
|
||||||
|
func (nopLogger) Log(...interface{}) error { return nil }
|
116
vendor/github.com/go-kit/kit/log/stdlib.go
generated
vendored
Normal file
116
vendor/github.com/go-kit/kit/log/stdlib.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StdlibWriter implements io.Writer by invoking the stdlib log.Print. It's
|
||||||
|
// designed to be passed to a Go kit logger as the writer, for cases where
|
||||||
|
// it's necessary to redirect all Go kit log output to the stdlib logger.
|
||||||
|
//
|
||||||
|
// If you have any choice in the matter, you shouldn't use this. Prefer to
|
||||||
|
// redirect the stdlib log to the Go kit logger via NewStdlibAdapter.
|
||||||
|
type StdlibWriter struct{}
|
||||||
|
|
||||||
|
// Write implements io.Writer.
|
||||||
|
func (w StdlibWriter) Write(p []byte) (int, error) {
|
||||||
|
log.Print(strings.TrimSpace(string(p)))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StdlibAdapter wraps a Logger and allows it to be passed to the stdlib
|
||||||
|
// logger's SetOutput. It will extract date/timestamps, filenames, and
|
||||||
|
// messages, and place them under relevant keys.
|
||||||
|
type StdlibAdapter struct {
|
||||||
|
Logger
|
||||||
|
timestampKey string
|
||||||
|
fileKey string
|
||||||
|
messageKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
// StdlibAdapterOption sets a parameter for the StdlibAdapter.
|
||||||
|
type StdlibAdapterOption func(*StdlibAdapter)
|
||||||
|
|
||||||
|
// TimestampKey sets the key for the timestamp field. By default, it's "ts".
|
||||||
|
func TimestampKey(key string) StdlibAdapterOption {
|
||||||
|
return func(a *StdlibAdapter) { a.timestampKey = key }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileKey sets the key for the file and line field. By default, it's "caller".
|
||||||
|
func FileKey(key string) StdlibAdapterOption {
|
||||||
|
return func(a *StdlibAdapter) { a.fileKey = key }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageKey sets the key for the actual log message. By default, it's "msg".
|
||||||
|
func MessageKey(key string) StdlibAdapterOption {
|
||||||
|
return func(a *StdlibAdapter) { a.messageKey = key }
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed
|
||||||
|
// logger. It's designed to be passed to log.SetOutput.
|
||||||
|
func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer {
|
||||||
|
a := StdlibAdapter{
|
||||||
|
Logger: logger,
|
||||||
|
timestampKey: "ts",
|
||||||
|
fileKey: "caller",
|
||||||
|
messageKey: "msg",
|
||||||
|
}
|
||||||
|
for _, option := range options {
|
||||||
|
option(&a)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a StdlibAdapter) Write(p []byte) (int, error) {
|
||||||
|
result := subexps(p)
|
||||||
|
keyvals := []interface{}{}
|
||||||
|
var timestamp string
|
||||||
|
if date, ok := result["date"]; ok && date != "" {
|
||||||
|
timestamp = date
|
||||||
|
}
|
||||||
|
if time, ok := result["time"]; ok && time != "" {
|
||||||
|
if timestamp != "" {
|
||||||
|
timestamp += " "
|
||||||
|
}
|
||||||
|
timestamp += time
|
||||||
|
}
|
||||||
|
if timestamp != "" {
|
||||||
|
keyvals = append(keyvals, a.timestampKey, timestamp)
|
||||||
|
}
|
||||||
|
if file, ok := result["file"]; ok && file != "" {
|
||||||
|
keyvals = append(keyvals, a.fileKey, file)
|
||||||
|
}
|
||||||
|
if msg, ok := result["msg"]; ok {
|
||||||
|
keyvals = append(keyvals, a.messageKey, msg)
|
||||||
|
}
|
||||||
|
if err := a.Logger.Log(keyvals...); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
logRegexpDate = `(?P<date>[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
|
||||||
|
logRegexpTime = `(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)?[ ]?`
|
||||||
|
logRegexpFile = `(?P<file>.+?:[0-9]+)?`
|
||||||
|
logRegexpMsg = `(: )?(?P<msg>.*)`
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
logRegexp = regexp.MustCompile(logRegexpDate + logRegexpTime + logRegexpFile + logRegexpMsg)
|
||||||
|
)
|
||||||
|
|
||||||
|
func subexps(line []byte) map[string]string {
|
||||||
|
m := logRegexp.FindSubmatch(line)
|
||||||
|
if len(m) < len(logRegexp.SubexpNames()) {
|
||||||
|
return map[string]string{}
|
||||||
|
}
|
||||||
|
result := map[string]string{}
|
||||||
|
for i, name := range logRegexp.SubexpNames() {
|
||||||
|
result[name] = string(m[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
116
vendor/github.com/go-kit/kit/log/sync.go
generated
vendored
Normal file
116
vendor/github.com/go-kit/kit/log/sync.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SwapLogger wraps another logger that may be safely replaced while other
|
||||||
|
// goroutines use the SwapLogger concurrently. The zero value for a SwapLogger
|
||||||
|
// will discard all log events without error.
|
||||||
|
//
|
||||||
|
// SwapLogger serves well as a package global logger that can be changed by
|
||||||
|
// importers.
|
||||||
|
type SwapLogger struct {
|
||||||
|
logger atomic.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
type loggerStruct struct {
|
||||||
|
Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log implements the Logger interface by forwarding keyvals to the currently
|
||||||
|
// wrapped logger. It does not log anything if the wrapped logger is nil.
|
||||||
|
func (l *SwapLogger) Log(keyvals ...interface{}) error {
|
||||||
|
s, ok := l.logger.Load().(loggerStruct)
|
||||||
|
if !ok || s.Logger == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return s.Log(keyvals...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap replaces the currently wrapped logger with logger. Swap may be called
|
||||||
|
// concurrently with calls to Log from other goroutines.
|
||||||
|
func (l *SwapLogger) Swap(logger Logger) {
|
||||||
|
l.logger.Store(loggerStruct{logger})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncWriter returns a new writer that is safe for concurrent use by
|
||||||
|
// multiple goroutines. Writes to the returned writer are passed on to w. If
|
||||||
|
// another write is already in progress, the calling goroutine blocks until
|
||||||
|
// the writer is available.
|
||||||
|
//
|
||||||
|
// If w implements the following interface, so does the returned writer.
|
||||||
|
//
|
||||||
|
// interface {
|
||||||
|
// Fd() uintptr
|
||||||
|
// }
|
||||||
|
func NewSyncWriter(w io.Writer) io.Writer {
|
||||||
|
switch w := w.(type) {
|
||||||
|
case fdWriter:
|
||||||
|
return &fdSyncWriter{fdWriter: w}
|
||||||
|
default:
|
||||||
|
return &syncWriter{Writer: w}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncWriter synchronizes concurrent writes to an io.Writer.
|
||||||
|
type syncWriter struct {
|
||||||
|
sync.Mutex
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes p to the underlying io.Writer. If another write is already in
|
||||||
|
// progress, the calling goroutine blocks until the syncWriter is available.
|
||||||
|
func (w *syncWriter) Write(p []byte) (n int, err error) {
|
||||||
|
w.Lock()
|
||||||
|
n, err = w.Writer.Write(p)
|
||||||
|
w.Unlock()
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fdWriter is an io.Writer that also has an Fd method. The most common
|
||||||
|
// example of an fdWriter is an *os.File.
|
||||||
|
type fdWriter interface {
|
||||||
|
io.Writer
|
||||||
|
Fd() uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// fdSyncWriter synchronizes concurrent writes to an fdWriter.
|
||||||
|
type fdSyncWriter struct {
|
||||||
|
sync.Mutex
|
||||||
|
fdWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes p to the underlying io.Writer. If another write is already in
|
||||||
|
// progress, the calling goroutine blocks until the fdSyncWriter is available.
|
||||||
|
func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
|
||||||
|
w.Lock()
|
||||||
|
n, err = w.fdWriter.Write(p)
|
||||||
|
w.Unlock()
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncLogger provides concurrent safe logging for another Logger.
|
||||||
|
type syncLogger struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
logger Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncLogger returns a logger that synchronizes concurrent use of the
|
||||||
|
// wrapped logger. When multiple goroutines use the SyncLogger concurrently
|
||||||
|
// only one goroutine will be allowed to log to the wrapped logger at a time.
|
||||||
|
// The other goroutines will block until the logger is available.
|
||||||
|
func NewSyncLogger(logger Logger) Logger {
|
||||||
|
return &syncLogger{logger: logger}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log logs keyvals to the underlying Logger. If another log is already in
|
||||||
|
// progress, the calling goroutine blocks until the syncLogger is available.
|
||||||
|
func (l *syncLogger) Log(keyvals ...interface{}) error {
|
||||||
|
l.mu.Lock()
|
||||||
|
err := l.logger.Log(keyvals...)
|
||||||
|
l.mu.Unlock()
|
||||||
|
return err
|
||||||
|
}
|
110
vendor/github.com/go-kit/kit/log/value.go
generated
vendored
Normal file
110
vendor/github.com/go-kit/kit/log/value.go
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Valuer generates a log value. When passed to With or WithPrefix in a
|
||||||
|
// value element (odd indexes), it represents a dynamic value which is re-
|
||||||
|
// evaluated with each log event.
|
||||||
|
type Valuer func() interface{}
|
||||||
|
|
||||||
|
// bindValues replaces all value elements (odd indexes) containing a Valuer
|
||||||
|
// with their generated value.
|
||||||
|
func bindValues(keyvals []interface{}) {
|
||||||
|
for i := 1; i < len(keyvals); i += 2 {
|
||||||
|
if v, ok := keyvals[i].(Valuer); ok {
|
||||||
|
keyvals[i] = v()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// containsValuer returns true if any of the value elements (odd indexes)
|
||||||
|
// contain a Valuer.
|
||||||
|
func containsValuer(keyvals []interface{}) bool {
|
||||||
|
for i := 1; i < len(keyvals); i += 2 {
|
||||||
|
if _, ok := keyvals[i].(Valuer); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp returns a timestamp Valuer. It invokes the t function to get the
|
||||||
|
// time; unless you are doing something tricky, pass time.Now.
|
||||||
|
//
|
||||||
|
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
|
||||||
|
// are TimestampFormats that use the RFC3339Nano format.
|
||||||
|
func Timestamp(t func() time.Time) Valuer {
|
||||||
|
return func() interface{} { return t() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampFormat returns a timestamp Valuer with a custom time format. It
|
||||||
|
// invokes the t function to get the time to format; unless you are doing
|
||||||
|
// something tricky, pass time.Now. The layout string is passed to
|
||||||
|
// Time.Format.
|
||||||
|
//
|
||||||
|
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
|
||||||
|
// are TimestampFormats that use the RFC3339Nano format.
|
||||||
|
func TimestampFormat(t func() time.Time, layout string) Valuer {
|
||||||
|
return func() interface{} {
|
||||||
|
return timeFormat{
|
||||||
|
time: t(),
|
||||||
|
layout: layout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A timeFormat represents an instant in time and a layout used when
|
||||||
|
// marshaling to a text format.
|
||||||
|
type timeFormat struct {
|
||||||
|
time time.Time
|
||||||
|
layout string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tf timeFormat) String() string {
|
||||||
|
return tf.time.Format(tf.layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText implements encoding.TextMarshaller.
|
||||||
|
func (tf timeFormat) MarshalText() (text []byte, err error) {
|
||||||
|
// The following code adapted from the standard library time.Time.Format
|
||||||
|
// method. Using the same undocumented magic constant to extend the size
|
||||||
|
// of the buffer as seen there.
|
||||||
|
b := make([]byte, 0, len(tf.layout)+10)
|
||||||
|
b = tf.time.AppendFormat(b, tf.layout)
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caller returns a Valuer that returns a file and line from a specified depth
|
||||||
|
// in the callstack. Users will probably want to use DefaultCaller.
|
||||||
|
func Caller(depth int) Valuer {
|
||||||
|
return func() interface{} {
|
||||||
|
_, file, line, _ := runtime.Caller(depth)
|
||||||
|
idx := strings.LastIndexByte(file, '/')
|
||||||
|
// using idx+1 below handles both of following cases:
|
||||||
|
// idx == -1 because no "/" was found, or
|
||||||
|
// idx >= 0 and we want to start at the character after the found "/".
|
||||||
|
return file[idx+1:] + ":" + strconv.Itoa(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultTimestamp is a Valuer that returns the current wallclock time,
|
||||||
|
// respecting time zones, when bound.
|
||||||
|
DefaultTimestamp = TimestampFormat(time.Now, time.RFC3339Nano)
|
||||||
|
|
||||||
|
// DefaultTimestampUTC is a Valuer that returns the current time in UTC
|
||||||
|
// when bound.
|
||||||
|
DefaultTimestampUTC = TimestampFormat(
|
||||||
|
func() time.Time { return time.Now().UTC() },
|
||||||
|
time.RFC3339Nano,
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultCaller is a Valuer that returns the file and line where the Log
|
||||||
|
// method was invoked. It can only be used with log.With.
|
||||||
|
DefaultCaller = Caller(3)
|
||||||
|
)
|
4
vendor/github.com/go-logfmt/logfmt/.gitignore
generated
vendored
Normal file
4
vendor/github.com/go-logfmt/logfmt/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
_testdata/
|
||||||
|
_testdata2/
|
||||||
|
logfmt-fuzz.zip
|
||||||
|
logfmt.test.exe
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue