Browse Source

Merge pull request #33 from rauls5382/tagshow

Add tagshow/taghide commands to select a subset of tags in a profile
Josef Jelinek 8 years ago
parent
commit
7dfb5e832b

+ 6
- 1
internal/driver/commands.go View File

199
 	"tagignore": &variable{stringKind, "", "", helpText(
199
 	"tagignore": &variable{stringKind, "", "", helpText(
200
 		"Discard samples with tags in range or matched by regexp",
200
 		"Discard samples with tags in range or matched by regexp",
201
 		"Discard samples that do include a node with a tag matching this regexp.")},
201
 		"Discard samples that do include a node with a tag matching this regexp.")},
202
-
202
+	"tagshow": &variable{stringKind, "", "", helpText(
203
+		"Only consider tags matching this regexp",
204
+		"Discard tags that do not match this regexp")},
205
+	"taghide": &variable{stringKind, "", "", helpText(
206
+		"Skip tags matching this regexp",
207
+		"Discard tags that match this regexp")},
203
 	// Heap profile options
208
 	// Heap profile options
204
 	"divide_by": &variable{floatKind, "1", "", helpText(
209
 	"divide_by": &variable{floatKind, "1", "", helpText(
205
 		"Ratio to divide all samples before visualization",
210
 		"Ratio to divide all samples before visualization",

+ 6
- 0
internal/driver/driver_focus.go View File

50
 	warnNoMatches(tagfocus == nil || tfm, "TagFocus", ui)
50
 	warnNoMatches(tagfocus == nil || tfm, "TagFocus", ui)
51
 	warnNoMatches(tagignore == nil || tim, "TagIgnore", ui)
51
 	warnNoMatches(tagignore == nil || tim, "TagIgnore", ui)
52
 
52
 
53
+	tagshow, err := compileRegexOption("tagshow", v["tagshow"].value, err)
54
+	taghide, err := compileRegexOption("taghide", v["taghide"].value, err)
55
+	tns, tnh := prof.FilterTagsByName(tagshow, taghide)
56
+	warnNoMatches(tagshow == nil || tns, "TagShow", ui)
57
+	warnNoMatches(tagignore == nil || tnh, "TagHide", ui)
58
+
53
 	if prunefrom != nil {
59
 	if prunefrom != nil {
54
 		prof.PruneFrom(prunefrom)
60
 		prof.PruneFrom(prunefrom)
55
 	}
61
 	}

+ 1
- 1
internal/symbolizer/symbolizer.go View File

292
 			missingBinaries = true
292
 			missingBinaries = true
293
 			continue
293
 			continue
294
 		}
294
 		}
295
-		
295
+
296
 		// Skip well-known system mappings
296
 		// Skip well-known system mappings
297
 		name := filepath.Base(m.File)
297
 		name := filepath.Base(m.File)
298
 		if name == "[vdso]" || strings.HasPrefix(name, "linux-vdso") {
298
 		if name == "[vdso]" || strings.HasPrefix(name, "linux-vdso") {

+ 30
- 0
profile/filter.go View File

73
 	return
73
 	return
74
 }
74
 }
75
 
75
 
76
+// FilterTagsByName filters the tags in a profile and only keeps
77
+// tags that match show and not hide.
78
+func (p *Profile) FilterTagsByName(show, hide *regexp.Regexp) (sm, hm bool) {
79
+	matchRemove := func(name string) bool {
80
+		matchShow := show == nil || show.MatchString(name)
81
+		matchHide := hide != nil && hide.MatchString(name)
82
+
83
+		if matchShow {
84
+			sm = true
85
+		}
86
+		if matchHide {
87
+			hm = true
88
+		}
89
+		return !matchShow || matchHide
90
+	}
91
+	for _, s := range p.Sample {
92
+		for lab := range s.Label {
93
+			if matchRemove(lab) {
94
+				delete(s.Label, lab)
95
+			}
96
+		}
97
+		for lab := range s.NumLabel {
98
+			if matchRemove(lab) {
99
+				delete(s.NumLabel, lab)
100
+			}
101
+		}
102
+	}
103
+	return
104
+}
105
+
76
 // matchesName returns whether the location matches the regular
106
 // matchesName returns whether the location matches the regular
77
 // expression. It checks any available function names, file names, and
107
 // expression. It checks any available function names, file names, and
78
 // mapping object filename.
108
 // mapping object filename.

+ 43
- 0
profile/profile_test.go View File

507
 	}
507
 	}
508
 }
508
 }
509
 
509
 
510
+func TestTagFilter(t *testing.T) {
511
+     // Perform several forms of tag filtering on the test profile.
512
+
513
+	type filterTestcase struct {
514
+		include, exclude *regexp.Regexp
515
+		im, em bool
516
+		count int
517
+	}
518
+
519
+	countTags := func (p *Profile) map[string]bool {
520
+		  tags := make(map[string]bool)
521
+
522
+		  for _, s := range p.Sample {
523
+		      for l := range s.Label {
524
+		      	  tags[l] = true
525
+		      }		      
526
+		      for l := range s.NumLabel {
527
+		      	  tags[l] = true
528
+		      }		      
529
+		  }
530
+		  return tags
531
+	}	
532
+	
533
+	for tx, tc := range []filterTestcase{
534
+		{nil, nil, true, false, 3},
535
+		{regexp.MustCompile("notfound"), nil, false, false, 0},
536
+		{regexp.MustCompile("key1"), nil, true, false, 1},
537
+		{nil, regexp.MustCompile("key[12]"), true, true, 1},
538
+	} {
539
+		prof := testProfile.Copy()
540
+		gim, gem := prof.FilterTagsByName(tc.include, tc.exclude)
541
+		if  gim != tc.im {
542
+			t.Errorf("Filter #%d, got include match=%v, want %v", tx, gim, tc.im)
543
+		}		
544
+		if  gem != tc.em {
545
+			t.Errorf("Filter #%d, got exclude match=%v, want %v", tx, gem, tc.em)
546
+		}		
547
+		if  tags := countTags(prof) ; len(tags) != tc.count {
548
+			t.Errorf("Filter #%d, got %d tags[%v], want %d", tx, len(tags), tags, tc.count)
549
+		}		
550
+	}
551
+}
552
+
510
 // locationHash constructs a string to use as a hashkey for a sample, based on its locations
553
 // locationHash constructs a string to use as a hashkey for a sample, based on its locations
511
 func locationHash(s *Sample) string {
554
 func locationHash(s *Sample) string {
512
 	var tb string
555
 	var tb string