|
@@ -63,6 +63,10 @@ var (
|
63
|
63
|
|
64
|
64
|
procMapsRE = regexp.MustCompile(`^` + cHexRange + cPerm + cSpaceHex + hexPair + spaceDigits + cSpaceString)
|
65
|
65
|
briefMapsRE = regexp.MustCompile(`^` + cHexRange + cPerm + cSpaceString + cSpaceAtOffset + cSpaceHex)
|
|
66
|
+
|
|
67
|
+ // Regular expression to parse log data, of the form:
|
|
68
|
+ // ... file:line] msg...
|
|
69
|
+ logInfoRE = regexp.MustCompile(`^[^\[\]]+:[0-9]+]\s`)
|
66
|
70
|
)
|
67
|
71
|
|
68
|
72
|
func isSpaceOrComment(line string) bool {
|
|
@@ -964,25 +968,11 @@ func ParseProcMaps(rd io.Reader) ([]*Mapping, error) {
|
964
|
968
|
func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error) {
|
965
|
969
|
var mapping []*Mapping
|
966
|
970
|
|
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
|
|
-
|
971
|
971
|
var attrs []string
|
972
|
|
- var r *strings.Replacer
|
973
|
972
|
const delimiter = "="
|
|
973
|
+ r := strings.NewReplacer()
|
974
|
974
|
for s.Scan() {
|
975
|
|
- line := s.Text()
|
976
|
|
- if len(line) > offset {
|
977
|
|
- line = line[offset:]
|
978
|
|
- }
|
979
|
|
- if line = strings.TrimSpace(line); line == "" {
|
980
|
|
- continue
|
981
|
|
- }
|
982
|
|
-
|
983
|
|
- if r != nil {
|
984
|
|
- line = r.Replace(line)
|
985
|
|
- }
|
|
975
|
+ line := r.Replace(removeLoggingInfo(s.Text()))
|
986
|
976
|
m, err := parseMappingEntry(line)
|
987
|
977
|
if err != nil {
|
988
|
978
|
if err == errUnrecognized {
|
|
@@ -1008,6 +998,16 @@ func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error) {
|
1008
|
998
|
return mapping, nil
|
1009
|
999
|
}
|
1010
|
1000
|
|
|
1001
|
+// removeLoggingInfo detects and removes log prefix entries generated
|
|
1002
|
+// by the glog package. If no logging prefix is detected, the string
|
|
1003
|
+// is returned unmodified.
|
|
1004
|
+func removeLoggingInfo(line string) string {
|
|
1005
|
+ if match := logInfoRE.FindStringIndex(line); match != nil {
|
|
1006
|
+ return line[match[1]:]
|
|
1007
|
+ }
|
|
1008
|
+ return line
|
|
1009
|
+}
|
|
1010
|
+
|
1011
|
1011
|
// ParseMemoryMap parses a memory map in the format of
|
1012
|
1012
|
// /proc/self/maps, and overrides the mappings in the current profile.
|
1013
|
1013
|
// It renumbers the samples and locations in the profile correspondingly.
|
|
@@ -1081,18 +1081,6 @@ func isMemoryMapSentinel(line string) bool {
|
1081
|
1081
|
return false
|
1082
|
1082
|
}
|
1083
|
1083
|
|
1084
|
|
-// memoryMapSentinelOffset returns the index of a known memory map
|
1085
|
|
-// sentinel in the string. If the string does not contain a sentinel,
|
1086
|
|
-// it returns 0.
|
1087
|
|
-func memoryMapSentinelOffset(line string) int {
|
1088
|
|
- for _, s := range memoryMapSentinels {
|
1089
|
|
- if i := strings.Index(line, s); i != -1 {
|
1090
|
|
- return i
|
1091
|
|
- }
|
1092
|
|
- }
|
1093
|
|
- return 0
|
1094
|
|
-}
|
1095
|
|
-
|
1096
|
1084
|
func (p *Profile) addLegacyFrameInfo() {
|
1097
|
1085
|
switch {
|
1098
|
1086
|
case isProfileType(p, heapzSampleTypes):
|