Browse Source

tweaking ui

pull/114/head
chrislusf 10 years ago
parent
commit
78bc7b393f
  1. 14
      go/stats/duration_counter.go
  2. 3
      go/storage/store.go
  3. 8
      go/storage/volume_ttl.go
  4. 2
      go/weed/weed_server/common.go
  5. 1
      go/weed/weed_server/master_server.go
  6. 10
      go/weed/weed_server/master_server_handlers_ui.go
  7. 4
      go/weed/weed_server/master_ui/templates.go
  8. 5
      go/weed/weed_server/volume_server_handlers_ui.go
  9. 59
      go/weed/weed_server/volume_server_ui/templates.go

14
go/stats/duration_counter.go

@ -58,6 +58,20 @@ func (rrc *RoundRobinCounter) Sum() (sum int64) {
return return
} }
func (rrc *RoundRobinCounter) ToList() (ret []int64) {
index := rrc.LastIndex
step := len(rrc.Values)
for step > 0 {
step--
index++
if index >= len(rrc.Values) {
index = 0
}
ret = append(ret, rrc.Values[index])
}
return
}
type DurationCounter struct { type DurationCounter struct {
MinuteCounter *RoundRobinCounter MinuteCounter *RoundRobinCounter
HourCounter *RoundRobinCounter HourCounter *RoundRobinCounter

3
go/storage/store.go

@ -243,7 +243,8 @@ func (s *Store) Status() []*VolumeInfo {
FileCount: v.nm.FileCount(), FileCount: v.nm.FileCount(),
DeleteCount: v.nm.DeletedCount(), DeleteCount: v.nm.DeletedCount(),
DeletedByteCount: v.nm.DeletedSize(), DeletedByteCount: v.nm.DeletedSize(),
ReadOnly: v.readOnly}
ReadOnly: v.readOnly,
Ttl: v.Ttl}
stats = append(stats, s) stats = append(stats, s)
} }
} }

8
go/storage/volume_ttl.go

@ -60,19 +60,19 @@ func LoadTTLFromUint32(ttl uint32) (t *TTL) {
} }
// save stored bytes to an output with 2 bytes // save stored bytes to an output with 2 bytes
func (t TTL) ToBytes(output []byte) {
func (t *TTL) ToBytes(output []byte) {
output[0] = t.count output[0] = t.count
output[1] = t.unit output[1] = t.unit
} }
func (t TTL) ToUint32() (output uint32) {
func (t *TTL) ToUint32() (output uint32) {
output = uint32(t.count) << 8 output = uint32(t.count) << 8
output += uint32(t.unit) output += uint32(t.unit)
return output return output
} }
func (t TTL) String() string {
if t.count == 0 {
func (t *TTL) String() string {
if t == nil || t.count == 0 {
return "" return ""
} }
if t.unit == Empty { if t.unit == Empty {

2
go/weed/weed_server/common.go

@ -9,6 +9,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/chrislusf/weed-fs/go/glog" "github.com/chrislusf/weed-fs/go/glog"
"github.com/chrislusf/weed-fs/go/operation" "github.com/chrislusf/weed-fs/go/operation"
@ -19,6 +20,7 @@ import (
) )
var serverStats *stats.ServerStats var serverStats *stats.ServerStats
var startTime = time.Now()
func init() { func init() {
serverStats = stats.NewServerStats() serverStats = stats.NewServerStats()

1
go/weed/weed_server/master_server.go

@ -60,6 +60,7 @@ func NewMasterServer(r *mux.Router, port int, metaFolder string,
ms.guard = security.NewGuard(whiteList, secureKey) ms.guard = security.NewGuard(whiteList, secureKey)
r.HandleFunc("/", ms.uiStatusHandler)
r.HandleFunc("/ui/index.html", ms.uiStatusHandler) r.HandleFunc("/ui/index.html", ms.uiStatusHandler)
r.HandleFunc("/dir/assign", ms.proxyToLeader(ms.guard.WhiteList(ms.dirAssignHandler))) r.HandleFunc("/dir/assign", ms.proxyToLeader(ms.guard.WhiteList(ms.dirAssignHandler)))
r.HandleFunc("/dir/lookup", ms.proxyToLeader(ms.guard.WhiteList(ms.dirLookupHandler))) r.HandleFunc("/dir/lookup", ms.proxyToLeader(ms.guard.WhiteList(ms.dirLookupHandler)))

10
go/weed/weed_server/master_server_handlers_ui.go

@ -3,24 +3,26 @@ package weed_server
import ( import (
"net/http" "net/http"
"github.com/chrislusf/weed-fs/go/stats"
"github.com/chrislusf/weed-fs/go/util" "github.com/chrislusf/weed-fs/go/util"
ui "github.com/chrislusf/weed-fs/go/weed/weed_server/master_ui" ui "github.com/chrislusf/weed-fs/go/weed/weed_server/master_ui"
) )
func (ms *MasterServer) uiStatusHandler(w http.ResponseWriter, r *http.Request) { func (ms *MasterServer) uiStatusHandler(w http.ResponseWriter, r *http.Request) {
stats := make(map[string]interface{})
stats["Version"] = util.VERSION
infos := make(map[string]interface{})
infos["Version"] = util.VERSION
args := struct { args := struct {
Version string Version string
Topology interface{} Topology interface{}
Peers interface{} Peers interface{}
Stats interface{} Stats interface{}
Counters *stats.ServerStats
}{ }{
util.VERSION, util.VERSION,
ms.Topo.ToMap(), ms.Topo.ToMap(),
ms.Topo.RaftServer.Peers(), ms.Topo.RaftServer.Peers(),
stats,
//serverStats,
infos,
serverStats,
} }
ui.StatusTpl.Execute(w, args) ui.StatusTpl.Execute(w, args)
} }

4
go/weed/weed_server/master_ui/templates.go

@ -44,6 +44,10 @@ var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
<div class="col-sm-6"> <div class="col-sm-6">
<h2>System Stats</h2> <h2>System Stats</h2>
<table class="table table-condensed table-striped"> <table class="table table-condensed table-striped">
<tr>
<th>Concurrent Connections</th>
<td>{{ .Counters.Connections.WeekCounter.Count }}</td>
</tr>
{{ range $key, $val := .Stats }} {{ range $key, $val := .Stats }}
<tr> <tr>
<th>{{ $key }}</th> <th>{{ $key }}</th>

5
go/weed/weed_server/volume_server_handlers_ui.go

@ -3,6 +3,7 @@ package weed_server
import ( import (
"net/http" "net/http"
"path/filepath" "path/filepath"
"time"
"github.com/chrislusf/weed-fs/go/stats" "github.com/chrislusf/weed-fs/go/stats"
"github.com/chrislusf/weed-fs/go/util" "github.com/chrislusf/weed-fs/go/util"
@ -11,7 +12,7 @@ import (
func (vs *VolumeServer) uiStatusHandler(w http.ResponseWriter, r *http.Request) { func (vs *VolumeServer) uiStatusHandler(w http.ResponseWriter, r *http.Request) {
infos := make(map[string]interface{}) infos := make(map[string]interface{})
infos["Version"] = util.VERSION
infos["Up Time"] = time.Now().Sub(startTime).String()
var ds []*stats.DiskStatus var ds []*stats.DiskStatus
for _, loc := range vs.store.Locations { for _, loc := range vs.store.Locations {
if dir, e := filepath.Abs(loc.Directory); e == nil { if dir, e := filepath.Abs(loc.Directory); e == nil {
@ -24,12 +25,14 @@ func (vs *VolumeServer) uiStatusHandler(w http.ResponseWriter, r *http.Request)
Volumes interface{} Volumes interface{}
DiskStatuses interface{} DiskStatuses interface{}
Stats interface{} Stats interface{}
Counters *stats.ServerStats
}{ }{
util.VERSION, util.VERSION,
vs.masterNode, vs.masterNode,
vs.store.Status(), vs.store.Status(),
ds, ds,
infos, infos,
serverStats,
} }
ui.StatusTpl.Execute(w, args) ui.StatusTpl.Execute(w, args)
} }

59
go/weed/weed_server/volume_server_ui/templates.go

@ -2,13 +2,48 @@ package master_ui
import ( import (
"html/template" "html/template"
"strconv"
"strings"
) )
var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
func join(data []int64) string {
var ret []string
for _, d := range data {
ret = append(ret, strconv.Itoa(int(d)))
}
return strings.Join(ret, ",")
}
var funcMap = template.FuncMap{
"join": join,
}
var StatusTpl = template.Must(template.New("status").Funcs(funcMap).Parse(`<!DOCTYPE html>
<html> <html>
<head> <head>
<title>Seaweed File System {{ .Version }}</title> <title>Seaweed File System {{ .Version }}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-sparklines/2.1.2/jquery.sparkline.min.js"></script>
<script type="text/javascript">
$(function() {
var periods = ['second', 'minute', 'hour', 'day'];
for (i = 0; i < periods.length; i++) {
var period = periods[i];
$('.inlinesparkline-'+period).sparkline('html', {
type: 'line',
barColor: 'red',
tooltipSuffix:' request per '+period,
});
}
});
</script>
<style>
#jqstooltip{
height: 28px !important;
width: 150px !important;
}
</style>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
@ -23,7 +58,7 @@ var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
{{ range .DiskStatuses }} {{ range .DiskStatuses }}
<tr> <tr>
<th>{{ .Dir }}</th> <th>{{ .Dir }}</th>
<td>{{ .Free }}</td>
<td>{{ .Free }} Bytes Free</td>
</tr> </tr>
{{ end }} {{ end }}
</table> </table>
@ -36,6 +71,22 @@ var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
<th>Master</th> <th>Master</th>
<td><a href="http://{{.Master}}/ui/index.html">{{.Master}}</a></td> <td><a href="http://{{.Master}}/ui/index.html">{{.Master}}</a></td>
</tr> </tr>
<tr>
<th>Weekly # ReadRequests</th>
<td><span class="inlinesparkline-day">{{ .Counters.ReadRequests.WeekCounter.ToList | join }}</span></td>
</tr>
<tr>
<th>Daily # ReadRequests</th>
<td><span class="inlinesparkline-hour">{{ .Counters.ReadRequests.DayCounter.ToList | join }}</span></td>
</tr>
<tr>
<th>Hourly # ReadRequests</th>
<td><span class="inlinesparkline-minute">{{ .Counters.ReadRequests.HourCounter.ToList | join }}</span></td>
</tr>
<tr>
<th>Last Minute # ReadRequests</th>
<td><span class="inlinesparkline-second">{{ .Counters.ReadRequests.MinuteCounter.ToList | join }}</span></td>
</tr>
{{ range $key, $val := .Stats }} {{ range $key, $val := .Stats }}
<tr> <tr>
<th>{{ $key }}</th> <th>{{ $key }}</th>
@ -52,6 +103,7 @@ var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
<thead> <thead>
<tr> <tr>
<th>Id</th> <th>Id</th>
<th>Collection</th>
<th>Size</th> <th>Size</th>
<th>Files</th> <th>Files</th>
<th>Trash</th> <th>Trash</th>
@ -62,7 +114,8 @@ var StatusTpl = template.Must(template.New("status").Parse(`<!DOCTYPE html>
{{ range .Volumes }} {{ range .Volumes }}
<tr> <tr>
<td><code>{{ .Id }}</code></td> <td><code>{{ .Id }}</code></td>
<td>{{ .Size }}</td>
<td>{{ .Collection }}</td>
<td>{{ .Size }} Bytes</td>
<td>{{ .FileCount }}</td> <td>{{ .FileCount }}</td>
<td>{{ .DeleteCount }} / {{.DeletedByteCount}} Bytes</td> <td>{{ .DeleteCount }} / {{.DeletedByteCount}} Bytes</td>
<td>{{ .Ttl }}</td> <td>{{ .Ttl }}</td>

Loading…
Cancel
Save