Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
张磊
/
FileStorageBeego
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
d314d12c
authored
2014-08-14 17:35:23 +0800
by
Lei Cao
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Added the UI for Admin monitor page
1 parent
14cd9e51
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
591 additions
and
122 deletions
admin.go
adminui.go
toolbox/statistics.go
admin.go
View file @
d314d12
// Beego (http://beego.me/)
//
// @description beego is an open-source, high-performance web framework for the Go programming language.
//
// @link http://github.com/astaxie/beego for the canonical source repository
//
// @license http://github.com/astaxie/beego/blob/master/LICENSE
//
// @authors astaxie
package
beego
import
(
"bytes"
"fmt"
"net/http"
"
strconv
"
"
text/template
"
"time"
"github.com/astaxie/beego/toolbox"
...
...
@@ -49,7 +46,6 @@ func init() {
beeAdminApp
.
Route
(
"/prof"
,
profIndex
)
beeAdminApp
.
Route
(
"/healthcheck"
,
healthcheck
)
beeAdminApp
.
Route
(
"/task"
,
taskStatus
)
beeAdminApp
.
Route
(
"/runtask"
,
runTask
)
beeAdminApp
.
Route
(
"/listconf"
,
listConf
)
FilterMonitorFunc
=
func
(
string
,
string
,
time
.
Duration
)
bool
{
return
true
}
}
...
...
@@ -57,22 +53,22 @@ func init() {
// AdminIndex is the default http.Handler for admin module.
// it matches url pattern "/".
func
adminIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
rw
.
Write
([]
byte
(
"<html><head><title>beego admin dashboard</title></head><body>"
))
rw
.
Write
([]
byte
(
"Welcome to Admin Dashboard<br>
\n
"
))
rw
.
Write
([]
byte
(
"There are servral functions:<br>
\n
"
))
rw
.
Write
([]
byte
(
"1. Record all request and request time, <a href='/qps'>http://localhost:"
+
strconv
.
Itoa
(
AdminHttpPort
)
+
"/qps</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"2. Get runtime profiling data by the pprof, <a href='/prof'>http://localhost:"
+
strconv
.
Itoa
(
AdminHttpPort
)
+
"/prof</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"3. Get healthcheck result from <a href='/healthcheck'>http://localhost:"
+
strconv
.
Itoa
(
AdminHttpPort
)
+
"/healthcheck</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"4. Get current task infomation from task <a href='/task'>http://localhost:"
+
strconv
.
Itoa
(
AdminHttpPort
)
+
"/task</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"5. To run a task passed a param <a href='/runtask'>http://localhost:"
+
strconv
.
Itoa
(
AdminHttpPort
)
+
"/runtask</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"6. Get all confige & router infomation <a href='/listconf'>http://localhost:"
+
strconv
.
Itoa
(
AdminHttpPort
)
+
"/listconf</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"</body></html>"
))
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
indexTpl
))
data
:=
make
(
map
[
interface
{}]
interface
{})
tmpl
.
Execute
(
rw
,
data
)
}
// QpsIndex is the http.Handler for writing qbs statistics map result info in http.ResponseWriter.
// it's registered with url pattern "/qbs" in admin module.
func
qpsIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
toolbox
.
StatisticsMap
.
GetMap
(
rw
)
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
qpsTpl
))
data
:=
make
(
map
[
interface
{}]
interface
{})
data
[
"Content"
]
=
toolbox
.
StatisticsMap
.
GetMap
()
tmpl
.
Execute
(
rw
,
data
)
}
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
...
...
@@ -81,112 +77,217 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
r
.
ParseForm
()
command
:=
r
.
Form
.
Get
(
"command"
)
if
command
!=
""
{
data
:=
make
(
map
[
interface
{}]
interface
{})
switch
command
{
case
"conf"
:
fmt
.
Fprintln
(
rw
,
"list all beego's conf:"
)
fmt
.
Fprintln
(
rw
,
"AppName:"
,
AppName
)
fmt
.
Fprintln
(
rw
,
"AppPath:"
,
AppPath
)
fmt
.
Fprintln
(
rw
,
"AppConfigPath:"
,
AppConfigPath
)
fmt
.
Fprintln
(
rw
,
"StaticDir:"
,
StaticDir
)
fmt
.
Fprintln
(
rw
,
"StaticExtensionsToGzip:"
,
StaticExtensionsToGzip
)
fmt
.
Fprintln
(
rw
,
"HttpAddr:"
,
HttpAddr
)
fmt
.
Fprintln
(
rw
,
"HttpPort:"
,
HttpPort
)
fmt
.
Fprintln
(
rw
,
"HttpTLS:"
,
EnableHttpTLS
)
fmt
.
Fprintln
(
rw
,
"HttpCertFile:"
,
HttpCertFile
)
fmt
.
Fprintln
(
rw
,
"HttpKeyFile:"
,
HttpKeyFile
)
fmt
.
Fprintln
(
rw
,
"RecoverPanic:"
,
RecoverPanic
)
fmt
.
Fprintln
(
rw
,
"AutoRender:"
,
AutoRender
)
fmt
.
Fprintln
(
rw
,
"ViewsPath:"
,
ViewsPath
)
fmt
.
Fprintln
(
rw
,
"RunMode:"
,
RunMode
)
fmt
.
Fprintln
(
rw
,
"SessionOn:"
,
SessionOn
)
fmt
.
Fprintln
(
rw
,
"SessionProvider:"
,
SessionProvider
)
fmt
.
Fprintln
(
rw
,
"SessionName:"
,
SessionName
)
fmt
.
Fprintln
(
rw
,
"SessionGCMaxLifetime:"
,
SessionGCMaxLifetime
)
fmt
.
Fprintln
(
rw
,
"SessionSavePath:"
,
SessionSavePath
)
fmt
.
Fprintln
(
rw
,
"SessionHashFunc:"
,
SessionHashFunc
)
fmt
.
Fprintln
(
rw
,
"SessionHashKey:"
,
SessionHashKey
)
fmt
.
Fprintln
(
rw
,
"SessionCookieLifeTime:"
,
SessionCookieLifeTime
)
fmt
.
Fprintln
(
rw
,
"UseFcgi:"
,
UseFcgi
)
fmt
.
Fprintln
(
rw
,
"MaxMemory:"
,
MaxMemory
)
fmt
.
Fprintln
(
rw
,
"EnableGzip:"
,
EnableGzip
)
fmt
.
Fprintln
(
rw
,
"DirectoryIndex:"
,
DirectoryIndex
)
fmt
.
Fprintln
(
rw
,
"HttpServerTimeOut:"
,
HttpServerTimeOut
)
fmt
.
Fprintln
(
rw
,
"ErrorsShow:"
,
ErrorsShow
)
fmt
.
Fprintln
(
rw
,
"XSRFKEY:"
,
XSRFKEY
)
fmt
.
Fprintln
(
rw
,
"EnableXSRF:"
,
EnableXSRF
)
fmt
.
Fprintln
(
rw
,
"XSRFExpire:"
,
XSRFExpire
)
fmt
.
Fprintln
(
rw
,
"CopyRequestBody:"
,
CopyRequestBody
)
fmt
.
Fprintln
(
rw
,
"TemplateLeft:"
,
TemplateLeft
)
fmt
.
Fprintln
(
rw
,
"TemplateRight:"
,
TemplateRight
)
fmt
.
Fprintln
(
rw
,
"BeegoServerName:"
,
BeegoServerName
)
fmt
.
Fprintln
(
rw
,
"EnableAdmin:"
,
EnableAdmin
)
fmt
.
Fprintln
(
rw
,
"AdminHttpAddr:"
,
AdminHttpAddr
)
fmt
.
Fprintln
(
rw
,
"AdminHttpPort:"
,
AdminHttpPort
)
m
:=
make
(
map
[
string
]
interface
{})
m
[
"AppName"
]
=
AppName
m
[
"AppPath"
]
=
AppPath
m
[
"AppConfigPath"
]
=
AppConfigPath
m
[
"StaticDir"
]
=
StaticDir
m
[
"StaticExtensionsToGzip"
]
=
StaticExtensionsToGzip
m
[
"HttpAddr"
]
=
HttpAddr
m
[
"HttpPort"
]
=
HttpPort
m
[
"HttpTLS"
]
=
EnableHttpTLS
m
[
"HttpCertFile"
]
=
HttpCertFile
m
[
"HttpKeyFile"
]
=
HttpKeyFile
m
[
"RecoverPanic"
]
=
RecoverPanic
m
[
"AutoRender"
]
=
AutoRender
m
[
"ViewsPath"
]
=
ViewsPath
m
[
"RunMode"
]
=
RunMode
m
[
"SessionOn"
]
=
SessionOn
m
[
"SessionProvider"
]
=
SessionProvider
m
[
"SessionName"
]
=
SessionName
m
[
"SessionGCMaxLifetime"
]
=
SessionGCMaxLifetime
m
[
"SessionSavePath"
]
=
SessionSavePath
m
[
"SessionHashFunc"
]
=
SessionHashFunc
m
[
"SessionHashKey"
]
=
SessionHashKey
m
[
"SessionCookieLifeTime"
]
=
SessionCookieLifeTime
m
[
"UseFcgi"
]
=
UseFcgi
m
[
"MaxMemory"
]
=
MaxMemory
m
[
"EnableGzip"
]
=
EnableGzip
m
[
"DirectoryIndex"
]
=
DirectoryIndex
m
[
"HttpServerTimeOut"
]
=
HttpServerTimeOut
m
[
"ErrorsShow"
]
=
ErrorsShow
m
[
"XSRFKEY"
]
=
XSRFKEY
m
[
"EnableXSRF"
]
=
EnableXSRF
m
[
"XSRFExpire"
]
=
XSRFExpire
m
[
"CopyRequestBody"
]
=
CopyRequestBody
m
[
"TemplateLeft"
]
=
TemplateLeft
m
[
"TemplateRight"
]
=
TemplateRight
m
[
"BeegoServerName"
]
=
BeegoServerName
m
[
"EnableAdmin"
]
=
EnableAdmin
m
[
"AdminHttpAddr"
]
=
AdminHttpAddr
m
[
"AdminHttpPort"
]
=
AdminHttpPort
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
configTpl
))
data
[
"Content"
]
=
m
tmpl
.
Execute
(
rw
,
data
)
case
"router"
:
fmt
.
Fprintln
(
rw
,
"Print all router infomation:"
)
resultList
:=
new
([][]
string
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
"header"
),
fmt
.
Sprintf
(
"Router Pattern"
),
fmt
.
Sprintf
(
"Methods"
),
fmt
.
Sprintf
(
"Controller"
),
}
*
resultList
=
append
(
*
resultList
,
result
)
for
method
,
t
:=
range
BeeApp
.
Handlers
.
routers
{
fmt
.
Fprintln
(
rw
)
fmt
.
Fprintln
(
rw
)
fmt
.
Fprintln
(
rw
,
" Method:"
,
method
)
printTree
(
rw
,
t
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
"success"
),
fmt
.
Sprintf
(
"Method: %s"
,
method
),
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
printTree
(
resultList
,
t
)
}
// @todo print routers
data
[
"Content"
]
=
resultList
data
[
"Title"
]
=
"Routers"
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
routerAndFilterTpl
))
tmpl
.
Execute
(
rw
,
data
)
case
"filter"
:
fmt
.
Fprintln
(
rw
,
"Print all filter infomation:"
)
resultList
:=
new
([][]
string
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
"header"
),
fmt
.
Sprintf
(
"Router Pattern"
),
fmt
.
Sprintf
(
"Filter Function"
),
}
*
resultList
=
append
(
*
resultList
,
result
)
if
BeeApp
.
Handlers
.
enableFilter
{
fmt
.
Fprintln
(
rw
,
"BeforeRouter:"
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
"success"
),
fmt
.
Sprintf
(
"Before Router"
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
if
bf
,
ok
:=
BeeApp
.
Handlers
.
filters
[
BeforeRouter
];
ok
{
for
_
,
f
:=
range
bf
{
fmt
.
Fprintln
(
rw
,
f
.
pattern
,
utils
.
GetFuncName
(
f
.
filterFunc
))
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
f
.
pattern
),
fmt
.
Sprintf
(
"%s"
,
utils
.
GetFuncName
(
f
.
filterFunc
)),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
}
fmt
.
Fprintln
(
rw
,
"BeforeExec:"
)
result
=
[]
string
{
fmt
.
Sprintf
(
"success"
),
fmt
.
Sprintf
(
"Before Exec"
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
if
bf
,
ok
:=
BeeApp
.
Handlers
.
filters
[
BeforeExec
];
ok
{
for
_
,
f
:=
range
bf
{
fmt
.
Fprintln
(
rw
,
f
.
pattern
,
utils
.
GetFuncName
(
f
.
filterFunc
))
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
f
.
pattern
),
fmt
.
Sprintf
(
"%s"
,
utils
.
GetFuncName
(
f
.
filterFunc
)),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
}
fmt
.
Fprintln
(
rw
,
"AfterExec:"
)
result
=
[]
string
{
fmt
.
Sprintf
(
"success"
),
fmt
.
Sprintf
(
"AfterExec Exec"
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
if
bf
,
ok
:=
BeeApp
.
Handlers
.
filters
[
AfterExec
];
ok
{
for
_
,
f
:=
range
bf
{
fmt
.
Fprintln
(
rw
,
f
.
pattern
,
utils
.
GetFuncName
(
f
.
filterFunc
))
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
f
.
pattern
),
fmt
.
Sprintf
(
"%s"
,
utils
.
GetFuncName
(
f
.
filterFunc
)),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
}
fmt
.
Fprintln
(
rw
,
"FinishRouter:"
)
result
=
[]
string
{
fmt
.
Sprintf
(
"success"
),
fmt
.
Sprintf
(
"Finish Router"
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
if
bf
,
ok
:=
BeeApp
.
Handlers
.
filters
[
FinishRouter
];
ok
{
for
_
,
f
:=
range
bf
{
fmt
.
Fprintln
(
rw
,
f
.
pattern
,
utils
.
GetFuncName
(
f
.
filterFunc
))
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
f
.
pattern
),
fmt
.
Sprintf
(
"%s"
,
utils
.
GetFuncName
(
f
.
filterFunc
)),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
}
}
data
[
"Content"
]
=
resultList
data
[
"Title"
]
=
"Filters"
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
routerAndFilterTpl
))
tmpl
.
Execute
(
rw
,
data
)
default
:
rw
.
Write
([]
byte
(
"command not support"
))
}
}
else
{
rw
.
Write
([]
byte
(
"<html><head><title>beego admin dashboard</title></head><body>"
))
rw
.
Write
([]
byte
(
"ListConf support this command:<br>
\n
"
))
rw
.
Write
([]
byte
(
"1. <a href='?command=conf'>command=conf</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"2. <a href='?command=router'>command=router</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"3. <a href='?command=filter'>command=filter</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"</body></html>"
))
}
}
func
printTree
(
r
w
http
.
ResponseWriter
,
t
*
Tree
)
{
func
printTree
(
r
esultList
*
[][]
string
,
t
*
Tree
)
{
for
_
,
tr
:=
range
t
.
fixrouters
{
printTree
(
r
w
,
tr
)
printTree
(
r
esultList
,
tr
)
}
if
t
.
wildcard
!=
nil
{
printTree
(
r
w
,
t
.
wildcard
)
printTree
(
r
esultList
,
t
.
wildcard
)
}
for
_
,
l
:=
range
t
.
leaves
{
if
v
,
ok
:=
l
.
runObject
.
(
*
controllerInfo
);
ok
{
if
v
.
routerType
==
routerTypeBeego
{
fmt
.
Fprintln
(
rw
,
v
.
pattern
,
v
.
methods
,
v
.
controllerType
.
Name
())
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
v
.
pattern
),
fmt
.
Sprintf
(
"%s"
,
v
.
methods
),
fmt
.
Sprintf
(
"%s"
,
v
.
controllerType
),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
else
if
v
.
routerType
==
routerTypeRESTFul
{
fmt
.
Fprintln
(
rw
,
v
.
pattern
,
v
.
methods
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
v
.
pattern
),
fmt
.
Sprintf
(
"%s"
,
v
.
methods
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
else
if
v
.
routerType
==
routerTypeHandler
{
fmt
.
Fprintln
(
rw
,
v
.
pattern
,
"handler"
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
v
.
pattern
),
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
""
),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
}
}
...
...
@@ -197,58 +298,106 @@ func printTree(rw http.ResponseWriter, t *Tree) {
func
profIndex
(
rw
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
r
.
ParseForm
()
command
:=
r
.
Form
.
Get
(
"command"
)
data
:=
make
(
map
[
interface
{}]
interface
{})
var
result
bytes
.
Buffer
if
command
!=
""
{
toolbox
.
ProcessInput
(
command
,
rw
)
toolbox
.
ProcessInput
(
command
,
&
result
)
data
[
"Content"
]
=
result
.
String
()
data
[
"Title"
]
=
command
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
profillingTpl
))
tmpl
.
Execute
(
rw
,
data
)
}
else
{
rw
.
Write
([]
byte
(
"<html><head><title>beego admin dashboard</title></head><body>"
))
rw
.
Write
([]
byte
(
"request url like '/prof?command=lookup goroutine'<br>
\n
"
))
rw
.
Write
([]
byte
(
"the command have below types:<br>
\n
"
))
rw
.
Write
([]
byte
(
"1. <a href='?command=lookup goroutine'>lookup goroutine</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"2. <a href='?command=lookup heap'>lookup heap</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"3. <a href='?command=lookup threadcreate'>lookup threadcreate</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"4. <a href='?command=lookup block'>lookup block</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"5. <a href='?command=start cpuprof'>start cpuprof</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"6. <a href='?command=stop cpuprof'>stop cpuprof</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"7. <a href='?command=get memprof'>get memprof</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"8. <a href='?command=gc summary'>gc summary</a><br>
\n
"
))
rw
.
Write
([]
byte
(
"</body></html>"
))
}
}
// Healthcheck is a http.Handler calling health checking and showing the result.
// it's in "/healthcheck" pattern in admin module.
func
healthcheck
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
data
:=
make
(
map
[
interface
{}]
interface
{})
resultList
:=
new
([][]
string
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
"header"
),
fmt
.
Sprintf
(
"Name"
),
fmt
.
Sprintf
(
"Status"
),
}
*
resultList
=
append
(
*
resultList
,
result
)
for
name
,
h
:=
range
toolbox
.
AdminCheckList
{
if
err
:=
h
.
Check
();
err
!=
nil
{
fmt
.
Fprintf
(
rw
,
"%s : %s
\n
"
,
name
,
err
.
Error
())
result
=
[]
string
{
fmt
.
Sprintf
(
"error"
),
fmt
.
Sprintf
(
"%s"
,
name
),
fmt
.
Sprintf
(
"%s"
,
err
.
Error
()),
}
}
else
{
fmt
.
Fprintf
(
rw
,
"%s : ok
\n
"
,
name
)
result
=
[]
string
{
fmt
.
Sprintf
(
"success"
),
fmt
.
Sprintf
(
"%s"
,
name
),
fmt
.
Sprintf
(
"OK"
),
}
}
*
resultList
=
append
(
*
resultList
,
result
)
}
data
[
"Content"
]
=
resultList
data
[
"Title"
]
=
"Health Check"
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
healthCheckTpl
))
tmpl
.
Execute
(
rw
,
data
)
}
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
// it's in "/task" pattern in admin module.
func
taskStatus
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
for
tname
,
tk
:=
range
toolbox
.
AdminTaskList
{
fmt
.
Fprintf
(
rw
,
"%s:%s:%s"
,
tname
,
tk
.
GetStatus
(),
tk
.
GetPrev
()
.
String
())
}
}
data
:=
make
(
map
[
interface
{}]
interface
{})
// RunTask is a http.Handler to run a Task from the "query string.
// the request url likes /runtask?taskname=sendmail.
func
runTask
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
// Run Task
req
.
ParseForm
()
taskname
:=
req
.
Form
.
Get
(
"taskname"
)
if
t
,
ok
:=
toolbox
.
AdminTaskList
[
taskname
];
ok
{
err
:=
t
.
Run
()
if
err
!=
nil
{
fmt
.
Fprintf
(
rw
,
"%v"
,
err
)
if
taskname
!=
""
{
if
t
,
ok
:=
toolbox
.
AdminTaskList
[
taskname
];
ok
{
err
:=
t
.
Run
()
if
err
!=
nil
{
data
[
"Message"
]
=
[]
string
{
"error"
,
fmt
.
Sprintf
(
"%s"
,
err
)}
}
data
[
"Message"
]
=
[]
string
{
"success"
,
fmt
.
Sprintf
(
"%s run success,Now the Status is %s"
,
taskname
,
t
.
GetStatus
())}
}
else
{
data
[
"Message"
]
=
[]
string
{
"warning"
,
fmt
.
Sprintf
(
"there's no task which named: %s"
,
taskname
)}
}
fmt
.
Fprintf
(
rw
,
"%s run success,Now the Status is %s"
,
taskname
,
t
.
GetStatus
())
}
else
{
fmt
.
Fprintf
(
rw
,
"there's no task which named:%s"
,
taskname
)
}
// List Tasks
resultList
:=
new
([][]
string
)
var
result
=
[]
string
{
fmt
.
Sprintf
(
"header"
),
fmt
.
Sprintf
(
"Task Name"
),
fmt
.
Sprintf
(
"Task Spec"
),
fmt
.
Sprintf
(
"Task Function"
),
}
*
resultList
=
append
(
*
resultList
,
result
)
for
tname
,
tk
:=
range
toolbox
.
AdminTaskList
{
result
=
[]
string
{
fmt
.
Sprintf
(
""
),
fmt
.
Sprintf
(
"%s"
,
tname
),
fmt
.
Sprintf
(
"%s"
,
tk
.
GetStatus
()),
fmt
.
Sprintf
(
"%s"
,
tk
.
GetPrev
()
.
String
()),
}
*
resultList
=
append
(
*
resultList
,
result
)
}
data
[
"Content"
]
=
resultList
data
[
"Title"
]
=
"Tasks"
tmpl
:=
template
.
Must
(
template
.
New
(
"dashboard"
)
.
Parse
(
dashboardTpl
))
tmpl
=
template
.
Must
(
tmpl
.
Parse
(
tasksTpl
))
tmpl
.
Execute
(
rw
,
data
)
}
// adminApp is an http.HandlerFunc map used as beeAdminApp.
...
...
adminui.go
0 → 100644
View file @
d314d12
// Beego (http://beego.me/)
// @description beego is an open-source, high-performance web framework for the Go programming language.
// @link http://github.com/astaxie/beego for the canonical source repository
// @license http://github.com/astaxie/beego/blob/master/LICENSE
// @authors astaxie
package
beego
var
indexTpl
=
`
{{define "content"}}
<h1>Beego Admin Dashboard</h1>
<p>
For detail usage please check our document:
</p>
<p>
<a target="_blank" href="http://beego.me/docs/module/toolbox.md">Toolbox</a>
</p>
<p>
<a target="_blank" href="http://beego.me/docs/advantage/monitor.md">Live Monitor</a>
</p>
{{.Content}}
{{end}}`
var
profillingTpl
=
`
{{define "content"}}
<h1>{{.Title}}</h1>
<pre>
{{.Content}}
</pre>
{{end}}`
var
qpsTpl
=
`
{{define "content"}}
<h1>Requests statistics</h1>
<table class="table table-striped table-hover ">
{{range $i, $slice := .Content}}
<tr>
{{range $j, $elem := $slice}}
{{if eq $i 0}}
<th>
{{else}}
<td>
{{end}}
{{$elem}}
{{if eq $i 0}}
</th>
{{else}}
</td>
{{end}}
{{end}}
</tr>
{{end}}
</table>
{{end}}
`
var
configTpl
=
`
{{define "content"}}
<h1>Configurations</h1>
<pre>
{{range $index, $elem := .Content}}
{{$index}}={{$elem}}
{{end}}
</pre>
{{end}}
`
var
routerAndFilterTpl
=
`
{{define "content"}}
<h1>{{.Title}}</h1>
<table class="table table-striped table-hover ">
{{range $i, $slice := .Content}}
<tr>
{{ $header := index $slice 0}}
{{if eq "header" $header }}
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<th>
{{$elem}}
</th>
{{end}}
{{end}}
{{else if eq "success" $header}}
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<th class="success">
{{$elem}}
</th>
{{end}}
{{end}}
{{else}}
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<td>
{{$elem}}
</td>
{{end}}
{{end}}
{{end}}
</tr>
{{end}}
</table>
{{end}}
`
var
tasksTpl
=
`
{{define "content"}}
<h1>{{.Title}}</h1>
{{if .Message }}
{{ $messageType := index .Message 0}}
<p class="message
{{if eq "error" $messageType}}
bg-danger
{{else if eq "success" $messageType}}
bg-success
{{else}}
bg-warning
{{end}}
">
{{index .Message 1}}
</p>
{{end}}
<table class="table table-striped table-hover ">
{{range $i, $slice := .Content}}
<tr>
{{ $header := index $slice 0}}
{{if eq "header" $header }}
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<th>
{{$elem}}
</th>
{{end}}
{{end}}
<th>
Run Task
</th>
{{else}}
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<td>
{{$elem}}
</td>
{{end}}
{{end}}
<td>
<a class="btn btn-primary btn-sm" href="/task?taskname={{index $slice 1}}">Run</a>
</td>
{{end}}
</tr>
{{end}}
</table>
{{end}}
`
var
healthCheckTpl
=
`
{{define "content"}}
<h1>{{.Title}}</h1>
<table class="table table-striped table-hover ">
{{range $i, $slice := .Content}}
{{ $header := index $slice 0}}
{{if eq "header" $header }}
<tr>
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<th>
{{$elem}}
</th>
{{end}}
{{end}}
</tr>
{{else}}
{{ if eq "success" $header}}
<tr class="success">
{{else if eq "error" $header}}
<tr class="danger">
{{else}}
<tr>
{{end}}
{{range $j, $elem := $slice}}
{{if ne $j 0}}
<td>
{{$elem}}
</td>
{{end}}
{{end}}
</tr>
{{end}}
{{end}}
</table>
{{end}}`
// The base dashboardTpl
var
dashboardTpl
=
`
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Meta, title, CSS, favicons, etc. -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
Welcome to Beego Admin Dashboard
</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
ul.nav li.dropdown:hover > ul.dropdown-menu {
display: block;
}
#logo {
width: 102px;
height: 32px;
margin-top: 5px;
}
.message {
padding: 15px;
}
</style>
</head>
<body>
<header class="navbar navbar-default navbar-static-top bs-docs-nav" id="top" role="banner">
<div class="container">
<div class="navbar-header">
<button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".bs-navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/">
<img id="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPYAAABNCAYAAACVH5l+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAV/QAAFf0BzXBRYQAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMi8xMy8xM+ovEHIAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAQAklEQVR4nO2de7RcVXnAfzM3MckmhLdKtZYqoimtERVtXSjFNvYE6rsnFMFKy2MJC4tGdNECalFsKxRQ5GGDClUjzS6lltcuUmiryxRqFaEaCkgVqAkSakKSneTm3rn949uHOTNzzp1zZs5j7mT/1pqVmzMze39z73xnf/vb36OBx+OZFRuEvwusBp4fu7wROE0ZfUs9UiUzMzMDQLNmOTyeucB1dCo17v/XVS5JRrxiezz9OSDn9drxiu3xjCFesT2eMcQrtsczhnjF9njGEK/YHs8Y4hXb4xlDvGJ7PGOIV2yPZwzxiu3x9OfpnNdrxyu2x9Ofk5HY8Dgb3fWRpFG3AB6Ppzh8EojHM8Z4xfZ4xhCv2B7PGOIV2+MZQ+bVLYDHUzU2CE8AXg+8GHguMAW0gOmEn6PH7q6fdwOTsceurp+fca+1wJPAz4GfKaM3V/EZvVfcs0dhg/AC4D3AgcAixGrNqgczOZ9ruOuTiGLfBVygjH4is8A5ibziXrE9eww2CI8C1gL7INZq9P2PFLBIorGjcacRBf82sFIZvbXg+WQyp9jzbBBuRj7osDwFPALcA9wC3K2MbhUw7rMUKGsWHgMuUUZfMcib55Ksg2CDcCnwR8CbgJcCe2d5G3AzcJYyelOJ4vVOHISLgEuB/YAJqlvUonkmgAXAa4HfR4ojDo0NwiXAIcAPldFT0fUinWcHAb8BfAC4E3jQBuHxBY5fNS8CPmuD8Ji6BclAZbLaIFxgg/AzwH8B5wCvIptSAyjgeOCvShIvkW1vflcDkfXltL/zMxU/QJR8EXCWDcIDh/lMNgjn2SD8MLAB+D6w3gbhC6Lny/SKvxS4wQbhGhuEqsR5yua36xYgB6XK6v6OtwN/zHDfnaOLkSgbzWbz5cDpwHySla5VwCNpzDTlPgSxdgbCBuGrgXuBTyM3S4BDgS/tWLGyAdV4xU8AltggfJsyerqC+YrG1i1ADkqT1QbhBLI/LcIq2FnAGJlwJviFwL7uUlzJQH5n6921pntM9Pk3crg1ux646w3apvd8es3++cApNgi/pox+PMdnUcAngLPd+N0sB04FVld13HUc8FHgYxXNVxSTwI11C5GRsmW9APk7FsHagsbJwnGIhRApQuQom0FuMOcpo68pY2IbhPsD/wwcRvtmECn5wcCHEesny1i/A1yDrPazcfGOFSu/1khx8rSABzJJL+znBJ0/y2t2A0uV0T/KMW4HBcmahUngIeAKZfQ9gwwwl2Tthw3Co5GjmjTz+xngx/T3LD8J/CNwTRXWm9vH3gr8Cr2KPQ3co4wue/tyKvAXtE3m+I1lM3CsMvr7s7z/AOBy4KQc0y5LW7G3KqNfmWOgyExYDnwcSHrvfMSBcUaecTOQW9YamUuyAs8qxxrSlXo14uWerE6qzKyivVpGRHvfzYhJWzZrgROB19DpuANYDPypDcL3KqN7tic2COcDdwO/lmO+B4D1hTnPlNFWGf115AOkmVrvtkG4oKg5PeWydfk7G8D1wC+kvOTfgDNGUaltEL4GCUSZR69DaxdwgzL6B2XLoYx+BnFybaftaIP2nv4NwG+lvH0p+ZR6DXDMotvX7i7cK+5MrFPoTUwHWAIcVfScnnKYmJhYBRyb8vTTwAmj6BC1QbgYcZhFx3BxpZ4GfgJcVqFIdyJe7Gl6veQK+IA7j+7mUcSy6MdPgBXK6BMX3b72aSjpuEsZvY30hmWvL2NOT7HYIDwS+PNZXnKyMvqnVcmTk5XAEXRGlEXKZBF/RGWyK6N3A+cjvojuVbuBrMpvSXjfNuCDswzdQm5QhyujTfyJMs+x70i5fniJc3oKwAbhPsANpDtDLx+19rERLkjjTGAhvWGdU8B/Al+tWi5l9P3A3zsZIpkiL/lC4P1Jq7Yy+jrgtoQh7wNep4xepYze3v1kmYqdtn/5pRLn9BTD55HMpyS+B5xboSx5ORuJxGvSuVq3ELN2VY0+gUuRLWp38EoDCTA5JeV9pyHh2iAWx7nAkcro76RNVJpiK6N/hhxxdXNQWXN6hscG4WlI2GcS24HjldG7KhQpMzYIXwmEtCPMoK08u4AvKKMfqkk8lNGPIdbCLto3G2g70k63Qdiz8Lltw1JgGXCwMvov43HhSZRdaCEpEsrngI8oNggPBT4zy0vOUEY/XJU8ebBBuBA5L47HrUf72WngYQpKvBiSaxFnV7cjrYGkkp7lovw6UEZPKaPvd172vtRRQeU5Nczp6YNLlPhrJEkhia8oo79coUh5eTfwCnq/05HD7GpnRdaKk+FqJLAortQgQTTvQFbnoShNsW0QNklOW6wsTtiTnWazeRLpceCPUHxgUWHYIDwYOIvORSPax04B6xDH1aiwBniQ3r02yJHwh1xwysCUuWKneb+fKnFOzwC41fqClKcnkX31tgpFysu5SEhzPFwzOrP+OXCRMnpHfeJ14nwUH0csiUi5ob3XPgZJhx2YMhU7LWHgkZTrnppoNptvQNJsk/gzZfR3q5QnDy7C7DjEjI0UJFKW3cAXZ4vFrgtl9L8C36RdYy1elGQRcN4w45ei2DYI9yU9a+XeMub0DEWQcv1x4JIqBcmDDcJ5wEVIzHX8zDoywR8ErqpHukx8EthCr0neBF5tgzDt79KXwhXbBTesRUyjJG4tek7P0CxLuX79KMaBxzgZ2fLFTfBo9dsGXFpWbbEiUEavR8qITdF7/DUBfMLlk+emMMW2QXiYDcKzkeyS5Skvu0sZ7U3x0eOQlOv/VKUQebBB+DzEKoyKEsbDR6eRNNNv1CNdLi5D4u67U16byOL4vkEGTTtT3sflE2dlr1nGivMnOcbMShZZp5B84S8ro2c7py2bUZV1r5TrP6xo/kE4Ddif5Hjwp4BPj2ogTRxl9BM2CK9DYsKjwJroM80D3mOD8AZl9IY8486mjEVX2LxIGV3W/jqLrAcg+5bNyujrS5IjC6Moa1Ixwkll9P9VMPegHE1bAeLKPQWsbrVaAxf0qIGrkGi/F9Kbs30gUl7s0jwDVhWgsobRKYv0jroFyEFVsibVzxqZ46EUor1nd8HA7a1W68rFd9zYr5rLyOCO4i6kvdeOWyAN4DfzjlmVYttWq1VojXHPHk8UudXNvGaz+dqqhSmAbyA30+7Chw3St0qpVKXYpzabzTL214NwU90C5GAuyVo162gfE8X/XQCc547C5hLLkfTNpPLIuX0Fs334LTnG2Zv+N4kLbRDeWlKwQD9Z4w6pOvfXMLdk7YsNwrcAHwFeRvY8gC3K6GHTd/8GeBtSVrg773op8FZGK4w0FZeHfS6iQy16Pfyp6ZlppCn2FmX0vinPpQl3CFKw/iMkRzFNAJ+iuBK2EbllrZG5JGtfbBC+CvgH6kkmegT4OlK9M4o6ixR8AZICeWfWbKiaORN4Acke/i0MUBiiyGKGP1ZGXwv8KtKfKYkVNgh/sag5PbVzLDX1WHe11r6InAEnpUC+GHhXHbLlweVfn0D75hTfWuxGbpy5Yz/KKGY4iTQdS+pw0KD4Fduzh9JqtR4F/o7OPTbu5wXAScP2yKqA85GMLuhcracRHbpskIKRZRUztEhCeRKvK2NOTy3cRmfyQqW4I60vAP9Lsof8RUhFlZHEtfU9is72QHGH2SeV0XkCxZ6lTDPq9pTrh5Y4p6dCXNbX24FvIdFeWxIeZcvwJLIHjRcuiJR8HnD8KK7arsHGxxBPeES8RPK/K6MHDokt80jgwZTrI/dL9gyOMvpm0n0qVfUJ10gwz6H0Nsd7IfCHwMUly5AZV4Tk/UiMfpLDbCuzl37uS5nFDLcixe+6GShbxeNJQxm9CVm1d9J7BtxEVu1Rqo77y8DvkZxDPgXcpIxOWxgzUbZHM6mSom/x4ymDmxDvcdyBBrIi7guckVQksGpc4MwHkUaW3VFmLeCnwGeHnadsxV6YcG3kM248cw93Xr0aWbW7yw01gDcDL6lHug7e6B5xEzzKIZ8Eriwi+abMYoYHkbw6D+Tl83gyYJAm9klFAhcjgSC1YYNwb2S1jm9H42fX31NGF9I7vMwV+00p1x8tcU7PYFRtRZWSeeV6ZH0KSaboPtduAEfbIDysjLkzciLi4Euq+LIFKZVUCKUotmu/mtZM7D/KmNMzFElOziU2CIuoAZ9URre0YzB3BPct0jtbripr7tlwIdd/QHrRxduU0YUVtihcsbcuf2djYmLiYtIDUUaymdseTtKeroEUMxgYG4TLEGXq5slhxs3A5ciRUbQaxpX7FTYIjyh5/g5cjfDIYQadN5xppJ/XlUXOWWTNs4U2CIOJiYm7gA+lvOxeZfQDRc3pKYy0aiNXOOXMjQ3Cw5EMrCTuG2TMrLj+XN+k1+RvIOGbv17m/Am8keQIMxCH2bUu0KYw0gJU9rZBmOeXvxjpotkv4KWMKip5Zc3CJPAQ0kf5ngLHHVVZ70B6SnfzMuA+G4QbgKztcZpIEFJalVqYJaClQK5CCu93x01MIJ+rElzV3vfRtlzi3voW0lPsxqLnTVPEJuklaQfl+u7m3AVRhqwARwKhDcJlwwYLxBhVWf8WcTo9N+X5g5ldUfPwMMn9novmUeAJekOYZyjus2Th7Ugac7w+W7Q92IbUAizceVlVyt3d1HzUMCDPYQ6k/jkGltW176ni7zMDnKmMLj1xxGVEbSL56CspvqJwXE+x99LZ1jceYWbK6rJSRfmYrwCnj1LvpJwkOX9GlYFlVUbfaIPwTMrrnNFClPrOksZPIjr26o7w6vneu7iLw5Fwz+cjyr8L6a+13Y21M/bvM4iDbguy8u6I96x2EWbnIFZQd+XRGUpwmMUpU7HvB853SQJzmSq/iMMylKzK6KttED6OpEKmmeWD8CPk5n5XgWNmIR47HhHV6wbABuEBiH/hWOB5iEJHCSTx9yTRMa4NwvhcDcSK6h5nBvGLfFUZvTHn58lMkYq9EcnoWgfcrIxeV+DYdfAYcIky+u66BclAYbIqo2+xQfgSxIRcARyBKHme78pOYAPwbaSlk46vZhUSrdjdit10ZvJKZA+8P+JU617ZI9KuZ6F77hYS0164wyzOMAJ7PCONDcKPIllUcV/SDHLjsUhySJNOPYgfRQ1L92rdcvOeX9aWZGZGRJ9rJVo9njx0r9iRib0QyWOIVzft7tZZBN2r9W7gX6rwM3jF9owzu+hVLkhW3CRPfZqC57V0W4hS/w9QST82r9ieccaSrIRpjrG4uRx15ZhAzPXoEa360f+hM6Ksm0kko3E98Lm8zfUGxSu2Z5x5Glkp59OrdElm8n8jOd3fUUYnJcYk4o62FrrHXu6hEP2yyNHYJhcvUAlesT3jzEbkDHoJnUdYcZN8J3IcN3BIrvP4b3OPTcMIXBResT3jzONIqaGFtE3qiB3AD5AAqnUul3ts8IrtGWc2IDHw5yAtdOYjoZzfRRoN3FdGnPYo4M+xPWONK2C4H+1FbArYXFPATOlE59j/D6WId7YitGZUAAAAAElFTkSuQmCC"/>
</a>
</div>
<nav class="collapse navbar-collapse bs-navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li>
<a href="/qps">
Requests statistics
</a>
</li>
<li>
<li class="dropdown">
<a href="#" class="dropdown-toggle disabled" data-toggle="dropdown">Performance profiling<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/prof?command=lookup goroutine">lookup goroutine</a></li>
<li><a href="/prof?command=lookup heap">lookup heap</a></li>
<li><a href="/prof?command=lookup threadcreate">lookup threadcreate</a></li>
<li><a href="/prof?command=lookup block">lookup block</a></li>
<li><a href="/prof?command=start cpuprof">start cpuprof</a></li>
<li><a href="/prof?command=stop cpuprof">stop cpuprof</a></li>
<li><a href="/prof?command=get memprof">get memprof</a></li>
<li><a href="/prof?command=gc summary">gc summary</a></li>
</ul>
</li>
<li>
<a href="/healthcheck">
Healthcheck
</a>
</li>
<li>
<a href="/task" class="dropdown-toggle disabled" data-toggle="dropdown">Tasks</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle disabled" data-toggle="dropdown">Config Status<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="/listconf?command=conf">Configs</a></li>
<li><a href="/listconf?command=router">Routers</a></li>
<li><a href="/listconf?command=filter">Filters</a></li>
</ul>
</li>
</ul>
</nav>
</div>
</header>
<div class="container">
{{template "content" .}}
</div>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</body>
</html>
`
toolbox/statistics.go
View file @
d314d12
// Beego (http://beego.me/)
//
// @description beego is an open-source, high-performance web framework for the Go programming language.
//
// @link http://github.com/astaxie/beego for the canonical source repository
//
// @license http://github.com/astaxie/beego/blob/master/LICENSE
//
// @authors astaxie
package
toolbox
import
(
"fmt"
"io"
"sync"
"time"
)
...
...
@@ -79,17 +74,29 @@ func (m *UrlMap) AddStatistics(requestMethod, requestUrl, requestController stri
}
// put url statistics result in io.Writer
func
(
m
*
UrlMap
)
GetMap
(
rw
io
.
Writer
)
{
func
(
m
*
UrlMap
)
GetMap
(
)
[][]
string
{
m
.
lock
.
RLock
()
defer
m
.
lock
.
RUnlock
()
fmt
.
Fprintf
(
rw
,
"| % -50s| % -10s | % -16s | % -16s | % -16s | % -16s | % -16s |
\n
"
,
"requestUrl"
,
"method"
,
"times"
,
"used"
,
"max used"
,
"min used"
,
"avg used"
)
resultLists
:=
make
([][]
string
,
0
)
var
result
=
[]
string
{
"requestUrl"
,
"method"
,
"times"
,
"used"
,
"max used"
,
"min used"
,
"avg used"
}
resultLists
=
append
(
resultLists
,
result
)
for
k
,
v
:=
range
m
.
urlmap
{
for
kk
,
vv
:=
range
v
{
fmt
.
Fprintf
(
rw
,
"| % -50s| % -10s | % -16d | % -16s | % -16s | % -16s | % -16s |
\n
"
,
k
,
kk
,
vv
.
RequestNum
,
toS
(
vv
.
TotalTime
),
toS
(
vv
.
MaxTime
),
toS
(
vv
.
MinTime
),
toS
(
time
.
Duration
(
int64
(
vv
.
TotalTime
)
/
vv
.
RequestNum
)),
)
result
:=
[]
string
{
fmt
.
Sprintf
(
"% -50s"
,
k
),
fmt
.
Sprintf
(
"% -10s"
,
kk
),
fmt
.
Sprintf
(
"% -16d"
,
vv
.
RequestNum
),
fmt
.
Sprintf
(
"% -16s"
,
toS
(
vv
.
TotalTime
)),
fmt
.
Sprintf
(
"% -16s"
,
toS
(
vv
.
MaxTime
)),
fmt
.
Sprintf
(
"% -16s"
,
toS
(
vv
.
MinTime
)),
fmt
.
Sprintf
(
"% -16s"
,
toS
(
time
.
Duration
(
int64
(
vv
.
TotalTime
)
/
vv
.
RequestNum
))),
}
resultLists
=
append
(
resultLists
,
result
)
}
}
fmt
.
Println
(
resultLists
)
return
resultLists
}
// global statistics data map
...
...
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment