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

View File

@@ -50,21 +50,27 @@ type Profiler interface {
GetLastError() error
QueriesChan() chan []QueryInfoAndCounters
TimeoutsChan() <-chan time.Time
ProcessDoc(proto.SystemProfile, map[StatsGroupKey]*QueryInfoAndCounters) error
Start()
Stop()
}
type Profile struct {
filters []filter.Filter
iterator pmgo.IterManager
ticker <-chan time.Time
queriesChan chan []QueryInfoAndCounters
stopChan chan bool
docsChan chan proto.SystemProfile
timeoutsChan chan time.Time
filters []filter.Filter
iterator pmgo.IterManager
ticker <-chan time.Time
queriesChan chan []QueryInfoAndCounters
stopChan chan bool
docsChan chan proto.SystemProfile
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
keyFilters []string
fingerprinter fingerprinter.Fingerprinter
lock sync.Mutex
running bool
lastError error
stopWaitGroup sync.WaitGroup
@@ -142,6 +148,8 @@ func (p *Profile) QueriesChan() chan []QueryInfoAndCounters {
}
func (p *Profile) Start() {
p.lock.Lock()
defer p.lock.Unlock()
if !p.running {
p.running = true
p.stopChan = make(chan bool)
@@ -150,15 +158,15 @@ func (p *Profile) Start() {
}
func (p *Profile) Stop() {
p.lock.Lock()
defer p.lock.Unlock()
if p.running {
select {
case p.stopChan <- true:
default:
}
close(p.timeoutsChan)
// Wait for getData to receive the stop signal
p.stopWaitGroup.Wait()
p.iterator.Close()
}
}
@@ -180,6 +188,7 @@ MAIN_GETDATA_LOOP:
p.queriesChan <- mapToArray(p.queriesInfoAndCounters)
p.queriesInfoAndCounters = make(map[StatsGroupKey]*QueryInfoAndCounters) // Reset stats
case <-p.stopChan:
// Close the iterator to break the loop on getDocs
p.iterator.Close()
break MAIN_GETDATA_LOOP
}
@@ -212,10 +221,7 @@ func (p *Profile) getDocs() {
}
}
p.queriesChan <- mapToArray(p.queriesInfoAndCounters)
select {
case p.stopChan <- true:
default:
}
p.Stop()
}
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 ok bool
p.countersMapLock.Lock()
defer p.countersMapLock.Unlock()
key := StatsGroupKey{
Operation: doc.Op,
Fingerprint: fp,
Namespace: doc.Ns,
}
if s, ok = p.queriesInfoAndCounters[key]; !ok {
if s, ok = stats[key]; !ok {
realQuery, _ := util.GetQueryField(doc.Query)
s = &QueryInfoAndCounters{
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,
Query: realQuery,
}
p.queriesInfoAndCounters[key] = s
stats[key] = s
}
s.Count++
s.NScanned = append(s.NScanned, float64(doc.DocsExamined))

View File

@@ -1,6 +1,7 @@
package profiler
import (
"fmt"
"log"
"os"
"reflect"
@@ -25,6 +26,11 @@ type testVars struct {
var vars testVars
func parseDate(dateStr string) time.Time {
date, _ := time.Parse(time.RFC3339Nano, dateStr)
return date
}
func TestMain(m *testing.M) {
var err error
if vars.RootPath, err = tutil.RootPath(); err != nil {
@@ -58,8 +64,8 @@ func TestRegularIterator(t *testing.T) {
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp)
firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00")
lastSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:20.214-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+00:00")
want := []QueryInfoAndCounters{
QueryInfoAndCounters{
ID: "c6466139b21c392acd0699e863b50d81",
@@ -113,17 +119,14 @@ func TestIteratorTimeout(t *testing.T) {
iter.EXPECT().Timeout().Return(false),
// When there are no more docs, iterator will 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{}
fp := fingerprinter.NewFingerprinter(fingerprinter.DEFAULT_KEY_FILTERS)
prof := NewProfiler(iter, filters, nil, fp)
firstSeen, _ := time.Parse(time.RFC3339Nano, "2017-04-01T23:01:19.914-03:00")
lastSeen, _ := 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+00:00")
want := []QueryInfoAndCounters{
QueryInfoAndCounters{
ID: "c6466139b21c392acd0699e863b50d81",
@@ -196,7 +199,7 @@ func TestTailIterator(t *testing.T) {
iter.EXPECT().Timeout().Return(false),
// 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
// 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().Timeout().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)
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{
QueryInfoAndCounters{
ID: "c6466139b21c392acd0699e863b50d81",
@@ -225,8 +222,8 @@ func TestTailIterator(t *testing.T) {
"shardVersion": []interface{}{float64(0), "000000000000000000000000"},
},
Fingerprint: "find",
FirstSeen: firstSeen,
LastSeen: lastSeen,
FirstSeen: parseDate("2017-04-01T23:01:20.214+00:00"),
LastSeen: parseDate("2017-04-01T23:01:20.214+00:00"),
TableScan: false,
Count: 1,
BlockedTime: Times(nil),
@@ -245,8 +242,8 @@ func TestTailIterator(t *testing.T) {
"shardVersion": []interface{}{float64(0), "000000000000000000000000"},
},
Fingerprint: "find",
FirstSeen: firstSeen2,
LastSeen: lastSeen2,
FirstSeen: parseDate("2017-04-01T23:01:19.914+00:00"),
LastSeen: parseDate("2017-04-01T23:01:19.914+00:00"),
TableScan: false,
Count: 1,
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()
uptime := uptime(session)
queriesStats := profiler.CalcQueriesStats(queries, uptime)
sortedQueryStats := sortQueries(queriesStats, opts.OrderBy)

View File

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