Added Glob pattern matching for "Windows Services" plugin (#8575)
* Allow glob patterns in config * Update README * Move creating filter to init * Need to explictly call init Co-authored-by: Bas <3441183+BattleBas@users.noreply.github.com>
This commit is contained in:
parent
045c3c18b8
commit
b858eb962a
|
|
@ -8,10 +8,11 @@ Monitoring some services may require running Telegraf with administrator privile
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[[inputs.win_services]]
|
[[inputs.win_services]]
|
||||||
## Names of the services to monitor. Leave empty to monitor all the available services on the host
|
## Names of the services to monitor. Leave empty to monitor all the available services on the host. Globs accepted.
|
||||||
service_names = [
|
service_names = [
|
||||||
"LanmanServer",
|
"LanmanServer",
|
||||||
"TermService",
|
"TermService",
|
||||||
|
"Win*",
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/filter"
|
||||||
"github.com/influxdata/telegraf/plugins/inputs"
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
"golang.org/x/sys/windows/svc/mgr"
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
|
|
@ -78,10 +79,11 @@ func (rmr *MgProvider) Connect() (WinServiceManager, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
## Names of the services to monitor. Leave empty to monitor all the available services on the host
|
## Names of the services to monitor. Leave empty to monitor all the available services on the host. Globs accepted.
|
||||||
service_names = [
|
service_names = [
|
||||||
"LanmanServer",
|
"LanmanServer",
|
||||||
"TermService",
|
"TermService",
|
||||||
|
"Win*",
|
||||||
]
|
]
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
@ -93,6 +95,8 @@ type WinServices struct {
|
||||||
|
|
||||||
ServiceNames []string `toml:"service_names"`
|
ServiceNames []string `toml:"service_names"`
|
||||||
mgrProvider ManagerProvider
|
mgrProvider ManagerProvider
|
||||||
|
|
||||||
|
servicesFilter filter.Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceInfo struct {
|
type ServiceInfo struct {
|
||||||
|
|
@ -102,6 +106,16 @@ type ServiceInfo struct {
|
||||||
StartUpMode int
|
StartUpMode int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *WinServices) Init() error {
|
||||||
|
var err error
|
||||||
|
m.servicesFilter, err = filter.NewIncludeExcludeFilter(m.ServiceNames, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *WinServices) Description() string {
|
func (m *WinServices) Description() string {
|
||||||
return description
|
return description
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +131,7 @@ func (m *WinServices) Gather(acc telegraf.Accumulator) error {
|
||||||
}
|
}
|
||||||
defer scmgr.Disconnect()
|
defer scmgr.Disconnect()
|
||||||
|
|
||||||
serviceNames, err := listServices(scmgr, m.ServiceNames)
|
serviceNames, err := m.listServices(scmgr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -152,16 +166,20 @@ func (m *WinServices) Gather(acc telegraf.Accumulator) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// listServices returns a list of services to gather.
|
// listServices returns a list of services to gather.
|
||||||
func listServices(scmgr WinServiceManager, userServices []string) ([]string, error) {
|
func (m *WinServices) listServices(scmgr WinServiceManager) ([]string, error) {
|
||||||
if len(userServices) != 0 {
|
|
||||||
return userServices, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
names, err := scmgr.ListServices()
|
names, err := scmgr.ListServices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Could not list services: %s", err)
|
return nil, fmt.Errorf("Could not list services: %s", err)
|
||||||
}
|
}
|
||||||
return names, nil
|
|
||||||
|
var services []string
|
||||||
|
for _, n := range names {
|
||||||
|
if m.servicesFilter.Match(n) {
|
||||||
|
services = append(services, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return services, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectServiceInfo gathers info about a service.
|
// collectServiceInfo gathers info about a service.
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,11 @@ func TestList(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer scmgr.Disconnect()
|
defer scmgr.Disconnect()
|
||||||
|
|
||||||
services, err := listServices(scmgr, KnownServices)
|
winServices := &WinServices{
|
||||||
|
ServiceNames: KnownServices,
|
||||||
|
}
|
||||||
|
winServices.Init()
|
||||||
|
services, err := winServices.listServices(scmgr)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, services, 2, "Different number of services")
|
require.Len(t, services, 2, "Different number of services")
|
||||||
require.Equal(t, services[0], KnownServices[0])
|
require.Equal(t, services[0], KnownServices[0])
|
||||||
|
|
@ -38,7 +42,11 @@ func TestEmptyList(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer scmgr.Disconnect()
|
defer scmgr.Disconnect()
|
||||||
|
|
||||||
services, err := listServices(scmgr, []string{})
|
winServices := &WinServices{
|
||||||
|
ServiceNames: []string{},
|
||||||
|
}
|
||||||
|
winServices.Init()
|
||||||
|
services, err := winServices.listServices(scmgr)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Condition(t, func() bool { return len(services) > 20 }, "Too few service")
|
require.Condition(t, func() bool { return len(services) > 20 }, "Too few service")
|
||||||
}
|
}
|
||||||
|
|
@ -52,6 +60,7 @@ func TestGatherErrors(t *testing.T) {
|
||||||
ServiceNames: InvalidServices,
|
ServiceNames: InvalidServices,
|
||||||
mgrProvider: &MgProvider{},
|
mgrProvider: &MgProvider{},
|
||||||
}
|
}
|
||||||
|
ws.Init()
|
||||||
require.Len(t, ws.ServiceNames, 3, "Different number of services")
|
require.Len(t, ws.ServiceNames, 3, "Different number of services")
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
require.NoError(t, ws.Gather(&acc))
|
require.NoError(t, ws.Gather(&acc))
|
||||||
|
|
|
||||||
|
|
@ -123,35 +123,50 @@ var testErrors = []testData{
|
||||||
{nil, errors.New("Fake srv query error"), nil, "Fake service 2", "", 0, 0},
|
{nil, errors.New("Fake srv query error"), nil, "Fake service 2", "", 0, 0},
|
||||||
{nil, nil, errors.New("Fake srv config error"), "Fake service 3", "", 0, 0},
|
{nil, nil, errors.New("Fake srv config error"), "Fake service 3", "", 0, 0},
|
||||||
}},
|
}},
|
||||||
{nil, nil, nil, []serviceTestInfo{
|
{[]string{"Fake service 1"}, nil, nil, []serviceTestInfo{
|
||||||
{errors.New("Fake srv open error"), nil, nil, "Fake service 1", "", 0, 0},
|
{errors.New("Fake srv open error"), nil, nil, "Fake service 1", "", 0, 0},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBasicInfo(t *testing.T) {
|
func TestBasicInfo(t *testing.T) {
|
||||||
|
|
||||||
winServices := &WinServices{testutil.Logger{}, nil, &FakeMgProvider{testErrors[0]}}
|
winServices := &WinServices{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
mgrProvider: &FakeMgProvider{testErrors[0]},
|
||||||
|
}
|
||||||
|
winServices.Init()
|
||||||
assert.NotEmpty(t, winServices.SampleConfig())
|
assert.NotEmpty(t, winServices.SampleConfig())
|
||||||
assert.NotEmpty(t, winServices.Description())
|
assert.NotEmpty(t, winServices.Description())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMgrErrors(t *testing.T) {
|
func TestMgrErrors(t *testing.T) {
|
||||||
//mgr.connect error
|
//mgr.connect error
|
||||||
winServices := &WinServices{testutil.Logger{}, nil, &FakeMgProvider{testErrors[0]}}
|
winServices := &WinServices{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
mgrProvider: &FakeMgProvider{testErrors[0]},
|
||||||
|
}
|
||||||
var acc1 testutil.Accumulator
|
var acc1 testutil.Accumulator
|
||||||
err := winServices.Gather(&acc1)
|
err := winServices.Gather(&acc1)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), testErrors[0].mgrConnectError.Error())
|
assert.Contains(t, err.Error(), testErrors[0].mgrConnectError.Error())
|
||||||
|
|
||||||
////mgr.listServices error
|
////mgr.listServices error
|
||||||
winServices = &WinServices{testutil.Logger{}, nil, &FakeMgProvider{testErrors[1]}}
|
winServices = &WinServices{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
mgrProvider: &FakeMgProvider{testErrors[1]},
|
||||||
|
}
|
||||||
var acc2 testutil.Accumulator
|
var acc2 testutil.Accumulator
|
||||||
err = winServices.Gather(&acc2)
|
err = winServices.Gather(&acc2)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), testErrors[1].mgrListServicesError.Error())
|
assert.Contains(t, err.Error(), testErrors[1].mgrListServicesError.Error())
|
||||||
|
|
||||||
////mgr.listServices error 2
|
////mgr.listServices error 2
|
||||||
winServices = &WinServices{testutil.Logger{}, []string{"Fake service 1"}, &FakeMgProvider{testErrors[3]}}
|
winServices = &WinServices{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
ServiceNames: []string{"Fake service 1"},
|
||||||
|
mgrProvider: &FakeMgProvider{testErrors[3]},
|
||||||
|
}
|
||||||
|
winServices.Init()
|
||||||
var acc3 testutil.Accumulator
|
var acc3 testutil.Accumulator
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
|
@ -162,7 +177,11 @@ func TestMgrErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceErrors(t *testing.T) {
|
func TestServiceErrors(t *testing.T) {
|
||||||
winServices := &WinServices{testutil.Logger{}, nil, &FakeMgProvider{testErrors[2]}}
|
winServices := &WinServices{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
mgrProvider: &FakeMgProvider{testErrors[2]},
|
||||||
|
}
|
||||||
|
winServices.Init()
|
||||||
var acc1 testutil.Accumulator
|
var acc1 testutil.Accumulator
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
|
@ -184,8 +203,13 @@ var testSimpleData = []testData{
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGather2(t *testing.T) {
|
func TestGatherContainsTag(t *testing.T) {
|
||||||
winServices := &WinServices{testutil.Logger{}, nil, &FakeMgProvider{testSimpleData[0]}}
|
winServices := &WinServices{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
ServiceNames: []string{"Service*"},
|
||||||
|
mgrProvider: &FakeMgProvider{testSimpleData[0]},
|
||||||
|
}
|
||||||
|
winServices.Init()
|
||||||
var acc1 testutil.Accumulator
|
var acc1 testutil.Accumulator
|
||||||
require.NoError(t, winServices.Gather(&acc1))
|
require.NoError(t, winServices.Gather(&acc1))
|
||||||
assert.Len(t, acc1.Errors, 0, "There should be no errors after gather")
|
assert.Len(t, acc1.Errors, 0, "There should be no errors after gather")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue