fix: Add setting to win_perf_counters input to ignore localization (#10101)
This commit is contained in:
parent
2b43934174
commit
6518745153
|
|
@ -20,6 +20,10 @@ as counters used when performance monitoring
|
|||
This file is likely to be updated in the future with more examples for
|
||||
useful configurations for separate scenarios.
|
||||
|
||||
For more information on concepts and terminology including object,
|
||||
counter, and instance names, see the help in the Windows Performance
|
||||
Monitor app.
|
||||
|
||||
### Plugin wide
|
||||
|
||||
Plugin wide entries are underneath `[[inputs.win_perf_counters]]`.
|
||||
|
|
@ -33,19 +37,39 @@ Example:
|
|||
|
||||
#### UseWildcardsExpansion
|
||||
|
||||
If `UseWildcardsExpansion` is set to true, wildcards can be used in the
|
||||
instance name and the counter name. When using localized Windows, counters
|
||||
will be also be localized. Instance indexes will also be returned in the
|
||||
instance name.
|
||||
If `UseWildcardsExpansion` is true, wildcards can be used in the
|
||||
instance name and the counter name. Instance indexes will also be
|
||||
returned in the instance name.
|
||||
|
||||
Partial wildcards (e.g. `chrome*`) are supported only in the instance name on Windows Vista and newer.
|
||||
Partial wildcards (e.g. `chrome*`) are supported only in the instance
|
||||
name on Windows Vista and newer.
|
||||
|
||||
If disabled, wildcards (not partial) in instance names can still be used, but
|
||||
instance indexes will not be returned in the instance names.
|
||||
If disabled, wildcards (not partial) in instance names can still be
|
||||
used, but instance indexes will not be returned in the instance names.
|
||||
|
||||
Example:
|
||||
`UseWildcardsExpansion=true`
|
||||
|
||||
#### LocalizeWildcardsExpansion
|
||||
|
||||
`LocalizeWildcardsExpansion` selects whether object and counter names
|
||||
are localized when `UseWildcardsExpansion` is true and Telegraf is
|
||||
running on a localized installation of Windows.
|
||||
|
||||
When `LocalizeWildcardsExpansion` is true, Telegraf produces metrics
|
||||
with localized tags and fields even when object and counter names are
|
||||
in English.
|
||||
|
||||
When `LocalizeWildcardsExpansion` is false, Telegraf expects object
|
||||
and counter names to be in English and produces metrics with English
|
||||
tags and fields.
|
||||
|
||||
When `LocalizeWildcardsExpansion` is false, wildcards can only be used
|
||||
in instances. Object and counter names must not have wildcards.
|
||||
|
||||
Example:
|
||||
`LocalizeWildcardsExpansion=true`
|
||||
|
||||
#### CountersRefreshInterval
|
||||
|
||||
Configured counters are matched against available counters at the interval
|
||||
|
|
@ -63,7 +87,7 @@ Example:
|
|||
|
||||
#### PreVistaSupport
|
||||
|
||||
_Deprecated. Necessary features on Windows Vista and newer are checked dynamically_
|
||||
(Deprecated. Necessary features on Windows Vista and newer are checked dynamically)
|
||||
|
||||
Bool, if set to `true`, the plugin will use the localized PerfCounter interface that has been present since before Vista for backwards compatibility.
|
||||
|
||||
|
|
@ -74,7 +98,7 @@ Example for Windows Server 2003, this would be set to true:
|
|||
|
||||
#### UsePerfCounterTime
|
||||
|
||||
Bool, if set to `true` will request a timestamp along with the PerfCounter data.
|
||||
Bool, if set to `true` will request a timestamp along with the PerfCounter data.
|
||||
If se to `false`, current time will be used.
|
||||
|
||||
Supported on Windows Vista/Windows Server 2008 and newer
|
||||
|
|
@ -86,6 +110,7 @@ Example:
|
|||
See Entry below.
|
||||
|
||||
### Entry
|
||||
|
||||
A new configuration entry consists of the TOML header starting with,
|
||||
`[[inputs.win_perf_counters.object]]`.
|
||||
This must follow before other plugin configurations,
|
||||
|
|
@ -94,14 +119,16 @@ beneath the main win_perf_counters entry, `[[inputs.win_perf_counters]]`.
|
|||
Following this are 3 required key/value pairs and three optional parameters and their usage.
|
||||
|
||||
#### ObjectName
|
||||
**Required**
|
||||
|
||||
(Required)
|
||||
|
||||
ObjectName is the Object to query for, like Processor, DirectoryServices, LogicalDisk or similar.
|
||||
|
||||
Example: `ObjectName = "LogicalDisk"`
|
||||
|
||||
#### Instances
|
||||
**Required**
|
||||
|
||||
(Required)
|
||||
|
||||
The instances key (this is an array) declares the instances of a counter you would like returned,
|
||||
it can be one or more values.
|
||||
|
|
@ -121,7 +148,8 @@ Here only one option is valid if you want data back,
|
|||
and that is to specify `Instances = ["------"]`.
|
||||
|
||||
#### Counters
|
||||
**Required**
|
||||
|
||||
(Required)
|
||||
|
||||
The Counters key (this is an array) declares the counters of the ObjectName
|
||||
you would like returned, it can also be one or more values.
|
||||
|
|
@ -133,7 +161,8 @@ This must be specified for every counter you want the results of, or use
|
|||
is set to `true`.
|
||||
|
||||
#### Measurement
|
||||
*Optional*
|
||||
|
||||
(Optional)
|
||||
|
||||
This key is optional. If it is not set it will be `win_perf_counters`.
|
||||
In InfluxDB this is the key underneath which the returned data is stored.
|
||||
|
|
@ -144,7 +173,8 @@ separately from Processor results.
|
|||
Example: `Measurement = "win_disk"``
|
||||
|
||||
#### IncludeTotal
|
||||
*Optional*
|
||||
|
||||
(Optional)
|
||||
|
||||
This key is optional. It is a simple bool.
|
||||
If it is not set to true or included it is treated as false.
|
||||
|
|
@ -154,7 +184,8 @@ like `_Total`, `0,_Total` and so on where applicable
|
|||
(Processor Information is one example).
|
||||
|
||||
#### WarnOnMissing
|
||||
*Optional*
|
||||
|
||||
(Optional)
|
||||
|
||||
This key is optional. It is a simple bool.
|
||||
If it is not set to true or included it is treated as false.
|
||||
|
|
@ -163,7 +194,8 @@ It will print out any ObjectName/Instance/Counter combinations
|
|||
asked for that do not match. Useful when debugging new configurations.
|
||||
|
||||
#### FailOnMissing
|
||||
*Internal*
|
||||
|
||||
(Internal)
|
||||
|
||||
This key should not be used. It is for testing purposes only.
|
||||
It is a simple bool. If it is not set to true or included this is treated as false.
|
||||
|
|
@ -173,6 +205,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
## Examples
|
||||
|
||||
### Generic Queries
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -217,6 +250,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### Active Directory Domain Controller
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[inputs.win_perf_counters.tags]
|
||||
|
|
@ -245,6 +279,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### DFS Namespace + Domain Controllers
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -258,6 +293,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### DFS Replication + Domain Controllers
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -271,6 +307,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### DNS Server + Domain Controllers
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -282,6 +319,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### IIS / ASP.NET
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -326,6 +364,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### Process
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -338,6 +377,7 @@ if any of the combinations of ObjectName/Instances/Counters are invalid.
|
|||
```
|
||||
|
||||
### .NET Monitoring
|
||||
|
||||
```toml
|
||||
[[inputs.win_perf_counters]]
|
||||
[[inputs.win_perf_counters.object]]
|
||||
|
|
@ -402,6 +442,7 @@ your performance counters.
|
|||
1. Drop into the C:\WINDOWS\System32 directory by typing `C:` then `cd \Windows\System32`
|
||||
1. Rebuild your counter values, which may take a few moments so please be
|
||||
patient, by running:
|
||||
```
|
||||
lodctr /r
|
||||
```
|
||||
|
||||
```batchfile
|
||||
lodctr /r
|
||||
```
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ var sampleConfig = `
|
|||
# and in case of localized Windows, counter paths will be also localized. It also returns instance indexes in instance names.
|
||||
# If false, wildcards (not partial) in instance names will still be expanded, but instance indexes will not be returned in instance names.
|
||||
#UseWildcardsExpansion = false
|
||||
# When running on a localized version of Windows and with UseWildcardsExpansion = true, Windows will
|
||||
# localize object and counter names. When LocalizeWildcardsExpansion = false, use the names in object.Counters instead
|
||||
# of the localized names. Only Instances can have wildcards in this case. ObjectName and Counters must not have wildcards when this
|
||||
# setting is false.
|
||||
#LocalizeWildcardsExpansion = true
|
||||
# Period after which counters will be reread from configuration and wildcards in counter paths expanded
|
||||
CountersRefreshInterval="1m"
|
||||
|
||||
|
|
@ -141,11 +146,12 @@ var sampleConfig = `
|
|||
type Win_PerfCounters struct {
|
||||
PrintValid bool
|
||||
//deprecated: determined dynamically
|
||||
PreVistaSupport bool
|
||||
UsePerfCounterTime bool
|
||||
Object []perfobject
|
||||
CountersRefreshInterval config.Duration
|
||||
UseWildcardsExpansion bool
|
||||
PreVistaSupport bool
|
||||
UsePerfCounterTime bool
|
||||
Object []perfobject
|
||||
CountersRefreshInterval config.Duration
|
||||
UseWildcardsExpansion bool
|
||||
LocalizeWildcardsExpansion bool
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
|
|
@ -247,6 +253,7 @@ func (m *Win_PerfCounters) SampleConfig() string {
|
|||
|
||||
//objectName string, counter string, instance string, measurement string, include_total bool
|
||||
func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instance string, counterName string, measurement string, includeTotal bool) error {
|
||||
origCounterPath := counterPath
|
||||
var err error
|
||||
var counterHandle PDH_HCOUNTER
|
||||
if !m.query.IsVistaOrNewer() {
|
||||
|
|
@ -273,21 +280,55 @@ func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instan
|
|||
return err
|
||||
}
|
||||
|
||||
origObjectName, _, origCounterName, err := extractCounterInfoFromCounterPath(origCounterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, counterPath := range counters {
|
||||
var err error
|
||||
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
||||
|
||||
objectName, instance, counterName, err = extractCounterInfoFromCounterPath(counterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newItem *counter
|
||||
if !m.LocalizeWildcardsExpansion {
|
||||
// On localized installations of Windows, Telegraf
|
||||
// should return English metrics, but
|
||||
// ExpandWildCardPath returns localized counters. Undo
|
||||
// that by using the original object and counter
|
||||
// names, along with the expanded instance.
|
||||
|
||||
var newInstance string
|
||||
if instance == "" {
|
||||
newInstance = emptyInstance
|
||||
} else {
|
||||
newInstance = instance
|
||||
}
|
||||
counterPath = formatPath(origObjectName, newInstance, origCounterName)
|
||||
counterHandle, err = m.query.AddEnglishCounterToQuery(counterPath)
|
||||
newItem = &counter{
|
||||
counterPath,
|
||||
origObjectName, origCounterName,
|
||||
instance, measurement,
|
||||
includeTotal, counterHandle,
|
||||
}
|
||||
} else {
|
||||
counterHandle, err = m.query.AddCounterToQuery(counterPath)
|
||||
newItem = &counter{
|
||||
counterPath,
|
||||
objectName, counterName,
|
||||
instance, measurement,
|
||||
includeTotal, counterHandle,
|
||||
}
|
||||
}
|
||||
|
||||
if instance == "_Total" && origInstance == "*" && !includeTotal {
|
||||
continue
|
||||
}
|
||||
|
||||
newItem := &counter{counterPath, objectName, counterName, instance, measurement,
|
||||
includeTotal, counterHandle}
|
||||
m.counters = append(m.counters, newItem)
|
||||
|
||||
if m.PrintValid {
|
||||
|
|
@ -306,6 +347,16 @@ func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instan
|
|||
return nil
|
||||
}
|
||||
|
||||
const emptyInstance = "------"
|
||||
|
||||
func formatPath(objectname string, instance string, counter string) string {
|
||||
if instance == emptyInstance {
|
||||
return "\\" + objectname + "\\" + counter
|
||||
} else {
|
||||
return "\\" + objectname + "(" + instance + ")\\" + counter
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Win_PerfCounters) ParseConfig() error {
|
||||
var counterPath string
|
||||
|
||||
|
|
@ -315,11 +366,7 @@ func (m *Win_PerfCounters) ParseConfig() error {
|
|||
for _, instance := range PerfObject.Instances {
|
||||
objectname := PerfObject.ObjectName
|
||||
|
||||
if instance == "------" {
|
||||
counterPath = "\\" + objectname + "\\" + counter
|
||||
} else {
|
||||
counterPath = "\\" + objectname + "(" + instance + ")\\" + counter
|
||||
}
|
||||
counterPath = formatPath(objectname, instance, counter)
|
||||
|
||||
err := m.AddItem(counterPath, objectname, instance, counter, PerfObject.Measurement, PerfObject.IncludeTotal)
|
||||
|
||||
|
|
@ -447,7 +494,7 @@ func shouldIncludeMetric(metric *counter, cValue CounterValue) bool {
|
|||
// Catch if we set it to total or some form of it
|
||||
return true
|
||||
}
|
||||
if metric.instance == "------" {
|
||||
if metric.instance == emptyInstance {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -476,8 +523,43 @@ func isKnownCounterDataError(err error) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (m *Win_PerfCounters) Init() error {
|
||||
if m.UseWildcardsExpansion && !m.LocalizeWildcardsExpansion {
|
||||
// Counters must not have wildcards with this option
|
||||
|
||||
found := false
|
||||
wildcards := []string{"*", "?"}
|
||||
|
||||
for _, object := range m.Object {
|
||||
for _, wildcard := range wildcards {
|
||||
if strings.Contains(object.ObjectName, wildcard) {
|
||||
found = true
|
||||
m.Log.Errorf("object: %s, contains wildcard %s", object.ObjectName, wildcard)
|
||||
}
|
||||
}
|
||||
for _, counter := range object.Counters {
|
||||
for _, wildcard := range wildcards {
|
||||
if strings.Contains(counter, wildcard) {
|
||||
found = true
|
||||
m.Log.Errorf("object: %s, counter: %s contains wildcard %s", object.ObjectName, counter, wildcard)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
return fmt.Errorf("wildcards can't be used with LocalizeWildcardsExpansion=false")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("win_perf_counters", func() telegraf.Input {
|
||||
return &Win_PerfCounters{query: &PerformanceQueryImpl{}, CountersRefreshInterval: config.Duration(time.Second * 60)}
|
||||
return &Win_PerfCounters{
|
||||
query: &PerformanceQueryImpl{},
|
||||
CountersRefreshInterval: config.Duration(time.Second * 60),
|
||||
LocalizeWildcardsExpansion: true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -452,7 +452,12 @@ func TestWinPerfcountersConfigError1Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
|
|
@ -486,7 +491,12 @@ func TestWinPerfcountersConfigError2Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
|
|
@ -522,7 +532,12 @@ func TestWinPerfcountersConfigError3Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
m.query.Open()
|
||||
|
||||
err := m.ParseConfig()
|
||||
|
|
@ -557,7 +572,12 @@ func TestWinPerfcountersCollect1Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
var acc testutil.Accumulator
|
||||
err := m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
|
@ -603,7 +623,14 @@ func TestWinPerfcountersCollect2Integration(t *testing.T) {
|
|||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, UsePerfCounterTime: true, Object: perfobjects, query: &PerformanceQueryImpl{}, UseWildcardsExpansion: true}
|
||||
m := Win_PerfCounters{
|
||||
PrintValid: false,
|
||||
UsePerfCounterTime: true,
|
||||
Object: perfobjects,
|
||||
query: &PerformanceQueryImpl{},
|
||||
UseWildcardsExpansion: true,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
var acc testutil.Accumulator
|
||||
err := m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -1024,3 +1024,47 @@ func TestUTF16ToStringArray(t *testing.T) {
|
|||
czechStrings := UTF16ToStringArray(unicodeStringListWithCzechChars)
|
||||
require.Equal(t, czechStrings, stringArrayWithCzechChars, "Not equal czech arrays")
|
||||
}
|
||||
|
||||
func TestNoWildcards(t *testing.T) {
|
||||
m := Win_PerfCounters{
|
||||
Object: createPerfObject("measurement", "object", []string{"instance"}, []string{"counter*"}, false, false),
|
||||
UseWildcardsExpansion: true,
|
||||
LocalizeWildcardsExpansion: false,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.Error(t, m.Init())
|
||||
m = Win_PerfCounters{
|
||||
Object: createPerfObject("measurement", "object?", []string{"instance"}, []string{"counter"}, false, false),
|
||||
UseWildcardsExpansion: true,
|
||||
LocalizeWildcardsExpansion: false,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.Error(t, m.Init())
|
||||
}
|
||||
|
||||
func TestLocalizeWildcardsExpansion(t *testing.T) {
|
||||
// this test is valid only on localized windows
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
|
||||
const counter = "% Processor Time"
|
||||
m := Win_PerfCounters{
|
||||
query: &PerformanceQueryImpl{},
|
||||
CountersRefreshInterval: config.Duration(time.Second * 60),
|
||||
Object: createPerfObject("measurement", "Processor Information",
|
||||
[]string{"_Total"}, []string{counter}, false, false),
|
||||
LocalizeWildcardsExpansion: false,
|
||||
UseWildcardsExpansion: true,
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
require.NoError(t, m.Init())
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, m.Gather(&acc))
|
||||
require.Len(t, acc.Metrics, 1)
|
||||
|
||||
//running on localized windows with UseWildcardsExpansion and
|
||||
//with LocalizeWildcardsExpansion, this will be localized. Using LocalizeWildcardsExpansion=false it will
|
||||
//be English.
|
||||
require.Contains(t, acc.Metrics[0].Fields, sanitizedChars.Replace(counter))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue