gopackage health
import (
"fmt"
"html/template"
"net/http"
_ "net/http/pprof"
"runtime"
"sync"
"time"
"github.com/gorilla/websocket"
)
type MemUsage struct {
Alloc uint64
TotalAlloc uint64
Sys uint64
NumGC uint32
Timestamp time.Time
}
var memUsageHistory []MemUsage
var mu sync.Mutex
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
func Run(addr string) {
// 启动 pprof HTTP 服务器
go func() {
fmt.Println(http.ListenAndServe(addr, nil))
}()
// 启动内存监控 HTTP 服务器
http.HandleFunc("/", memUsageHandler)
http.HandleFunc("/ws", wsHandler)
go func() {
fmt.Println(http.ListenAndServe("localhost:8080", nil))
}()
// 定期记录内存使用情况
go func() {
for {
mu.Lock()
memUsageHistory = append(memUsageHistory, getMemUsage())
mu.Unlock()
time.Sleep(10 * time.Second)
}
}()
}
func memUsageHandler(w http.ResponseWriter, r *http.Request) {
const htmlTemplate = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Memory Usage</title>
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
background-color: #f8f9fa;
}
.header {
position: fixed;
top: 0;
width: 100%;
background-color: #007bff;
color: white;
padding: 10px 0;
text-align: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.container {
margin-top: 70px;
padding: 20px;
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th, .table td {
padding: 8px;
border: 1px solid #dee2e6;
}
.table th {
background-color: #007bff;
color: white;
}
.table tr:nth-child(even) {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<div class="header">
<h1>Memory Usage</h1>
</div>
<div class="container">
<table class="table">
<thead>
<tr>
<th>Timestamp</th>
<th>Alloc (MiB)</th>
<th>TotalAlloc (MiB)</th>
<th>Sys (MiB)</th>
<th>NumGC</th>
</tr>
</thead>
<tbody id="memUsageTable">
{{range .}}
<tr>
<td>{{.Timestamp.Format "2006-01-02 15:04:05"}}</td>
<td>{{.Alloc}}</td>
<td>{{.TotalAlloc}}</td>
<td>{{.Sys}}</td>
<td>{{.NumGC}}</td>
</tr>
{{end}}
</tbody>
</table>
</div>
<script>
var ws = new WebSocket("ws://localhost:8080/ws");
ws.onmessage = function(event) {
var data = JSON.parse(event.data);
var row = "<tr>";
row += "<td>" + new Date(data.Timestamp).toLocaleString() + "</td>";
row += "<td>" + data.Alloc + "</td>";
row += "<td>" + data.TotalAlloc + "</td>";
row += "<td>" + data.Sys + "</td>";
row += "<td>" + data.NumGC + "</td>";
row += "</tr>";
document.getElementById("memUsageTable").innerHTML += row;
};
</script>
</body>
</html>
`
tmpl := template.Must(template.New("memUsage").Parse(htmlTemplate))
mu.Lock()
defer mu.Unlock()
tmpl.Execute(w, memUsageHistory)
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("Upgrade error:", err)
return
}
defer conn.Close()
for {
mu.Lock()
if len(memUsageHistory) > 0 {
lastUsage := memUsageHistory[len(memUsageHistory)-1]
err := conn.WriteJSON(lastUsage)
if err != nil {
fmt.Println("Write error:", err)
break
}
}
mu.Unlock()
time.Sleep(1 * time.Second)
}
}
func getMemUsage() MemUsage {
var m runtime.MemStats
runtime.ReadMemStats(&m)
return MemUsage{
Alloc: bToMb(m.Alloc),
TotalAlloc: bToMb(m.TotalAlloc),
Sys: bToMb(m.Sys),
NumGC: m.NumGC,
Timestamp: time.Now(),
}
}
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}
go内存监控,主要使用runtime获取参数
本文作者:yowayimono
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!