From 9009c795a7fb6a987cae6da51d39ce5bb62e13f3 Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Tue, 28 Jul 2015 14:14:34 +0900 Subject: [PATCH] =?UTF-8?q?Go=20=E7=89=88=E3=81=A7=20-dump=20=E3=82=AA?= =?UTF-8?q?=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- myprofiler.go | 35 ++++++++++++++++++----------------- myprofiler_test.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 myprofiler_test.go diff --git a/myprofiler.go b/myprofiler.go index 4b2bef5..ced1d6b 100644 --- a/myprofiler.go +++ b/myprofiler.go @@ -10,7 +10,6 @@ import ( "os/user" "regexp" "sort" - "strings" "time" _ "github.com/go-sql-driver/mysql" @@ -32,17 +31,16 @@ func (p *NormalizePattern) Normalize(q string) string { return p.re.ReplaceAllString(q, p.subs) } -var ( - normalizePatterns []NormalizePattern = []NormalizePattern{ - NormalizePattern{regexp.MustCompile(`[+\-]{0,1}\b\d+\b`), "N"}, - NormalizePattern{regexp.MustCompile(`\b0x[0-9A-Fa-f]+\b`), "0xN"}, - NormalizePattern{regexp.MustCompile(`(\\')`), ""}, - NormalizePattern{regexp.MustCompile(`(\\")`), ""}, - NormalizePattern{regexp.MustCompile(`'[^']+'`), "S"}, - NormalizePattern{regexp.MustCompile(`"[^"]+"`), "S"}, - NormalizePattern{regexp.MustCompile(`(([NS]\s*,\s*){4,})`), "..."}, - } -) +var normalizePatterns = []NormalizePattern{ + NormalizePattern{regexp.MustCompile(` +`), " "}, + NormalizePattern{regexp.MustCompile(`[+\-]{0,1}\b\d+\b`), "N"}, + NormalizePattern{regexp.MustCompile(`\b0x[0-9A-Fa-f]+\b`), "0xN"}, + NormalizePattern{regexp.MustCompile(`(\\')`), ""}, + NormalizePattern{regexp.MustCompile(`(\\")`), ""}, + NormalizePattern{regexp.MustCompile(`'[^']+'`), "S"}, + NormalizePattern{regexp.MustCompile(`"[^"]+"`), "S"}, + NormalizePattern{regexp.MustCompile(`(([NS]\s*,\s*){4,})`), "..."}, +} func processList(db *sql.DB) []string { procList := "SHOW FULL PROCESSLIST" @@ -68,8 +66,6 @@ func processList(db *sql.DB) []string { } func normalizeQuery(query string) string { - parts := strings.Split(query, " ") - query = strings.Join(parts, " ") for _, pat := range normalizePatterns { query = pat.Normalize(query) } @@ -95,7 +91,7 @@ func (pl pairList) Swap(i, j int) { } func showSummary(sum map[string]int64, n int) { - counts := []pair{} + counts := make([]pair, 0, len(sum)) for q, c := range sum { counts = append(counts, pair{q, c}) } @@ -114,9 +110,14 @@ func profile(db *sql.DB, cfg *Config) { count := make(map[string]int64) for { queries := processList(db) + if cfg.dump != nil { + for _, q := range queries { + cfg.dump.Write([]byte(q)) + cfg.dump.Write([]byte{'\n'}) + } + } for _, q := range queries { - q = normalizeQuery(q) - count[q]++ + count[normalizeQuery(q)]++ } showSummary(count, cfg.numSummary) time.Sleep(time.Duration(float64(time.Second) * cfg.interval)) diff --git a/myprofiler_test.go b/myprofiler_test.go new file mode 100644 index 0000000..feef63d --- /dev/null +++ b/myprofiler_test.go @@ -0,0 +1,20 @@ +package main + +import ( + "testing" +) + +func TestNormalize(t *testing.T) { + var data = []struct{ input, expected string }{ + {"IN ('a', 'b', 'c')", "IN (S, S, S)"}, + {"IN ('a', 'b', 'c', 'd', 'e')", "IN (...S)"}, + {"IN (1, 2, 3)", "IN (N, N, N)"}, + {"IN (1, 2, 3, 4, 5)", "IN (...N)"}, + } + + for _, d := range data { + if a := normalizeQuery(d.input); a != d.expected { + t.Errorf("data=%v, actual=%q", d, a) + } + } +}