瀏覽代碼

Merge pull request #71 from vlankhaar/master

Expose logic for looking up SampleTypes by string instead of integer
Raul Silvera 8 年之前
父節點
當前提交
226a84fc89
共有 5 個檔案被更改,包括 188 行新增46 行删除
  1. 0
    44
      internal/driver/commands.go
  2. 1
    1
      internal/driver/driver.go
  3. 9
    1
      internal/driver/interactive.go
  4. 64
    0
      profile/index.go
  5. 114
    0
      profile/index_test.go

+ 0
- 44
internal/driver/commands.go 查看文件

28
 
28
 
29
 	"github.com/google/pprof/internal/plugin"
29
 	"github.com/google/pprof/internal/plugin"
30
 	"github.com/google/pprof/internal/report"
30
 	"github.com/google/pprof/internal/report"
31
-	"github.com/google/pprof/profile"
32
 	"github.com/google/pprof/third_party/svg"
31
 	"github.com/google/pprof/third_party/svg"
33
 )
32
 )
34
 
33
 
456
 	}
455
 	}
457
 }
456
 }
458
 
457
 
459
-// locateSampleIndex returns the appropriate index for a value of sample index.
460
-// If numeric, it returns the number, otherwise it looks up the text in the
461
-// profile sample types.
462
-func locateSampleIndex(p *profile.Profile, sampleIndex string) (int, error) {
463
-	if sampleIndex == "" {
464
-		if dst := p.DefaultSampleType; dst != "" {
465
-			for i, t := range sampleTypes(p) {
466
-				if t == dst {
467
-					return i, nil
468
-				}
469
-			}
470
-		}
471
-		// By default select the last sample value
472
-		return len(p.SampleType) - 1, nil
473
-	}
474
-	if i, err := strconv.Atoi(sampleIndex); err == nil {
475
-		if i < 0 || i >= len(p.SampleType) {
476
-			return 0, fmt.Errorf("sample_index %s is outside the range [0..%d]", sampleIndex, len(p.SampleType)-1)
477
-		}
478
-		return i, nil
479
-	}
480
-
481
-	// Remove the inuse_ prefix to support legacy pprof options
482
-	// "inuse_space" and "inuse_objects" for profiles containing types
483
-	// "space" and "objects".
484
-	noInuse := strings.TrimPrefix(sampleIndex, "inuse_")
485
-	for i, t := range p.SampleType {
486
-		if t.Type == sampleIndex || t.Type == noInuse {
487
-			return i, nil
488
-		}
489
-	}
490
-
491
-	return 0, fmt.Errorf("sample_index %q must be one of: %v", sampleIndex, sampleTypes(p))
492
-}
493
-
494
-func sampleTypes(p *profile.Profile) []string {
495
-	types := make([]string, len(p.SampleType))
496
-	for i, t := range p.SampleType {
497
-		types[i] = t.Type
498
-	}
499
-	return types
500
-}
501
-
502
 // variables describe the configuration parameters recognized by pprof.
458
 // variables describe the configuration parameters recognized by pprof.
503
 type variables map[string]*variable
459
 type variables map[string]*variable
504
 
460
 

+ 1
- 1
internal/driver/driver.go 查看文件

258
 	if len(p.SampleType) == 0 {
258
 	if len(p.SampleType) == 0 {
259
 		return nil, nil, nil, fmt.Errorf("profile has no samples")
259
 		return nil, nil, nil, fmt.Errorf("profile has no samples")
260
 	}
260
 	}
261
-	index, err := locateSampleIndex(p, sampleIndex)
261
+	index, err := p.SampleIndexByName(sampleIndex)
262
 	if err != nil {
262
 	if err != nil {
263
 		return nil, nil, nil, err
263
 		return nil, nil, nil, err
264
 	}
264
 	}

+ 9
- 1
internal/driver/interactive.go 查看文件

69
 				if v := pprofVariables[name]; v != nil {
69
 				if v := pprofVariables[name]; v != nil {
70
 					if name == "sample_index" {
70
 					if name == "sample_index" {
71
 						// Error check sample_index=xxx to ensure xxx is a valid sample type.
71
 						// Error check sample_index=xxx to ensure xxx is a valid sample type.
72
-						index, err := locateSampleIndex(p, value)
72
+						index, err := p.SampleIndexByName(value)
73
 						if err != nil {
73
 						if err != nil {
74
 							o.UI.PrintErr(err)
74
 							o.UI.PrintErr(err)
75
 							continue
75
 							continue
161
 	return s
161
 	return s
162
 }
162
 }
163
 
163
 
164
+func sampleTypes(p *profile.Profile) []string {
165
+	types := make([]string, len(p.SampleType))
166
+	for i, t := range p.SampleType {
167
+		types[i] = t.Type
168
+	}
169
+	return types
170
+}
171
+
164
 func printCurrentOptions(p *profile.Profile, ui plugin.UI) {
172
 func printCurrentOptions(p *profile.Profile, ui plugin.UI) {
165
 	var args []string
173
 	var args []string
166
 	type groupInfo struct {
174
 	type groupInfo struct {

+ 64
- 0
profile/index.go 查看文件

1
+// Copyright 2016 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 profile
16
+
17
+import (
18
+	"fmt"
19
+	"strconv"
20
+	"strings"
21
+)
22
+
23
+// SampleIndexByName returns the appropriate index for a value of sample index.
24
+// If numeric, it returns the number, otherwise it looks up the text in the
25
+// profile sample types.
26
+func (p *Profile) SampleIndexByName(sampleIndex string) (int, error) {
27
+	if sampleIndex == "" {
28
+		if dst := p.DefaultSampleType; dst != "" {
29
+			for i, t := range sampleTypes(p) {
30
+				if t == dst {
31
+					return i, nil
32
+				}
33
+			}
34
+		}
35
+		// By default select the last sample value
36
+		return len(p.SampleType) - 1, nil
37
+	}
38
+	if i, err := strconv.Atoi(sampleIndex); err == nil {
39
+		if i < 0 || i >= len(p.SampleType) {
40
+			return 0, fmt.Errorf("sample_index %s is outside the range [0..%d]", sampleIndex, len(p.SampleType)-1)
41
+		}
42
+		return i, nil
43
+	}
44
+
45
+	// Remove the inuse_ prefix to support legacy pprof options
46
+	// "inuse_space" and "inuse_objects" for profiles containing types
47
+	// "space" and "objects".
48
+	noInuse := strings.TrimPrefix(sampleIndex, "inuse_")
49
+	for i, t := range p.SampleType {
50
+		if t.Type == sampleIndex || t.Type == noInuse {
51
+			return i, nil
52
+		}
53
+	}
54
+
55
+	return 0, fmt.Errorf("sample_index %q must be one of: %v", sampleIndex, sampleTypes(p))
56
+}
57
+
58
+func sampleTypes(p *Profile) []string {
59
+	types := make([]string, len(p.SampleType))
60
+	for i, t := range p.SampleType {
61
+		types[i] = t.Type
62
+	}
63
+	return types
64
+}

+ 114
- 0
profile/index_test.go 查看文件

1
+// Copyright 2016 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 profile
16
+
17
+import (
18
+	"testing"
19
+)
20
+
21
+func TestSampleIndexByName(t *testing.T) {
22
+	for _, c := range []struct {
23
+		desc              string
24
+		sampleTypes       []string
25
+		defaultSampleType string
26
+		index             string
27
+		want              int
28
+		wantError         bool
29
+	}{
30
+		{
31
+			desc:        "use last by default",
32
+			index:       "",
33
+			want:        1,
34
+			sampleTypes: []string{"zero", "default"},
35
+		},
36
+		{
37
+			desc:              "honour specified default",
38
+			index:             "",
39
+			want:              1,
40
+			defaultSampleType: "default",
41
+			sampleTypes:       []string{"zero", "default", "two"},
42
+		},
43
+		{
44
+			desc:              "invalid default is ignored",
45
+			index:             "",
46
+			want:              2,
47
+			defaultSampleType: "non-existent",
48
+			sampleTypes:       []string{"zero", "one", "default"},
49
+		},
50
+		{
51
+			desc:        "index by int",
52
+			index:       "0",
53
+			want:        0,
54
+			sampleTypes: []string{"zero", "one", "two"},
55
+		},
56
+		{
57
+			desc:              "index by int ignores default",
58
+			index:             "0",
59
+			want:              0,
60
+			defaultSampleType: "default",
61
+			sampleTypes:       []string{"zero", "default", "two"},
62
+		},
63
+		{
64
+			desc:        "index by name",
65
+			index:       "two",
66
+			want:        2,
67
+			sampleTypes: []string{"zero", "one", "two", "three"},
68
+		},
69
+		{
70
+			desc:              "index by name ignores default",
71
+			index:             "zero",
72
+			want:              0,
73
+			defaultSampleType: "default",
74
+			sampleTypes:       []string{"zero", "default", "two"},
75
+		},
76
+		{
77
+			desc:        "out of bound int causes error",
78
+			index:       "100",
79
+			wantError:   true,
80
+			sampleTypes: []string{"zero", "default"},
81
+		},
82
+		{
83
+			desc:        "unknown name causes error",
84
+			index:       "does not exist",
85
+			wantError:   true,
86
+			sampleTypes: []string{"zero", "default"},
87
+		},
88
+		{
89
+			desc:        "'inused_{x}' recognized for legacy '{x}'",
90
+			index:       "inuse_zero",
91
+			want:        0,
92
+			sampleTypes: []string{"zero", "default"},
93
+		},
94
+	} {
95
+		p := &Profile{
96
+			DefaultSampleType: c.defaultSampleType,
97
+			SampleType:        []*ValueType{},
98
+		}
99
+		for _, st := range c.sampleTypes {
100
+			p.SampleType = append(p.SampleType, &ValueType{Type: st, Unit: "milliseconds"})
101
+		}
102
+
103
+		got, err := p.SampleIndexByName(c.index)
104
+
105
+		switch {
106
+		case c.wantError && err == nil:
107
+			t.Errorf("%s: error should have been returned not index=%d, err=%v", c.desc, got, err)
108
+		case !c.wantError && err != nil:
109
+			t.Errorf("%s: unexpected got index=%d, err=%v; wanted index=%d, err=nil", c.desc, got, err, c.want)
110
+		case !c.wantError && got != c.want:
111
+			t.Errorf("%s: got index=%d, want index=%d", c.desc, got, c.want)
112
+		}
113
+	}
114
+}