资讯动态

使用 go-humanize 让 Loki 日志系统的字节与时间输出更易读:Sizes、Times、Ordinals 等函数详解

发布时间:2026/9/13 13:05:50 来源:尧图企业网站定制
使用 go-humanize 让 Loki 日志系统的字节与时间输出更易读Sizes、Times、Ordinals 等函数详解【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki导读go-humanize是一个轻量级 Go 工具库提供把原始数字、字节数和时间戳转换成人类可读字符串的小函数例如把82854982输出为83 MB把time.Time输出为7 hours ago。在 Loki 日志聚合系统中它被广泛用于查询统计日志、块大小日志、LogQL 字节比较等场景是日志系统可观测性和可读性的重要依赖。读完本文你将掌握 go-humanize 的 Sizes、Times、Ordinals、Commas、Ftoa、SI notation 等全部核心函数的使用方法与底层实现并理解它在 Loki 中的真实应用位置。概述go-humanize 是什么README 中这样描述它Just a few functions for helping humanize times and sizes.安装方式为go get github.com/dustin/go-humanize导入方式为github.com/dustin/go-humanize使用别名humanize。该库提供 6 大类函数类别核心函数用途SizesBytes、IBytes、ParseBytes字节数 ↔ 人类可读字符串TimesTime、RelTime、CustomRelTime相对时间表达OrdinalsOrdinal序数后缀1st/2nd/3rdCommasComma、Commaf、BigComma千分位逗号分隔FtoaFtoa、FtoaWithDigits去除浮点尾部零SISI、SIWithDigits、ComputeSI、ParseSISI 前缀科学计数此外还有一个humanize/english子包提供Plural、PluralWord、WordSeries、OxfordWordSeries等英文复数与词组功能。在 Loki 仓库中的实际位置该依赖以 vendored 形式存在于 vendor/github.com/dustin/go-humanize并已被 Loki 大量使用。通过源码检索可在以下位置找到真实调用pkg/logql/log/metrics_extraction.gohumanize.ParseBytes用于解析 LogQL 指标提取中的字节表达式。pkg/logql/log/label_filter.go 与 pkg/logql/syntax/lex.go解析日志标签过滤器中的字节字面量。pkg/logqlmodel/stats/context.go查询统计信息Ingester 头块字节、解压/压缩字节、缓存字节等输出时使用humanize.Bytes。pkg/bloombuild/planner/strategies/chunksize.gobloom 构建任务目标大小日志。pkg/logql/bench/bench_test.go基准测试输出每秒处理字节数。cmd/dataobj-inspect/stats.go 与 tools/dataobj-locality/report.go数据对象检查工具。由此可以推断go-humanize 在 Loki 中扮演可读化输出层角色底层统计、解析、日志系统以原始字节/数字计算展示层统一转成人话。Sizes字节数的人类可读表示Bytes / IBytes / ParseBytesREADME 的核心示例是fmt.Printf(That file is %s., humanize.Bytes(82854982)) // That file is 83 MB.十进制SI与二进制IEC两种体系源码 vendor/github.com/dustin/go-humanize/bytes.go 中定义了两套常量IEC二进制1024 进制Byte 1 (iota * 10) // 1, KiByte1024, MiByte, GiByte, TiByte, PiByte, EiByteSI十进制1000 进制IByte 1 KByte IByte * 1000 // MByte, GByte, TByte, PByte, EByteBytes(s uint64)使用 1000 进制SIIBytes(s uint64)使用 1024 进制IECBytes(82854982)→83 MBSIIBytes(82854982)→79 MiBIEC底层格式化函数humanateBytes见 bytes.go的实现细节小于 10 字节时直接输出N B使用math.Floor(logn(s, base))计算数量级指数数值四舍五入到 1 位小数math.Floor(val*100.5)/10值小于 10 时保留 1 位小数否则保留 0 位小数。ParseBytes从字符串反向解析ParseBytes(42 MB) - 42000000, nil ParseBytes(42 mib) - 44040192, nil源码中的bytesSizeTable支持大小写不敏感的单位后缀包括b、kb/kib、mb/mib、gb/gib、tb/tib、pb/pib、eb/eib以及无后缀的缩写k、m、g等。解析时会提取数字部分兼容小数点和逗号千分位将单位后缀小写化后查表超出math.MaxUint64时报错too large无法识别的单位报错unhandled size name。Loki 的 LogQL 中1MB、500KiB这类字节字面量正是通过ParseBytes解析见 pkg/logql/syntax/lex.go实现了查询语言中人类可写的字节单位支持。Times相对时间表达README 示例fmt.Printf(This was touched %s., humanize.Time(someTimeInstance)) // This was touched 7 hours ago.时间单位常量与分级源码 vendor/github.com/dustin/go-humanize/times.go 定义了Day 24 * time.Hour Week 7 * Day Month 30 * Day Year 12 * Month LongTime 37 * Year默认的defaultMagnitudes分级表部分节选实现了逐步升级单位策略时间差输出格式 1snow 2s1 second ago 1minN seconds ago 2min1 minute ago 1hN minutes ago 2h1 hour ago 1dayN hours ago 2day1 day ago 1weekN days ago...... 37 年N years ago更长a long while agoRelTime(a, b, albl, blbl)支持自定义两个时间点与两个标签如earlier/laterCustomRelTime则允许传入自定义的分级表实现完全可控的相对时间格式。搜索通过sort.Search在升序分级表中二分定位。关键限制Time依赖time.Now()适用于刚刚、几分钟前、几天前这类展示场景如 UI 时间戳不适用于需要精确时间计算的场景。Ordinals序数后缀README 示例fmt.Printf(Youre my %s best friend., humanize.Ordinal(193)) // You are my 193rd best friend.规则为0th, 1st, 2nd, 3rd, 4th ...。源码 vendor/github.com/dustin/go-humanize/ordinals.go 的正确性保证x%10 1且x%100 ! 11→stx%10 2且x%100 ! 12→ndx%10 3且x%100 ! 13→rd其余为th。这样11th、12th、13th不会被误写成11st、12nd、13rd。Commas千分位逗号分隔README 示例0 - 0 100 - 100 1000 - 1,000 1000000000 - 1,000,000,000 -100000 - -100,000fmt.Printf(You owe $%s.\n, humanize.Comma(6582491)) // You owe $6,582,491.源码 vendor/github.com/dustin/go-humanize/comma.go 提供Comma(v int64)整型千分位特殊处理了math.MinInt64返回-9,223,372,036,854,775,808Commaf(v float64)浮点千分位整数部分每三位加逗号小数部分原样保留CommafWithDigits(f, decimals)限制小数位数BigComma(b *big.Int)大整数千分位适用于超过 int64 范围的超大数字。Ftoa更友好的浮点数格式化README 对比示例fmt.Printf(%f, 2.24) // 2.240000 fmt.Printf(%s, humanize.Ftoa(2.24)) // 2.24 fmt.Printf(%f, 2.0) // 2.000000 fmt.Printf(%s, humanize.Ftoa(2.0)) // 2实现位于 vendor/github.com/dustin/go-humanize/ftoa.go先用strconv.FormatFloat(num, f, 6, 64)固定 6 位小数格式化再用stripTrailingZeros去掉尾部零含小数点的零从而得到2.24、2这样干净的输出。FtoaWithDigits(num, digits)额外限制最多保留的小数位数。SI notationSI 前缀格式化README 示例humanize.SI(0.00000000223, M) // 2.23 nM完整函数族ComputeSI(input float64) (float64, string)计算最合适的 SI 前缀并返回调整后的数值与前缀SI(input, unit)默认格式输出如SI(1000000, B) → 1 MB、SI(2.2345e-12, F) → 2.2345 pFSIWithDigits(input, decimals, unit)限定小数位数如SIWithDigits(2.2345e-12, 2, F) → 2.23 pFParseSI(input) (float64, string, error)反向解析如ParseSI(2.2345 pF) → (2.2345e-12, F, nil)。前缀表源码 vendor/github.com/dustin/go-humanize/si.go从qquecto10⁻³⁰到Qquetta10³⁰共 21 档指数前缀指数前缀-30q0无-27r3k-24y6M-21z9G-18a12T-15f15P-12p18E-9n21Z-6µ24Y-3m27R30Q实现细节ComputeSI取绝对值的以 10 为底对数并向下取整到 3 的倍数math.Floor(exponent/3)*3并特殊处理了value 1000.0的情况返回1 M而非1000 kParseSI用 init 中动态拼接的正则表达式解析数字可选前缀单位格式并通过反转前缀表revfmap换算回原始数值。English-specific functionshumanize/english 子包README 说明这些函数位于humanize/english子包注当前 vendored 版本中该子包源码未包含在 vendor/github.com/dustin/go-humanize 目录内以下为 README 记录的功能说明。Plurals简单英文复数化english.PluralWord(1, object, ) // object english.PluralWord(42, object, ) // objects english.PluralWord(2, bus, ) // buses english.PluralWord(99, locus, loci) // loci english.Plural(1, object, ) // 1 object english.Plural(42, object, ) // 42 objects english.Plural(2, bus, ) // 2 buses english.Plural(99, locus, loci) // 99 loci第三个参数支持传入自定义复数形式如locus → loci这类不规则复数。Word series带连接词的词组english.WordSeries([]string{foo}, and) // foo english.WordSeries([]string{foo, bar}, and) // foo and bar english.WordSeries([]string{foo, bar, baz}, and) // foo, bar and baz english.OxfordWordSeries([]string{foo, bar, baz}, and) // foo, bar, and bazWordSeries将列表以逗号连接词连接单元素无分隔、双元素直接连接OxfordWordSeries额外在最后一个元素前保留逗号牛津逗号。在 Loki 中的实战应用场景1. 查询统计日志可读化pkg/logqlmodel/stats/context.go 中Loki 把查询过程中统计的原始字节数Ingester 头块字节、解压/压缩字节、缓存命中/发送字节、Summary 总处理字节等全部用humanize.Bytes转成83 MB这样的形式后写入日志例如Querier.DecompressedBytes, humanize.Bytes(uint64(...))。这让运维人员在日志中一眼看出查询处理的数据量级。2. LogQL 字节单位解析Loki 的 LogQL 语法pkg/logql/syntax/lex.go与标签过滤器pkg/logql/log/label_filter.go、指标提取pkg/logql/log/metrics_extraction.go中用humanize.ParseBytes把查询文本中的1GB、500MiB等字面量解析为字节数参与比较运算。例如查询{jobnginx} | bytes 1MB中的1MB会在词法/语法阶段被解析成1048576按MB对应MByte1000*1000或1,048,576按MiB从而支持人类可写的过滤条件。3. 基准测试与运维工具输出pkg/logql/bench/bench_test.go基准测试报告每秒处理字节数时使用humanize.Bytespkg/bloombuild/planner/strategies/chunksize.gobloom 构建任务目标大小日志cmd/dataobj-inspect/stats.go 与 tools/dataobj-locality/report.go数据对象检查工具输出。总结与使用建议go-humanize 的核心价值在于计算与存储保持原始数值字节、纳秒、大整数只在展示层转换为人类可读字符串。它不改变数据精度只改变呈现形式。在 Loki 中使用时建议日志输出、CLI 工具展示使用BytesSI或IBytesIEC并明确标注单位体系避免混淆如83 MBvs79 MiB解析用户输入的字节量使用ParseBytes注意其单位表同时支持带/不带后缀的缩写时间展示使用Time依赖time.Now()自定义比较基准使用RelTime/CustomRelTime大数展示使用BigComma或SI浮点展示使用Ftoa避免尾部零噪声。相关文件索引README 原文位于 vendor/github.com/dustin/go-humanize/README.markdown核心实现位于 bytes.go、times.go、si.go、comma.go、ftoa.go、ordinals.go。【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价