瀏覽代碼

Handle memory maps generated by logging

If the memory map is generated by logging routines such as glog, they
may include some initial text which confuses the parsing of legacy
mappings. The initial text is the same for all mapping entries,
so detect it on the proc map sentinel and remove it from the mapping
entries.
Raul Silvera 8 年之前
父節點
當前提交
251ad27be0
共有 1 個文件被更改,包括 36 次插入22 次删除
  1. 36
    22
      profile/legacy_profile.go

+ 36
- 22
profile/legacy_profile.go 查看文件

@@ -509,7 +509,7 @@ func parseHeap(b []byte) (p *Profile, err error) {
509 509
 			continue
510 510
 		}
511 511
 
512
-		if sectionTrigger(line) != unrecognizedSection {
512
+		if isMemoryMapSentinel(line) {
513 513
 			break
514 514
 		}
515 515
 
@@ -837,7 +837,7 @@ func parseThread(b []byte) (*Profile, error) {
837 837
 	if m := threadzStartRE.FindStringSubmatch(line); m != nil {
838 838
 		// Advance over initial comments until first stack trace.
839 839
 		for s.Scan() {
840
-			if line = s.Text(); sectionTrigger(line) != unrecognizedSection || strings.HasPrefix(line, "-") {
840
+			if line = s.Text(); isMemoryMapSentinel(line) || strings.HasPrefix(line, "-") {
841 841
 				break
842 842
 			}
843 843
 		}
@@ -853,7 +853,7 @@ func parseThread(b []byte) (*Profile, error) {
853 853
 
854 854
 	locs := make(map[uint64]*Location)
855 855
 	// Recognize each thread and populate profile samples.
856
-	for sectionTrigger(line) == unrecognizedSection {
856
+	for !isMemoryMapSentinel(line) {
857 857
 		if strings.HasPrefix(line, "---- no stack trace for") {
858 858
 			line = ""
859 859
 			break
@@ -944,12 +944,12 @@ func parseThreadSample(s *bufio.Scanner) (nextl string, addrs []uint64, err erro
944 944
 // parseAdditionalSections parses any additional sections in the
945 945
 // profile, ignoring any unrecognized sections.
946 946
 func parseAdditionalSections(s *bufio.Scanner, p *Profile) error {
947
-	for sectionTrigger(s.Text()) != memoryMapSection && s.Scan() {
947
+	for !isMemoryMapSentinel(s.Text()) && s.Scan() {
948 948
 	}
949 949
 	if err := s.Err(); err != nil {
950 950
 		return err
951 951
 	}
952
-	return p.parseMemoryMapFromScanner(s)
952
+	return p.ParseMemoryMapFromScanner(s)
953 953
 }
954 954
 
955 955
 // ParseProcMaps parses a memory map in the format of /proc/self/maps.
@@ -964,12 +964,19 @@ func ParseProcMaps(rd io.Reader) ([]*Mapping, error) {
964 964
 func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error) {
965 965
 	var mapping []*Mapping
966 966
 
967
+	// If the memory-map sentinel is at column X, assume memory mappings
968
+	// also start at X. This is useful to eliminate logging information.
969
+	offset := memoryMapSentinelOffset(s.Text())
970
+
967 971
 	var attrs []string
968 972
 	var r *strings.Replacer
969 973
 	const delimiter = "="
970 974
 	for s.Scan() {
971
-		line := strings.TrimSpace(s.Text())
972
-		if line == "" {
975
+		line := s.Text()
976
+		if len(line) > offset {
977
+			line = line[offset:]
978
+		}
979
+		if line = strings.TrimSpace(line); line == "" {
973 980
 			continue
974 981
 		}
975 982
 
@@ -1005,10 +1012,10 @@ func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error) {
1005 1012
 // /proc/self/maps, and overrides the mappings in the current profile.
1006 1013
 // It renumbers the samples and locations in the profile correspondingly.
1007 1014
 func (p *Profile) ParseMemoryMap(rd io.Reader) error {
1008
-	return p.parseMemoryMapFromScanner(bufio.NewScanner(rd))
1015
+	return p.ParseMemoryMapFromScanner(bufio.NewScanner(rd))
1009 1016
 }
1010 1017
 
1011
-func (p *Profile) parseMemoryMapFromScanner(s *bufio.Scanner) error {
1018
+func (p *Profile) ParseMemoryMapFromScanner(s *bufio.Scanner) error {
1012 1019
 	mapping, err := parseProcMapsFromScanner(s)
1013 1020
 	if err != nil {
1014 1021
 		return err
@@ -1054,25 +1061,32 @@ func parseMappingEntry(l string) (*Mapping, error) {
1054 1061
 	return mapping, nil
1055 1062
 }
1056 1063
 
1057
-type sectionType int
1058
-
1059
-const (
1060
-	unrecognizedSection sectionType = iota
1061
-	memoryMapSection
1062
-)
1063
-
1064
-var memoryMapTriggers = []string{
1064
+var memoryMapSentinels = []string{
1065 1065
 	"--- Memory map: ---",
1066 1066
 	"MAPPED_LIBRARIES:",
1067 1067
 }
1068 1068
 
1069
-func sectionTrigger(line string) sectionType {
1070
-	for _, trigger := range memoryMapTriggers {
1071
-		if strings.Contains(line, trigger) {
1072
-			return memoryMapSection
1069
+// isMemoryMapSentinel returns true if the string contains one of the
1070
+// known sentinels for memory map information.
1071
+func isMemoryMapSentinel(line string) bool {
1072
+	for _, s := range memoryMapSentinels {
1073
+		if strings.Contains(line, s) {
1074
+			return true
1075
+		}
1076
+	}
1077
+	return false
1078
+}
1079
+
1080
+// memoryMapSentinelOffset returns the index of a known memory map
1081
+// sentinel in the string. If the string does not contain a sentinel,
1082
+// it returns 0.
1083
+func memoryMapSentinelOffset(line string) int {
1084
+	for _, s := range memoryMapSentinels {
1085
+		if i := strings.Index(line, s); i != -1 {
1086
+			return i
1073 1087
 		}
1074 1088
 	}
1075
-	return unrecognizedSection
1089
+	return 0
1076 1090
 }
1077 1091
 
1078 1092
 func (p *Profile) addLegacyFrameInfo() {