第6节 解析模块的实现

❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.topopen in new window

Go语言基础篇open in new window

Go语言100篇进阶open in new window


[TOC]

解析模块的功能

  1. 从Read Channel中读取每行日志数据
  2. 正则表达式提取所需要的监控数据(path,status,method等)
  3. 写入到write channel

解析模块的实现

func (l *LogProcess) Process() {
	//解析模块
	/* 输入数据:
	[07/July/2022:18:01:41 +0000] http "GET /foo?query=t HTTP/1.0" 200 2133 "-"
	"KeepAliveClient" "-" 1.005 1.854
	*/
	//处理数据--将data中的所有字符修改为其大写格式。对于非ASCII字符,它的大写格式需要查表转换
	r := regexp.MustCompile(`\[([^\]]+)\]\s+(.*?)\s+\"(.*?)\"\s+(\d{3})\s+(\d+)\s+\"([^"]+
	)\"\s+\"(.*?)\"\s+\"([\d\.-]+)\"\s+([\d\.-]+)\s+([\d\.-]+)`)

	loc, err := time.LoadLocation("Asia/Shanghai") //我们用的是上海时区
	if err != nil {                                //可以忽略err一般不会有错
		panic(fmt.Sprintf("time error:%s", err.Error()))
	}
	for v := range l.rc {
		ret := r.FindStringSubmatch(string(v)) //匹配数据内容,正则括号内容匹配到返回到
		//fmt.Println(ret)
		if len(ret) != 14 { //正则表达式有十三个括号
			log.Println("FindStringSubmatch fail:", string(v))
			continue //继续下一次匹配
		}

		message := &Message{}
		t, err := time.ParseInLocation("09/Jan/2006:15:04:05 +0000", ret[4], loc)
		if err != nil {
			panic(fmt.Sprintf("parseninlocation error:%s", ret[4]))
		}
		message.TimeLocal = t
		byteSent, _ := strconv.Atoi(ret[8]) //将string类型转化为int
		// if err != nil {
		// 	panic(fmt.Sprintf("parseninlocation error:%s", err.Error(), ret[4]))
		// }
		message.BytesSent = byteSent

		//第六个括号匹配的是GET /foo?query=t HTTP/1.0
		reqSli := strings.Split(ret[6], " ") //按照空格切割第六个字段
		if len(reqSli) != 3 {
			log.Println("strings.split fail", ret[6]) //长度不是3说明报错了
			continue
		}

		message.Method = reqSli[0]

		u, err := url.Parse(reqSli[1])
		if err != nil {
			log.Println("url parse fail", ret[1])
			continue
		}
		message.Path = u.Path //此时可以直接从结构体中取到path

		message.Scheme = ret[5] //HTTP/1.0协议可以直接赋值给mess
		message.Status = ret[7]

		//UpstreamTime, RequestTime    float64   //监控数据  1.005 1.854在十二到十三
		upstreamTime, err := strconv.ParseFloat(ret[12], 64) //转化为float64
		if err != nil {
			fmt.Println("err = ", err, ret[1])
			continue
		}
		requestTime, err := strconv.ParseFloat(ret[13], 64) //转化为float64
		if err != nil {
			fmt.Println("err = ", err, ret[1])
			continue
		}
		message.UpstreamTime = upstreamTime
		message.RequestTime = requestTime

		l.wc <- message //data是byte类型,需要转化为string类型
	}
}

END 链接