/* * Copyright (c) 2013 Matt Jibson * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * These are modified from the python appstats implementation. * If the above license infringes in some way on the original owner's * copyright, I will change it. */ package appstats const htmlBase = ` {{ define "top" }} Appstats - {{.Env.APPLICATION_ID}} {{ end }} {{ define "body" }}
{{/* Header begin */}}

Application Stats for {{.Env.APPLICATION_ID}}

All costs displayed in micropennies (1 dollar equals 100 pennies, 1 penny equals 1 million micropennies)
{{/* Header end */}} {{/* Body begin */}}
{{/* Content begin */}}
{{ end }} {{ define "end" }}
{{/* Content end */}}
{{/* Body end */}}
{{ end }} {{ define "footer" }} {{ end }} ` const htmlMain = ` {{ define "main" }} {{ template "top" . }} {{ template "body" . }}
{{ if .Requests }}
{{/* RPC stats table begin */}}

RPC Stats

{{ range $index, $item := .AllStatsByCount }} {{ range $subitem := $item.SubStats }} {{ end }} {{ end }}
RPC Count Cost Cost %
{{$item.Name}} {{$item.Count}} {{$item.Cost}} {{/*$item.CostPct*/}}
{{$subitem.Name}} {{$subitem.Count}} {{$subitem.Cost}} {{/*$subitem.CostPct*/}}
{{/* RPC stats table end */}}
{{/* Path stats table begin */}}

Path Stats

{{ range $index, $item := .PathStatsByCount }} {{ range $subitem := $item.SubStats }} {{ end }} {{ end }}
Path #RPCs Cost Cost% #Requests Most Recent requests
{{$item.Name}} {{$item.Count}} {{$item.Cost}} {{/*$item.CostPct*/}} {{$item.Requests}} {{ range $index, $element := $item.RecentReqs }} {{ if lt $index 10 }} ({{$element}}) {{ end }} {{ if eq $index 10 }} ... {{ end }} {{ end }}
{{$subitem.Name}} {{$subitem.Count}} {{$subitem.Cost}} {{/*$subitem.CostPct*/}}
{{/* Path stats table end */}}

Requests History

{{ range $index, $r := .Requests }} {{ range $item := $r.SubStats }} {{/**/}} {{ end }} {{ end }}
Request
({{$index}}) {{$r.RequestStats.Start}} "{{$r.RequestStats.Method}} {{$r.RequestStats.Path}}{{if $r.RequestStats.Query}}?{{$r.RequestStats.Query}}{{end}}" {{if $r.RequestStats.Status}}{{$r.RequestStats.Status}}{{end}} real={{$r.RequestStats.Duration}} {{/* overhead={{$r.overhead_walltime_milliseconds}}ms ({{$r.combined_rpc_count}} RPC{{$r.combined_rpc_count}}, billed_ops=[{{$r.combined_rpc_billed_ops}}]) */}} ({{$r.RequestStats.RPCStats | len}} RPCs, cost={{$r.RequestStats.Cost}})
{{$item.Name}} {{$item.Count}} {{$item.Cost}}{{$item.total_billed_ops_str}}
{{ else }}
No requests have been recorded yet. While it is possible that you simply need to wait until your server receives some requests, this is often caused by a configuration problem. Learn more
{{ end }} {{ template "end" . }} {{ template "footer" . }} {{ end }} ` const htmlDetails = ` {{ define "details" }} {{ template "top" . }} {{ template "body" . }} {{ if not .Record }}

Invalid or stale record key!

{{ else }}
{{.Record.Start}}
{{.Record.Status}}
{{.Record.Method}} {{.Record.Path}}{{if .Record.Query}}?{{.Record.Query}}{{end}}
{{.Record.User}}{{ if .Record.Admin }}*{{ end }} real={{.Record.Duration}} cost={{.Record.Cost}} {{/* overhead={{.Record.overhead_walltime_milliseconds}}ms
billed_ops={{.Record.combined_rpc_billed_ops}} */}}

Timeline

[Chart goes here]
{{ if .Record.RPCStats }}

RPC Call Traces

{{ range $index, $t := .Record.RPCStats }} {{ if $t.In }} {{ end }} {{ if $t.Out }} {{ end }} {{ if $t.StackData }} {{ range $stackindex, $f := $t.Stack }} {{/* {{ if $f.variables_size }} {{ end }}{{# f.variables_size #} */}} {{ end }}{{/* t.call_stack_list */}} {{ end }}{{/* t.call_stack_size */}} {{ end }}{{/* .Record.individual_stats_list */}}
RPC
@{{$t.Offset}} {{$t.Name}} real={{$t.Duration}} cost={{$t.Cost}} {{/* billed_ops=[{{t.billed_ops_str}}] */}}
Request: {{$t.Request}}
Response: {{$t.Response}}
Stack:
  {{ $f.Location }}:{{ $f.Lineno }} {{ $f.Call }}
{{ for item in f.variables_list }}{{item.key}} = {{item.value}}
{{ end }}
{{ end }}{{/* traces */}}
{{ if .AllStatsByCount }}

RPC Stats

{{ range $item := .AllStatsByCount }} {{ end }}
service.call #RPCs real time Cost Billed Ops
{{$item.Name}} {{$item.Count}} {{$item.Duration}} {{$item.Cost}}
{{ end }}{{/* rpcstats_by_count */}} {{ if .Header }}

CGI Environment

{{ range $key, $value := .Header }} {{ end }}
{{$key}}= {{$value}}
{{ end }}{{/* .Header */}} {{ end }} {{ template "end" . }} {{ template "footer" . }} {{ end }} ` const htmlFile = ` {{ define "file" }} {{ template "top" . }} {{ template "body" . }}

{{.Filename}}

Go to line {{.Lineno}} | Go to bottom
{{ range $index, $line := .Fp }}{{ rjust $index 4 }}: {{ $line }}
{{ end }}
Back to top {{ template "end" . }} {{ template "footer" . }} {{ end }} `