// Copyright 2017, OpenCensus Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package zpages import ( "fmt" "html/template" "io/ioutil" "log" "strconv" "time" "go.opencensus.io/trace" "go.opencensus.io/zpages/internal" ) var ( fs = internal.FS(false) templateFunctions = template.FuncMap{ "count": countFormatter, "ms": msFormatter, "rate": rateFormatter, "datarate": dataRateFormatter, "even": even, "traceid": traceIDFormatter, } headerTemplate = parseTemplate("header") summaryTableTemplate = parseTemplate("summary") statsTemplate = parseTemplate("rpcz") tracesTableTemplate = parseTemplate("traces") footerTemplate = parseTemplate("footer") ) func parseTemplate(name string) *template.Template { f, err := fs.Open("/templates/" + name + ".html") if err != nil { log.Panicf("%v: %v", name, err) } defer f.Close() text, err := ioutil.ReadAll(f) if err != nil { log.Panicf("%v: %v", name, err) } return template.Must(template.New(name).Funcs(templateFunctions).Parse(string(text))) } func countFormatter(num uint64) string { if num <= 0 { return " " } var floatVal float64 var suffix string if num >= 1e18 { floatVal = float64(num) / 1e18 suffix = " E " } else if num >= 1e15 { floatVal = float64(num) / 1e15 suffix = " P " } else if num >= 1e12 { floatVal = float64(num) / 1e12 suffix = " T " } else if num >= 1e9 { floatVal = float64(num) / 1e9 suffix = " G " } else if num >= 1e6 { floatVal = float64(num) / 1e6 suffix = " M " } if floatVal != 0 { return fmt.Sprintf("%1.3f%s", floatVal, suffix) } return fmt.Sprint(num) } func msFormatter(d time.Duration) string { if d == 0 { return "0" } if d < 10*time.Millisecond { return fmt.Sprintf("%.3f", float64(d)*1e-6) } return strconv.Itoa(int(d / time.Millisecond)) } func rateFormatter(r float64) string { return fmt.Sprintf("%.3f", r) } func dataRateFormatter(b float64) string { return fmt.Sprintf("%.3f", b/1e6) } func traceIDFormatter(r traceRow) template.HTML { sc := r.SpanContext if sc == (trace.SpanContext{}) { return "" } col := "black" if sc.TraceOptions.IsSampled() { col = "blue" } if r.ParentSpanID != (trace.SpanID{}) { return template.HTML(fmt.Sprintf(`trace_id: %s span_id: %s parent_span_id: %s`, col, sc.TraceID, sc.SpanID, r.ParentSpanID)) } return template.HTML(fmt.Sprintf(`trace_id: %s span_id: %s`, col, sc.TraceID, sc.SpanID)) } func even(x int) bool { return x%2 == 0 }