Source File
rpcz.go
Belonging Package
go.opencensus.io/zpages
package zpages
import (
)
const bytesPerKb = 1024
var (
programStartTime = time.Now()
mu sync.Mutex // protects snaps
snaps = make(map[methodKey]*statSnapshot)
viewType = map[*view.View]bool{
ocgrpc.ClientCompletedRPCsView: false,
ocgrpc.ClientSentBytesPerRPCView: false,
ocgrpc.ClientSentMessagesPerRPCView: false,
ocgrpc.ClientReceivedBytesPerRPCView: false,
ocgrpc.ClientReceivedMessagesPerRPCView: false,
ocgrpc.ClientRoundtripLatencyView: false,
ocgrpc.ServerCompletedRPCsView: true,
ocgrpc.ServerReceivedBytesPerRPCView: true,
ocgrpc.ServerReceivedMessagesPerRPCView: true,
ocgrpc.ServerSentBytesPerRPCView: true,
ocgrpc.ServerSentMessagesPerRPCView: true,
ocgrpc.ServerLatencyView: true,
}
)
func () {
:= make([]*view.View, 0, len(viewType))
for := range viewType {
= append(, )
}
if := view.Register(...); != nil {
log.Printf("error subscribing to views: %v", )
}
view.RegisterExporter(snapExporter{})
}
func ( http.ResponseWriter, *http.Request) {
.Header().Set("Content-Type", "text/html; charset=utf-8")
WriteHTMLRpczPage()
}
func ( io.Writer) {
if := headerTemplate.Execute(, headerData{Title: "RPC Stats"}); != nil {
log.Printf("zpages: executing template: %v", )
}
WriteHTMLRpczSummary()
if := footerTemplate.Execute(, nil); != nil {
log.Printf("zpages: executing template: %v", )
}
}
func ( io.Writer) {
mu.Lock()
defer mu.Unlock()
:= getStatsPage()
for , := range .StatGroups {
switch {
case 0:
fmt.Fprint(, "Sent:\n")
case 1:
fmt.Fprint(, "\nReceived:\n")
}
:= tabwriter.NewWriter(, 6, 8, 1, ' ', 0)
fmt.Fprint(, "Method\tCount\t\t\tAvgLat\t\t\tMaxLat\t\t\tRate\t\t\tIn (MiB/s)\t\t\tOut (MiB/s)\t\t\tErrors\t\t\n")
fmt.Fprint(, "\tMin\tHr\tTot\tMin\tHr\tTot\tMin\tHr\tTot\tMin\tHr\tTot\tMin\tHr\tTot\tMin\tHr\tTot\tMin\tHr\tTot\n")
for , := range .Snapshots {
fmt.Fprintf(, "%s\t%d\t%d\t%d\t%v\t%v\t%v\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d\t%d\t%d\n",
.Method,
.CountMinute,
.CountHour,
.CountTotal,
.AvgLatencyMinute,
.AvgLatencyHour,
.AvgLatencyTotal,
.RPCRateMinute,
.RPCRateHour,
.RPCRateTotal,
.InputRateMinute/bytesPerKb,
.InputRateHour/bytesPerKb,
.InputRateTotal/bytesPerKb,
.OutputRateMinute/bytesPerKb,
.OutputRateHour/bytesPerKb,
.OutputRateTotal/bytesPerKb,
.ErrorsMinute,
.ErrorsHour,
.ErrorsTotal)
}
.Flush()
}
}
type headerData struct {
Title string
}
type statsPage struct {
StatGroups []*statGroup
}
Method string
Received bool
CountMinute uint64
CountHour uint64
CountTotal uint64
AvgLatencyMinute time.Duration
AvgLatencyHour time.Duration
AvgLatencyTotal time.Duration
RPCRateMinute float64
RPCRateHour float64
RPCRateTotal float64
InputRateMinute float64
InputRateHour float64
InputRateTotal float64
OutputRateMinute float64
OutputRateHour float64
OutputRateTotal float64
ErrorsMinute uint64
ErrorsHour uint64
ErrorsTotal uint64
}
type methodKey struct {
method string
received bool
}
type snapExporter struct{}
func ( snapExporter) ( *view.Data) {
, := viewType[.View]
if ! {
return
}
if len(.Rows) == 0 {
return
}
:= float64(time.Since(programStartTime)) / float64(time.Second)
:= func(, float64) float64 {
:=
if > 0 && > {
=
}
return /
}
:= func( float64) time.Duration {
if math.IsInf(, 0) || math.IsNaN() {
return 0
}
return time.Duration(float64(time.Millisecond) * )
}
:= make(map[string]struct{})
mu.Lock()
defer mu.Unlock()
for , := range .Rows {
var string
for , := range .Tags {
if .Key == ocgrpc.KeyClientMethod || .Key == ocgrpc.KeyServerMethod {
= .Value
break
}
}
:= methodKey{method: , received: }
:= snaps[]
if == nil {
= &statSnapshot{Method: , Received: }
snaps[] =
}
var (
float64
float64
)
switch v := .Data.(type) {
case *view.CountData:
= float64(.Value)
= float64(.Value)
case *view.DistributionData:
= .Sum()
= float64(.Count)
case *view.SumData:
= .Value
= .Value
}
switch .View {
case ocgrpc.ClientCompletedRPCsView:
if , := []; ! {
[] = struct{}{}
.ErrorsTotal = 0
}
for , := range .Tags {
if .Key == ocgrpc.KeyClientStatus && .Value != "OK" {
.ErrorsTotal += uint64()
}
}
case ocgrpc.ClientRoundtripLatencyView:
.AvgLatencyTotal = ( / )
case ocgrpc.ClientSentBytesPerRPCView:
.OutputRateTotal = (0, )
case ocgrpc.ClientReceivedBytesPerRPCView:
.InputRateTotal = (0, )
case ocgrpc.ClientSentMessagesPerRPCView:
.CountTotal = uint64()
.RPCRateTotal = (0, )
case ocgrpc.ServerCompletedRPCsView:
if , := []; ! {
[] = struct{}{}
.ErrorsTotal = 0
}
for , := range .Tags {
if .Key == ocgrpc.KeyServerStatus && .Value != "OK" {
.ErrorsTotal += uint64()
}
}
case ocgrpc.ServerLatencyView:
.AvgLatencyTotal = ( / )
case ocgrpc.ServerSentBytesPerRPCView:
.OutputRateTotal = (0, )
case ocgrpc.ServerReceivedMessagesPerRPCView:
.CountTotal = uint64()
.RPCRateTotal = (0, )
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |