源码:https://github.com/vectordotdev/vector

helm repo: https://helm.vector.dev/

repo chart: https://github.com/vectordotdev/helm-charts/tree/develop

文档: https://vector.dev/docs/

验证与测试方法

1、当前目录中创建vector.yaml文件,文件名必须为vector.yaml
2、执行命令验证

alias vector='nerdctl run -it -v $(pwd)/:/etc/vector/ -v /var/log/:/var/log/ --rm harbor.kylincloudnative.com/docker.io/timberio/vector:0.39.0-alpine'
nerdctl pull harbor.kylincloudnative.com/docker.io/timberio/vector:0.39.0-alpine
vector

ingress-controller日志示例(/var/log/test-pod-log-ingress)

2024-07-15T14:28:37+08:00       error   ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_10250"}
2024-07-15T14:28:37+08:00       error   ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_10250"}
2024-07-15T14:28:37+08:00       warn    ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_10255"}
2024-07-15T14:28:37+08:00       warn    ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_4194"}
2024-07-15T14:28:38+08:00       error   ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_10250"}
2024-07-15T14:28:38+08:00       warn    ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_10255"}
2024-07-15T14:28:38+08:00       warn    ingress/controller.go:653       upstream is not referenced      {"cluster": "name=default; base_url=http://apisix-admin.apisix-system:9180/apisix/admin", "upstream": "default_kubelet_4194"}

vector.yaml配置

api:
  enabled: true
  address: 127.0.0.1:58686
  playground: false
sources:
  ingress:
    type: file
    include: 
      - /var/log/test-pod-log-ingress
    data_dir: /etc/vector/workdir
transforms:
  parse_ingress:
    inputs:
      - ingress
    type: remap
    source: |
      . |= parse_regex!(.message, r'^(?P<timestamp>\d+-\d+-\d+T\d+:\d+:\d+\+\d+:\d+)\s+(?P<log_level>\w+)\s+(?P<file_path>[\w./:-]+)\s+(?P<message>[^\{]+)\s+(?P<structured_data>\{.*\})$')
      .structured_data = parse_json!(.structured_data)
      .structured_data = parse_key_value!(.structured_data.cluster, key_value_delimiter: "=" )
      . = merge(., .structured_data)
      del(.structured_data)
  ingress_filter:
    type: filter
    inputs:
      - parse_ingress
    condition:
      type: vrl
      source: .log_level == "error"
sinks:
  http_log:
    inputs:
      - ingress_filter
    uri: http://10.42.16.241:8080/push
    type: http
    encoding:
      codec: json
  console_log:
    inputs:
      - parse_ingress
    type: console
    encoding:
      codec: json

sources配置说明

直接从文件读取日志

transforms配置说明

1、parse_ingress使用正则表达式解析日志的timestamp、log_level、file_path、message、structured_data,然后将structured_data再次通过key-value的方式解析。

{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"ce629edcbdf8","log_level":"warn","message":"upstream is not referenced","name":"default;","source_type":"file","structured_data":{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","name":"default;"},"timestamp":"2024-07-15T14:28:38+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"warn","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:38+08:00"}

2、ingress_filterparse_ingress的数据过滤,只取log_level为error的日志。

sink配置说明

1、http_log将ingress_filter过滤后的日志发送至指定url,服务端收到数据如下

{Message:upstream is not referenced File:/var/log/test-pod-log-ingress Host:ce629edcbdf8 BaseUrl:http://apisix-admin.apisix-system:9180/apisix/admin FilePath:ingress/controller.go:653 LogLevel:error}
{Message:upstream is not referenced File:/var/log/test-pod-log-ingress Host:ce629edcbdf8 BaseUrl:http://apisix-admin.apisix-system:9180/apisix/admin FilePath:ingress/controller.go:653 LogLevel:error}
{Message:upstream is not referenced File:/var/log/test-pod-log-ingress Host:ce629edcbdf8 BaseUrl:http://apisix-admin.apisix-system:9180/apisix/admin FilePath:ingress/controller.go:653 LogLevel:error}

2、console_log将解析后,没有过滤的完整日志答应到控制台,解析完成之后数据如下

{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"error","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:37+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"error","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:37+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"warn","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:37+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"warn","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:37+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"error","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:38+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"warn","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:38+08:00"}
{"base_url":"http://apisix-admin.apisix-system:9180/apisix/admin","file":"/var/log/test-pod-log-ingress","file_path":"ingress/controller.go:653","host":"960f99dafe96","log_level":"warn","message":"upstream is not referenced","name":"default;","source_type":"file","timestamp":"2024-07-15T14:28:38+08:00"}

接收日志后端demo(语言:Golang,http框架:gin)

type LogData struct {
    // 根据你的Vector数据格式定义结构体字段
    Message string `json:"message"`
    // 添加更多字段...
    File     string `json:"file"`
    Host     string `json:"host"`
    BaseUrl  string `json:"base_url"`
    FilePath string `json:"file_path"`
    LogLevel string `json:"log_level"`
}
 
func pushTest() {
    router := gin.Default()
    router.POST("/push", func(c *gin.Context) {
		var LogData []LogData

		// 使用GetRawData获取原始数据
		// body, err := c.GetRawData()
		// json.Unmarshal(body, &LogData)

		// 使用bind
		err := c.Bind(&LogData)
		if err != nil {
			c.String(500, "Error reading request body")
			return
		}
		// Respond with a message including the received data
		// responseMessage := fmt.Sprintf("Hello, this is a POST response. Post data: %s", string(body))
		for _, ld := range LogData {
			fmt.Printf("%+v\n", ld)
		}
		c.String(200, "ok")
    })
    router.Run(":8080")
}