Path: blob/main/pkg/integrations/node_exporter/config.go
5304 views
package node_exporter //nolint:golint12import (3"fmt"4"os"5"runtime"6"strings"7"time"89"github.com/go-kit/log"10"github.com/grafana/agent/pkg/integrations"11integrations_v2 "github.com/grafana/agent/pkg/integrations/v2"12"github.com/grafana/agent/pkg/integrations/v2/metricsutils"13"github.com/grafana/dskit/flagext"14"github.com/prometheus/procfs"15"gopkg.in/alecthomas/kingpin.v2"16)1718var (19// DefaultConfig holds non-zero default options for the Config when it is20// unmarshaled from YAML.21//22// DefaultConfig's defaults are populated from init functions in this package.23// See the init function here and in node_exporter_linux.go.24DefaultConfig = Config{25ProcFSPath: procfs.DefaultMountPoint,26RootFSPath: "/",2728DiskStatsDeviceExclude: "^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$",2930EthtoolMetricsInclude: ".*",3132FilesystemMountTimeout: 5 * time.Second,3334NTPIPTTL: 1,35NTPLocalOffsetTolerance: time.Millisecond,36NTPMaxDistance: time.Microsecond * 3466080,37NTPProtocolVersion: 4,38NTPServer: "127.0.0.1",3940NetclassIgnoredDevices: "^$",41NetstatFields: "^(.*_(InErrors|InErrs)|Ip_Forwarding|Ip(6|Ext)_(InOctets|OutOctets)|Icmp6?_(InMsgs|OutMsgs)|TcpExt_(Listen.*|Syncookies.*|TCPSynRetrans|TCPTimeouts)|Tcp_(ActiveOpens|InSegs|OutSegs|OutRsts|PassiveOpens|RetransSegs|CurrEstab)|Udp6?_(InDatagrams|OutDatagrams|NoPorts|RcvbufErrors|SndbufErrors))$",4243PowersupplyIgnoredSupplies: "^$",4445RunitServiceDir: "/etc/service",4647SupervisordURL: "http://localhost:9001/RPC2",4849SystemdUnitExclude: ".+\\.(automount|device|mount|scope|slice)",50SystemdUnitInclude: ".+",5152TapestatsIgnoredDevices: "^$",5354VMStatFields: "^(oom_kill|pgpg|pswp|pg.*fault).*",55}56)5758func init() {59// The default values for the filesystem collector are to ignore everything,60// but some platforms have specific defaults. We'll fill these in below at61// initialization time, but the values can still be overridden via the config62// file.63switch runtime.GOOS {64case "linux":65DefaultConfig.FilesystemMountPointsExclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"66DefaultConfig.FilesystemFSTypesExclude = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"67case "darwin":68DefaultConfig.FilesystemMountPointsExclude = "^/(dev)($|/)"69DefaultConfig.FilesystemFSTypesExclude = "^(autofs|devfs)$"70case "freebsd", "netbsd", "openbsd":71DefaultConfig.FilesystemMountPointsExclude = "^/(dev)($|/)"72DefaultConfig.FilesystemFSTypesExclude = "^devfs$"73}7475if url := os.Getenv("SUPERVISORD_URL"); url != "" {76DefaultConfig.SupervisordURL = url77}78}7980// Config controls the node_exporter integration.81type Config struct {82IncludeExporterMetrics bool `yaml:"include_exporter_metrics,omitempty"`8384ProcFSPath string `yaml:"procfs_path,omitempty"`85SysFSPath string `yaml:"sysfs_path,omitempty"`86RootFSPath string `yaml:"rootfs_path,omitempty"`8788// Collectors to mark as enabled89EnableCollectors flagext.StringSlice `yaml:"enable_collectors,omitempty"`9091// Collectors to mark as disabled92DisableCollectors flagext.StringSlice `yaml:"disable_collectors,omitempty"`9394// Overrides the default set of enabled collectors with the collectors95// listed.96SetCollectors flagext.StringSlice `yaml:"set_collectors,omitempty"`9798// Collector-specific config options99BcachePriorityStats bool `yaml:"enable_bcache_priority_stats,omitempty"`100CPUBugsInclude string `yaml:"cpu_bugs_include,omitempty"`101CPUEnableCPUGuest bool `yaml:"enable_cpu_guest_seconds_metric,omitempty"`102CPUEnableCPUInfo bool `yaml:"enable_cpu_info_metric,omitempty"`103CPUFlagsInclude string `yaml:"cpu_flags_include,omitempty"`104DiskStatsDeviceExclude string `yaml:"diskstats_device_exclude,omitempty"`105DiskStatsDeviceInclude string `yaml:"diskstats_device_include,omitempty"`106EthtoolDeviceExclude string `yaml:"ethtool_device_exclude,omitempty"`107EthtoolDeviceInclude string `yaml:"ethtool_device_include,omitempty"`108EthtoolMetricsInclude string `yaml:"ethtool_metrics_include,omitempty"`109FilesystemFSTypesExclude string `yaml:"filesystem_fs_types_exclude,omitempty"`110FilesystemMountPointsExclude string `yaml:"filesystem_mount_points_exclude,omitempty"`111FilesystemMountTimeout time.Duration `yaml:"filesystem_mount_timeout,omitempty"`112IPVSBackendLabels []string `yaml:"ipvs_backend_labels,omitempty"`113NTPIPTTL int `yaml:"ntp_ip_ttl,omitempty"`114NTPLocalOffsetTolerance time.Duration `yaml:"ntp_local_offset_tolerance,omitempty"`115NTPMaxDistance time.Duration `yaml:"ntp_max_distance,omitempty"`116NTPProtocolVersion int `yaml:"ntp_protocol_version,omitempty"`117NTPServer string `yaml:"ntp_server,omitempty"`118NTPServerIsLocal bool `yaml:"ntp_server_is_local,omitempty"`119NetclassIgnoreInvalidSpeedDevice bool `yaml:"netclass_ignore_invalid_speed_device,omitempty"`120NetclassIgnoredDevices string `yaml:"netclass_ignored_devices,omitempty"`121NetdevAddressInfo bool `yaml:"netdev_address_info,omitempty"`122NetdevDeviceExclude string `yaml:"netdev_device_exclude,omitempty"`123NetdevDeviceInclude string `yaml:"netdev_device_include,omitempty"`124NetstatFields string `yaml:"netstat_fields,omitempty"`125PerfCPUS string `yaml:"perf_cpus,omitempty"`126PerfTracepoint flagext.StringSlice `yaml:"perf_tracepoint,omitempty"`127PowersupplyIgnoredSupplies string `yaml:"powersupply_ignored_supplies,omitempty"`128RunitServiceDir string `yaml:"runit_service_dir,omitempty"`129SupervisordURL string `yaml:"supervisord_url,omitempty"`130SysctlInclude flagext.StringSlice `yaml:"sysctl_include,omitempty"`131SysctlIncludeInfo flagext.StringSlice `yaml:"sysctl_include_info,omitempty"`132SystemdEnableRestartsMetrics bool `yaml:"systemd_enable_restarts_metrics,omitempty"`133SystemdEnableStartTimeMetrics bool `yaml:"systemd_enable_start_time_metrics,omitempty"`134SystemdEnableTaskMetrics bool `yaml:"systemd_enable_task_metrics,omitempty"`135SystemdUnitExclude string `yaml:"systemd_unit_exclude,omitempty"`136SystemdUnitInclude string `yaml:"systemd_unit_include,omitempty"`137TapestatsIgnoredDevices string `yaml:"tapestats_ignored_devices,omitempty"`138TextfileDirectory string `yaml:"textfile_directory,omitempty"`139VMStatFields string `yaml:"vmstat_fields,omitempty"`140141UnmarshalWarnings []string `yaml:"-"`142}143144// UnmarshalYAML implements yaml.Unmarshaler for Config.145func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {146*c = DefaultConfig147148type baseConfig Config149type config struct {150baseConfig `yaml:",inline"`151152// Deprecated field names:153NetdevDeviceWhitelist string `yaml:"netdev_device_whitelist,omitempty"`154NetdevDeviceBlacklist string `yaml:"netdev_device_blacklist,omitempty"`155SystemdUnitWhitelist string `yaml:"systemd_unit_whitelist,omitempty"`156SystemdUnitBlacklist string `yaml:"systemd_unit_blacklist,omitempty"`157FilesystemIgnoredMountPoints string `yaml:"filesystem_ignored_mount_points,omitempty"`158FilesystemIgnoredFSTypes string `yaml:"filesystem_ignored_fs_types,omitempty"`159DiskStatsIgnoredDevices string `yaml:"diskstats_ignored_devices,omitempty"`160}161162var fc config // our full config (schema + deprecated names)163fc.baseConfig = baseConfig(*c)164165type migratedField struct {166OldName, NewName string167OldValue, NewValue *string168169defaultValue string170}171migratedFields := []*migratedField{172{173OldName: "netdev_device_whitelist", NewName: "netdev_device_include",174OldValue: &fc.NetdevDeviceWhitelist, NewValue: &fc.NetdevDeviceInclude,175},176{177OldName: "netdev_device_blacklist", NewName: "netdev_device_exclude",178OldValue: &fc.NetdevDeviceBlacklist, NewValue: &fc.NetdevDeviceExclude,179},180{181OldName: "systemd_unit_whitelist", NewName: "systemd_unit_include",182OldValue: &fc.SystemdUnitWhitelist, NewValue: &fc.SystemdUnitInclude,183},184{185OldName: "systemd_unit_blacklist", NewName: "systemd_unit_exclude",186OldValue: &fc.SystemdUnitBlacklist, NewValue: &fc.SystemdUnitExclude,187},188{189OldName: "filesystem_ignored_mount_points", NewName: "filesystem_mount_points_exclude",190OldValue: &fc.FilesystemIgnoredMountPoints, NewValue: &fc.FilesystemMountPointsExclude,191},192{193OldName: "filesystem_ignored_fs_types", NewName: "filesystem_fs_types_exclude",194OldValue: &fc.FilesystemIgnoredFSTypes, NewValue: &fc.FilesystemFSTypesExclude,195},196{197OldName: "diskstats_ignored_devices", NewName: "diskstats_device_exclude",198OldValue: &fc.DiskStatsIgnoredDevices, NewValue: &fc.DiskStatsDeviceExclude,199},200}201202// We don't know when fields are unmarshaled unless they have non-zero203// values. Defaults stop us from being able to check, so we'll temporarily204// cache the default and make sure both the old and new migrated fields are205// zero.206for _, mf := range migratedFields {207mf.defaultValue = *mf.NewValue208*mf.NewValue = ""209}210211if err := unmarshal(&fc); err != nil {212return err213}214215for _, mf := range migratedFields {216switch {217case *mf.OldValue != "" && *mf.NewValue != "": // New set, old set218return fmt.Errorf("only one of %q and %q may be specified", mf.OldName, mf.NewName)219220case *mf.NewValue == "" && *mf.OldValue != "": // New unset, old set221*mf.NewValue = *mf.OldValue222223warning := fmt.Sprintf("%q is deprecated by %q and will be removed in a future version", mf.OldName, mf.NewName)224fc.UnmarshalWarnings = append(fc.UnmarshalWarnings, warning)225226case *mf.NewValue == "" && *mf.OldValue == "": // Neither set.227// Copy the default back to mf.NewValue.228*mf.NewValue = mf.defaultValue229230case *mf.NewValue != "" && *mf.OldValue == "": // New set, old unset231// Nothing to do232}233}234235*c = (Config)(fc.baseConfig)236return nil237}238239// Name returns the name of the integration that this config represents.240func (c *Config) Name() string {241return "node_exporter"242}243244// InstanceKey returns the hostname:port of the agent process.245func (c *Config) InstanceKey(agentKey string) (string, error) {246return agentKey, nil247}248249// NewIntegration converts this config into an instance of an integration.250func (c *Config) NewIntegration(l log.Logger) (integrations.Integration, error) {251return New(l, c)252}253254func init() {255integrations.RegisterIntegration(&Config{})256integrations_v2.RegisterLegacy(&Config{}, integrations_v2.TypeSingleton, metricsutils.Shim)257}258259// MapConfigToNodeExporterFlags takes in a node_exporter Config and converts260// it to the set of flags that node_exporter usually expects when running as a261// separate binary.262func MapConfigToNodeExporterFlags(c *Config) (accepted []string, ignored []string) {263collectors := make(map[string]CollectorState, len(Collectors))264for k, v := range Collectors {265collectors[k] = v266}267268// Override the set of defaults with the provided set of collectors if269// set_collectors has at least one element in it.270if len(c.SetCollectors) != 0 {271customDefaults := map[string]struct{}{}272for _, c := range c.SetCollectors {273customDefaults[c] = struct{}{}274}275276for k := range collectors {277_, shouldEnable := customDefaults[k]278if shouldEnable {279collectors[k] = CollectorStateEnabled280} else {281collectors[k] = CollectorStateDisabled282}283}284}285286// Explicitly disable/enable specific collectors287for _, c := range c.DisableCollectors {288collectors[c] = CollectorStateDisabled289}290for _, c := range c.EnableCollectors {291collectors[c] = CollectorStateEnabled292}293294DisableUnavailableCollectors(collectors)295296var flags flags297flags.accepted = append(flags.accepted, MapCollectorsToFlags(collectors)...)298299flags.add(300"--path.procfs", c.ProcFSPath,301"--path.sysfs", c.SysFSPath,302"--path.rootfs", c.RootFSPath,303)304305if collectors[CollectorBCache] {306flags.addBools(map[*bool]string{307&c.BcachePriorityStats: "collector.bcache.priorityStats",308})309}310311if collectors[CollectorCPU] {312flags.addBools(map[*bool]string{313&c.CPUEnableCPUGuest: "collector.cpu.guest",314&c.CPUEnableCPUInfo: "collector.cpu.info",315})316flags.add("--collector.cpu.info.flags-include", c.CPUFlagsInclude)317flags.add("--collector.cpu.info.bugs-include", c.CPUBugsInclude)318}319320if collectors[CollectorDiskstats] {321if c.DiskStatsDeviceInclude != "" {322flags.add("--collector.diskstats.device-include", c.DiskStatsDeviceInclude)323} else {324flags.add("--collector.diskstats.device-exclude", c.DiskStatsDeviceExclude)325}326}327328if collectors[CollectorEthtool] {329flags.add("--collector.ethtool.device-include", c.EthtoolDeviceInclude)330flags.add("--collector.ethtool.device-exclude", c.EthtoolDeviceExclude)331flags.add("--collector.ethtool.metrics-include", c.EthtoolMetricsInclude)332}333334if collectors[CollectorFilesystem] {335flags.add(336"--collector.filesystem.mount-timeout", c.FilesystemMountTimeout.String(),337"--collector.filesystem.mount-points-exclude", c.FilesystemMountPointsExclude,338"--collector.filesystem.fs-types-exclude", c.FilesystemFSTypesExclude,339)340}341342if collectors[CollectorIPVS] {343flags.add("--collector.ipvs.backend-labels", strings.Join(c.IPVSBackendLabels, ","))344}345346if collectors[CollectorNetclass] {347flags.addBools(map[*bool]string{348&c.NetclassIgnoreInvalidSpeedDevice: "collector.netclass.ignore-invalid-speed",349})350351flags.add("--collector.netclass.ignored-devices", c.NetclassIgnoredDevices)352}353354if collectors[CollectorNetdev] {355flags.addBools(map[*bool]string{356&c.NetdevAddressInfo: "collector.netdev.address-info",357})358359flags.add(360"--collector.netdev.device-include", c.NetdevDeviceInclude,361"--collector.netdev.device-exclude", c.NetdevDeviceExclude,362)363}364365if collectors[CollectorNetstat] {366flags.add("--collector.netstat.fields", c.NetstatFields)367}368369if collectors[CollectorNTP] {370flags.add(371"--collector.ntp.server", c.NTPServer,372"--collector.ntp.protocol-version", fmt.Sprintf("%d", c.NTPProtocolVersion),373"--collector.ntp.ip-ttl", fmt.Sprintf("%d", c.NTPIPTTL),374"--collector.ntp.max-distance", c.NTPMaxDistance.String(),375"--collector.ntp.local-offset-tolerance", c.NTPLocalOffsetTolerance.String(),376)377378flags.addBools(map[*bool]string{379&c.NTPServerIsLocal: "collector.ntp.server-is-local",380})381}382383if collectors[CollectorPerf] {384flags.add("--collector.perf.cpus", c.PerfCPUS)385386for _, tp := range c.PerfTracepoint {387flags.add("--collector.perf.tracepoint", tp)388}389}390391if collectors[CollectorPowersuppply] {392flags.add("--collector.powersupply.ignored-supplies", c.PowersupplyIgnoredSupplies)393}394395if collectors[CollectorRunit] {396flags.add("--collector.runit.servicedir", c.RunitServiceDir)397}398399if collectors[CollectorSupervisord] {400flags.add("--collector.supervisord.url", c.SupervisordURL)401}402403if collectors[CollectorSysctl] {404for _, numValue := range c.SysctlInclude {405flags.add("--collector.sysctl.include", numValue)406}407408for _, stringValue := range c.SysctlIncludeInfo {409flags.add("--collector.sysctl.include-info", stringValue)410}411}412413if collectors[CollectorSystemd] {414flags.add(415"--collector.systemd.unit-include", c.SystemdUnitInclude,416"--collector.systemd.unit-exclude", c.SystemdUnitExclude,417)418419flags.addBools(map[*bool]string{420&c.SystemdEnableTaskMetrics: "collector.systemd.enable-task-metrics",421&c.SystemdEnableRestartsMetrics: "collector.systemd.enable-restarts-metrics",422&c.SystemdEnableStartTimeMetrics: "collector.systemd.enable-start-time-metrics",423})424}425426if collectors[CollectorTapestats] {427flags.add("--collector.tapestats.ignored-devices", c.TapestatsIgnoredDevices)428}429430if collectors[CollectorTextfile] {431flags.add("--collector.textfile.directory", c.TextfileDirectory)432}433434if collectors[CollectorVMStat] {435flags.add("--collector.vmstat.fields", c.VMStatFields)436}437438return flags.accepted, flags.ignored439}440441type flags struct {442accepted []string443ignored []string444}445446// add pushes new flags as key value pairs. If the flag isn't registered with kingpin,447// it will be ignored.448func (f *flags) add(kvp ...string) {449if (len(kvp) % 2) != 0 {450panic("missing value for added flag")451}452453for i := 0; i < len(kvp); i += 2 {454key := kvp[i+0]455value := kvp[i+1]456457rawFlag := strings.TrimPrefix(key, "--")458if kingpin.CommandLine.GetFlag(rawFlag) == nil {459f.ignored = append(f.ignored, rawFlag)460continue461}462463f.accepted = append(f.accepted, key, value)464}465}466467func (f *flags) addBools(m map[*bool]string) {468for setting, key := range m {469// The flag might not exist on this platform, so skip it if it's not470// defined.471if kingpin.CommandLine.GetFlag(key) == nil {472f.ignored = append(f.ignored, key)473continue474}475476if *setting {477f.accepted = append(f.accepted, "--"+key)478} else {479f.accepted = append(f.accepted, "--no-"+key)480}481}482}483484485