背景
工具构想
工具实现历程
工具设想:
// AccessFile 访问日志对象
type AccessFile struct {
FirstLine *AccessLog //文件第一行
LastLine *AccessLog //文件最后一行
Stat os.FileInfo //文件句柄
Filename string //文件名
File *os.File。 //文件句柄
StartFlag int64 //需要数据匹配的第一个位置
EndFlag int64 //需要数据匹配的最后一个位置
All bool //需求内容全包含
Some bool //需求内容部分包含
}
读取第一行和最后一行的函数是这样的:
// ReadFileFirstLine 读取文件的第一行
func ReadFileFirstLine(filename string) (line string) {
file, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
defer file.Close()
if err != nil {
panic(err)
}
var linebyte = make([]byte, 5*logger.KB)
length, err := file.Read(linebyte)
if length < 0 {
return ""
}
if err != nil && err != io.EOF {
panic(err)
}
linebuf := bytes.NewReader(linebyte)
linebufio := bufio.NewReader(linebuf)
lineb, _, err := linebufio.ReadLine()
if err != nil {
panic(err)
}
if err == io.EOF {
return
}
return string(lineb)
}
// ReadFileLastLine 读取文件的最后一行
func ReadFileLastLine(filename string) (line string) {
stat, err := os.Stat(filename)
if err != nil {
panic(err)
}
file, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
defer file.Close()
if err != nil {
panic(err)
}
var linebyte = make([]byte, 5*logger.KB)
indexlog := stat.Size() - 5*logger.KB
if indexlog < 0 {
indexlog = 0
}
DeBugPrintln("file: ", filename, "filesize:", stat.Size())
length, err := file.ReadAt(linebyte, indexlog)
if length < 0 {
return ""
}
if err != nil && err != io.EOF {
panic(err)
}
linebuf := string(linebyte)
linelist := strings.Split(linebuf, "\n")
if len(linelist) < 2 {
return ""
}
line = linelist[len(linelist)-2:][0]
DeBugPrintln(string(line))
return line
}
伪思维:
假设我们需要的日志区间是 logstime ~ logetime (logstime 是小于 logetime的)
一个文件第一行和最后一行的时间是 filestime ~ fileetime (回想写日志的场景, filestime 必定 小于 fileetime)
然后会有如下六种情况:
1. Filestime -> fileetime —> logstime —> logetime f.All=false , f.Some=false
2. Filestime -> logstime -> fileetime -> logetime f.All=false , f.Some=true
3. Logstime -> filestime -> logetime -> fileetime f.All=false , f.Some=true
4. Logstime -> logetime -> filestime -> fileetime f.All=false , f.Some=false
5. Filestime -> logstime -> logetime -> Fileetime f.All=false , f.Some=true
6. Logstime -> Filestime -> Fileetime -> Logetime. f.All=true , f.Some=false
通过如上算法实现,我们可以筛选掉一些不在我们需要的范围内的文件,然后留下需要分析的文件处理。
代码逻辑:
假设文件的修改时间为mtime, 日志区间还是logstime ~ logetime
会有如下几种情况:
mtime -> logstime -> logetime 直接忽略,一定不会包含我们需要的文件
Logstime -> mtime -> logstime 一定包含我们需要的信息
Logstime -> logetime -> mtime 可能包含我们需要的信息
for _, uf := range upro.LogFile {
var n int64
DeBugPrintln(uf.Filename)
for n < uf.Stat.Size() {
var linedata = make([]byte, zonesize)
nu, err := uf.File.ReadAt(linedata, n)
DeBugPrintln(nu, n, err)
if err != nil && err != io.EOF {
break
}
wg.Add(1)
go proUpstreamLogFile(uf.All, uf.Some, linedata, upro, host, directory, &wg)
n += int64(nu)
}
wg.Wait()
if upro.AllNum >= upro.MaxSize {
break
}
}
背景:日志都在服务器上存储,当有上千台的服务需要处理日志时,我们应该这么做呢?
下面是我对于我遇到的问题的思考:
下面是我当前实施的方案:
最后感谢各位的查阅,有更多的想法,欢迎和我一起探讨。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有