mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-13 06:30:10 +00:00
More profiler tests
This commit is contained in:
@@ -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
|
||||||
|
}
|
||||||
|
@@ -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))
|
||||||
|
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -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)
|
||||||
|
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
265
src/go/tests/profiler_docs_stats.json
Normal file
265
src/go/tests/profiler_docs_stats.json
Normal 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
|
||||||
|
}
|
||||||
|
]
|
161
src/go/tests/profiler_docs_stats.want.json
Normal file
161
src/go/tests/profiler_docs_stats.want.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
7
src/go/tests/profiler_docs_total_counters.want.json
Normal file
7
src/go/tests/profiler_docs_total_counters.want.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"Count": 3,
|
||||||
|
"Scanned": 10075,
|
||||||
|
"Returned": 75,
|
||||||
|
"QueryTime": 7,
|
||||||
|
"Bytes": 1061660
|
||||||
|
}
|
53
src/go/tests/profiler_docs_total_stats.want.json
Executable file
53
src/go/tests/profiler_docs_total_stats.want.json
Executable 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
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user