-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
160 lines (137 loc) · 3.91 KB
/
main.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/shirou/gopsutil/process"
"net/http"
"os"
"strings"
"sync"
"time"
)
var (
cpuUsage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "Cpuinfo",
Help: "CPU使用率",
}, []string{"process"})
memUsage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "Meminfo",
Help: "内存使用率",
}, []string{"process"})
pidUsage = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "Pidinfo",
Help: "进程pid",
}, []string{"process"})
// 使用互斥锁确保在更新指标时不被同时执行
mutex sync.Mutex
// 存储每个进程上次更新的时间戳
lastUpdate = make(map[string]time.Time)
)
func init() {
// Register metrics once
prometheus.MustRegister(cpuUsage, memUsage, pidUsage)
}
func main() {
processNames := os.Args[1:]
if len(processNames) == 0 {
fmt.Println("Usage: go run main.go <process1> <process2> ... <processN>")
return
}
// 开启一个子协程执行更新指标逻辑
go func() {
for range time.Tick(time.Second * 5) { // 每隔 5 秒更新一次指标
updateMetrics(processNames)
}
}()
// 开启一个子协程定时打印 metrics 到控制台
go func() {
for range time.Tick(time.Second * 5) { // 每隔 5 秒打印一次
printMetrics()
}
}()
// Start HTTP server
http.Handle("/metrics", promhttp.Handler())
err := http.ListenAndServe("0.0.0.0:9100", nil)
if err != nil {
fmt.Printf("Error starting HTTP server: %s\n", err)
}
}
func updateMetrics(processNames []string) {
// 使用互斥锁确保在更新指标时不被同时执行
mutex.Lock()
defer mutex.Unlock()
for _, processName := range processNames {
// 获取进程的 PID
pid := getPID(processName)
if pid == 0 {
// 如果进程不存在,设置指标为 0 表示未知值
cpuUsage.WithLabelValues(processName).Set(float64(0)) // NaN
memUsage.WithLabelValues(processName).Set(float64(0)) // NaN
pidUsage.WithLabelValues(processName).Set(float64(0)) // NaN
continue
}
lastUpdateTime, ok := lastUpdate[processName]
// 检查是否需要更新,避免在短时间内频繁更新导致数据丢失
if !ok || time.Since(lastUpdateTime) >= time.Second*5 {
p, err := process.NewProcess(int32(pid))
if err != nil {
fmt.Printf("Error getting process: %s\n", err)
return
}
// 获取进程的 CPU 使用率
cpuPercent, err := p.CPUPercent()
if err != nil {
fmt.Printf("Error getting CPU percent: %s\n", err)
return
}
cpuUsage.WithLabelValues(processName).Set(cpuPercent)
// 获取进程的 mem 使用率
memoryPercent, err := p.MemoryPercent()
if err != nil {
fmt.Printf("Error getting mem percent: %s\n", err)
return
}
memUsage.WithLabelValues(processName).Set(float64(memoryPercent))
// 获取进程的 pid
pidUsage.WithLabelValues(processName).Set(float64(pid))
// 更新上次更新时间
lastUpdate[processName] = time.Now()
}
}
}
func getPID(processName string) int {
processes, err := process.Processes()
if err != nil {
fmt.Printf("Error getting processes: %s\n", err)
return 0
}
for _, p := range processes {
name, _ := p.Name()
if name == processName {
return int(p.Pid)
}
}
fmt.Printf("Process with name %s not found\n", processName)
return 0
}
func printMetrics() {
// 使用互斥锁确保在清除指标和打印指标时不被同时执行
mutex.Lock()
defer mutex.Unlock()
// 打印最新的指标
mfs, err := prometheus.DefaultGatherer.Gather()
if err != nil {
fmt.Printf("Error gathering metrics: %s\n", err)
return
}
for _, mf := range mfs {
for _, m := range mf.Metric {
// 检查标签是否以 "go_" 开头
if len(m.Label) > 0 && !strings.HasPrefix(*m.Label[0].Name, "go_") {
fmt.Printf("Metric: %s - Value: %f\n", m, m.Gauge.GetValue())
}
}
}
fmt.Println("==========================================")
}