fix up browse.
Change-Id: Id5beab2e3caf929be14598df64fd170a03e7ea46
diff --git a/services/debug/debug/browse.go b/services/debug/debug/browse.go
index cb28605..2826698 100644
--- a/services/debug/debug/browse.go
+++ b/services/debug/debug/browse.go
@@ -32,6 +32,7 @@
"v.io/x/ref/lib/signals"
"v.io/x/ref/lib/v23cmd"
"v.io/x/ref/services/internal/pproflib"
+ "encoding/hex"
)
func init() {
@@ -102,6 +103,8 @@
http.Handle("/glob", &globHandler{ctx})
http.Handle(browseProfilesPath, &profilesHandler{ctx})
http.Handle(browseProfilesPath+"/", &profilesHandler{ctx})
+ http.Handle("/vtraces", &allTracesHandler{ctx})
+ http.Handle("/vtrace", &vtraceHandler{ctx})
http.Handle("/favicon.ico", http.NotFoundHandler())
addr := flagBrowseAddr
if len(addr) == 0 {
@@ -480,13 +483,62 @@
pproflib.PprofProxy(h.ctx, browseProfilesPath, name).ServeHTTP(w, r)
}
+type allTracesHandler struct { ctx *context.T }
+
+func (a *allTracesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ var (
+ server = r.FormValue("n")
+ name = naming.Join(server, "__debug", "vtrace")
+ )
+ if len(server) == 0 {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(w, "Must specify a server with the URL query parameter 'n'")
+ return
+ }
+ ctx, tracer := newTracer(a.ctx)
+ stub := svtrace.StoreClient(name)
+
+ fmt.Println("calling out to", name)
+ call, err := stub.AllTraces(ctx)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ fmt.Fprintf(w, "Failed to get all trace ids on %s: %v", name, err)
+ return
+ }
+ stream := call.RecvStream()
+ var traces []string
+ for stream.Advance() {
+ id := stream.Value().Id
+ fmt.Printf("Got back: %x", id)
+ traces = append(traces, hex.EncodeToString(id[:]))
+ }
+
+ data := struct {
+ Ids []string
+ StreamError error
+ CallError error
+ ServerName string
+ CommandLine string
+ Vtrace *Tracer
+ }{
+ Ids: traces,
+ StreamError: stream.Err(),
+ CallError: call.Finish(),
+ CommandLine: fmt.Sprintf("debug vtraces %q", name),
+ ServerName: server,
+ Vtrace: tracer,
+ }
+ executeTemplate(a.ctx, w, r, tmplBrowseAllTraces, data)
+ fmt.Println("Done with template")
+}
+
type divTree struct {
// Start is a value from 0-100 which is the percentage of time into the parent span's duration
// that this span started.
Start int
// End is a value from 0-100 which is the percentage of time into the parent span's duration
// that this span ended.
- End int
+ Width int
// VerticalOffset is the number of pixels from the top of the parent div this div should appear.
VerticalOffset int
Name string
@@ -513,11 +565,13 @@
}
parentDuration := parentEnd.Sub(parentStart).Seconds()
- start := int(100 * n.Span.Start.Sub(parentStart).Seconds() / parentDuration)
- end := int(100 * n.Span.End.Sub(parentStart).Seconds() / parentDuration)
+ fmt.Println("parent start is", parentStart, "start", startTime, "parentEnd", parentEnd, "end", endTime)
+ start := int(100 * startTime.Sub(parentStart).Seconds() / parentDuration)
+ width := int(100 * endTime.Sub(parentStart).Seconds() / parentDuration) - start
+ fmt.Println("start:", start, "end", width)
top := &divTree{
Start: start,
- End: end,
+ Width: width,
Name: n.Span.Name,
VerticalOffset: verticalPosition,
}
@@ -531,10 +585,10 @@
top.Annotations[i].Position = int(100 * a.When.Sub(parentStart).Seconds() / parentDuration) - start
}
top.Children = make([]divTree, len(n.Children))
- pos := 15
+ pos := 2
for i, c := range n.Children {
top.Children[i] = *convertToTree(c, startTime, endTime, pos)
- pos += 15
+ pos += 2
}
return top
@@ -605,7 +659,7 @@
}
stub := svtrace.StoreClient(name)
-
+ ctx, tracer := newTracer(v.ctx)
id, err := uniqueid.FromHexString(traceId)
if err != nil {
@@ -614,13 +668,16 @@
return
}
- trace, err := stub.Trace(v.ctx, id)
+ trace, err := stub.Trace(ctx, id)
if err != nil {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Unknown trace id: %s", traceId)
return
}
+ var buf bytes.Buffer
+
+ vtrace.FormatTrace(&buf, &trace, nil)
node := vtrace.BuildTree(&trace)
if node == nil {
@@ -633,9 +690,18 @@
data := struct{
Id string
Root *divTree
+ ServerName string
+ CommandLine string
+ DebugTrace string
+ Vtrace *Tracer
}{
Id: traceId,
Root: tree,
+ ServerName: server,
+ CommandLine: fmt.Sprintf("debug vtraces %q", name),
+ Vtrace: tracer,
+ DebugTrace: buf.String(),
+
}
executeTemplate(v.ctx, w, r, tmplBrowseVtrace, data)
}
@@ -654,6 +720,8 @@
content = "{{template `.header` .}}" + content + "{{template `.footer` .}}"
t := template.Must(tmplBrowseHeader.Clone())
t = template.Must(t.AddParseTree(tmplBrowseFooter.Name(), tmplBrowseFooter.Tree))
+ colors := []string{"red", "blue", "green"}
+ pos := 0
t = t.Funcs(template.FuncMap{
"verrorID": verror.ErrorID,
"unmarshalPublicKey": security.UnmarshalPublicKey,
@@ -669,6 +737,11 @@
vdl.Convert(&ret, v)
return ret
},
+ "nextColor": func() string {
+ c := colors[pos]
+ pos = (pos + 1) % len(colors)
+ return c
+ },
})
t = template.Must(t.New(name).Parse(content))
return t
@@ -945,18 +1018,29 @@
</div>
</section>
`)
+ tmplBrowseAllTraces = makeTemplate("alltraces", `
+<section class="section-center mdl-grid">
+ <ul>
+ {{$name := .ServerName}}
+ {{range .Ids}}
+ <li><a href="/vtrace?n={{$name}}&t={{.}}">{{.}}</a></li>
+ {{end}}
+ </ul>
+ </section>
+`)
tmplBrowseVtrace = makeTemplate("vtrace",`
{{define ".span"}}
-<div style='position:relative;left:{{.Start}}%;width{{.Width}};top:{{.VerticalPosition}px'>
+<div style="position:relative;left:{{.Start}}%;width:{{.Width}}%;top:{{.VerticalOffset}}px;margin:0px;padding:0px">
<!-- Root span -->
- <span title='{{.Name}}' style='position:relative;left:0%;width:100%;background:red></span>
- {{range _, $child := .Children}}
+ <div title="{{.Name}}" style="position:relative;left:0%;width:100%;background:{{nextColor}};height:15px;display:block;margin:0px;padding:0px"></div>
+ {{range $i, $child := .Children}}
{{template ".span" $child}}
{{end}}
</div>
{{end}}
<section class="section--center mdl-grid">
<h5>Vtrace for {{.Id}}</h5>
+ <pre>{{.DebugTrace}}</pre>
<div id="parent" class="mdl-cell mdl-cell--12-col">
{{template ".span" .Root}}
</div>