需要golang kafka zookeeper 等组件 还需要无闻老师的第三方库以及其他的库
"github.com/hpcloud/tail" "github.com/sirupsen/logrus" "github.com/go-ini/ini"
"agent/kafka" "agent/tailfile"
答题思路如下:
首先main看 用了无闻老师的go—ini的开源库 用来做读配置文件
加载kafka和colletc的配置项目
把配置加入configobj 后面加载这个configobj
打印日志
第二步初始化kafka
连接kafka
初始化Msg Channel 气候态goroutine去往kafka里面发msg
根据配置文件中指定的路径创建了一个tailobj
从tailobj.lines 通道中一行一行的读日志包装成kafka的msg
丢到msgChan中
检测是否成功 我们需要先启动zookeeper
命令为(前提是你自己改的文件路径已经ok)
bin\windows\zookeeper-server-start.bat config\zookeeper.properties
然后我们启动kafka
命令
bin\windows\kafka-server-start.bat config\server.properties
kafka启动成功之后 我们项目也已经存到kafka中
最后在开启终端查看日志(指定服务ip跟端口)(web_log为已经写死的文件名)beginning(启动)
bin\windows\kafka-console-consumer.bat --bootstrap-server 192.168.56.1:9092 --topic web_log --from-beginning
首先我们先看配置文件
[kafka] address=192.168.56.1:9092 //ip地址 topic=web_log //项目名字 chan_size=10000 [collect] logfile_path=E:\logs\s4.log //收集的日志存在的路径
文件1 kafka.go
package kafka //kafka 相关操作 import ( "github.com/Shopify/sarama" "github.com/sirupsen/logrus" ) var ( client sarama.SyncProducer MsgChan chan *sarama.ProducerMessage ) //Init 是初始化全局的kafka client func Init(address []string, chanSize int64) (err error) { //1.生产者配置 config := sarama.NewConfig() config.Producer.RequiredAcks = sarama.WaitForAll //ack config.Producer.Partitioner = sarama.NewRandomPartitioner //分区 config.Producer.Return.Successes = true //确认 //2 连接kafka client, err = sarama.NewSyncProducer(address, config) if err != nil { logrus.Error("kafka:producer closed,err:", err) return } //初始化msgCHan MsgChan = make(chan *sarama.ProducerMessage, chanSize) //起一个后台的goroutine从msgchan中读数据 go sendMsg() return } //msgchan中读取msg,发送给kafka func sendMsg() { for { select { case msg := <-MsgChan: pid, offset, err := client.SendMessage(msg) if err != nil { logrus.Warning("send msg failed,err:", err) return } logrus.Infof("send msg to kafka success pid:%v offset:%v", pid, offset) } } }
文件二 tailfile
package tailfile import ( "github.com/hpcloud/tail" "github.com/sirupsen/logrus" ) var ( Tailobj *tail.Tail ) func Init(filename string) (err error) { config := tail.Config{ ReOpen: true, Follow: true, Location: &tail.SeekInfo{Offset: 0, Whence: 2}, MustExist: false, Poll: true, } Tailobj, err = tail.TailFile(filename, config) if err != nil { logrus.Error("tailfile:create tailobj for path%ss failed,err:%v\n", filename, err) return } return }
文件三 main.go 主函数
package main import ( "agent/kafka" "agent/tailfile" "fmt" "github.com/Shopify/sarama" "github.com/go-ini/ini" "github.com/sirupsen/logrus" "time" ) //日志收集的客户端 //类似的开源项目还有filebeat //收集指定目录下的日志文件,发送到kafka中 //整个logagent的配置结构体 type Config struct { KafkaConfig `ini:"kafka"` CollectConfig `ini:"collect"` } type KafkaConfig struct { Address string `ini:"address"` Topic string `ini:"topic"` ChanSize int64 `ini:"chan_size"` } type CollectConfig struct { LogFilePath string `ini:"logfile_path"` } //run 真在的业务逻辑 func run() (err error) { //TailObj -->log --->Client--->kafka for { //循环读数据 line, ok := <-tailfile.Tailobj.Lines //chan tail.line if !ok { logrus.Warn("tail file close reopen.filename:%s\n", tailfile.Tailobj.Filename) time.Sleep(time.Second) //读取出错等一秒 continue } //利用通道讲同步的代码改为异步的 //把读出来的一行日志包装成kafka里面的msg类型,丢到通道中。 msg := &sarama.ProducerMessage{} msg.Topic = "web_log" msg.Value = sarama.StringEncoder(line.Text) //丢到通道中 kafka.MsgChan <- msg } } func main() { 0.读配置文件 `go—ini` var configobj = new(Config) err := ini.MapTo(configobj, "./conf/config.ini") if err != nil { logrus.Error("load config failed,err:%v", err) return } fmt.Printf("%#v\n", configobj) //1.初始化(做准备工作) err = kafka.Init([]string{configobj.KafkaConfig.Address}, configobj.KafkaConfig.ChanSize) if err != nil { logrus.Error("init kafka failed,err;%v", err) return } logrus.Info("init kafka success!") //2.根据配置中的日志路径。初始化tail去收集日志 err = tailfile.Init(configobj.CollectConfig.LogFilePath) if err != nil { logrus.Error("init tailfile failed,err:%v", err) return } logrus.Info("init tail success!") //3.把日志通过sarama发往kafka err = run() if err != nil { logrus.Error("run failed,err:%v", err) } }
配置到这里结束了。正常运行就好,如果说收集到的日志为乱码的话。因为没在cmd命令中设置中文格式输入。建议大家在文件下英文输入。