Skip to content

Commit 61416d4

Browse files
committed
Add integration test
1 parent 13327e4 commit 61416d4

File tree

8 files changed

+122
-29
lines changed

8 files changed

+122
-29
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
exporter/exporter
2-
2+
proc_exporter_integration_dummy
3+
dummyfile

cmd/exporter/exporter

3.9 KB
Binary file not shown.

cmd/exporter/flags/flags.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package flags
22

33
import "flag"
44

5-
func Parse(arguments []string) (namespace, binary, argName string) {
5+
func Parse(arguments []string) (namespace, binary, argName string, port int) {
66
flagSet := flag.NewFlagSet("flags", flag.ExitOnError)
77
namespacePtr := flagSet.String("namespace", "mine", "Prometheus metric namespace.")
88
binaryPtr := flagSet.String("binary", "", "Filter which processes to watch by binary name.")
9-
argNamePtr := flagSet.String("argname", "name", "Set Prometheus \"name\"-label value to value of this command line argument of the monitored processes.")
9+
nameFlagPtr := flagSet.String("nameflag", "name", "Set Prometheus \"name\"-label value to value of this command line argument of the monitored processes.")
10+
portPtr := flagSet.Int("port", 80, "Port on which to listen to requests to /metrics.")
1011
err := flagSet.Parse(arguments)
1112
if err != nil {
1213
panic(err)
1314
}
14-
return *namespacePtr, *binaryPtr, *argNamePtr
15+
return *namespacePtr, *binaryPtr, *nameFlagPtr, *portPtr
1516
}

cmd/exporter/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"fmt"
45
"log"
56
"net/http"
67
"os"
@@ -10,7 +11,7 @@ import (
1011
)
1112

1213
func main() {
13-
namespace, procBinaryName, argName := flags.Parse(os.Args[1:])
14-
http.Handle("/metrics", newHttpHandler(metrics.NewProcessMetricsSet(namespace, procBinaryName, argName)))
15-
log.Fatal(http.ListenAndServe(":8771", nil))
14+
namespace, procBinaryName, nameFlag, port := flags.Parse(os.Args[1:])
15+
http.Handle("/metrics", newHttpHandler(metrics.NewProcessMetricsSet(namespace, procBinaryName, nameFlag)))
16+
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
1617
}

cmd/exporter/metrics/metrics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"testing"
66

77
"github.com/mitchellh/go-ps"
8-
"github.com/setlog/libvirt_exporter/metrics"
8+
"github.com/setlog/process_exporter/cmd/exporter/metrics"
99
)
1010

1111
type proc struct {

cmd/exporter/metrics/prom_proc_metrics_set.go

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package metrics
22

33
import (
4-
"flag"
54
"fmt"
65
"path/filepath"
76

@@ -14,15 +13,15 @@ type ProcessMetricsSet struct {
1413
processMetrics map[int]*PrometheusProcessMetrics
1514
namespace string
1615
procBinaryName string
17-
procArgName string
16+
nameFlag string
1817
}
1918

20-
func NewProcessMetricsSet(namespace, procBinaryName, procArgName string) *ProcessMetricsSet {
19+
func NewProcessMetricsSet(namespace, procBinaryName, nameFlag string) *ProcessMetricsSet {
2120
return &ProcessMetricsSet{
2221
processMetrics: make(map[int]*PrometheusProcessMetrics),
2322
namespace: namespace,
2423
procBinaryName: procBinaryName,
25-
procArgName: procArgName,
24+
nameFlag: nameFlag,
2625
}
2726
}
2827

@@ -31,7 +30,7 @@ func (set *ProcessMetricsSet) UpdateMonitoredSet() {
3130
panic("called update on disposed ProcessMetricsSet")
3231
}
3332
processIds := findProcesses(set.procBinaryName)
34-
errs := AdjustMetricsMap(set.processMetrics, processIds, set.namespace)
33+
errs := AdjustMetricsMap(set.processMetrics, processIds, set.namespace, set.nameFlag)
3534
for _, err := range errs {
3635
log.Warn(fmt.Sprintf("Could not report metrics for process: %v.", err))
3736
}
@@ -52,7 +51,6 @@ func findProcesses(processName string) (pids map[int]ps.Process) {
5251
}
5352
for _, proc := range procs {
5453
name := proc.Executable()
55-
fmt.Println(name)
5654
if processName == "" || filepath.Base(name) == processName {
5755
pid := proc.Pid()
5856
pids[pid] = proc
@@ -61,10 +59,10 @@ func findProcesses(processName string) (pids map[int]ps.Process) {
6159
return pids
6260
}
6361

64-
func AdjustMetricsMap(metricMap map[int]*PrometheusProcessMetrics, pids map[int]ps.Process, metricNamespace string) (errs []error) {
62+
func AdjustMetricsMap(metricMap map[int]*PrometheusProcessMetrics, pids map[int]ps.Process, metricNamespace string, nameFlag string) (errs []error) {
6563
removePids, newPids := FindPidDifferences(metricMap, pids)
6664
for _, pid := range newPids {
67-
name, err := procDescriptiveName(pid)
65+
name, err := procDescriptiveName(pid, nameFlag)
6866
if err != nil {
6967
errs = append(errs, fmt.Errorf("failed to get descriptive process name for PID %d: %w", pid, err))
7068
continue
@@ -82,7 +80,7 @@ func AdjustMetricsMap(metricMap map[int]*PrometheusProcessMetrics, pids map[int]
8280
m := metricMap[pid]
8381
m.Unregister()
8482
delete(metricMap, pid)
85-
log.Infof("Stopped monitoring of process with PID %d.", pids[pid].Pid())
83+
log.Infof("Stopped monitoring of process with PID %d.", pid)
8684
}
8785
return errs
8886
}
@@ -116,7 +114,7 @@ func updateMetrics(pm *PrometheusProcessMetrics, withPid int) {
116114
pm.Set(processMetrics)
117115
}
118116

119-
func procDescriptiveName(pid int) (string, error) {
117+
func procDescriptiveName(pid int, nameFlag string) (string, error) {
120118
proc, err := process.NewProcess(int32(pid))
121119
if err != nil {
122120
return "", err
@@ -125,23 +123,25 @@ func procDescriptiveName(pid int) (string, error) {
125123
if err != nil {
126124
return "", err
127125
}
128-
return descriptiveNameFromArgs(args)
126+
return descriptiveNameFromArgs(args, nameFlag)
129127
}
130128

131-
func descriptiveNameFromArgs(args []string) (string, error) {
129+
func descriptiveNameFromArgs(args []string, flagName string) (string, error) {
132130
if len(args) <= 1 {
133131
return "", fmt.Errorf("too few arguments")
134132
}
135133
args = args[1:]
136-
flagSet := flag.NewFlagSet("", flag.ContinueOnError)
137-
flagSet.Usage = func() {}
138-
name := flagSet.String("name", "", "")
139-
err := flagSet.Parse(args)
140-
if err != nil {
141-
return "", err
134+
nextIsName := false
135+
for _, arg := range args {
136+
if nextIsName {
137+
return arg, nil
138+
}
139+
if arg == "-"+flagName || arg == "--"+flagName {
140+
nextIsName = true
141+
}
142142
}
143-
if *name == "" {
144-
return "", fmt.Errorf("name not found or empty")
143+
if nextIsName {
144+
return "", fmt.Errorf("no value for flag \"%s\" in args %v", flagName, args)
145145
}
146-
return *name, nil
146+
return "", fmt.Errorf("no flag \"%s\" in args %v", flagName, args)
147147
}

test/dummy/main.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
7+
)
8+
9+
const dummyFilePath = "dummyfile"
10+
11+
func main() {
12+
defer os.Remove(dummyFilePath)
13+
writeTestFile()
14+
fmt.Printf(".")
15+
ioutil.ReadAll(os.Stdin)
16+
}
17+
18+
func writeTestFile() {
19+
f, err := os.OpenFile(dummyFilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
20+
if err != nil {
21+
panic(err)
22+
}
23+
defer f.Close()
24+
f.WriteString("What a beautiful string") // 23 bytes
25+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package integration
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net/http"
7+
"os"
8+
"os/exec"
9+
"testing"
10+
)
11+
12+
func TestIntegration(t *testing.T) {
13+
const port = "8771"
14+
run("go", "build", "-o", "exporter", "github.com/setlog/process_exporter/cmd/exporter")
15+
defer os.Remove("exporter")
16+
run("go", "build", "-o", "proc_exporter_integration_dummy", "github.com/setlog/process_exporter/test/dummy")
17+
defer os.Remove("proc_exporter_integration_dummy")
18+
cmd := exec.Command("exporter", "-port", port, "-binary", "proc_exporter_integration_dummy")
19+
err := cmd.Start()
20+
if err != nil {
21+
panic(err)
22+
}
23+
cmdDummy := exec.Command("proc_exporter_integration_dummy", "-name", "iamdummy")
24+
dummyReader, err := cmdDummy.StdoutPipe()
25+
if err != nil {
26+
panic(err)
27+
}
28+
dummyWriter, err := cmdDummy.StdinPipe()
29+
if err != nil {
30+
panic(err)
31+
}
32+
err = cmdDummy.Start()
33+
if err != nil {
34+
panic(err)
35+
}
36+
b := make([]byte, 1, 1)
37+
_, err = io.ReadAtLeast(dummyReader, b, 1)
38+
if err != nil {
39+
panic(err)
40+
}
41+
resp, err := http.Get("http://localhost:" + port)
42+
if err != nil {
43+
panic(err)
44+
}
45+
if resp.StatusCode != http.StatusOK {
46+
panic(fmt.Sprintf("got code %d when %d expected", resp.StatusCode, http.StatusOK))
47+
}
48+
err = dummyWriter.Close()
49+
if err != nil {
50+
panic(err)
51+
}
52+
err = cmdDummy.Wait()
53+
if err != nil {
54+
panic(err)
55+
}
56+
57+
}
58+
59+
func run(command string, args ...string) {
60+
cmd := exec.Command(command, args...)
61+
err := cmd.Run()
62+
if err != nil {
63+
panic(err)
64+
}
65+
}

0 commit comments

Comments
 (0)