-
Notifications
You must be signed in to change notification settings - Fork 49
/
jvm.go
94 lines (81 loc) · 2.38 KB
/
jvm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package containers
import (
"bytes"
"fmt"
"path/filepath"
"strconv"
"time"
"github.com/coroot/coroot-node-agent/common"
"github.com/coroot/coroot-node-agent/proc"
"github.com/prometheus/client_golang/prometheus"
"github.com/xin053/hsperfdata"
"k8s.io/klog/v2"
)
func isJvm(cmdline []byte) bool {
idx := bytes.Index(cmdline, []byte{0})
if idx < 0 {
return false
}
return bytes.HasSuffix(cmdline[:idx], []byte("java"))
}
func jvmMetrics(pid uint32) (string, []prometheus.Metric) {
p := proc.Path(pid, "root/tmp/hsperfdata_*/"+strconv.Itoa(int(proc.GetNsPid(pid))))
files, _ := filepath.Glob(p)
if len(files) != 1 {
return "", nil
}
pd, err := readPerfData(files[0])
if err != nil {
if !common.IsNotExist(err) {
klog.Warningln(err)
}
return "", nil
}
jvm := pd.getString("sun.rt.javaCommand")
var res []prometheus.Metric
res = append(res, gauge(metrics.JvmInfo, 1, jvm, pd.getString("java.property.java.version")))
func() {
size := float64(0)
used := float64(0)
for _, gen := range []int{0, 1} {
spaces := pd.getInt64("sun.gc.generation.%d.spaces", gen)
for s := 0; s < int(spaces); s++ {
size += float64(pd.getInt64("sun.gc.generation.%d.space.%d.capacity", gen, s))
used += float64(pd.getInt64("sun.gc.generation.%d.space.%d.used", gen, s))
}
}
res = append(res, gauge(metrics.JvmHeapSize, size, jvm))
res = append(res, gauge(metrics.JvmHeapUsed, used, jvm))
}()
gc := func(prefix string) {
name := pd.getString(prefix + "name")
if name == "" {
return
}
res = append(res, counter(metrics.JvmGCTime, time.Duration(pd.getInt64(prefix+"time")).Seconds(), jvm, name))
}
gc("sun.gc.collector.0.")
gc("sun.gc.collector.1.")
gc("sun.gc.collector.2.")
res = append(res, counter(metrics.JvmSafepointTime, time.Duration(pd.getInt64("sun.rt.safepointTime")).Seconds(), jvm))
res = append(res, counter(metrics.JvmSafepointSyncTime, time.Duration(pd.getInt64("sun.rt.safepointSyncTime")).Seconds(), jvm))
return jvm, res
}
type perfData struct {
data map[string]interface{}
}
func readPerfData(p string) (*perfData, error) {
data, err := hsperfdata.ReadPerfData(p, true)
return &perfData{data: data}, err
}
func (pd *perfData) getString(key string) string {
v, _ := pd.data[key].(string)
return v
}
func (pd *perfData) getInt64(key string, a ...any) int64 {
if len(a) > 0 {
key = fmt.Sprintf(key, a...)
}
v, _ := pd.data[key].(int64)
return v
}