Beats作为Elastic Stack家族中重要的部分。它可以和方便地让我们把我们的数据发送到Elasticsearch或Logstash之中。如果我们想要生成自己的Beat,请使用GitHub的beats仓库中提供的Beat生成器。在今天的文章中,我们将详细介绍如何一步一步地来创建一个我们自己想要的beat。

设置自己的开发环境

安装go环境

Beats实际上是go程序。我们可以参照链接“Go get started”(https://golang.org/doc/install)来安装自己的golang语言开发环境。等我们安装好我们的go后,我们可以在terminal中打入如下的命令:

  1. $ which go
  2. /usr/local/go/bin/go

那么我们需要在我们的环境中设置如下的变量:

  1. export GOROOT=/usr/local/go
  2. export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
  3. export GOPATH=$HOME/go/beats

在这里,我也设置了以GOPATH。你可以设置自己的路径。针对我的情况,我在我的home目录下创建了一个go目录,并在go目录下生产一个叫做beats的目录。在一下,我们会在这个目录里生成我们的定制的beat。

下载Elastic beats源码

在这一步我们下载Elastic beats的源码。在termnial中打入如下的命令:

  1. mkdir -p ${GOPATH}/src/github.com/elastic
  2. git clone https://github.com/elastic/beats ${GOPATH}/src/github.com/elastic/beats

安装Python

目前generator只对Python2适用,所以,我们需要安装Python2。我们可以参照页面https://www.python.org/downloads/进行安装我们的python2。

安装virtualenv

我们必须安装virtualenv才能使得generator正常工作。可以参照链接https://virtualenv.pypa.io/en/latest/installation/来进行安装。如果自己的电脑上同时已经安装了python3,那么我们需要同时设置如写变量:

  1. export PYTHON_EXE='python2.7'
  2. export VIRTUALENV_PARAMS='-p python2.7'
  3. export VIRTUALENV_PYTHON='/usr/bin/python2.7'
  4. export VIRTUALENV_PYTHON='/usr/local/bin/python' (for Mac)

请注意:这里的python是2.x版本的python,而不是python3。我们需要保证VIRTUALENV_PYTHON指向我们的Python2的执行文件。

安装mage

我们需要在地址https://github.com/magefile/mage下载这个源码,并编译:

  1. go get -u -d github.com/magefile/mage
  2. cd $GOPATH/src/github.com/magefile/mage
  3. go run bootstrap.go

等上面的命令执行完后,我们可以在如下的目录中找到编译好的执行文件mage:

  1. liuxg-2:bin liuxg$ ls $GOPATH/bin
  2. mage

创建定制beat

首先创建一个目录在$GOPATH下,并进入该目录。

  1. mkdir ${GOPATH}/src/github.com/{user}
  2. cd ${GOPATH}/src/github.com/{user}

注意这里的user指的是自己在github上的用户名。比如针对我的情况是liu-xiao-guo。我打入如下写的命令:

  1. mkdir ${GOPATH}/src/github.com/liu-xiao-guo
  2. cd $GOPATH/src/github.com/elastic/beats/

接下来,我们运行如下的命令:

  1. mage GenerateCustomBeat

执行结果:

  1. $ mage GenerateCustomBeat
  2. 2019/11/13 15:24:01 Found Elastic Beats dir at /Users/liuxg/go/beats/src/github.com/elastic/beats
  3. Enter the beat name [examplebeat]: Countbeat
  4. Enter your github name [your-github-name]: liu-xiao-guo
  5. Enter the beat path [github.com/liu-xiao-guo/countbeat]:
  6. Enter your full name [Firstname Lastname]: Xiaoguo Liu
  7. Enter the beat type [beat]:
  8. DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
  9. DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
  10. WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='pypi.tuna.tsinghua.edu.cn', port=443): Read timed out. (read timeout=15)",)': /simple/semver/
  11. 2019/11/13 15:25:50 Found Elastic Beats dir at /Users/liuxg/go/beats/src/github.com/liu-xiao-guo/countbeat/vendor/github.com/elastic/beats
  12. Generated fields.yml for countbeat to /Users/liuxg/go/beats/src/github.com/liu-xiao-guo/countbeat/fields.yml
  13. 2019/11/13 15:25:52 Found Elastic Beats dir at /Users/liuxg/go/beats/src/github.com/liu-xiao-guo/countbeat/vendor/github.com/elastic/beats
  14. Auto packing the repository in background for optimum performance.
  15. See "git help gc" for manual housekeeping.
  16. =======================
  17. Your custom beat is now available as /Users/liuxg/go/beats/src/github.com/liu-xiao-guo/countbeat
  18. =======================

这样,我们基本上就生产了一个最基本的beat的框架。

接下来,我们进入到我们的beat目录里,并进行编译:

  1. cd ${GOPATH}/src/github.com/{user}/countbeat

针对我的情况:

  1. cd ${GOPATH}/src/github.com/liu-xiao-guo/countbeat

我们可以看一下里面最基本的文件:

  1. $ pwd
  2. /Users/liuxg/go/beats/src/github.com/liu-xiao-guo/countbeat
  3. liuxg-2:countbeat liuxg$ ls
  4. CONTRIBUTING.md cmd magefile.go
  5. LICENSE.txt config main.go
  6. Makefile countbeat.docker.yml main_test.go
  7. NOTICE.txt countbeat.reference.yml make.bat
  8. README.md countbeat.yml tests
  9. _meta docs vendor
  10. beater fields.yml
  11. build include

这里有最基本的框架文件。里面含有一个叫做countbeat.yml的配置文件及一些标准的模板文件。我们在命令行中直接打入如下的指令:

  1. make
  2. $ make
  3. go build -i -ldflags "-X github.com/liu-xiao-guo/countbeat/vendor/github.com/elastic/beats/libbeat/version.buildTime=2019-11-13T07:33:25Z -X github.com/liu-xiao-guo/countbeat/vendor/github.com/elastic/beats/libbeat/version.commit=501bd87da668346f78398676c78b4a39394a3640"

经过上面的编译,我们可以发现在当前的目录下,有一个已经编译好的countbeat可执行文件:

我们在当前的目录下直接运行这个可执行的文件:

  1. ./countbeat -e -d "*"

我们可以在terminal中看到:

那么在我们的Kibana中也可以看到如下信息:

显然数据已经被成功上传到Elasticsearch中了。

每一个文档的内容如下:

  1. {
  2. "@timestamp": "2019-11-13T07:38:57.095Z",
  3. "agent": {
  4. "version": "8.0.0",
  5. "type": "countbeat",
  6. "ephemeral_id": "d3f0638e-ee58-45ff-92cc-74f188fd66a4",
  7. "hostname": "liuxg-2.local",
  8. "id": "1d35220e-7f75-442a-88eb-43ec1e97f0d0"
  9. },
  10. "counter": 5,
  11. "ecs": {
  12. "version": "1.2.0"
  13. },
  14. "host": {
  15. "hostname": "liuxg-2.local",
  16. "architecture": "x86_64",
  17. "os": {
  18. "build": "19B88",
  19. "platform": "darwin",
  20. "version": "10.15.1",
  21. "family": "darwin",
  22. "name": "Mac OS X",
  23. "kernel": "19.0.0"
  24. },
  25. "id": "E51545F1-4BDC-5890-B194-83D23620325A",
  26. "name": "liuxg-2.local"
  27. },
  28. "type": "liuxg-2.local"
  29. }

它里面含有一个counter的整数值。

所有关于beat的设计上的代码可以在目录${GOPATH}/src/github.com/liu-xiao-guo/countbeat下的/beater/CountBeat.go文件里实现的。设计比较直接。大家可以看一下代码应该可以明白。

读取JSON文件beat

在上面我们已经熟悉了如何去创建一个template的beat。它是一个最基本的beat,并没有什么特别的功能。在这节里,我们接着如法炮制来创建一个稍微有一点用途的beat。我们的这个beat叫做readjson beat。它的源码可以按照如下的方法得到:

  1. git clone https://github.com/liu-xiao-guo/beats-readjson

首先,我们可以准备一个我们想要的json文件,比如:

  1. users.json
  2. {
  3. "users": [
  4. {
  5. "name": "Elliot",
  6. "type": "Reader",
  7. "age": 23,
  8. "social": {
  9. "facebook": "https://facebook.com",
  10. "twitter": "https://twitter.com"
  11. }
  12. },
  13. {
  14. "name": "Fraser",
  15. "type": "Author",
  16. "age": 17,
  17. "social": {
  18. "facebook": "https://facebook.com",
  19. "twitter": "https://twitter.com"
  20. }
  21. }
  22. ]
  23. }

我们可以把这个文件放入到我们如何喜欢的位置。针对我的情况,我把它置于我的电脑的如下位置:

  1. /Users/liuxg/data/beats/users.json

我们可以在readjson.yml文件中进行配置:

  1. readjson.yml

我们的readjson.go设计也相当简单:

  1. readjson.go
  2. package beater
  3. import (
  4. "fmt"
  5. "os"
  6. "io/ioutil"
  7. "encoding/json"
  8. "strconv"
  9. "time"
  10. "os/signal"
  11. "syscall"
  12. "github.com/elastic/beats/libbeat/beat"
  13. "github.com/elastic/beats/libbeat/common"
  14. "github.com/elastic/beats/libbeat/logp"
  15. "github.com/liu-xiao-guo/readjson/config"
  16. )
  17. type Users struct {
  18. Users []User `json:"users"`
  19. }
  20. // User struct which contains a name
  21. // a type and a list of social links
  22. type User struct {
  23. Name string `json:"name"`
  24. Type string `json:"type"`
  25. Age int `json:"Age"`
  26. Social Social `json:"social"`
  27. }
  28. // Social struct which contains a
  29. // list of links
  30. type Social struct {
  31. Facebook string `json:"facebook"`
  32. Twitter string `json:"twitter"`
  33. }
  34. // readjson configuration.
  35. type readjson struct {
  36. done chan struct{}
  37. config config.Config
  38. client beat.Client
  39. }
  40. // New creates an instance of readjson.
  41. func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) {
  42. c := config.DefaultConfig
  43. if err := cfg.Unpack(&c); err != nil {
  44. return nil, fmt.Errorf("Error reading config file: %v", err)
  45. }
  46. bt := &readjson{
  47. done: make(chan struct{}),
  48. config: c,
  49. }
  50. return bt, nil
  51. }
  52. // Run starts readjson.
  53. func (bt *readjson) Run(b *beat.Beat) error {
  54. logp.Info("readjson is running! Hit CTRL-C to stop it.")
  55. var err error
  56. bt.client, err = b.Publisher.Connect()
  57. if err != nil {
  58. return err
  59. }
  60. fmt.Println("Path: ", bt.config.Path)
  61. fmt.Println("Period: ", bt.config.Period)
  62. // Open our jsonFile
  63. jsonFile, err := os.Open(bt.config.Path)
  64. // if we os.Open returns an error then handle it
  65. if err != nil {
  66. fmt.Println(err)
  67. }
  68. fmt.Println("Successfully Opened users.json")
  69. // defer the closing of our jsonFile so that we can parse it later on
  70. defer jsonFile.Close()
  71. byteValue, _ := ioutil.ReadAll(jsonFile)
  72. // we initialize our Users array
  73. var users Users
  74. json.Unmarshal(byteValue, &users)
  75. // we iterate through every user within our users array and
  76. // print out the user Type, their name, and their facebook url
  77. // as just an example
  78. for i := 0; i < len(users.Users); i++ {
  79. fmt.Println("User Type: " + users.Users[i].Type)
  80. fmt.Println("User Age: " + strconv.Itoa(users.Users[i].Age))
  81. fmt.Println("User Name: " + users.Users[i].Name)
  82. fmt.Println("Facebook Url: " + users.Users[i].Social.Facebook)
  83. event := beat.Event{
  84. Timestamp: time.Now(),
  85. Fields: common.MapStr {
  86. "ostype": b.Info.Name,
  87. "name": users.Users[i].Name,
  88. "type": users.Users[i].Type,
  89. "age": users.Users[i].Age,
  90. "social": users.Users[i].Social,
  91. },
  92. }
  93. bt.client.Publish(event)
  94. }
  95. c := make(chan os.Signal)
  96. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  97. go func() {
  98. <-c
  99. os.Exit(1)
  100. }()
  101. for {
  102. fmt.Println("sleeping...")
  103. time.Sleep(10 * time.Second)
  104. }
  105. }
  106. // Stop stops readjson.
  107. func (bt *readjson) Stop() {
  108. bt.client.Close()
  109. close(bt.done)
  110. }

它在run method里把json文件读入,并把它们分别发送出去到我们的Elasticsearch中。

我们按照上面的步骤进行编译,并最终运行我们的readjson beat。

  1. ./readjson -e

我们可以在Kibana中看到我们已经发送上来的beat信息:

参考:

【1】https://www.elastic.co/guide/en/beats/devguide/7.5/newbeat-generate.html

Beats:如何创建一个定制的Elastic Beat的更多相关文章

  1. wordpress插件开发从创建一个新的菜单开始

    创建插件的目的 1.我们为什么要创建一个插件? IT界有一个知名的论调叫做不要造重复的轮子,如果有可能的话,你应该尽可能的从现有的网络资源上选择一个已有的插件来使用,而不是重新创造一个.它耗费的精力很 ...

  2. ASP.NET Core管道深度剖析(2):创建一个“迷你版”的管道来模拟真实管道请求处理流程

    从<ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求>我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但 ...

  3. 利用django创建一个投票网站(一)

    这是教程的原始链接:http://django-intro-zh.readthedocs.io/zh_CN/latest/part1/ 创建你的第一个 Django 项目, 第一部分 来跟着实际项目学 ...

  4. 创建一个Portlet工程

    使用Liferay的SDK创建一个简单的Portlet,此Portlet不包括业务逻辑.不包括数据库,只有简单的页面展现,用以说明Portlet的开发过程. 一.创建Portlet工程 1.打开Lif ...

  5. soapui中文操作手册(二)----通过您的WSDL请求创建一个测试

      1.通过您的WSDL请求创建一个测试 点击加号旁边的导航拓展项目树的Web服务,并选择请求: 在SoapUI Pro中,所述请求编辑出现在右边.SoapUI Pro有一个编辑器,它简化了XML的层 ...

  6. 创建一个Table View

    在本课程中,您将创建应用程序FoodTracker的主屏幕.您将创建第二个,表视图为主场景,列出了用户的菜谱.你会设计定制表格单元格显示每一个菜谱,它是这样的: 学习目标 在课程结束时,你将能够: 创 ...

  7. [转]通过Mesos、Docker和Go,使用300行代码创建一个分布式系统

    http://www.csdn.net/article/2015-07-31/2825348 [编者按]时下,对于大部分IT玩家来说,Docker和Mesos都是熟悉和陌生的:熟悉在于这两个词无疑已成 ...

  8. UE4编程之C++创建一个FPS工程(二)角色网格、动画、HUD、子弹类

    转自:http://blog.csdn.net/u011707076/article/details/44243103 紧接上回,本篇文章将和大家一同整理总结UE4关于角色网格.动画.子弹类和HUD的 ...

  9. 通过 Mesos、Docker 和 Go,使用 300 行代码创建一个分布式系统

    [摘要]虽然 Docker 和 Mesos 已成为不折不扣的 Buzzwords ,但是对于大部分人来说它们仍然是陌生的,下面我们就一起领略 Mesos .Docker 和 Go 配合带来的强大破坏力 ...

随机推荐

  1. ES5 Object.defineProperties / Object.defineProperty 的使用

    临时笔记,稍后整理 var obj = { v: , render: function () { console.log(") } }; // Object.defineProperties ...

  2. java poi 导入导出Excel xsl xslx

    import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import  ...

  3. Delphi XE2 之 FireMonkey 入门(21) - 和 FMX 相关的类(表)

    TObject TPersistent TComponent IInterface,IInterfaceComponentReference         TBasicAction TControl ...

  4. if else 更优雅的写法(转)

    https://www.cnblogs.com/y896926473/articles/9675819.html

  5. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第1节 Scanner类_3-Scanner的使用步骤

    Scanner如何进行键盘输入,引用类型就包含了Scanner,它就是引用类型,所以也有这三个步骤, 导包.创建.使用 先通过api文档找到它.左边输入要查找scanner.双夹scanner右边就会 ...

  6. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第5节 String类_10_练习:统计输入的字符串中

    char类型在发生数学运算的时候,可以提升为int类型 这就表示char在A到Z之间的

  7. [Forward]C++ Properties - a Library Solution

    orig url: https://accu.org/index.php/journals/255 roperties are a feature of a number of programming ...

  8. sprint test 添加事务回滚机制

    1.原因: 单元测试的时候频繁操作数据库需要修改很多数据,造成不必要的操作,添加事务之后就可以重复对一条数据进行操作,并且在返回结果后进行回滚. 2.解决: 原先继承的是  AbstractJUnit ...

  9. PYTHON2.7之前需要独立安装pip

    如果python2版本是>=2.7.9, python3版本是>=3.4, pip已将一起随python安装成功了. 对于Python 2.6,你需要更旧setuptools.适用于Pyt ...

  10. python基础数据类型补充以及编码的进阶

    一.基本数据类型的补充循环列表改变列表大小的问题#请把列表中索引为基数的元素写出l1=[1,2,3,4,5,6]for i in l1: if i%2!=0: print(i)结果:135二:基本数据 ...