I am new to telegraf. I wanted to write a telegraf input plugin in Golang to read as well as print Window events logs. Please tell me which Libraries should I use in Golang to do the above Job and also wanted to know how to organize the code into the four main basic functions used to write a telegraf input plugin which are "gather","description","init","sample config"
I know how to build the telegraf source code.I tried to make my own folder inside the folder(go\src\github.com\influxdata\telegraf\plugins\inputs) named"eventlog" . I pasted the win_services.go file inside the eventlog folder and renamed the services as eventlog .I even added the folder i created,inside the all.go file. Then I tried to build the telegraf and the .exe file was created ,but all the win_services got printed .I want the eventlogs to be printed.So can you please tell me how to write the code for it,especially what are the libraries to be used and what are the contents of those 4 main functions?
package win_eventlogs
import (
"fmt"
"log"
"os"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
)z
type ServiceErr struct {
Message string
Service string
Err error
}
func (e *ServiceErr) Error() string {
return fmt.Sprintf("%s: '%s': %v", e.Message, e.Service, e.Err)
}
func IsPermission(err error) bool {
if err, ok := err.(*ServiceErr); ok {
return os.IsPermission(err.Err)
}
return false
}
// WinService provides interface for svc.Service
type WinService interface {
Close() error
Config() (mgr.Config, error)
Query() (svc.Status, error)
}
// ManagerProvider sets interface for acquiring manager instance, like mgr.Mgr
type ManagerProvider interface {
Connect() (WinServiceManager, error)
}
// WinServiceManager provides interface for mgr.Mgr
type WinServiceManager interface {
Disconnect() error
OpenService(name string) (WinService, error)
ListServices() ([]string, error)
}
// WinSvcMgr is wrapper for mgr.Mgr implementing WinServiceManager interface
type WinSvcMgr struct {
realMgr *mgr.Mgr
}
func (m *WinSvcMgr) Disconnect() error {
return m.realMgr.Disconnect()
}
func (m *WinSvcMgr) OpenService(name string) (WinService, error) {
return m.realMgr.OpenService(name)
}
func (m *WinSvcMgr) ListServices() ([]string, error) {
return m.realMgr.ListServices()
}
// MgProvider is an implementation of WinServiceManagerProvider interface returning WinSvcMgr
type MgProvider struct {
}
func (rmr *MgProvider) Connect() (WinServiceManager, error) {
scmgr, err := mgr.Connect()
if err != nil {
return nil, err
} else {
return &WinSvcMgr{scmgr}, nil
}
}
var sampleConfig = `
## Names of the services to monitor. Leave empty to monitor all the available services on the host
service_names = [
"LanmanServer",
"TermService",
]
`
var description = "Input plugin to report Windows services info."
//WinServices is an implementation if telegraf.Input interface, providing info about Windows Services
type WinServices struct {
ServiceNames []string `toml:"service_names"`
mgrProvider ManagerProvider
}
type ServiceInfo struct {
ServiceName string
DisplayName string
State int
StartUpMode int
}
func (m *WinServices) Description() string {
return description
}
func (m *WinServices) SampleConfig() string {
return sampleConfig
}
func (m *WinServices) Gather(acc telegraf.Accumulator) error {
scmgr, err := m.mgrProvider.Connect()
if err != nil {
return fmt.Errorf("Could not open service manager: %s", err)
}
defer scmgr.Disconnect()
serviceNames, err := listServices(scmgr, m.ServiceNames)
if err != nil {
return err
}
for _, srvName := range serviceNames {
service, err := collectServiceInfo(scmgr, srvName)
if err != nil {
if IsPermission(err) {
log.Printf("D! Error in plugin [inputs.win_eventlogs]: %v", err)
} else {
acc.AddError(err)
}
continue
}
tags := map[string]string{
"service_name": service.ServiceName,
}
//display name could be empty, but still valid service
if len(service.DisplayName) > 0 {
tags["display_name"] = service.DisplayName
}
fields := map[string]interface{}{
"state": service.State,
"startup_mode": service.StartUpMode,
}
acc.AddFields("win_eventlogs", fields, tags)
}
return nil
}
// listServices returns a list of services to gather.
func listServices(scmgr WinServiceManager, userServices []string) ([]string, error) {
if len(userServices) != 0 {
return userServices, nil
}
names, err := scmgr.ListServices()
if err != nil {
return nil, fmt.Errorf("Could not list services: %s", err)
}
return names, nil
}
// collectServiceInfo gathers info about a service.
func collectServiceInfo(scmgr WinServiceManager, serviceName string) (*ServiceInfo, error) {
srv, err := scmgr.OpenService(serviceName)
if err != nil {
return nil, &ServiceErr{
Message: "could not open service",
Service: serviceName,
Err: err,
}
}
defer srv.Close()
srvStatus, err := srv.Query()
if err != nil {
return nil, &ServiceErr{
Message: "could not query service",
Service: serviceName,
Err: err,
}
}
srvCfg, err := srv.Config()
if err != nil {
return nil, &ServiceErr{
Message: "could not get config of service",
Service: serviceName,
Err: err,
}
}
serviceInfo := &ServiceInfo{
ServiceName: serviceName,
DisplayName: srvCfg.DisplayName,
StartUpMode: int(srvCfg.StartType),
State: int(srvStatus.State),
}
return serviceInfo, nil
}
func init() {
inputs.Add("win_eventlogs", func() telegraf.Input {
return &WinServices{
mgrProvider: &MgProvider{},
}
})
}
win_services are getting printed but I want the win_eventlogs to be printed.