mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 02:00:43 +00:00
Expose keys, sort and dedupe traces, and hide show children in ui.
This commit is contained in:
@@ -4,13 +4,15 @@ import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"log"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/msackman/skiplist"
|
||||
|
||||
"github.com/weaveworks/scope/experimental/tracer/ptrace"
|
||||
)
|
||||
|
||||
const epsilon = int64(5)
|
||||
const epsilon = int64(5) * 1000 // milliseconds
|
||||
|
||||
// Traces are indexed by from addr, from port, and start time.
|
||||
type key struct {
|
||||
@@ -19,14 +21,25 @@ type key struct {
|
||||
startTime int64
|
||||
}
|
||||
|
||||
func (k key) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("\"%x.%x.%x\"", k.fromAddr, k.fromPort, k.startTime)), nil
|
||||
}
|
||||
|
||||
type trace struct {
|
||||
PID int
|
||||
Key key
|
||||
ServerDetails *ptrace.ConnectionDetails
|
||||
ClientDetails *ptrace.ConnectionDetails
|
||||
Children []*trace
|
||||
Level int
|
||||
}
|
||||
|
||||
type byKey []*trace
|
||||
|
||||
func (a byKey) Len() int { return len(a) }
|
||||
func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byKey) Less(i, j int) bool { return a[i].Key.startTime < a[j].Key.startTime }
|
||||
|
||||
type store struct {
|
||||
sync.RWMutex
|
||||
traces *skiplist.SkipList
|
||||
@@ -67,6 +80,7 @@ func (s *store) RecordConnection(pid int, connection *ptrace.Fd) {
|
||||
|
||||
newTrace := &trace{
|
||||
PID: pid,
|
||||
Key: newKey(connection),
|
||||
ServerDetails: &connection.ConnectionDetails,
|
||||
}
|
||||
for _, child := range connection.Children {
|
||||
@@ -76,7 +90,7 @@ func (s *store) RecordConnection(pid int, connection *ptrace.Fd) {
|
||||
})
|
||||
}
|
||||
|
||||
newTraceKey := newKey(connection)
|
||||
newTraceKey := newTrace.Key
|
||||
|
||||
// First, see if this new conneciton is a child of an existing connection.
|
||||
// This indicates we have a parent connection to attach to.
|
||||
@@ -119,11 +133,20 @@ func (s *store) Traces() []*trace {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
traces := []*trace{}
|
||||
traces := map[key]*trace{}
|
||||
var cur = s.traces.First()
|
||||
for cur != nil {
|
||||
traces = append(traces, cur.Value.(*trace))
|
||||
trace := cur.Value.(*trace)
|
||||
traces[trace.Key] = trace
|
||||
cur = cur.Next()
|
||||
}
|
||||
return traces
|
||||
|
||||
result := []*trace{}
|
||||
for _, trace := range traces {
|
||||
result = append(result, trace)
|
||||
}
|
||||
|
||||
sort.Sort(byKey(result))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<script>
|
||||
$(function () {
|
||||
var currentContainer = null;
|
||||
var expandedTrace = null;
|
||||
var containersByID = {};
|
||||
var containers = [];
|
||||
var traces = [];
|
||||
@@ -28,6 +29,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('isExpanded', function(options) {
|
||||
if (expandedTrace && this.Key === expandedTrace) {
|
||||
return options.fn(this)
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('spaces', function(input) {
|
||||
return new Array(input + 1).join("> ");
|
||||
});
|
||||
@@ -51,6 +58,7 @@
|
||||
});
|
||||
|
||||
Handlebars.registerPartial('traces', $("#traces").html());
|
||||
Handlebars.registerPartial('children', $("#children").html());
|
||||
|
||||
function render() {
|
||||
var template = $('script#process-template').text();
|
||||
@@ -80,7 +88,7 @@
|
||||
containersByID[container.Id] = container
|
||||
});
|
||||
// auto-select first container
|
||||
if (containers.length) {
|
||||
if (containers.length && currentContainer === null) {
|
||||
currentContainer = containersByID[containers[0].Id];
|
||||
}
|
||||
render();
|
||||
@@ -118,6 +126,16 @@
|
||||
type: 'DELETE',
|
||||
});
|
||||
})
|
||||
|
||||
$("body").on("click", "table tr.trace", function() {
|
||||
var key = $(this).data("key");
|
||||
if (expandedTrace === key) {
|
||||
expandedTrace = null;
|
||||
} else {
|
||||
expandedTrace = key;
|
||||
}
|
||||
render()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
@@ -174,6 +192,9 @@
|
||||
opacity: 0.4;
|
||||
font-weight: normal;
|
||||
}
|
||||
tr.trace {
|
||||
cursor: pointer;
|
||||
}
|
||||
.mainview {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
@@ -187,6 +208,28 @@
|
||||
}
|
||||
</style>
|
||||
<script type="text/x-handlebars-template" id="traces">
|
||||
{{#.}}
|
||||
<tr class="trace" data-key="{{Key}}">
|
||||
{{#if ServerDetails}}
|
||||
{{#with ServerDetails}}
|
||||
<td>{{spaces ../Level}}{{ts Start}}</td><td>{{duration .}}</td>
|
||||
<td>{{../PID}}</td><td>{{FromAddr}}:{{FromPort}}</td>
|
||||
<td>{{ToAddr}}:{{ToPort}}</td><td>{{count ../Children}}</td>
|
||||
{{/with}}
|
||||
{{else}}
|
||||
{{#with ClientDetails}}
|
||||
<td>{{spaces ../Level}}{{ts Start}}</td><td>{{duration .}}</td>
|
||||
<td>{{../PID}}</td><td>{{FromAddr}}:{{FromPort}}</td>
|
||||
<td>{{ToAddr}}:{{ToPort}}</td><td>{{count ../Children}}</td>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</tr>
|
||||
{{#isExpanded}}
|
||||
{{>children Children}}
|
||||
{{/isExpanded}}
|
||||
{{/.}}
|
||||
</script>
|
||||
<script type="text/x-handlebars-template" id="children">
|
||||
{{#.}}
|
||||
{{#if ServerDetails}}
|
||||
{{#with ServerDetails}}
|
||||
@@ -203,7 +246,7 @@
|
||||
<td>{{ToAddr}}:{{ToPort}}</td><td>{{count ../Children}}</tr>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
{{>traces Children}}
|
||||
{{>children Children}}
|
||||
{{/.}}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user