Skip to content

Commit add6712

Browse files
committed
process metrics linux: better performance + tests
rebased on master (v1.35.2 -> v1.40.2)
1 parent 58ce999 commit add6712

12 files changed

+599
-229
lines changed

process_metrics_linux.go

Lines changed: 297 additions & 174 deletions
Large diffs are not rendered by default.

process_metrics_linux_test.go

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,108 @@
11
package metrics
22

3-
import "testing"
4-
5-
func TestGetMaxFilesLimit(t *testing.T) {
6-
f := func(want uint64, path string, wantErr bool) {
7-
t.Helper()
8-
got, err := getMaxFilesLimit(path)
9-
if err != nil && !wantErr {
10-
t.Fatalf("unexpected error: %v", err)
11-
}
12-
if got != want {
13-
t.Fatalf("unexpected result: %d, want: %d at getMaxFilesLimit", got, want)
14-
}
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"os"
8+
"regexp"
9+
"strings"
10+
"testing"
11+
)
1512

13+
var testdir string
14+
15+
func init() {
16+
testdir, _ = os.Getwd()
17+
testdir += "/testdata/"
18+
}
19+
20+
func getTestData(filename string, t *testing.T) string {
21+
data, err := os.ReadFile(testdir + filename)
22+
if err != nil {
23+
t.Fatalf("%v", err)
24+
}
25+
s := string(data)
26+
if filename == "linux.proc_metrics.out" {
27+
// since linux stat.starttime is relative to boot, we need to adjust
28+
// the expected results regarding this.
29+
m := regexp.MustCompile("process_start_time_seconds [0-9]+")
30+
n := fmt.Sprintf("process_start_time_seconds %d", startTimeSeconds)
31+
return m.ReplaceAllString(s, n)
1632
}
17-
f(1024, "testdata/limits", false)
18-
f(0, "testdata/bad_path", true)
19-
f(0, "testdata/limits_bad", true)
33+
return s
2034
}
2135

22-
func TestGetOpenFDsCount(t *testing.T) {
23-
f := func(want uint64, path string, wantErr bool) {
24-
t.Helper()
25-
got, err := getOpenFDsCount(path)
26-
if (err != nil && !wantErr) || (err == nil && wantErr) {
27-
t.Fatalf("unexpected error: %v", err)
28-
}
29-
if got != want {
30-
t.Fatalf("unexpected result: %d, want: %d at getOpenFDsCount", got, want)
36+
func stripComments(input string) string {
37+
var builder strings.Builder
38+
lines := strings.Split(input, "\n")
39+
for _, line := range lines {
40+
s := strings.TrimSpace(line)
41+
if strings.HasPrefix(s, "#") || s == "" {
42+
continue
3143
}
44+
builder.WriteString(line + "\n")
3245
}
33-
f(5, "testdata/fd/", false)
34-
f(0, "testdata/fd/0", true)
35-
f(0, "testdata/limits", true)
46+
return builder.String()
3647
}
3748

38-
func TestGetMemStats(t *testing.T) {
39-
f := func(want memStats, path string, wantErr bool) {
40-
t.Helper()
41-
got, err := getMemStats(path)
42-
if (err != nil && !wantErr) || (err == nil && wantErr) {
43-
t.Fatalf("unexpected error: %v", err)
44-
}
45-
if got != nil && *got != want {
46-
t.Fatalf("unexpected result: %d, want: %d at getMemStats", *got, want)
49+
func Test_processMetrics(t *testing.T) {
50+
diffFormat := "Test %s:\n\tgot:\n'%v'\n\twant:\n'%v'"
51+
tests := []struct {
52+
name string
53+
wantW string
54+
fn func(w io.Writer)
55+
}{
56+
{"pm", getTestData("linux.proc_metrics.out", t), writeProcessMetrics},
57+
{"fdm", getTestData("linux.fd_metrics.out", t), writeFDMetrics},
58+
}
59+
for _, compact := range []bool{true, false} {
60+
ExposeMetadata(!compact)
61+
for _, tt := range tests {
62+
want := tt.wantW
63+
if compact {
64+
want = stripComments(want)
65+
}
66+
t.Run(tt.name, func(t *testing.T) {
67+
w := &bytes.Buffer{}
68+
tt.fn(w)
69+
if gotW := w.String(); gotW != want {
70+
t.Errorf(diffFormat, tt.name, gotW, want)
71+
}
72+
})
4773
}
4874
}
49-
f(memStats{vmPeak: 2130489344, rssPeak: 200679424, rssAnon: 121602048, rssFile: 11362304}, "testdata/status", false)
50-
f(memStats{}, "testdata/status_bad", true)
75+
76+
// missing /proc/<pid>/io file - just omit the process_io_* metric entries
77+
// see https://github.com/VictoriaMetrics/metrics/issues/42
78+
tt := tests[0]
79+
want := stripComments(tt.wantW)
80+
m := regexp.MustCompile("process_io_[_a-z]+ [0-9]+\n")
81+
wantW := m.ReplaceAllString(want, "")
82+
testfiles[FD_IO] = "/doesNotExist"
83+
ExposeMetadata(false) // no need to check comments again
84+
init2()
85+
t.Run(tt.name, func(t *testing.T) {
86+
w := &bytes.Buffer{}
87+
tt.fn(w)
88+
if gotW := w.String(); gotW != wantW {
89+
t.Errorf(diffFormat, tt.name, gotW, wantW)
90+
}
91+
})
92+
93+
// bad limits: just omit the process_max_fds metric entry
94+
tt = tests[1]
95+
want = stripComments(tt.wantW)
96+
m = regexp.MustCompile("process_max_fds [0-9]+\n")
97+
wantW = m.ReplaceAllString(want, "")
98+
testfiles[FD_LIMITS] = "/limits_bad"
99+
init2()
100+
t.Run(tt.name, func(t *testing.T) {
101+
w := &bytes.Buffer{}
102+
tt.fn(w)
103+
if gotW := w.String(); gotW != wantW {
104+
t.Errorf(diffFormat, tt.name, gotW, wantW)
105+
}
106+
})
107+
51108
}

testdata/limits

Lines changed: 0 additions & 17 deletions
This file was deleted.

testdata/linux.fd_metrics.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# HELP process_max_fds
2+
# TYPE process_max_fds gauge
3+
process_max_fds 2048
4+
# HELP process_open_fds
5+
# TYPE process_open_fds gauge
6+
process_open_fds 5

testdata/linux.proc_metrics.out

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# HELP process_io_read_bytes
2+
# TYPE process_io_read_bytes gauge
3+
process_io_read_bytes 0
4+
# HELP process_io_written_bytes
5+
# TYPE process_io_written_bytes gauge
6+
process_io_written_bytes 0
7+
# HELP process_io_read_syscalls
8+
# TYPE process_io_read_syscalls gauge
9+
process_io_read_syscalls 0
10+
# HELP process_io_write_syscalls
11+
# TYPE process_io_write_syscalls gauge
12+
process_io_write_syscalls 0
13+
# HELP process_io_storage_read_bytes
14+
# TYPE process_io_storage_read_bytes gauge
15+
process_io_storage_read_bytes 0
16+
# HELP process_io_storage_written_bytes
17+
# TYPE process_io_storage_written_bytes gauge
18+
process_io_storage_written_bytes 0
19+
# HELP process_psi_cpu_some_us
20+
# TYPE process_psi_cpu_some_us counter
21+
process_psi_cpu_some_us 8655568
22+
# HELP process_psi_cpu_full_us
23+
# TYPE process_psi_cpu_full_us counter
24+
process_psi_cpu_full_us 8558482
25+
# HELP process_psi_io_some_us
26+
# TYPE process_psi_io_some_us counter
27+
process_psi_io_some_us 10791243
28+
# HELP process_psi_io_full_us
29+
# TYPE process_psi_io_full_us counter
30+
process_psi_io_full_us 10763684
31+
# HELP process_psi_memory_some_us
32+
# TYPE process_psi_memory_some_us counter
33+
process_psi_memory_some_us 0
34+
# HELP process_psi_memory_full_us
35+
# TYPE process_psi_memory_full_us counter
36+
process_psi_memory_full_us 0
37+
# HELP process_system_cpu_seconds
38+
# TYPE process_system_cpu_seconds counter
39+
process_system_cpu_seconds 0.08
40+
# HELP process_total_cpu_seconds
41+
# TYPE process_total_cpu_seconds counter
42+
process_total_cpu_seconds 0.18
43+
# HELP process_user_cpu_seconds
44+
# TYPE process_user_cpu_seconds counter
45+
process_user_cpu_seconds 0.1
46+
# HELP process_major_pagefaults
47+
# TYPE process_major_pagefaults counter
48+
process_major_pagefaults 0
49+
# HELP process_minor_pagefaults
50+
# TYPE process_minor_pagefaults counter
51+
process_minor_pagefaults 3111
52+
# HELP process_num_threads
53+
# TYPE process_num_threads gauge
54+
process_num_threads 1
55+
# HELP process_resident_memory_bytes
56+
# TYPE process_resident_memory_bytes gauge
57+
process_resident_memory_bytes 4231168
58+
# HELP process_start_time_seconds
59+
# TYPE process_start_time_seconds gauge
60+
process_start_time_seconds 1742515804
61+
# HELP process_virtual_memory_bytes
62+
# TYPE process_virtual_memory_bytes gauge
63+
process_virtual_memory_bytes 25751552

testdata/linux.ps_io

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
Name: tcsh
2+
Umask: 0022
3+
State: S (sleeping)
4+
Tgid: 847024
5+
Ngid: 0
6+
Pid: 847024
7+
PPid: 847023
8+
TracerPid: 0
9+
Uid: 6018 6018 6018 6018
10+
Gid: 1502 1502 1502 1502
11+
FDSize: 64
12+
Groups: 14 1501 1502 1504 1510 1520 1530
13+
NStgid: 847024
14+
NSpid: 847024
15+
NSpgid: 847024
16+
NSsid: 847024
17+
VmPeak: 25148 kB
18+
VmSize: 25148 kB
19+
VmLck: 0 kB
20+
VmPin: 0 kB
21+
VmHWM: 4132 kB
22+
VmRSS: 4132 kB
23+
RssAnon: 1588 kB
24+
RssFile: 2544 kB
25+
RssShmem: 0 kB
26+
VmData: 2584 kB
27+
VmStk: 132 kB
28+
VmExe: 304 kB
29+
VmLib: 1972 kB
30+
VmPTE: 68 kB
31+
VmSwap: 0 kB
32+
HugetlbPages: 0 kB
33+
CoreDumping: 0
34+
THP_enabled: 1
35+
Threads: 1
36+
SigQ: 0/254739
37+
SigPnd: 0000000000000000
38+
ShdPnd: 0000000000000000
39+
SigBlk: 0000000000000002
40+
SigIgn: 0000000000384004
41+
SigCgt: 0000000009812003
42+
CapInh: 0000000000000000
43+
CapPrm: 0000000000000000
44+
CapEff: 0000000000000000
45+
CapBnd: 000001ffffffffff
46+
CapAmb: 0000000000000000
47+
NoNewPrivs: 0
48+
Seccomp: 0
49+
Seccomp_filters: 0
50+
Speculation_Store_Bypass: thread vulnerable
51+
SpeculationIndirectBranch: conditional enabled
52+
Cpus_allowed: ffffff
53+
Cpus_allowed_list: 0-23
54+
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
55+
Mems_allowed_list: 0
56+
voluntary_ctxt_switches: 821
57+
nonvoluntary_ctxt_switches: 6

testdata/linux.ps_limits

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Limit Soft Limit Hard Limit Units
2+
Max cpu time unlimited unlimited seconds
3+
Max file size unlimited unlimited bytes
4+
Max data size unlimited unlimited bytes
5+
Max stack size 8388608 unlimited bytes
6+
Max core file size unlimited unlimited bytes
7+
Max resident set unlimited unlimited bytes
8+
Max processes 254739 254739 processes
9+
Max open files 2048 1048576 files
10+
Max locked memory 8351289344 8351289344 bytes
11+
Max address space unlimited unlimited bytes
12+
Max file locks unlimited unlimited locks
13+
Max pending signals 254739 254739 signals
14+
Max msgqueue size 819200 819200 bytes
15+
Max nice priority 0 0
16+
Max realtime priority 0 0
17+
Max realtime timeout unlimited unlimited us

testdata/linux.ps_psi_cpu

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
some avg10=0.00 avg60=0.00 avg300=0.00 total=8655568
2+
full avg10=0.00 avg60=0.00 avg300=0.00 total=8558482

testdata/linux.ps_psi_io

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
some avg10=0.00 avg60=0.00 avg300=0.00 total=10791243
2+
full avg10=0.00 avg60=0.00 avg300=0.00 total=10763684

testdata/linux.ps_psi_mem

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
2+
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

0 commit comments

Comments
 (0)