Skip to content
This repository has been archived by the owner on Mar 22, 2021. It is now read-only.

Commit

Permalink
增加runtime.MemStats Dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
hb-chen committed Jul 10, 2018
1 parent 1de9cb9 commit 03d2147
Show file tree
Hide file tree
Showing 8 changed files with 542 additions and 2 deletions.
2 changes: 0 additions & 2 deletions router/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ func Routers() *echo.Echo {

e.Static("/favicon.ico", "./assets/img/favicon.ico")



// Cache
e.Use(cache.Cache())

Expand Down
106 changes: 106 additions & 0 deletions router/web/dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package web

import (
"time"
"runtime"
"fmt"

"github.com/labstack/echo"

"github.com/hb-go/echo-web/util/conv"
)

func DashboardHandler(c echo.Context) error {
updateSystemStatus()

c.Set("tmpl", "web/dashboard")
c.Set("data", map[string]interface{}{
"title": "Dashboard",
"SysStatus": sysStatus,
})

return nil
}

var (
startTime = time.Now()
)

var sysStatus struct {
Uptime string
NumGoroutine int

// General statistics.
MemAllocated string // bytes allocated and still in use
MemTotal string // bytes allocated (even if freed)
MemSys string // bytes obtained from system (sum of XxxSys below)
Lookups uint64 // number of pointer lookups
MemMallocs uint64 // number of mallocs
MemFrees uint64 // number of frees

// Main allocation heap statistics.
HeapAlloc string // bytes allocated and still in use
HeapSys string // bytes obtained from system
HeapIdle string // bytes in idle spans
HeapInuse string // bytes in non-idle span
HeapReleased string // bytes released to the OS
HeapObjects uint64 // total number of allocated objects

// Low-level fixed-size structure allocator statistics.
// Inuse is bytes used now.
// Sys is bytes obtained from system.
StackInuse string // bootstrap stacks
StackSys string
MSpanInuse string // mspan structures
MSpanSys string
MCacheInuse string // mcache structures
MCacheSys string
BuckHashSys string // profiling bucket hash table
GCSys string // GC metadata
OtherSys string // other system allocations

// Garbage collector statistics.
NextGC string // next run in HeapAlloc time (bytes)
LastGC string // last run in absolute time (ns)
PauseTotalNs string
PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
NumGC uint32
}

func updateSystemStatus() {
sysStatus.Uptime = conv.TimeSincePro(startTime)

m := new(runtime.MemStats)
runtime.ReadMemStats(m)
sysStatus.NumGoroutine = runtime.NumGoroutine()

sysStatus.MemAllocated = conv.FileSize(int64(m.Alloc))
sysStatus.MemTotal = conv.FileSize(int64(m.TotalAlloc))
sysStatus.MemSys = conv.FileSize(int64(m.Sys))
sysStatus.Lookups = m.Lookups
sysStatus.MemMallocs = m.Mallocs
sysStatus.MemFrees = m.Frees

sysStatus.HeapAlloc = conv.FileSize(int64(m.HeapAlloc))
sysStatus.HeapSys = conv.FileSize(int64(m.HeapSys))
sysStatus.HeapIdle = conv.FileSize(int64(m.HeapIdle))
sysStatus.HeapInuse = conv.FileSize(int64(m.HeapInuse))
sysStatus.HeapReleased = conv.FileSize(int64(m.HeapReleased))
sysStatus.HeapObjects = m.HeapObjects

sysStatus.StackInuse = conv.FileSize(int64(m.StackInuse))
sysStatus.StackSys = conv.FileSize(int64(m.StackSys))
sysStatus.MSpanInuse = conv.FileSize(int64(m.MSpanInuse))
sysStatus.MSpanSys = conv.FileSize(int64(m.MSpanSys))
sysStatus.MCacheInuse = conv.FileSize(int64(m.MCacheInuse))
sysStatus.MCacheSys = conv.FileSize(int64(m.MCacheSys))
sysStatus.BuckHashSys = conv.FileSize(int64(m.BuckHashSys))
sysStatus.GCSys = conv.FileSize(int64(m.GCSys))
sysStatus.OtherSys = conv.FileSize(int64(m.OtherSys))

sysStatus.NextGC = conv.FileSize(int64(m.NextGC))
sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000)
sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000)
sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000)
sysStatus.NumGC = m.NumGC
}
2 changes: 2 additions & 0 deletions router/web/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ func Routers() *echo.Echo {
e.POST("/login", handler(LoginPostHandler))
e.POST("/register", handler(RegisterPostHandler))

e.GET("/dashboard", DashboardHandler)

e.GET("/jwt/tester", handler(JWTTesterHandler))
e.GET("/ws", handler(WsHandler))

Expand Down
1 change: 1 addition & 0 deletions template/pongo2/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
</li>
<li><a href="/jwt/tester">JWT</a></li>
<li><a href="/ws">Socket</a></li>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="http://jaeger.hbchen.com" target="Jaeger">Jaeger</a></li>
<li><a href="https://github.com/hb-chen" target="GitHub">GitHub</a></li>
</ul>
Expand Down
131 changes: 131 additions & 0 deletions template/pongo2/web/dashboard.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{% extends "../base.html" %}

{% block head_title %}
{{title}}
{% endblock %}


{% block head_scripts %}
<script type="text/javascript">
requirejs(['bootstrap']);
</script>
{% endblock %}

{% block content %}
<div class="container" style="padding:0px 10px; width:900px;">
<table class="table table-striped">
<tr>
<td>服务运行时间</td>
<td>{{SysStatus.Uptime}}</td>
</tr>
<tr>
<td>当前 Goroutines 数量</td>
<td>{{SysStatus.NumGoroutine}}</td>
</tr>
<tr>
<td>当前内存使用量</td>
<td>{{SysStatus.MemAllocated}}</td>
</tr>
<tr>
<td>所有被分配的内存</td>
<td>{{SysStatus.MemTotal}}</td>
</tr>
<tr>
<td>内存占用量</td>
<td>{{SysStatus.MemSys}}</td>
</tr>
<tr>
<td>指针查找次数</td>
<td>{{SysStatus.Lookups}}</td>
</tr>
<tr>
<td>内存分配次数</td>
<td>{{SysStatus.MemMallocs}}</td>
</tr>
<tr>
<td>内存释放次数</td>
<td>{{SysStatus.MemFrees}}</td>
</tr>
<tr>
<td>当前 Heap 内存使用量</td>
<td>{{SysStatus.HeapAlloc}}</td>
</tr>
<tr>
<td>Heap 内存占用量</td>
<td>{{SysStatus.HeapSys}}</td>
</tr>
<tr>
<td>Heap 内存空闲量</td>
<td>{{SysStatus.HeapIdle}}</td>
</tr>
<tr>
<td>正在使用的 Heap 内存</td>
<td>{{SysStatus.HeapInuse}}</td>
</tr>
<tr>
<td>被释放的 Heap 内存</td>
<td>{{SysStatus.HeapReleased}}</td>
</tr>
<tr>
<td>Heap 对象数量</td>
<td>{{SysStatus.HeapObjects}}</td>
</tr>
<tr>
<td>启动 Stack 使用量</td>
<td>{{SysStatus.StackInuse}}</td>
</tr>
<tr>
<td>被分配的 Stack 内存</td>
<td>{{SysStatus.StackSys}}</td>
</tr>
<tr>
<td>MSpan 结构内存使用量</td>
<td>{{SysStatus.MSpanInuse}}</td>
</tr>
<tr>
<td>被分配的 MSpan 结构内存</td>
<td>{{SysStatus.HeapSys}}</td>
</tr>
<tr>
<td>MCache 结构内存使用量</td>
<td>{{SysStatus.MCacheInuse}}</td>
</tr>
<tr>
<td>被分配的 MCache 结构内存</td>
<td>{{SysStatus.MCacheSys}}</td>
</tr>
<tr>
<td>被分配的剖析哈希表内存</td>
<td>{{SysStatus.BuckHashSys}}</td>
</tr>
<tr>
<td>被分配的 GC 元数据内存</td>
<td>{{SysStatus.GCSys}}</td>
</tr>
<tr>
<td>其它被分配的系统内存</td>
<td>{{SysStatus.OtherSys}}</td>
</tr>
<tr>
<td>下次 GC 内存回收量</td>
<td>{{SysStatus.NextGC}}</td>
</tr>
<tr>
<td>距离上次 GC 时间</td>
<td>{{SysStatus.LastGC}}</td>
</tr>
<tr>
<td>GC 执行时间总量</td>
<td>{{SysStatus.PauseTotalNs}}</td>
</tr>
<tr>
<td>GC 暂停时间总量</td>
<td>{{SysStatus.PauseNs}}</td>
</tr>
<tr>
<td>上次 GC 暂停时间</td>
<td>{{SysStatus.NumGC}}</td>
</tr>
</table>
</div>
{% endblock %}
21 changes: 21 additions & 0 deletions template/template.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 77 additions & 0 deletions util/conv/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package conv

import (
"fmt"
"math"
"net/http"
"strings"
)

// IsTextFile returns true if file content format is plain text or empty.
func IsTextFile(data []byte) bool {
if len(data) == 0 {
return true
}
return strings.Contains(http.DetectContentType(data), "text/")
}

func IsImageFile(data []byte) bool {
return strings.Contains(http.DetectContentType(data), "image/")
}

func IsPDFFile(data []byte) bool {
return strings.Contains(http.DetectContentType(data), "application/pdf")
}

func IsVideoFile(data []byte) bool {
return strings.Contains(http.DetectContentType(data), "video/")
}

const (
Byte = 1
KByte = Byte * 1024
MByte = KByte * 1024
GByte = MByte * 1024
TByte = GByte * 1024
PByte = TByte * 1024
EByte = PByte * 1024
)

var bytesSizeTable = map[string]uint64{
"b": Byte,
"kb": KByte,
"mb": MByte,
"gb": GByte,
"tb": TByte,
"pb": PByte,
"eb": EByte,
}

func logn(n, b float64) float64 {
return math.Log(n) / math.Log(b)
}

func humanateBytes(s uint64, base float64, sizes []string) string {
if s < 10 {
return fmt.Sprintf("%d B", s)
}
e := math.Floor(logn(float64(s), base))
suffix := sizes[int(e)]
val := float64(s) / math.Pow(base, math.Floor(e))
f := "%.0f"
if val < 10 {
f = "%.1f"
}

return fmt.Sprintf(f+" %s", val, suffix)
}

// FileSize calculates the file size and generate user-friendly string.
func FileSize(s int64) string {
sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
return humanateBytes(uint64(s), 1024, sizes)
}
Loading

0 comments on commit 03d2147

Please sign in to comment.