Fix instance and object name in performance counters with backslashes (#4572)
This commit is contained in:
parent
ca9505a3b1
commit
90b4a1e435
|
@ -6,7 +6,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -119,28 +118,57 @@ type instanceGrouping struct {
|
||||||
var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
|
var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
|
||||||
" ", "_", "%", "Percent", `\`, "")
|
" ", "_", "%", "Percent", `\`, "")
|
||||||
|
|
||||||
//General Counter path pattern is: \\computer\object(parent/instance#index)\counter
|
// extractCounterInfoFromCounterPath gets object name, instance name (if available) and counter name from counter path
|
||||||
//parent/instance#index part is skipped in single instance objects (e.g. Memory): \\computer\object\counter
|
// General Counter path pattern is: \\computer\object(parent/instance#index)\counter
|
||||||
|
// parent/instance#index part is skipped in single instance objects (e.g. Memory): \\computer\object\counter
|
||||||
|
func extractCounterInfoFromCounterPath(counterPath string) (object string, instance string, counter string, err error) {
|
||||||
|
|
||||||
var counterPathRE = regexp.MustCompile(`.*\\(.*)\\(.*)`)
|
rightObjectBorderIndex := -1
|
||||||
var objectInstanceRE = regexp.MustCompile(`(.*)\((.*)\)`)
|
leftObjectBorderIndex := -1
|
||||||
|
leftCounterBorderIndex := -1
|
||||||
|
rightInstanceBorderIndex := -1
|
||||||
|
leftInstanceBorderIndex := -1
|
||||||
|
bracketLevel := 0
|
||||||
|
|
||||||
//extractObjectInstanceCounterFromQuery gets object name, instance name (if available) and counter name from counter path
|
for i := len(counterPath) - 1; i >= 0; i-- {
|
||||||
func extractObjectInstanceCounterFromQuery(query string) (object string, instance string, counter string, err error) {
|
switch counterPath[i] {
|
||||||
pathParts := counterPathRE.FindAllStringSubmatch(query, -1)
|
case '\\':
|
||||||
if pathParts == nil || len(pathParts[0]) != 3 {
|
if bracketLevel == 0 {
|
||||||
err = errors.New("Could not extract counter info from: " + query)
|
if leftCounterBorderIndex == -1 {
|
||||||
|
leftCounterBorderIndex = i
|
||||||
|
} else if leftObjectBorderIndex == -1 {
|
||||||
|
leftObjectBorderIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case '(':
|
||||||
|
bracketLevel--
|
||||||
|
if leftInstanceBorderIndex == -1 && bracketLevel == 0 && leftObjectBorderIndex == -1 && leftCounterBorderIndex > -1 {
|
||||||
|
leftInstanceBorderIndex = i
|
||||||
|
rightObjectBorderIndex = i
|
||||||
|
}
|
||||||
|
case ')':
|
||||||
|
if rightInstanceBorderIndex == -1 && bracketLevel == 0 && leftCounterBorderIndex > -1 {
|
||||||
|
rightInstanceBorderIndex = i
|
||||||
|
}
|
||||||
|
bracketLevel++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rightObjectBorderIndex == -1 {
|
||||||
|
rightObjectBorderIndex = leftCounterBorderIndex
|
||||||
|
}
|
||||||
|
if rightObjectBorderIndex == -1 || leftObjectBorderIndex == -1 {
|
||||||
|
err = errors.New("cannot parse object from: " + counterPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
counter = pathParts[0][2]
|
|
||||||
//try to get instance name
|
if leftInstanceBorderIndex > -1 && rightInstanceBorderIndex > -1 {
|
||||||
objectInstanceParts := objectInstanceRE.FindAllStringSubmatch(pathParts[0][1], -1)
|
instance = counterPath[leftInstanceBorderIndex+1 : rightInstanceBorderIndex]
|
||||||
if objectInstanceParts == nil || len(objectInstanceParts[0]) != 3 {
|
} else if (leftInstanceBorderIndex == -1 && rightInstanceBorderIndex > -1) || (leftInstanceBorderIndex > -1 && rightInstanceBorderIndex == -1) {
|
||||||
object = pathParts[0][1]
|
err = errors.New("cannot parse instance from: " + counterPath)
|
||||||
} else {
|
return
|
||||||
object = objectInstanceParts[0][1]
|
|
||||||
instance = objectInstanceParts[0][2]
|
|
||||||
}
|
}
|
||||||
|
object = counterPath[leftObjectBorderIndex+1 : rightObjectBorderIndex]
|
||||||
|
counter = counterPath[leftCounterBorderIndex+1:]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +212,7 @@ func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instan
|
||||||
var err error
|
var err error
|
||||||
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
||||||
|
|
||||||
objectName, instance, counterName, err = extractObjectInstanceCounterFromQuery(counterPath)
|
objectName, instance, counterName, err = extractCounterInfoFromCounterPath(counterPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ type FakePerformanceQuery struct {
|
||||||
var MetricTime = time.Date(2018, 5, 28, 12, 0, 0, 0, time.UTC)
|
var MetricTime = time.Date(2018, 5, 28, 12, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
func (m *testCounter) ToCounterValue() *CounterValue {
|
func (m *testCounter) ToCounterValue() *CounterValue {
|
||||||
_, inst, _, _ := extractObjectInstanceCounterFromQuery(m.path)
|
_, inst, _, _ := extractCounterInfoFromCounterPath(m.path)
|
||||||
if inst == "" {
|
if inst == "" {
|
||||||
inst = "--"
|
inst = "--"
|
||||||
}
|
}
|
||||||
|
@ -211,6 +211,50 @@ func createCounterMap(counterPaths []string, values []float64) map[string]testCo
|
||||||
return counters
|
return counters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var counterPathsAndRes = map[string][]string{
|
||||||
|
"\\O\\CT": {"O", "", "CT"},
|
||||||
|
"\\O\\CT(i)": {"O", "", "CT(i)"},
|
||||||
|
"\\O\\CT(d:\\f\\i)": {"O", "", "CT(d:\\f\\i)"},
|
||||||
|
"\\\\CM\\O\\CT": {"O", "", "CT"},
|
||||||
|
"\\O(I)\\CT": {"O", "I", "CT"},
|
||||||
|
"\\O(I)\\CT(i)": {"O", "I", "CT(i)"},
|
||||||
|
"\\O(I)\\CT(i)x": {"O", "I", "CT(i)x"},
|
||||||
|
"\\O(I)\\CT(d:\\f\\i)": {"O", "I", "CT(d:\\f\\i)"},
|
||||||
|
"\\\\CM\\O(I)\\CT": {"O", "I", "CT"},
|
||||||
|
"\\O(d:\\f\\I)\\CT": {"O", "d:\\f\\I", "CT"},
|
||||||
|
"\\O(d:\\f\\I(d))\\CT": {"O", "d:\\f\\I(d)", "CT"},
|
||||||
|
"\\O(d:\\f\\I(d)x)\\CT": {"O", "d:\\f\\I(d)x", "CT"},
|
||||||
|
"\\O(d:\\f\\I)\\CT(i)": {"O", "d:\\f\\I", "CT(i)"},
|
||||||
|
"\\O(d:\\f\\I)\\CT(d:\\f\\i)": {"O", "d:\\f\\I", "CT(d:\\f\\i)"},
|
||||||
|
"\\\\CM\\O(d:\\f\\I)\\CT": {"O", "d:\\f\\I", "CT"},
|
||||||
|
"\\\\CM\\O(d:\\f\\I)\\CT(d:\\f\\i)": {"O", "d:\\f\\I", "CT(d:\\f\\i)"},
|
||||||
|
"\\O(I(info))\\CT": {"O", "I(info)", "CT"},
|
||||||
|
"\\\\CM\\O(I(info))\\CT": {"O", "I(info)", "CT"},
|
||||||
|
}
|
||||||
|
|
||||||
|
var invalidCounterPaths = []string{
|
||||||
|
"\\O(I\\C",
|
||||||
|
"\\OI)\\C",
|
||||||
|
"\\O(I\\C",
|
||||||
|
"\\O/C",
|
||||||
|
"\\O(I/C",
|
||||||
|
"\\O(I/C)",
|
||||||
|
"\\O(I\\)C",
|
||||||
|
"\\O(I\\C)",
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCounterPathParsing(t *testing.T) {
|
||||||
|
for path, vals := range counterPathsAndRes {
|
||||||
|
o, i, c, err := extractCounterInfoFromCounterPath(path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, assert.ObjectsAreEqual(vals, []string{o, i, c}), "arrays: %#v and %#v are not equal", vals, []string{o, i, c})
|
||||||
|
}
|
||||||
|
for _, path := range invalidCounterPaths {
|
||||||
|
_, _, _, err := extractCounterInfoFromCounterPath(path)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddItemSimple(t *testing.T) {
|
func TestAddItemSimple(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
cps1 := []string{"\\O(I)\\C"}
|
cps1 := []string{"\\O(I)\\C"}
|
||||||
|
|
Loading…
Reference in New Issue