dongzine3782 2019-08-26 06:53
浏览 266

如何编写Telegraf输入插件以获取Window事件日志?

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.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥100 求数学坐标画圆以及直线的算法
    • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
    • ¥15 名为“Product”的列已属于此 DataTable
    • ¥15 安卓adb backup备份应用数据失败
    • ¥15 eclipse运行项目时遇到的问题
    • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
    • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
    • ¥15 自己瞎改改,结果现在又运行不了了
    • ¥15 链式存储应该如何解决
    • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站