jvm.go 2.4 KB

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