[Golang] winlogbeat二次開發

入口函數
beats/winlogbeat/beater/winlogbeat.go

func New(b *beat.Beat, _ *common.Config) (beat.Beater, error) {
	// Read configuration.
	config := config.DefaultSettings
	err := b.BeatConfig.Unpack(&config)
	if err != nil {
		return nil, fmt.Errorf("Error reading configuration file. %v", err)
	}

	// resolve registry file path
	config.RegistryFile = paths.Resolve(paths.Data, config.RegistryFile)
	logp.Info("State will be read from and persisted to %s",
		config.RegistryFile)

	eb := &Winlogbeat{
		beat:   b,
		config: config,
		done:   make(chan struct{}),
	}

	if err := eb.init(b); err != nil {   //初始化配置文件 查看取的日誌名稱是否存在
		return nil, err
	}

	return eb, nil
}

beats/libbeat/cmd/run.go

func genRunCmd(settings instance.Settings, beatCreator beat.Creator) *cobra.Command {
	name := settings.Name
	runCmd := cobra.Command{
		Use:   "run",
		Short: "Run " + name,
		Run: func(cmd *cobra.Command, args []string) {
			err := instance.Run(settings, beatCreator)  // 下一個運行點調用run
			if err != nil {
				os.Exit(1)
			}
		},
	}

	// Run subcommand flags, only available to *beat run
	runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("N"))
	runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("httpprof"))
	runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("cpuprofile"))
	runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("memprofile"))

	if settings.RunFlags != nil {
		runCmd.Flags().AddFlagSet(settings.RunFlags)
	}

	return &runCmd
}

beats/libbeat/cmd/instance/beat.go

func Run(settings Settings, bt beat.Creator) error {
	err := setUmaskWithSettings(settings)
	if err != nil && err != errNotImplemented {
		return errw.Wrap(err, "could not set umask")
	}

	......

		return b.launch(settings, bt)  // 下一個點
	}())
}

beats/libbeat/cmd/instance/beat.go

func (b *Beat) launch(settings Settings, bt beat.Creator) error {
	defer logp.Sync()
	......
	return beater.Run(&b.Beat) // 運行入口點
}

beats/winlogbeat/beater/winlogbeat.go 根據採集的日誌類型會創建相應的協程。

// Run is used within the beats interface to execute the Winlogbeat workers.
func (eb *Winlogbeat) Run(b *beat.Beat) error {
	if err := eb.setup(b); err != nil {
		return err
	}

	acker := newEventACKer(eb.checkpoint)
	persistedState := eb.checkpoint.States()

	// Initialize metrics.
	initMetrics("total")

	// setup global event ACK handler
	err := eb.pipeline.SetACKHandler(beat.PipelineACKHandler{
		ACKEvents: acker.ACKEvents,
	})
	if err != nil {
		return err
	}

	var wg sync.WaitGroup
	for _, log := range eb.eventLogs {
		state, _ := persistedState[log.source.Name()]

		// Start a goroutine for each event log.
		wg.Add(1)
		go eb.processEventLog(&wg, log, state, acker)  // 主要採集函數
	}

	wg.Wait()
	defer eb.checkpoint.Shutdown()

	if eb.config.ShutdownTimeout > 0 {
		logp.Info("Shutdown will wait max %v for the remaining %v events to publish.",
			eb.config.ShutdownTimeout, acker.Active())
		ctx, cancel := context.WithTimeout(context.Background(), eb.config.ShutdownTimeout)
		defer cancel()
		acker.Wait(ctx)
	}

	return nil
}

beats/winlogbeat/beater/winlogbeat.go

func (eb *Winlogbeat) processEventLog(
	wg *sync.WaitGroup,
	logger *eventLogger,
	state checkpoint.EventLogState,
	acker *eventACKer,
) {
	defer wg.Done()
	logger.run(eb.done, eb.pipeline, state, acker)
}

連接獲取日誌並Publish
winlogbeat/beater/eventlogger.go

func (e *eventLogger) run(
	done <-chan struct{},
	pipeline beat.Pipeline,
	state checkpoint.EventLogState,
	acker *eventACKer,
) {
	api := e.source

	// Initialize per event log metrics.
	initMetrics(api.Name())

	client, err := e.connect(pipeline)
	if err != nil {
		logp.Warn("EventLog[%s] Pipeline error. Failed to connect to publisher pipeline",
			api.Name())
		return
	}

	// close client on function return or when `done` is triggered (unblock client)
	defer client.Close()
	go func() {
		<-done
		client.Close()
	}()

	err = api.Open(state)
	if err != nil {
		logp.Warn("EventLog[%s] Open() error. No events will be read from "+
			"this source. %v", api.Name(), err)
		return
	}
	defer func() {
		logp.Info("EventLog[%s] Stop processing.", api.Name())

		if err := api.Close(); err != nil {
			logp.Warn("EventLog[%s] Close() error. %v", api.Name(), err)
			return
		}
	}()

	debugf("EventLog[%s] opened successfully", api.Name())

	for stop := false; !stop; {
		select {
		case <-done:
			return
		default:
		}

		// Read from the event.
		records, err := api.Read()
		switch err {
		case nil:
		case io.EOF:
			// Graceful stop.
			stop = true
		default:
			logp.Warn("EventLog[%s] Read() error: %v", api.Name(), err)
			return
		}

		debugf("EventLog[%s] Read() returned %d records", api.Name(), len(records))
		if len(records) == 0 {
			time.Sleep(time.Second)
			continue
		}

		acker.Add(len(records))
		for _, lr := range records {
			client.Publish(lr.ToEvent())
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章