golang-NSQ源码阅读 5-nsq_to_file源码解析-3 输出 | KaiQ.Gu|KerwinKoo Blog
nsq_to_file 输出文件管理
本文在NSQ代码阅读-nsq_to_file代码阅读的基础上,对NSQ消息获取及获取之后的文件操作进行代码解析。涉及解析文件为:
nsq_to_file.gostrftime.go功能解析
1 文件名格式化:
1 | datetimeFormat = flag.String("datetime-format", "%Y-%m-%d_%H", "strftime compatible format for <DATETIME> in filename format") |
2 文件压缩
1 | gzipLevel = flag.Int("gzip-level", 6, "gzip compression level (1-9, 1=BestSpeed, 9=BestCompression)") |
3 文件滚动
1 | rotateSize = flag.Int64("rotate-size", 0, "rotate the file when it grows bigger than `rotate-size` bytes") |
文件滚动指的是,在到达指定文件size,或指定文件读写时间段的情况下,创建新的文件,续写新的message。
4 跳过空白文件
1 | skipEmptyFiles = flag.Bool("skip-empty-files", false, "Skip writing empty files") |
功能实现
文件名称格式化
函数NewFileLogger主要负责对输出的文件名进行格式化。
函数NewFileLogger在nsq_to_file中只被使用一次,但会根据topic的个数来调用多次。其功能是获取日志文件句柄,并对文件名、文件操作(是否压缩及压缩level、文件滚动写入等)做规范。
代码
1 | func NewFileLogger(gzipEnabled bool, compressionLevel int, filenameFormat, topic string) (*FileLogger, error) { |
函数最终会返回一个FileLogger结构体实例,但结构体中没有topic及channel的属性,因此可以看做是比较独立的输出文件句柄结构体。但是该结构体承接着信息的读取、文件的编辑等功能,则其围绕的功能函数需要将功能一一实现。
句柄结构体
1 | type FileLogger struct { |
获取时间戳做输出文件名
1 | func (f *FileLogger) calculateCurrentFilename() string { |
注意
- 输出文件名格式要求是用户在opt中进行指定的,默认为:"%Y-%m-%d_%H",实现过程中需要转换为go的time format(在文件strftime.go中实现);
- 生成的时间戳最终会替换掉文件名格式化占位符中的
<DATETIME>。
nsq_to_file的其他代码阅读
hasArg
在main函数中首次用到,用于检索opt中是否有指定的key。
1 | func hasArg(s string) bool { |
之前版本的实现有字符串包含的bug,上面的代码实现是阅读代码后我在github中做出的提交(目前已commit主版本)。函数的核心是下面这段代码:
1 | flag.Visit(func(f *flag.Flag) { |
其中参数func(f *flag.Flag)中,参数f会在flag包中被赋值:
1 | // Visit visits the flags in lexicographical order, calling fn for each. |
上面代码中可以看到,函数参数fn会被for循环调用,因此fn函数内部的比较if f.Name == s亦会被多次调用,轮询对比。