Skip to content

Commit

Permalink
Add -debug command line option.
Browse files Browse the repository at this point in the history
  • Loading branch information
ncabatoff committed Aug 12, 2018
1 parent af8a1e3 commit c16c837
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 42 deletions.
26 changes: 22 additions & 4 deletions cmd/process-exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ type (
}
)

func (nmr *nameMapperRegex) String() string {
return fmt.Sprintf("%+v", nmr.mapping)
}

// Create a nameMapperRegex based on a string given as the -namemapper argument.
func parseNameMapper(s string) (*nameMapperRegex, error) {
mapper := make(map[string]*prefixRegex)
Expand Down Expand Up @@ -290,6 +294,8 @@ func main() {
"path to YAML config file")
recheck = flag.Bool("recheck", false,
"recheck process names on each scrape")
debug = flag.Bool("debug", false,
"log debugging information to stdout")
)
flag.Parse()

Expand All @@ -305,12 +311,15 @@ func main() {
log.Fatalf("-config.path cannot be used with -namemapping or -procnames")
}

cfg, err := config.ReadFile(*configPath)
cfg, err := config.ReadFile(*configPath, *debug)
if err != nil {
log.Fatalf("error reading config file %q: %v", *configPath, err)
}
log.Printf("Reading metrics from %s based on %q", *procfsPath, *configPath)
matchnamer = cfg.MatchNamers
if *debug {
log.Printf("using config matchnamer: %v", cfg.MatchNamers)
}
} else {
namemapper, err := parseNameMapper(*nameMapping)
if err != nil {
Expand All @@ -328,10 +337,13 @@ func main() {
}

log.Printf("Reading metrics from %s for procnames: %v", *procfsPath, names)
if *debug {
log.Printf("using cmdline matchnamer: %v", namemapper)
}
matchnamer = namemapper
}

pc, err := NewProcessCollector(*procfsPath, *children, *threads, matchnamer, *recheck)
pc, err := NewProcessCollector(*procfsPath, *children, *threads, matchnamer, *recheck, *debug)
if err != nil {
log.Fatalf("Error initializing: %v", err)
}
Expand Down Expand Up @@ -378,6 +390,7 @@ type (
scrapeErrors int
scrapeProcReadErrors int
scrapePartialErrors int
debug bool
}
)

Expand All @@ -387,20 +400,25 @@ func NewProcessCollector(
threads bool,
n common.MatchNamer,
recheck bool,
debug bool,
) (*NamedProcessCollector, error) {
fs, err := proc.NewFS(procfsPath)
fs, err := proc.NewFS(procfsPath, debug)
if err != nil {
return nil, err
}
p := &NamedProcessCollector{
scrapeChan: make(chan scrapeRequest),
Grouper: proc.NewGrouper(n, children, threads, recheck),
Grouper: proc.NewGrouper(n, children, threads, recheck, debug),
source: fs,
threads: threads,
debug: debug,
}

colErrs, _, err := p.Update(p.source.AllProcs())
if err != nil {
if debug {
log.Print(err)
}
return nil, err
}
p.scrapePartialErrors += colErrs.Partial
Expand Down
3 changes: 3 additions & 0 deletions common.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package common

import "fmt"

type (
ProcAttributes struct {
Name string
Expand All @@ -11,5 +13,6 @@ type (
// MatchAndName returns false if the match failed, otherwise
// true and the resulting name.
MatchAndName(ProcAttributes) (bool, string)
fmt.Stringer
}
)
48 changes: 40 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io/ioutil"
"log"
"path/filepath"
"regexp"
"strings"
Expand All @@ -19,8 +20,11 @@ type (
Match(common.ProcAttributes) bool
}

FirstMatcher []common.MatchNamer
Config struct {
FirstMatcher struct {
matchers []common.MatchNamer
}

Config struct {
MatchNamers FirstMatcher
}

Expand Down Expand Up @@ -57,15 +61,40 @@ type (
}
)

func (c *cmdlineMatcher) String() string {
return fmt.Sprintf("cmdlines: %+v", c.regexes)

}

func (e *exeMatcher) String() string {
return fmt.Sprintf("exes: %+v", e.exes)
}

func (c *commMatcher) String() string {
var comms = make([]string, 0, len(c.comms))
for cm := range c.comms {
comms = append(comms, cm)
}
return fmt.Sprintf("comms: %+v", comms)
}

func (f FirstMatcher) String() string {
return fmt.Sprintf("%v", f.matchers)
}

func (f FirstMatcher) MatchAndName(nacl common.ProcAttributes) (bool, string) {
for _, m := range f {
for _, m := range f.matchers {
if matched, name := m.MatchAndName(nacl); matched {
return true, name
}
}
return false, ""
}

func (m *matchNamer) String() string {
return fmt.Sprintf("%+v", m.andMatcher)
}

func (m *matchNamer) MatchAndName(nacl common.ProcAttributes) (bool, string) {
if !m.Match(nacl) {
return false, ""
Expand Down Expand Up @@ -146,16 +175,19 @@ func (m andMatcher) Match(nacl common.ProcAttributes) bool {
}

// ReadRecipesFile opens the named file and extracts recipes from it.
func ReadFile(cfgpath string) (*Config, error) {
func ReadFile(cfgpath string, debug bool) (*Config, error) {
content, err := ioutil.ReadFile(cfgpath)
if err != nil {
return nil, err
return nil, fmt.Errorf("error reading config file %q: %v", cfgpath, err)
}
if debug {
log.Printf("Config file %q contents:\n%s", cfgpath, content)
}
return GetConfig(string(content))
return GetConfig(string(content), debug)
}

// GetConfig extracts Config from content by parsing it as YAML.
func GetConfig(content string) (*Config, error) {
func GetConfig(content string, debug bool) (*Config, error) {
var yamldata map[string]interface{}

err := yaml.Unmarshal([]byte(content), &yamldata)
Expand All @@ -177,7 +209,7 @@ func GetConfig(content string) (*Config, error) {
if err != nil {
return nil, fmt.Errorf("unable to parse process_name entry %d: %v", i, err)
}
cfg.MatchNamers = append(cfg.MatchNamers, mn)
cfg.MatchNamers.matchers = append(cfg.MatchNamers.matchers, mn)
}

return &cfg, nil
Expand Down
30 changes: 15 additions & 15 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,35 @@ process_names:
- exe:
- /bin/ksh
`
cfg, err := GetConfig(yml)
cfg, err := GetConfig(yml, false)
c.Assert(err, IsNil)
c.Check(cfg.MatchNamers, HasLen, 3)
c.Check(cfg.MatchNamers.matchers, HasLen, 3)

bash := common.ProcAttributes{Name: "bash", Cmdline: []string{"/bin/bash"}}
sh := common.ProcAttributes{Name: "sh", Cmdline: []string{"sh"}}
ksh := common.ProcAttributes{Name: "ksh", Cmdline: []string{"/bin/ksh"}}

found, name := cfg.MatchNamers[0].MatchAndName(bash)
found, name := cfg.MatchNamers.matchers[0].MatchAndName(bash)
c.Check(found, Equals, true)
c.Check(name, Equals, "bash")
found, name = cfg.MatchNamers[0].MatchAndName(sh)
found, name = cfg.MatchNamers.matchers[0].MatchAndName(sh)
c.Check(found, Equals, false)
found, name = cfg.MatchNamers[0].MatchAndName(ksh)
found, name = cfg.MatchNamers.matchers[0].MatchAndName(ksh)
c.Check(found, Equals, false)

found, name = cfg.MatchNamers[1].MatchAndName(bash)
found, name = cfg.MatchNamers.matchers[1].MatchAndName(bash)
c.Check(found, Equals, false)
found, name = cfg.MatchNamers[1].MatchAndName(sh)
found, name = cfg.MatchNamers.matchers[1].MatchAndName(sh)
c.Check(found, Equals, true)
c.Check(name, Equals, "sh")
found, name = cfg.MatchNamers[1].MatchAndName(ksh)
found, name = cfg.MatchNamers.matchers[1].MatchAndName(ksh)
c.Check(found, Equals, false)

found, name = cfg.MatchNamers[2].MatchAndName(bash)
found, name = cfg.MatchNamers.matchers[2].MatchAndName(bash)
c.Check(found, Equals, false)
found, name = cfg.MatchNamers[2].MatchAndName(sh)
found, name = cfg.MatchNamers.matchers[2].MatchAndName(sh)
c.Check(found, Equals, false)
found, name = cfg.MatchNamers[2].MatchAndName(ksh)
found, name = cfg.MatchNamers.matchers[2].MatchAndName(ksh)
c.Check(found, Equals, true)
c.Check(name, Equals, "ksh")
}
Expand All @@ -61,17 +61,17 @@ process_names:
- prometheus
name: "{{.ExeFull}}"
`
cfg, err := GetConfig(yml)
cfg, err := GetConfig(yml, false)
c.Assert(err, IsNil)
c.Check(cfg.MatchNamers, HasLen, 2)
c.Check(cfg.MatchNamers.matchers, HasLen, 2)

postgres := common.ProcAttributes{Name: "postmaster", Cmdline: []string{"/usr/bin/postmaster", "-D", "/data/pg"}}
found, name := cfg.MatchNamers[0].MatchAndName(postgres)
found, name := cfg.MatchNamers.matchers[0].MatchAndName(postgres)
c.Check(found, Equals, true)
c.Check(name, Equals, "postmaster:pg")

pm := common.ProcAttributes{Name: "prometheus", Cmdline: []string{"/usr/local/bin/prometheus"}}
found, name = cfg.MatchNamers[1].MatchAndName(pm)
found, name = cfg.MatchNamers.matchers[1].MatchAndName(pm)
c.Check(found, Equals, true)
c.Check(name, Equals, "/usr/local/bin/prometheus")
}
9 changes: 9 additions & 0 deletions proc/base_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package proc

import (
"fmt"
"time"

common "github.com/ncabatoff/process-exporter"
Expand Down Expand Up @@ -47,6 +48,14 @@ func newNamer(names ...string) namer {
return nr
}

func (n namer) String() string {
var ss = make([]string, 0, len(n))
for s := range n {
ss = append(ss, s)
}
return fmt.Sprintf("%v", ss)
}

func (n namer) MatchAndName(nacl common.ProcAttributes) (bool, string) {
if _, ok := n[nacl.Name]; ok {
return true, nacl.Name
Expand Down
6 changes: 4 additions & 2 deletions proc/grouper.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type (
groupAccum map[string]Counts
tracker *Tracker
threadAccum map[string]map[string]Threads
debug bool
}

// GroupByName maps group name to group metrics.
Expand Down Expand Up @@ -47,11 +48,12 @@ type (
func lessThreads(x, y Threads) bool { return seq.Compare(x, y) < 0 }

// NewGrouper creates a grouper.
func NewGrouper(namer common.MatchNamer, trackChildren, trackThreads, alwaysRecheck bool) *Grouper {
func NewGrouper(namer common.MatchNamer, trackChildren, trackThreads, alwaysRecheck, debug bool) *Grouper {
g := Grouper{
groupAccum: make(map[string]Counts),
threadAccum: make(map[string]map[string]Threads),
tracker: NewTracker(namer, trackChildren, trackThreads, alwaysRecheck),
tracker: NewTracker(namer, trackChildren, trackThreads, alwaysRecheck, debug),
debug: debug,
}
return &g
}
Expand Down
8 changes: 4 additions & 4 deletions proc/grouper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestGrouperBasic(t *testing.T) {
},
}

gr := NewGrouper(newNamer(n1, n2), false, false, false)
gr := NewGrouper(newNamer(n1, n2), false, false, false, false)
for i, tc := range tests {
got := rungroup(t, gr, procInfoIter(tc.procs...))
if diff := cmp.Diff(got, tc.want); diff != "" {
Expand Down Expand Up @@ -128,7 +128,7 @@ func TestGrouperProcJoin(t *testing.T) {
},
}

gr := NewGrouper(newNamer(n1), false, false, false)
gr := NewGrouper(newNamer(n1), false, false, false, false)
for i, tc := range tests {
got := rungroup(t, gr, procInfoIter(tc.procs...))
if diff := cmp.Diff(got, tc.want); diff != "" {
Expand Down Expand Up @@ -171,7 +171,7 @@ func TestGrouperNonDecreasing(t *testing.T) {
},
}

gr := NewGrouper(newNamer(n1), false, false, false)
gr := NewGrouper(newNamer(n1), false, false, false, false)
for i, tc := range tests {
got := rungroup(t, gr, procInfoIter(tc.procs...))
if diff := cmp.Diff(got, tc.want); diff != "" {
Expand Down Expand Up @@ -224,7 +224,7 @@ func TestGrouperThreads(t *testing.T) {
}

opts := cmpopts.SortSlices(lessThreads)
gr := NewGrouper(newNamer(n), false, true, false)
gr := NewGrouper(newNamer(n), false, true, false, false)
for i, tc := range tests {
got := rungroup(t, gr, procInfoIter(tc.proc))
if diff := cmp.Diff(got, tc.want, opts); diff != "" {
Expand Down
11 changes: 8 additions & 3 deletions proc/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,14 @@ type (
procfs.FS
BootTime uint64
MountPoint string
debug bool
}
)

func (ii IDInfo) String() string {
return fmt.Sprintf("%+v:%+v", ii.ID, ii.Static)
}

// Add adds c2 to the counts.
func (c *Counts) Add(c2 Delta) {
c.CPUUserTime += c2.CPUUserTime
Expand Down Expand Up @@ -501,7 +506,7 @@ const userHZ = 100

// NewFS returns a new FS mounted under the given mountPoint. It will error
// if the mount point can't be read.
func NewFS(mountPoint string) (*FS, error) {
func NewFS(mountPoint string, debug bool) (*FS, error) {
fs, err := procfs.NewFS(mountPoint)
if err != nil {
return nil, err
Expand All @@ -510,7 +515,7 @@ func NewFS(mountPoint string) (*FS, error) {
if err != nil {
return nil, err
}
return &FS{fs, stat.BootTime, mountPoint}, nil
return &FS{fs, stat.BootTime, mountPoint, debug}, nil
}

func (fs *FS) threadFs(pid int) (*FS, error) {
Expand All @@ -519,7 +524,7 @@ func (fs *FS) threadFs(pid int) (*FS, error) {
if err != nil {
return nil, err
}
return &FS{tfs, fs.BootTime, mountPoint}, nil
return &FS{tfs, fs.BootTime, mountPoint, false}, nil
}

// AllProcs implements Source.
Expand Down
Loading

0 comments on commit c16c837

Please sign in to comment.