More profiler tests

This commit is contained in:
Carlos Salguero
2017-04-10 16:51:52 -03:00
parent 64a5c6d8b6
commit ced858214d
9 changed files with 740 additions and 37 deletions

View File

@@ -8,6 +8,10 @@ import (
"strings" "strings"
) )
const (
updateSamplesEnvVar = "UPDATE_SAMPLES"
)
func RootPath() (string, error) { func RootPath() (string, error) {
out, err := exec.Command("git", "rev-parse", "--show-toplevel").Output() out, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
if err != nil { if err != nil {
@@ -42,14 +46,21 @@ func LoadJson(filename string, destination interface{}) error {
func WriteJson(filename string, data interface{}) error { func WriteJson(filename string, data interface{}) error {
buf, err := json.Marshal(data) buf, err := json.MarshalIndent(data, "", " ")
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(filename, buf, 0) err = ioutil.WriteFile(filename, buf, 777)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func ShouldUpdateSamples() bool {
if os.Getenv(updateSamplesEnvVar) != "" {
return true
}
return false
}

View File

@@ -50,6 +50,7 @@ type Profiler interface {
GetLastError() error GetLastError() error
QueriesChan() chan []QueryInfoAndCounters QueriesChan() chan []QueryInfoAndCounters
TimeoutsChan() <-chan time.Time TimeoutsChan() <-chan time.Time
ProcessDoc(proto.SystemProfile, map[StatsGroupKey]*QueryInfoAndCounters) error
Start() Start()
Stop() Stop()
} }
@@ -62,9 +63,14 @@ type Profile struct {
stopChan chan bool stopChan chan bool
docsChan chan proto.SystemProfile docsChan chan proto.SystemProfile
timeoutsChan chan time.Time timeoutsChan chan time.Time
// For the moment ProcessDoc is exportable to it could be called from the "outside"
// For that reason, we need a mutex to make it thread safe. In the future this func
// will be unexported
countersMapLock sync.Mutex
queriesInfoAndCounters map[StatsGroupKey]*QueryInfoAndCounters queriesInfoAndCounters map[StatsGroupKey]*QueryInfoAndCounters
keyFilters []string keyFilters []string
fingerprinter fingerprinter.Fingerprinter fingerprinter fingerprinter.Fingerprinter
lock sync.Mutex
running bool running bool
lastError error lastError error
stopWaitGroup sync.WaitGroup stopWaitGroup sync.WaitGroup
@@ -142,6 +148,8 @@ func (p *Profile) QueriesChan() chan []QueryInfoAndCounters {
} }
func (p *Profile) Start() { func (p *Profile) Start() {
p.lock.Lock()
defer p.lock.Unlock()
if !p.running { if !p.running {
p.running = true p.running = true
p.stopChan = make(chan bool) p.stopChan = make(chan bool)
@@ -150,15 +158,15 @@ func (p *Profile) Start() {
} }
func (p *Profile) Stop() { func (p *Profile) Stop() {
p.lock.Lock()
defer p.lock.Unlock()
if p.running { if p.running {
select { select {
case p.stopChan <- true: case p.stopChan <- true:
default: default:
} }
close(p.timeoutsChan)
// Wait for getData to receive the stop signal // Wait for getData to receive the stop signal
p.stopWaitGroup.Wait() p.stopWaitGroup.Wait()
p.iterator.Close()
} }
} }
@@ -180,6 +188,7 @@ MAIN_GETDATA_LOOP:
p.queriesChan <- mapToArray(p.queriesInfoAndCounters) p.queriesChan <- mapToArray(p.queriesInfoAndCounters)
p.queriesInfoAndCounters = make(map[StatsGroupKey]*QueryInfoAndCounters) // Reset stats p.queriesInfoAndCounters = make(map[StatsGroupKey]*QueryInfoAndCounters) // Reset stats
case <-p.stopChan: case <-p.stopChan:
// Close the iterator to break the loop on getDocs
p.iterator.Close() p.iterator.Close()
break MAIN_GETDATA_LOOP break MAIN_GETDATA_LOOP
} }
@@ -212,10 +221,7 @@ func (p *Profile) getDocs() {
} }
} }
p.queriesChan <- mapToArray(p.queriesInfoAndCounters) p.queriesChan <- mapToArray(p.queriesInfoAndCounters)
select { p.Stop()
case p.stopChan <- true:
default:
}
} }
func (p *Profile) ProcessDoc(doc proto.SystemProfile, stats map[StatsGroupKey]*QueryInfoAndCounters) error { func (p *Profile) ProcessDoc(doc proto.SystemProfile, stats map[StatsGroupKey]*QueryInfoAndCounters) error {
@@ -226,12 +232,15 @@ func (p *Profile) ProcessDoc(doc proto.SystemProfile, stats map[StatsGroupKey]*Q
} }
var s *QueryInfoAndCounters var s *QueryInfoAndCounters
var ok bool var ok bool
p.countersMapLock.Lock()
defer p.countersMapLock.Unlock()
key := StatsGroupKey{ key := StatsGroupKey{
Operation: doc.Op, Operation: doc.Op,
Fingerprint: fp, Fingerprint: fp,
Namespace: doc.Ns, Namespace: doc.Ns,
} }
if s, ok = p.queriesInfoAndCounters[key]; !ok { if s, ok = stats[key]; !ok {
realQuery, _ := util.GetQueryField(doc.Query) realQuery, _ := util.GetQueryField(doc.Query)
s = &QueryInfoAndCounters{ s = &QueryInfoAndCounters{
ID: fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%s", key)))), ID: fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%s", key)))),
@@ -241,7 +250,7 @@ func (p *Profile) ProcessDoc(doc proto.SystemProfile, stats map[StatsGroupKey]*Q
TableScan: false, TableScan: false,
Query: realQuery, Query: realQuery,
} }
p.queriesInfoAndCounters[key] = s stats[key] = s
} }
s.Count++ s.Count++
s.NScanned = append(s.NScanned, float64(doc.DocsExamined)) s.NScanned = append(s.NScanned, float64(doc.DocsExamined))

View File

@@ -1,6 +1,7 @@
package profiler package profiler
import ( import (
"fmt"
"log" "log"
"os" "os"
"reflect" "reflect"
@@ -25,6 +26,11 @@ type testVars struct {
var vars testVars var vars testVars
func parseDate(dateStr string) time.Time {
date, _ := time.Parse(time.RFC3339Nano, dateStr)
return date
}
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
var err error var err error
if vars.RootPath, err = tutil.RootPath(); err != nil { if vars.RootPath, err = tutil.RootPath(); err != nil {
@@ -58,8 +64,8 @@ func TestRegularIterator(t *testing.T) {
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS) fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp) prof := NewProfiler(iter, filters, nil, fp)
firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00") firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914+00:00")
lastSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:20.214-03:00") lastSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:20.214+00:00")
want := []QueryInfoAndCounters{ want := []QueryInfoAndCounters{
QueryInfoAndCounters{ QueryInfoAndCounters{
ID: "c6466139b21c392acd0699e863b50d81", ID: "c6466139b21c392acd0699e863b50d81",
@@ -113,17 +119,14 @@ func TestIteratorTimeout(t *testing.T) {
iter.EXPECT().Timeout().Return(false), iter.EXPECT().Timeout().Return(false),
// When there are no more docs, iterator will close // When there are no more docs, iterator will close
iter.EXPECT().Close(), iter.EXPECT().Close(),
// And we are closing it again (to force the getData go-routine to end)
// at the profiler.Stop() method
iter.EXPECT().Close(),
) )
filters := []filter.Filter{} filters := []filter.Filter{}
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS) fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp) prof := NewProfiler(iter, filters, nil, fp)
firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00") firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914+00:00")
lastSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00") lastSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914+00:00")
want := []QueryInfoAndCounters{ want := []QueryInfoAndCounters{
QueryInfoAndCounters{ QueryInfoAndCounters{
ID: "c6466139b21c392acd0699e863b50d81", ID: "c6466139b21c392acd0699e863b50d81",
@@ -196,7 +199,7 @@ func TestTailIterator(t *testing.T) {
iter.EXPECT().Timeout().Return(false), iter.EXPECT().Timeout().Return(false),
// A Tail iterator will wait if the are no available docs. // A Tail iterator will wait if the are no available docs.
// Do a 1500 ms sleep before returning the second doc to simulate a tail wait // Do a 1500 ms sleep before returning the second doc to simulate a tail wait
// and to let the ticker ticks // and to let the ticker tick
iter.EXPECT().Next(gomock.Any()).Do(sleep).SetArg(0, docs[1]).Return(true), iter.EXPECT().Next(gomock.Any()).Do(sleep).SetArg(0, docs[1]).Return(true),
iter.EXPECT().Timeout().Return(false), iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).Return(false), iter.EXPECT().Next(gomock.Any()).Return(false),
@@ -209,12 +212,6 @@ func TestTailIterator(t *testing.T) {
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS) fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, ticker.C, fp) prof := NewProfiler(iter, filters, ticker.C, fp)
firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:20.214-03:00")
lastSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:20.214-03:00")
firstSeen2, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00")
lastSeen2, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00")
want := []QueryInfoAndCounters{ want := []QueryInfoAndCounters{
QueryInfoAndCounters{ QueryInfoAndCounters{
ID: "c6466139b21c392acd0699e863b50d81", ID: "c6466139b21c392acd0699e863b50d81",
@@ -225,8 +222,8 @@ func TestTailIterator(t *testing.T) {
"shardVersion": []interface{}{float64(0), "000000000000000000000000"}, "shardVersion": []interface{}{float64(0), "000000000000000000000000"},
}, },
Fingerprint: "find", Fingerprint: "find",
FirstSeen: firstSeen, FirstSeen: parseDate("2017-04-01T23:01:20.214+00:00"),
LastSeen: lastSeen, LastSeen: parseDate("2017-04-01T23:01:20.214+00:00"),
TableScan: false, TableScan: false,
Count: 1, Count: 1,
BlockedTime: Times(nil), BlockedTime: Times(nil),
@@ -245,8 +242,8 @@ func TestTailIterator(t *testing.T) {
"shardVersion": []interface{}{float64(0), "000000000000000000000000"}, "shardVersion": []interface{}{float64(0), "000000000000000000000000"},
}, },
Fingerprint: "find", Fingerprint: "find",
FirstSeen: firstSeen2, FirstSeen: parseDate("2017-04-01T23:01:19.914+00:00"),
LastSeen: lastSeen2, LastSeen: parseDate("2017-04-01T23:01:19.914+00:00"),
TableScan: false, TableScan: false,
Count: 1, Count: 1,
BlockedTime: Times(nil), BlockedTime: Times(nil),
@@ -271,3 +268,202 @@ func TestTailIterator(t *testing.T) {
} }
} }
} }
func TestCalcStats(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
docs := []proto.SystemProfile{}
err := tutil.LoadJson(vars.RootPath+samples+"profiler_docs_stats.json", &docs)
if err != nil {
t.Fatalf("cannot load samples: %s", err.Error())
}
want := []QueryStats{}
err = tutil.LoadJson(vars.RootPath+samples+"profiler_docs_stats.want.json", &want)
if err != nil {
t.Fatalf("cannot load expected results: %s", err.Error())
}
iter := pmgomock.NewMockIterManager(ctrl)
gomock.InOrder(
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[0]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[1]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[2]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).Return(false),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Close(),
)
filters := []filter.Filter{}
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp)
prof.Start()
select {
case queries := <-prof.QueriesChan():
stats := CalcQueriesStats(queries, 1)
if os.Getenv("UPDATE_SAMPLES") != "" {
tutil.WriteJson(vars.RootPath+samples+"profiler_docs_stats.want.json", stats)
}
if !reflect.DeepEqual(stats, want) {
t.Errorf("Invalid stats.\nGot:%#v\nWant: %#v\n", stats, want)
}
case <-time.After(2 * time.Second):
t.Error("Didn't get any query")
}
}
func TestCalcTotalStats(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
docs := []proto.SystemProfile{}
err := tutil.LoadJson(vars.RootPath+samples+"profiler_docs_stats.json", &docs)
if err != nil {
t.Fatalf("cannot load samples: %s", err.Error())
}
want := QueryStats{}
err = tutil.LoadJson(vars.RootPath+samples+"profiler_docs_total_stats.want.json", &want)
if err != nil && !tutil.ShouldUpdateSamples() {
t.Fatalf("cannot load expected results: %s", err.Error())
}
iter := pmgomock.NewMockIterManager(ctrl)
gomock.InOrder(
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[0]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[1]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[2]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).Return(false),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Close(),
)
filters := []filter.Filter{}
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp)
prof.Start()
select {
case queries := <-prof.QueriesChan():
stats := CalcTotalQueriesStats(queries, 1)
if os.Getenv("UPDATE_SAMPLES") != "" {
fmt.Println("Updating samples: " + vars.RootPath + samples + "profiler_docs_total_stats.want.json")
err := tutil.WriteJson(vars.RootPath+samples+"profiler_docs_total_stats.want.json", stats)
if err != nil {
fmt.Printf("cannot update samples: %s", err.Error())
}
}
if !reflect.DeepEqual(stats, want) {
t.Errorf("Invalid stats.\nGot:%#v\nWant: %#v\n", stats, want)
}
case <-time.After(2 * time.Second):
t.Error("Didn't get any query")
}
}
func TestCalcTotalCounters(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
docs := []proto.SystemProfile{}
err := tutil.LoadJson(vars.RootPath+samples+"profiler_docs_stats.json", &docs)
if err != nil {
t.Fatalf("cannot load samples: %s", err.Error())
}
want := totalCounters{}
err = tutil.LoadJson(vars.RootPath+samples+"profiler_docs_total_counters.want.json", &want)
if err != nil && !tutil.ShouldUpdateSamples() {
t.Fatalf("cannot load expected results: %s", err.Error())
}
iter := pmgomock.NewMockIterManager(ctrl)
gomock.InOrder(
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[0]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[1]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).SetArg(0, docs[2]).Return(true),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Next(gomock.Any()).Return(false),
iter.EXPECT().Timeout().Return(false),
iter.EXPECT().Close(),
)
filters := []filter.Filter{}
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp)
prof.Start()
select {
case queries := <-prof.QueriesChan():
counters := calcTotalCounters(queries)
if tutil.ShouldUpdateSamples() {
fmt.Println("Updating samples: " + vars.RootPath + samples + "profiler_docs_total_counters.want.json")
err := tutil.WriteJson(vars.RootPath+samples+"profiler_docs_total_counters.want.json", counters)
if err != nil {
fmt.Printf("cannot update samples: %s", err.Error())
}
}
if !reflect.DeepEqual(counters, want) {
t.Errorf("Invalid counters.\nGot:%#v\nWant: %#v\n", counters, want)
}
case <-time.After(2 * time.Second):
t.Error("Didn't get any query")
}
}
func TestProcessDoc(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
docs := []proto.SystemProfile{}
err := tutil.LoadJson(vars.RootPath+samples+"profiler_docs_stats.json", &docs)
if err != nil {
t.Fatalf("cannot load samples: %s", err.Error())
}
iter := pmgomock.NewMockIterManager(ctrl)
filters := []filter.Filter{}
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp)
var stats = make(map[StatsGroupKey]*QueryInfoAndCounters)
err = prof.ProcessDoc(docs[1], stats)
if err != nil {
t.Errorf("Error processing doc: %s\n", err.Error())
}
statsKey := StatsGroupKey{Operation: "query", Fingerprint: "s2", Namespace: "samples.col1"}
statsVal := &QueryInfoAndCounters{
ID: "84e09ef6a3dc35f472df05fa98eee7d3",
Namespace: "samples.col1",
Operation: "query",
Query: map[string]interface{}{"s2": map[string]interface{}{"$gte": "41991", "$lt": "33754"}},
Fingerprint: "s2",
FirstSeen: parseDate("2017-04-10T13:15:53.532-03:00"),
LastSeen: parseDate("2017-04-10T13:15:53.532-03:00"),
TableScan: false,
Count: 1,
BlockedTime: nil,
LockTime: nil,
NReturned: []float64{0},
NScanned: []float64{10000},
QueryTime: []float64{7},
ResponseLength: []float64{215},
}
want := map[StatsGroupKey]*QueryInfoAndCounters{statsKey: statsVal}
if !reflect.DeepEqual(stats, want) {
t.Errorf("Error in ProcessDoc.\nGot:%#v\nWant: %#v\n", stats, want)
}
}

View File

@@ -140,6 +140,7 @@ func main() {
queries := <-prof.QueriesChan() queries := <-prof.QueriesChan()
uptime := uptime(session) uptime := uptime(session)
queriesStats := profiler.CalcQueriesStats(queries, uptime) queriesStats := profiler.CalcQueriesStats(queries, uptime)
sortedQueryStats := sortQueries(queriesStats, opts.OrderBy) sortedQueryStats := sortQueries(queriesStats, opts.OrderBy)

View File

@@ -76,7 +76,7 @@
] ]
}, },
"ResponseLength": 1061230, "ResponseLength": 1061230,
"Ts": "2017-04-01T23:01:20.214-03:00", "Ts": "2017-04-01T23:01:20.214+00:00",
"User": "", "User": "",
"WriteConflicts": 0 "WriteConflicts": 0
}, },
@@ -157,7 +157,7 @@
] ]
}, },
"ResponseLength": 1061230, "ResponseLength": 1061230,
"Ts": "2017-04-01T23:01:19.914-03:00", "Ts": "2017-04-01T23:01:19.914+00:00",
"User": "", "User": "",
"WriteConflicts": 0 "WriteConflicts": 0
} }

View File

@@ -0,0 +1,265 @@
[
{
"AllUsers": [],
"Client": "127.0.0.1",
"CursorExhausted": false,
"DocsExamined": 75,
"ExecStats": {
"Advanced": 75,
"ExecutionTimeMillisEstimate": 10,
"InputStage": {
"Advanced": 0,
"Direction": "",
"DocsExamined": 0,
"ExecutionTimeMillisEstimate": 0,
"Filter": {
"Date": {
"Eq": ""
}
},
"Invalidates": 0,
"IsEOF": 0,
"NReturned": 0,
"NeedTime": 0,
"NeedYield": 0,
"RestoreState": 0,
"SaveState": 0,
"Stage": "",
"Works": 0
},
"Invalidates": 0,
"IsEOF": 0,
"LimitAmount": 0,
"NReturned": 75,
"NeedTime": 1,
"NeedYield": 0,
"RestoreState": 0,
"SaveState": 1,
"Stage": "COLLSCAN",
"Works": 76
},
"KeyUpdates": 0,
"KeysExamined": 0,
"Locks": {
"Collection": {
"AcquireCount": {
"R": 0
}
},
"Database": {
"AcquireCount": {
"R": 1
}
},
"Global": {
"AcquireCount": {
"R": 2
}
},
"MMAPV1Journal": {
"AcquireCount": {
"R": 0
}
}
},
"Millis": 0,
"Nreturned": 75,
"Ns": "samples.col1",
"NumYield": 0,
"Op": "query",
"Protocol": "op_command",
"Query": {
"find": "col1",
"shardVersion": [
0,
"000000000000000000000000"
]
},
"ResponseLength": 1061230,
"Ts": "2017-04-10T13:16:23.29-03:00",
"User": "",
"WriteConflicts": 0
},
{
"AllUsers": [],
"Client": "127.0.0.1",
"CursorExhausted": true,
"DocsExamined": 10000,
"ExecStats": {
"Advanced": 0,
"ExecutionTimeMillisEstimate": 10,
"InputStage": {
"Advanced": 0,
"Direction": "",
"DocsExamined": 0,
"ExecutionTimeMillisEstimate": 0,
"Filter": {
"Date": {
"Eq": ""
}
},
"Invalidates": 0,
"IsEOF": 0,
"NReturned": 0,
"NeedTime": 0,
"NeedYield": 0,
"RestoreState": 0,
"SaveState": 0,
"Stage": "",
"Works": 0
},
"Invalidates": 0,
"IsEOF": 1,
"LimitAmount": 0,
"NReturned": 0,
"NeedTime": 10001,
"NeedYield": 0,
"RestoreState": 78,
"SaveState": 78,
"Stage": "COLLSCAN",
"Works": 10002
},
"KeyUpdates": 0,
"KeysExamined": 0,
"Locks": {
"Collection": {
"AcquireCount": {
"R": 0
}
},
"Database": {
"AcquireCount": {
"R": 79
}
},
"Global": {
"AcquireCount": {
"R": 158
}
},
"MMAPV1Journal": {
"AcquireCount": {
"R": 0
}
}
},
"Millis": 7,
"Nreturned": 0,
"Ns": "samples.col1",
"NumYield": 78,
"Op": "query",
"Protocol": "op_command",
"Query": {
"filter": {
"s2": {
"$gte": "41991",
"$lt": "33754"
}
},
"find": "col1",
"shardVersion": [
0,
"000000000000000000000000"
]
},
"ResponseLength": 215,
"Ts": "2017-04-10T13:15:53.532-03:00",
"User": "",
"WriteConflicts": 0
},
{
"AllUsers": [],
"Client": "127.0.0.1",
"CursorExhausted": true,
"DocsExamined": 0,
"ExecStats": {
"Advanced": 0,
"ExecutionTimeMillisEstimate": 0,
"InputStage": {
"Advanced": 0,
"Direction": "",
"DocsExamined": 0,
"ExecutionTimeMillisEstimate": 0,
"Filter": {
"Date": {
"Eq": ""
}
},
"Invalidates": 0,
"IsEOF": 1,
"NReturned": 0,
"NeedTime": 1,
"NeedYield": 0,
"RestoreState": 0,
"SaveState": 0,
"Stage": "SORT_KEY_GENERATOR",
"Works": 2
},
"Invalidates": 0,
"IsEOF": 1,
"LimitAmount": 0,
"NReturned": 0,
"NeedTime": 1,
"NeedYield": 0,
"RestoreState": 0,
"SaveState": 0,
"Stage": "PROJECTION",
"Works": 2
},
"KeyUpdates": 0,
"KeysExamined": 0,
"Locks": {
"Collection": {
"AcquireCount": {
"R": 0
}
},
"Database": {
"AcquireCount": {
"R": 1
}
},
"Global": {
"AcquireCount": {
"R": 2
}
},
"MMAPV1Journal": {
"AcquireCount": {
"R": 0
}
}
},
"Millis": 0,
"Nreturned": 0,
"Ns": "samples.col1",
"NumYield": 0,
"Op": "query",
"Protocol": "op_command",
"Query": {
"filter": {
"user_id": {
"$gte": 3384024924,
"$lt": 195092007
}
},
"find": "col1",
"projection": {
"$sortKey": {
"$meta": "sortKey"
}
},
"shardVersion": [
0,
"000000000000000000000000"
],
"sort": {
"user_id": 1
}
},
"ResponseLength": 215,
"Ts": "2017-04-10T13:15:53.524-03:00",
"User": "",
"WriteConflicts": 0
}
]

View File

@@ -0,0 +1,161 @@
[
{
"ID": "c6466139b21c392acd0699e863b50d81",
"Namespace": "samples.col1",
"Operation": "query",
"Query": "{\"find\":\"col1\",\"shardVersion\":[0,\"000000000000000000000000\"]}",
"Fingerprint": "find",
"FirstSeen": "2017-04-10T13:16:23.29-03:00",
"LastSeen": "2017-04-10T13:16:23.29-03:00",
"Count": 1,
"QPS": 1,
"Rank": 0,
"Ratio": 1,
"QueryTime": {
"Pct": 0,
"Total": 0,
"Min": 0,
"Max": 0,
"Avg": 0,
"Pct95": 0,
"StdDev": 0,
"Median": 0
},
"ResponseLength": {
"Pct": 0.9995949739087844,
"Total": 1061230,
"Min": 1061230,
"Max": 1061230,
"Avg": 1061230,
"Pct95": 1061230,
"StdDev": 0,
"Median": 1061230
},
"Returned": {
"Pct": 100,
"Total": 75,
"Min": 75,
"Max": 75,
"Avg": 75,
"Pct95": 75,
"StdDev": 0,
"Median": 75
},
"Scanned": {
"Pct": 0.7444168734491315,
"Total": 75,
"Min": 75,
"Max": 75,
"Avg": 75,
"Pct95": 75,
"StdDev": 0,
"Median": 75
}
},
{
"ID": "84e09ef6a3dc35f472df05fa98eee7d3",
"Namespace": "samples.col1",
"Operation": "query",
"Query": "{\"s2\":{\"$gte\":\"41991\",\"$lt\":\"33754\"}}",
"Fingerprint": "s2",
"FirstSeen": "2017-04-10T13:15:53.532-03:00",
"LastSeen": "2017-04-10T13:15:53.532-03:00",
"Count": 1,
"QPS": 1,
"Rank": 0,
"Ratio": 0,
"QueryTime": {
"Pct": 100,
"Total": 7,
"Min": 7,
"Max": 7,
"Avg": 7,
"Pct95": 7,
"StdDev": 0,
"Median": 7
},
"ResponseLength": {
"Pct": 0.00020251304560782172,
"Total": 215,
"Min": 215,
"Max": 215,
"Avg": 215,
"Pct95": 215,
"StdDev": 0,
"Median": 215
},
"Returned": {
"Pct": 0,
"Total": 0,
"Min": 0,
"Max": 0,
"Avg": 0,
"Pct95": 0,
"StdDev": 0,
"Median": 0
},
"Scanned": {
"Pct": 99.25558312655087,
"Total": 10000,
"Min": 10000,
"Max": 10000,
"Avg": 10000,
"Pct95": 10000,
"StdDev": 0,
"Median": 10000
}
},
{
"ID": "69e3b2f5f0aefcec868c0fa5ec8cebe5",
"Namespace": "samples.col1",
"Operation": "query",
"Query": "{\"user_id\":{\"$gte\":3384024924,\"$lt\":195092007}}",
"Fingerprint": "user_id",
"FirstSeen": "2017-04-10T13:15:53.524-03:00",
"LastSeen": "2017-04-10T13:15:53.524-03:00",
"Count": 1,
"QPS": 1,
"Rank": 0,
"Ratio": 0,
"QueryTime": {
"Pct": 0,
"Total": 0,
"Min": 0,
"Max": 0,
"Avg": 0,
"Pct95": 0,
"StdDev": 0,
"Median": 0
},
"ResponseLength": {
"Pct": 0.00020251304560782172,
"Total": 215,
"Min": 215,
"Max": 215,
"Avg": 215,
"Pct95": 215,
"StdDev": 0,
"Median": 215
},
"Returned": {
"Pct": 0,
"Total": 0,
"Min": 0,
"Max": 0,
"Avg": 0,
"Pct95": 0,
"StdDev": 0,
"Median": 0
},
"Scanned": {
"Pct": 0,
"Total": 0,
"Min": 0,
"Max": 0,
"Avg": 0,
"Pct95": 0,
"StdDev": 0,
"Median": 0
}
}
]

View File

@@ -0,0 +1,7 @@
{
"Count": 3,
"Scanned": 10075,
"Returned": 75,
"QueryTime": 7,
"Bytes": 1061660
}

View File

@@ -0,0 +1,53 @@
{
"ID": "",
"Namespace": "",
"Operation": "",
"Query": "null",
"Fingerprint": "",
"FirstSeen": "0001-01-01T00:00:00Z",
"LastSeen": "0001-01-01T00:00:00Z",
"Count": 0,
"QPS": 0,
"Rank": 0,
"Ratio": 134.33333333333334,
"QueryTime": {
"Pct": 100,
"Total": 7,
"Min": 0,
"Max": 7,
"Avg": 2.3333333333333335,
"Pct95": 7,
"StdDev": 3.2998316455372216,
"Median": 0
},
"ResponseLength": {
"Pct": 1,
"Total": 1061660,
"Min": 215,
"Max": 1061230,
"Avg": 353886.6666666667,
"Pct95": 1061230,
"StdDev": 500167.26762709644,
"Median": 215
},
"Returned": {
"Pct": 100,
"Total": 75,
"Min": 0,
"Max": 75,
"Avg": 25,
"Pct95": 75,
"StdDev": 35.35533905932738,
"Median": 0
},
"Scanned": {
"Pct": 100,
"Total": 10075,
"Min": 0,
"Max": 10000,
"Avg": 3358.3333333333335,
"Pct95": 10000,
"StdDev": 4696.46734850308,
"Median": 75
}
}