mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-13 14:39:28 +00:00
Fixed get profiler status func
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/howeyc/gopass"
|
"github.com/howeyc/gopass"
|
||||||
|
"github.com/kr/pretty"
|
||||||
"github.com/montanaflynn/stats"
|
"github.com/montanaflynn/stats"
|
||||||
"github.com/pborman/getopt"
|
"github.com/pborman/getopt"
|
||||||
"github.com/percona/percona-toolkit/src/go/lib/config"
|
"github.com/percona/percona-toolkit/src/go/lib/config"
|
||||||
@@ -71,6 +73,7 @@ func (a times) Less(i, j int) bool { return a[i].Before(a[j]) }
|
|||||||
|
|
||||||
type stat struct {
|
type stat struct {
|
||||||
ID string
|
ID string
|
||||||
|
Operation string
|
||||||
Fingerprint string
|
Fingerprint string
|
||||||
Namespace string
|
Namespace string
|
||||||
Query map[string]interface{}
|
Query map[string]interface{}
|
||||||
@@ -87,6 +90,7 @@ type stat struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type groupKey struct {
|
type groupKey struct {
|
||||||
|
Operation string
|
||||||
Fingerprint string
|
Fingerprint string
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
@@ -104,6 +108,8 @@ type statistics struct {
|
|||||||
|
|
||||||
type queryInfo struct {
|
type queryInfo struct {
|
||||||
Count int
|
Count int
|
||||||
|
Operation string
|
||||||
|
Query string
|
||||||
Fingerprint string
|
Fingerprint string
|
||||||
FirstSeen time.Time
|
FirstSeen time.Time
|
||||||
ID string
|
ID string
|
||||||
@@ -151,7 +157,7 @@ func main() {
|
|||||||
log.Infof("cannot check version updates: %s", err.Error())
|
log.Infof("cannot check version updates: %s", err.Error())
|
||||||
} else {
|
} else {
|
||||||
if advice != "" {
|
if advice != "" {
|
||||||
log.Infof(advice)
|
log.Warn(advice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +172,7 @@ func main() {
|
|||||||
dialer := pmgo.NewDialer()
|
dialer := pmgo.NewDialer()
|
||||||
session, err := dialer.DialWithInfo(di)
|
session, err := dialer.DialWithInfo(di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error connecting to the db %s", err)
|
log.Errorf("Error connecting to the db: %s while trying to connect to %s", err, di.Addrs[0])
|
||||||
os.Exit(3)
|
os.Exit(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +183,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isProfilerEnabled == false {
|
if isProfilerEnabled == false {
|
||||||
log.Errorf("Cannot get profiler status: %s", err.Error())
|
log.Error("Profiler is not enabled")
|
||||||
os.Exit(5)
|
os.Exit(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +192,8 @@ func main() {
|
|||||||
|
|
||||||
uptime := uptime(session)
|
uptime := uptime(session)
|
||||||
|
|
||||||
|
printHeader(opts)
|
||||||
|
|
||||||
queryTotals := calcTotalQueryStats(queries, uptime)
|
queryTotals := calcTotalQueryStats(queries, uptime)
|
||||||
tt, _ := template.New("query").Funcs(template.FuncMap{
|
tt, _ := template.New("query").Funcs(template.FuncMap{
|
||||||
"Format": format,
|
"Format": format,
|
||||||
@@ -282,10 +290,13 @@ func calcQueryStats(queries []stat, uptime int64) []queryInfo {
|
|||||||
queryStats := []queryInfo{}
|
queryStats := []queryInfo{}
|
||||||
_, totalScanned, totalReturned, totalQueryTime, totalBytes := calcTotals(queries)
|
_, totalScanned, totalReturned, totalQueryTime, totalBytes := calcTotals(queries)
|
||||||
for rank, query := range queries {
|
for rank, query := range queries {
|
||||||
|
buf, _ := json.Marshal(query.Query)
|
||||||
qi := queryInfo{
|
qi := queryInfo{
|
||||||
Rank: rank,
|
Rank: rank,
|
||||||
Count: query.Count,
|
Count: query.Count,
|
||||||
ID: query.ID,
|
ID: query.ID,
|
||||||
|
Operation: query.Operation,
|
||||||
|
Query: string(buf),
|
||||||
Fingerprint: query.Fingerprint,
|
Fingerprint: query.Fingerprint,
|
||||||
Scanned: calcStats(query.NScanned),
|
Scanned: calcStats(query.NScanned),
|
||||||
Returned: calcStats(query.NReturned),
|
Returned: calcStats(query.NReturned),
|
||||||
@@ -296,7 +307,6 @@ func calcQueryStats(queries []stat, uptime int64) []queryInfo {
|
|||||||
Namespace: query.Namespace,
|
Namespace: query.Namespace,
|
||||||
QPS: float64(query.Count) / float64(uptime),
|
QPS: float64(query.Count) / float64(uptime),
|
||||||
}
|
}
|
||||||
fmt.Printf("QPS>> query.Count: %v, uptime: %v, QPS: %v\n", query.Count, uptime, qi.QPS)
|
|
||||||
if totalScanned > 0 {
|
if totalScanned > 0 {
|
||||||
qi.Scanned.Pct = qi.Scanned.Total * 100 / totalScanned
|
qi.Scanned.Pct = qi.Scanned.Total * 100 / totalScanned
|
||||||
}
|
}
|
||||||
@@ -369,6 +379,8 @@ func getData(i iter) []stat {
|
|||||||
log.Debug(`Documents returned by db.getSiblinfDB("<dbnamehere>").system.profile.Find({"op": {"$nin": []string{"getmore", "delete"}}).Sort("-$natural")`)
|
log.Debug(`Documents returned by db.getSiblinfDB("<dbnamehere>").system.profile.Find({"op": {"$nin": []string{"getmore", "delete"}}).Sort("-$natural")`)
|
||||||
|
|
||||||
for i.Next(&doc) && i.Err() == nil {
|
for i.Next(&doc) && i.Err() == nil {
|
||||||
|
log.Debugln("====================================================================================================")
|
||||||
|
log.Debug(pretty.Sprint(doc))
|
||||||
if len(doc.Query) > 0 {
|
if len(doc.Query) > 0 {
|
||||||
query := doc.Query
|
query := doc.Query
|
||||||
if squery, ok := doc.Query["$query"]; ok {
|
if squery, ok := doc.Query["$query"]; ok {
|
||||||
@@ -380,12 +392,14 @@ func getData(i iter) []stat {
|
|||||||
var s *stat
|
var s *stat
|
||||||
var ok bool
|
var ok bool
|
||||||
key := groupKey{
|
key := groupKey{
|
||||||
|
Operation: doc.Op,
|
||||||
Fingerprint: fp,
|
Fingerprint: fp,
|
||||||
Namespace: doc.Ns,
|
Namespace: doc.Ns,
|
||||||
}
|
}
|
||||||
if s, ok = stats[key]; !ok {
|
if s, ok = stats[key]; !ok {
|
||||||
s = &stat{
|
s = &stat{
|
||||||
ID: fmt.Sprintf("%x", md5.Sum([]byte(fp+doc.Ns))),
|
ID: fmt.Sprintf("%x", md5.Sum([]byte(fp+doc.Ns))),
|
||||||
|
Operation: doc.Op,
|
||||||
Fingerprint: fp,
|
Fingerprint: fp,
|
||||||
Namespace: doc.Ns,
|
Namespace: doc.Ns,
|
||||||
TableScan: false,
|
TableScan: false,
|
||||||
@@ -421,7 +435,7 @@ func getData(i iter) []stat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getOptions() (*options, error) {
|
func getOptions() (*options, error) {
|
||||||
opts := &options{Host: "localhost:27017", LogLevel: "error", OrderBy: []string{"count"}}
|
opts := &options{Host: "localhost:27017", LogLevel: "warn", OrderBy: []string{"count"}}
|
||||||
getopt.BoolVarLong(&opts.Help, "help", '?', "Show help")
|
getopt.BoolVarLong(&opts.Help, "help", '?', "Show help")
|
||||||
getopt.BoolVarLong(&opts.Version, "version", 'v', "show version & exit")
|
getopt.BoolVarLong(&opts.Version, "version", 'v', "show version & exit")
|
||||||
getopt.BoolVarLong(&opts.NoVersionCheck, "no-version-check", 'c', "Don't check for updates")
|
getopt.BoolVarLong(&opts.NoVersionCheck, "no-version-check", 'c', "Don't check for updates")
|
||||||
@@ -518,6 +532,12 @@ func keys(query map[string]interface{}, level int) []string {
|
|||||||
return ks
|
return ks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printHeader(opts *options) {
|
||||||
|
fmt.Printf("%s - %s\n", TOOLNAME, time.Now().Format(time.RFC1123Z))
|
||||||
|
fmt.Printf("Host: %s", opts.Host)
|
||||||
|
fmt.Println("")
|
||||||
|
}
|
||||||
|
|
||||||
func getQueryTemplate() string {
|
func getQueryTemplate() string {
|
||||||
|
|
||||||
t := `
|
t := `
|
||||||
@@ -533,15 +553,15 @@ func getQueryTemplate() string {
|
|||||||
# Bytes recv {{printf "% 4.0f" .ResponseLength.Pct}} {{Format .ResponseLength.Total 7.2}} {{Format .ResponseLength.Min 7.2}} {{Format .ResponseLength.Max 7.2}} {{Format .ResponseLength.Avg 7.2}} {{Format .ResponseLength.Pct95 7.2}} {{Format .ResponseLength.StdDev 7.2}} {{Format .ResponseLength.Median 7.2}}
|
# Bytes recv {{printf "% 4.0f" .ResponseLength.Pct}} {{Format .ResponseLength.Total 7.2}} {{Format .ResponseLength.Min 7.2}} {{Format .ResponseLength.Max 7.2}} {{Format .ResponseLength.Avg 7.2}} {{Format .ResponseLength.Pct95 7.2}} {{Format .ResponseLength.StdDev 7.2}} {{Format .ResponseLength.Median 7.2}}
|
||||||
# String:
|
# String:
|
||||||
# Namespaces {{.Namespace}}
|
# Namespaces {{.Namespace}}
|
||||||
|
# Operation {{.Operation}}
|
||||||
# Fingerprint {{.Fingerprint}}
|
# Fingerprint {{.Fingerprint}}
|
||||||
|
# Query {{.Query}}
|
||||||
`
|
`
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTotalsTemplate() string {
|
func getTotalsTemplate() string {
|
||||||
t := `
|
t := `
|
||||||
pt-query profile
|
|
||||||
|
|
||||||
# Totals
|
# Totals
|
||||||
# Ratio {{Format .Ratio 7.2}} (docs scanned/returned)
|
# Ratio {{Format .Ratio 7.2}} (docs scanned/returned)
|
||||||
# Attribute pct total min max avg 95% stddev median
|
# Attribute pct total min max avg 95% stddev median
|
||||||
@@ -701,11 +721,6 @@ func sortQueries(queries []stat, orderby []string) []stat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isProfilerEnabled(dialer pmgo.Dialer, di *mgo.DialInfo) (bool, error) {
|
func isProfilerEnabled(dialer pmgo.Dialer, di *mgo.DialInfo) (bool, error) {
|
||||||
session, err := dialer.DialWithInfo(di)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("error connecting to the db %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ps proto.ProfilerStatus
|
var ps proto.ProfilerStatus
|
||||||
replicaMembers, err := util.GetReplicasetMembers(dialer, di)
|
replicaMembers, err := util.GetReplicasetMembers(dialer, di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -713,10 +728,18 @@ func isProfilerEnabled(dialer pmgo.Dialer, di *mgo.DialInfo) (bool, error) {
|
|||||||
}
|
}
|
||||||
for _, member := range replicaMembers {
|
for _, member := range replicaMembers {
|
||||||
if member.State == proto.REPLICA_SET_MEMBER_PRIMARY {
|
if member.State == proto.REPLICA_SET_MEMBER_PRIMARY {
|
||||||
if err := session.DB(di.Database).Run(bson.M{"profile": -1}, &ps); err == nil {
|
di.Addrs = []string{member.Name}
|
||||||
if ps.Was == 0 {
|
session, err := dialer.DialWithInfo(di)
|
||||||
return false, nil
|
if err != nil {
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
if err := session.DB(di.Database).Run(bson.M{"profile": -1}, &ps); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ps.Was == 0 {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user