【Go】go-es统计接口被刷数和ip访问来源

go-es模块统计日志中接口被刷数和ip访问来源

  • 以下是使用go的web框架gin作为后端,展示的统计页面


背景

  • 上面的数据来自elk日志统计。因为elk通过kibana进行展示,但是kibana有一定学习成本且不太能满足定制化的需求,所以考虑用编程的方式对数据进行处理
  • 首先是接口统计,kibana的页面只会在 字段uri 的 top500 进行百分比统计,展示前5条数据,统计不够充分
  • 其次是网关日志,ip来源的采集字段是通过x_forward_for,这记录了各级的代理来源ip。并不能直接对用户的ip进行数据聚合的统计
    • 举例,这里面 "223.104.195.51,192.168.29.135" ,这种数据我需要拿到223.104.195.51,因为这才是用户的ip。所以需要进行编程的处理

环境

go-elasticsearch 模块

eql

  • 实现统计数据分析的核心就是eql(es查询语言),通过go-elasticsearch模块进行eql的发送,再接收es返回的回复体
  • 以下是使用go-es发送eql后,es的回复体的struct源码
  • 可以看到type Response struct 中,我们想要的json数据在Body中,但是注意Body的类型为 io.ReadCloser , 因此是需要用go的io模块进行获取json数据
    • 这边解决读取问题的代码如下。该函数接收es响应体,并返回未序列化的byte切片
go 复制代码
// 处理es的响应,获取响应体里的Body
func getResponseBody(result *esapi.Response, context *gin.Context) []byte {
	// 接收es回复体里返回的数据,这里返回io流,需要用对应方法接收
	var bodyBytes []byte
	bodyBytes, err := io.ReadAll(result.Body)
	if err != nil {
		panic(err)
	}
	return bodyBytes
}

es客户端建立连接

go 复制代码
package esinit

import (
	"github.com/elastic/go-elasticsearch/v7"
	"io/ioutil"
	"log"
)

var EsClient *elasticsearch.Client

func init() {
	EsClient = newEsClient()
}

func newEsClient() *elasticsearch.Client {
	cert, certErr := ioutil.ReadFile("esinit/es.crt")  // 你的不受信任的https证书
	if certErr != nil {
		log.Println(certErr)
	}
	EsClient, error := elasticsearch.NewClient(elasticsearch.Config{
		Username: "你的用户名",
		Password: "你的密码",
		Addresses: []string{
			"https://es-cluster1:9200",
			"https://es-cluster2:9200",
			"https://es-cluster3:9200",
		},
		CACert: cert,
	})
	if error != nil {
		panic(error)
	}
	return EsClient
}

实现统计的三段eql

  • 这里eql使用 fmt.Sprintf() 方法进行参数传递
  • 第一段eql是统计PV
    • 这里注意的是,我们在东八区,所以统计pv从16:00开始。这里根据@timestamp字段进行"aggs"聚合统计
go 复制代码
func getPvResponse(startYear int, startMonth int, startDay int, endYear, endMonth int, endDay int) *esapi.Response {
	query := fmt.Sprintf(`
{
  "query": {
	"bool": {
	  "must": [
		{
		  "range": {
			"@timestamp": {
			  "gte": "%d-%02d-%02dT16:00:00",
			  "lte": "%d-%02d-%02dT16:00:00"
			}
		  }
		}
	  ]
	}
  },
  "aggs": {
	"log_count": {
	  "value_count": {
		"field": "@timestamp"
	  }
	}
  }
}
`, startYear, startMonth, startDay, endYear, endMonth, endDay)
	result, _ := esinit.EsClient.Search(
		esinit.EsClient.Search.WithIndex("k8s-istio-ingress*"), // 索引名
		esinit.EsClient.Search.WithBody(strings.NewReader(query)), // eql
	)
	return result
}
  • 第二段是对微服务(java)的接口(uri字段)的聚合统计
    • 这里用的 sortUri 是gin的绑定uri功能(动态获取二级路由的名字)
    • 这里返回前1天10000条es文档的uri字段数据
go 复制代码
func getSortResponse(context *gin.Context) *esapi.Response {
	if err := context.ShouldBindUri(&sortUri); err != nil { // sortUri二级路由,传递索引名
		context.JSON(400, gin.H{"msg": err})
	}
	//搜索文档
	// eql 搜索时间范围内10000条记录,并只展示uri字段的内容
	query := fmt.Sprintf(`
		{
		  "_source": ["uri"],
		  "query": {
			"bool": {
			  "filter": [
				{
				  "range": {
					"@timestamp": {
					  "gte": "now-1d/d",
					  "lte": "now/d"
					}
				  }
				}
			  ]
			}
		  },
		  "size": 10000
		}
		`)
	// 对应索引进行搜索
	result, _ := esinit.EsClient.Search(
		esinit.EsClient.Search.WithIndex(sortUri.Name+"*"),
		esinit.EsClient.Search.WithBody(strings.NewReader(query)),
	)
	return result
}
  • 第三段是对istio前一小时的ip请求统计,返回2000条记录
go 复制代码
func getIstioDataResponse() *esapi.Response {
	query := `
{
  "_source": [
    "x_forwarded_for",
    "@timestamp",
    "path",
    "user_agent_a",
    "response_code",
    "method",
    "upstream_cluster"
  ],
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "@timestamp": {
              "gte": "now-1h/h",
              "lte": "now/d"
            }
          }
        }
      ]
    }
  },
  "size": 2000
}
`
	result, _ := esinit.EsClient.Search(
		esinit.EsClient.Search.WithIndex("k8s-istio-ingress*"),
		esinit.EsClient.Search.WithBody(strings.NewReader(query)),
	)
	return result
}
  • 上面的eql函数,会return 一个 []byte切片,可以进行 json.Unmarshal 或其他struct转json的模块进行处理,就能够得到数据。然后便可进行渲染
相关推荐
Elastic 中国社区官方博客5 小时前
为 Elastic Cloud Serverless 和 Elasticsearch 引入统一的 API 密钥
大数据·运维·elasticsearch·搜索引擎·云原生·serverless
anzhxu7 小时前
Go基础之环境搭建
开发语言·后端·golang
vastsmile8 小时前
(R)26.04.23 hermes agent执行本地命令超级慢的原因
开发语言·elasticsearch·r语言
ILYT NCTR10 小时前
搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程
开发语言·后端·golang
OtIo TALL13 小时前
Java进阶(ElasticSearch的安装与使用)
java·elasticsearch·jenkins
Elastic 中国社区官方博客16 小时前
Jina embeddings v3 现已在 Gemini Enterprise Agent Platform Model Garden 上可用
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索·jina
前端若水17 小时前
Git 撤销与恢复完全指南(超级详细版)
大数据·git·elasticsearch
tonydf17 小时前
日志模块该如何设计
后端·elasticsearch
前端若水18 小时前
Git 可以做的所有操作(完整分类)
大数据·git·elasticsearch
Elasticsearch18 小时前
我们如何构建 Elasticsearch simdvec,使向量搜索成为世界上最快之一
elasticsearch