...

Source file src/pkg/cmd/vendor/github.com/google/pprof/internal/driver/driver_focus.go

     1	// Copyright 2014 Google Inc. All Rights Reserved.
     2	//
     3	// Licensed under the Apache License, Version 2.0 (the "License");
     4	// you may not use this file except in compliance with the License.
     5	// You may obtain a copy of the License at
     6	//
     7	//     http://www.apache.org/licenses/LICENSE-2.0
     8	//
     9	// Unless required by applicable law or agreed to in writing, software
    10	// distributed under the License is distributed on an "AS IS" BASIS,
    11	// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12	// See the License for the specific language governing permissions and
    13	// limitations under the License.
    14	
    15	package driver
    16	
    17	import (
    18		"fmt"
    19		"regexp"
    20		"strconv"
    21		"strings"
    22	
    23		"github.com/google/pprof/internal/measurement"
    24		"github.com/google/pprof/internal/plugin"
    25		"github.com/google/pprof/profile"
    26	)
    27	
    28	var tagFilterRangeRx = regexp.MustCompile("([+-]?[[:digit:]]+)([[:alpha:]]+)")
    29	
    30	// applyFocus filters samples based on the focus/ignore options
    31	func applyFocus(prof *profile.Profile, numLabelUnits map[string]string, v variables, ui plugin.UI) error {
    32		focus, err := compileRegexOption("focus", v["focus"].value, nil)
    33		ignore, err := compileRegexOption("ignore", v["ignore"].value, err)
    34		hide, err := compileRegexOption("hide", v["hide"].value, err)
    35		show, err := compileRegexOption("show", v["show"].value, err)
    36		showfrom, err := compileRegexOption("show_from", v["show_from"].value, err)
    37		tagfocus, err := compileTagFilter("tagfocus", v["tagfocus"].value, numLabelUnits, ui, err)
    38		tagignore, err := compileTagFilter("tagignore", v["tagignore"].value, numLabelUnits, ui, err)
    39		prunefrom, err := compileRegexOption("prune_from", v["prune_from"].value, err)
    40		if err != nil {
    41			return err
    42		}
    43	
    44		fm, im, hm, hnm := prof.FilterSamplesByName(focus, ignore, hide, show)
    45		warnNoMatches(focus == nil || fm, "Focus", ui)
    46		warnNoMatches(ignore == nil || im, "Ignore", ui)
    47		warnNoMatches(hide == nil || hm, "Hide", ui)
    48		warnNoMatches(show == nil || hnm, "Show", ui)
    49	
    50		sfm := prof.ShowFrom(showfrom)
    51		warnNoMatches(showfrom == nil || sfm, "ShowFrom", ui)
    52	
    53		tfm, tim := prof.FilterSamplesByTag(tagfocus, tagignore)
    54		warnNoMatches(tagfocus == nil || tfm, "TagFocus", ui)
    55		warnNoMatches(tagignore == nil || tim, "TagIgnore", ui)
    56	
    57		tagshow, err := compileRegexOption("tagshow", v["tagshow"].value, err)
    58		taghide, err := compileRegexOption("taghide", v["taghide"].value, err)
    59		tns, tnh := prof.FilterTagsByName(tagshow, taghide)
    60		warnNoMatches(tagshow == nil || tns, "TagShow", ui)
    61		warnNoMatches(tagignore == nil || tnh, "TagHide", ui)
    62	
    63		if prunefrom != nil {
    64			prof.PruneFrom(prunefrom)
    65		}
    66		return err
    67	}
    68	
    69	func compileRegexOption(name, value string, err error) (*regexp.Regexp, error) {
    70		if value == "" || err != nil {
    71			return nil, err
    72		}
    73		rx, err := regexp.Compile(value)
    74		if err != nil {
    75			return nil, fmt.Errorf("parsing %s regexp: %v", name, err)
    76		}
    77		return rx, nil
    78	}
    79	
    80	func compileTagFilter(name, value string, numLabelUnits map[string]string, ui plugin.UI, err error) (func(*profile.Sample) bool, error) {
    81		if value == "" || err != nil {
    82			return nil, err
    83		}
    84	
    85		tagValuePair := strings.SplitN(value, "=", 2)
    86		var wantKey string
    87		if len(tagValuePair) == 2 {
    88			wantKey = tagValuePair[0]
    89			value = tagValuePair[1]
    90		}
    91	
    92		if numFilter := parseTagFilterRange(value); numFilter != nil {
    93			ui.PrintErr(name, ":Interpreted '", value, "' as range, not regexp")
    94			labelFilter := func(vals []int64, unit string) bool {
    95				for _, val := range vals {
    96					if numFilter(val, unit) {
    97						return true
    98					}
    99				}
   100				return false
   101			}
   102			numLabelUnit := func(key string) string {
   103				return numLabelUnits[key]
   104			}
   105			if wantKey == "" {
   106				return func(s *profile.Sample) bool {
   107					for key, vals := range s.NumLabel {
   108						if labelFilter(vals, numLabelUnit(key)) {
   109							return true
   110						}
   111					}
   112					return false
   113				}, nil
   114			}
   115			return func(s *profile.Sample) bool {
   116				if vals, ok := s.NumLabel[wantKey]; ok {
   117					return labelFilter(vals, numLabelUnit(wantKey))
   118				}
   119				return false
   120			}, nil
   121		}
   122	
   123		var rfx []*regexp.Regexp
   124		for _, tagf := range strings.Split(value, ",") {
   125			fx, err := regexp.Compile(tagf)
   126			if err != nil {
   127				return nil, fmt.Errorf("parsing %s regexp: %v", name, err)
   128			}
   129			rfx = append(rfx, fx)
   130		}
   131		if wantKey == "" {
   132			return func(s *profile.Sample) bool {
   133			matchedrx:
   134				for _, rx := range rfx {
   135					for key, vals := range s.Label {
   136						for _, val := range vals {
   137							// TODO: Match against val, not key:val in future
   138							if rx.MatchString(key + ":" + val) {
   139								continue matchedrx
   140							}
   141						}
   142					}
   143					return false
   144				}
   145				return true
   146			}, nil
   147		}
   148		return func(s *profile.Sample) bool {
   149			if vals, ok := s.Label[wantKey]; ok {
   150				for _, rx := range rfx {
   151					for _, val := range vals {
   152						if rx.MatchString(val) {
   153							return true
   154						}
   155					}
   156				}
   157			}
   158			return false
   159		}, nil
   160	}
   161	
   162	// parseTagFilterRange returns a function to checks if a value is
   163	// contained on the range described by a string. It can recognize
   164	// strings of the form:
   165	// "32kb" -- matches values == 32kb
   166	// ":64kb" -- matches values <= 64kb
   167	// "4mb:" -- matches values >= 4mb
   168	// "12kb:64mb" -- matches values between 12kb and 64mb (both included).
   169	func parseTagFilterRange(filter string) func(int64, string) bool {
   170		ranges := tagFilterRangeRx.FindAllStringSubmatch(filter, 2)
   171		if len(ranges) == 0 {
   172			return nil // No ranges were identified
   173		}
   174		v, err := strconv.ParseInt(ranges[0][1], 10, 64)
   175		if err != nil {
   176			panic(fmt.Errorf("failed to parse int %s: %v", ranges[0][1], err))
   177		}
   178		scaledValue, unit := measurement.Scale(v, ranges[0][2], ranges[0][2])
   179		if len(ranges) == 1 {
   180			switch match := ranges[0][0]; filter {
   181			case match:
   182				return func(v int64, u string) bool {
   183					sv, su := measurement.Scale(v, u, unit)
   184					return su == unit && sv == scaledValue
   185				}
   186			case match + ":":
   187				return func(v int64, u string) bool {
   188					sv, su := measurement.Scale(v, u, unit)
   189					return su == unit && sv >= scaledValue
   190				}
   191			case ":" + match:
   192				return func(v int64, u string) bool {
   193					sv, su := measurement.Scale(v, u, unit)
   194					return su == unit && sv <= scaledValue
   195				}
   196			}
   197			return nil
   198		}
   199		if filter != ranges[0][0]+":"+ranges[1][0] {
   200			return nil
   201		}
   202		if v, err = strconv.ParseInt(ranges[1][1], 10, 64); err != nil {
   203			panic(fmt.Errorf("failed to parse int %s: %v", ranges[1][1], err))
   204		}
   205		scaledValue2, unit2 := measurement.Scale(v, ranges[1][2], unit)
   206		if unit != unit2 {
   207			return nil
   208		}
   209		return func(v int64, u string) bool {
   210			sv, su := measurement.Scale(v, u, unit)
   211			return su == unit && sv >= scaledValue && sv <= scaledValue2
   212		}
   213	}
   214	
   215	func warnNoMatches(match bool, option string, ui plugin.UI) {
   216		if !match {
   217			ui.PrintErr(option + " expression matched no samples")
   218		}
   219	}
   220	

View as plain text