博客/释放

洛基v1.4.0发布,查询统计和300 x正则表达式优化

2020年4月1日11分钟

这是一个小1.3.0 / 2个月版本被释放了。我们开始准备1.4.0释放几个星期前;然而,当我在写这篇博文的版本中,我们发现了一些令人困惑的新统计数据对象(这一点我们会讲到)。整理出来后,我们玩一般的游戏,“等等,还不释放!我想有一件事!“这重置时钟的时间我们想测试更改标签和释放之前,所以几周的时间已经过去了,但最终我们到了!

洛基v1.4.0带来超过130来自40多个贡献者PRs !我认为我们这样说很多,但是洛基就不会是现在的一半如果没有社区提供的帮助和支持!这130个覆盖很大范围的变化特性和补丁和升级也有一些重要的笔记,但首先,让我们先从有趣的东西:

有什么新鲜事

查询统计

1.3.0介绍了查询前端,它允许大通过并行查询的性能收益。但多么好吗? ?我们意识到我们需要更好的数据,想让他们通过API,这样客户可以看到多少数据查询处理。

作为一个例子,让我对洛基运行一个大型查询使用logcli——统计数据国旗(也用时间我们可以看到多久总查询了)。

work-pc: ~ ewelch $ logcli查询' {container_name =“ingress-nginx”} | =“pppppppp”——因为= 1 h统计https://logs-dev-ops-tools1.grafana.net/loki/api/v1/query_range?方向= BACKWARD&end = 1585742819881616000限制= 30查询= % 7 bcontainer_name % 3 d % 22 ingress-nginx % 22% 7 d + % 7 c % 3 d + % 22 pppppppp % 22 +开始= 1585739219881616000摄取。TotalReached 84摄取。TotalChunksMatched 7435摄取。TotalBatches 0摄取。TotalLinesSent 0摄取。HeadChunkBytes 26 MB摄取。HeadChunkLines 89057摄取。DecompressedBytes 2.3 GB摄取。DecompressedLines 7599926摄取。CompressedBytes 598 MB摄取。TotalDuplicates 0存储。TotalChunksRef 6064商店。TotalChunksDownloaded 6064商店。ChunksDownloadTime 14.038946798 s商店。HeadChunkBytes 0 B商店。HeadChunkLines 0存储。DecompressedBytes 30 GB的存储。DecompressedLines 97844591 Store.CompressedBytes 7.7 GB Store.TotalDuplicates 0 Summary.BytesProcessedPerSeconds 6.2 GB Summary.LinesProcessedPerSeconds 20169102 Summary.TotalBytesProcessed 32 GB Summary.TotalLinesProcessed 105533574 Summary.ExecTime 5.232437764s real 0m5.811s user 0m0.092s sys 0m0.104s

这个查询的方法是故意设计来匹配和返回任何日志行(我敢肯定我们的入口豆荚没有pppppppp的在他们)。这将迫使洛基打开每一块在时间范围和搜索每一个日志行寻找任何匹配pppppppp返回请求的限制。

我们可以看到我们相当多的数据处理!数据很详细,我们一直在使用他们在洛基微调所有移动部件。然而,主要统计大多数人感兴趣的是可能的简介:

总结。BytesProcessedPerSeconds 6.2 GB的总结。LinesProcessedPerSeconds 20169102总结。TotalBytesProcessed 32 GB的总结。TotalLinesProcessed 105533574总结。ExecTime 5.232437764秒

这是我们设置并行化的力量:在这个环境中分片,查询请求到5米块,这都是在12查询器并行执行。至少对我来说,它仍然是令人印象深刻的看到2000万日志行和6.2 gb每秒处理。:)

我不得不问自己,所以我认为这是值得注意的。我们没有84 ingesters在这个环境中运行;我们有7。然而,这12个人查询器请求每个分片摄取的时间范围为他们负责,所以这个总数84摄取请求。

这个信息现在作为额外的json返回的结果对象。可以找到更多的信息文档

介绍中我提到的这个结果对象的来源是1.4.0释放的延迟,所以让我解释这一点。进一步下面提到这个博客是另一个新特性,它允许promtail添加一个度量阶段,可以发送线数每流。我查询这个数据与处理数据的准确性,和数字没有调整好!

作为一个例子,如果我运行这个查询sum(率(promtail_custom_line_count_total {container_name =“ingress-nginx”} [1 m])) * 60 * 60——以每秒记录的容器,繁殖这60的行数,再由60行一个小时——结果是77309672。

然而,与之相比,从上面统计(逗号为可读性添加):

总结。TotalLinesProcessed 105533574

它向我们展示了处理一些额外28223902行!这是特别令人困惑,因为摄取和储存TotalDuplicates零!

我很高兴地说,在一个详尽的调查,我们没有发现任何错误的统计代码。不过,我们确实发现,在重复的计数器是一个实现细节;也就是说,我们只有重复的行数他们通过筛选器表达式,在我的例子中,没有匹配/通过筛选器表达式。调查发现有很多重复的日志块存储(复制)的结果比我们的预期。我们仍在调查方面我们可以进一步减少重复。

此外,有块重叠的性质要求这样的。我们有很多入口nginx豆荚在许多集群,所有的日志在同一时间段,洛基已经阅读和整理试图以适当的顺序返回。这将导致一些加工的块。虽然不是重复一样重要在我们的调查,这是一个领域,我们在未来可以进一步优化。

二元操作符,在LogQL数字字面值

这个版本有几个PRs扩大LogQL能够支持二元操作符与数字字面值。或者更简单,你现在可以做数学度量查询是这样的:

  • sum(率({应用= " foo "} [5 m])) * 2
  • sum(率({应用= " foo "} [5 m])) / 1 e6

更多信息在二进制操作可以做什么,看看这个公关

更多信息在数字字面值。看看这个公关

正则表达式的优化

后盯着一堆的痕迹,试图优化查询,我们发现某些类型的基于正则表达式的过滤器已经比他们的字符串匹配性能慢得多。一个示例查询:

{应用= " foo "} | ~“val1 | val2”

这个正则表达式测试在每个日志行是否包含val1和val2相比是非常缓慢的bytes.Contains我们使用一个类似的过滤查询,不使用正则表达式:

{应用= " foo "} | = " val1”

事实上,在这种情况下,我们发现它更快替换正则表达式val1 | val2与一个等价的bytes.Contains (val1) | | bytes.Contains (“val2”)

可以找到更多的细节公关为各种用例,但我们看到基准改进从5到300 x !

最好的部分是所有这一切实现从用户完全透明的,我们现在有一个机制来发现和优化更多的这些问题在未来!

管数据promtail和排练

更新2020/04/07:我们发现后不久发布1.4.0管特性是为Linux和Windows操作系统不工作!1.4.1发布解决这个问题!

这是一个迟到的功能设置和调试时promtail管道,但是现在你可以测试一个日志:

work-pc:洛基ewelch echo - n级美元=调试味精=“测试日志(200)”“| promtail -config.file = cmd / promtail / promtail-local-config。yaml——即将日志。水平=调试2 > & 1 | sed ' s / ^。*期/期/ g’level=info ts=2020-03-31T21:20:58.74432Z caller=server.go:147 http=[::]:80 grpc=[::]:9095 msg="server listening on addresses" level=info ts=2020-03-31T21:20:58.746217Z caller=main.go:67 msg="Starting Promtail" version="(version=step-log-query-94d6cf9-WIP, branch=step-log-query, revision=94d6cf97)" stage=0 name=regex labels={} time=2020-03-31T17:20:58.743671-04:00 entry="level=debug msg=\"test log (200)\"" stage=1 name=labels labels={} time=2020-03-31T17:20:58.743671-04:00 entry="level=debug msg=\"test log (200)\"" stage=2 name=regex labels="{level=\"debug\"}" time=2020-03-31T17:20:58.743671-04:00 entry="level=debug msg=\"test log (200)\"" stage=3 name=labels labels="{level=\"debug\"}" time=2020-03-31T17:20:58.743671-04:00 entry="level=debug msg=\"test log (200)\"" stage=4 name=regex labels="{level=\"debug\", status_code=\"200\"}" time=2020-03-31T17:20:58.743671-04:00 entry="level=debug msg=\"test log (200)\"" stage=5 name=output labels="{level=\"debug\", status_code=\"200\"}" time=2020-03-31T17:20:58.743671-04:00 entry="level=debug msg=\"test log (200)\"" level=debug ts=2020-03-31T21:20:58.748601Z caller=pipeline.go:97 component=pipeline component=pipeline msg="finished processing log line" labels="{level=\"debug\", status_code=\"200\"}" time=2020-03-31T17:20:58.743671-04:00 entry="test log (200)" duration_s=0.004902197 2020-03-31T17:20:58 {level="debug", status_code="200"} test log (200)

这个例子是一个精简的配置文件promtail配置来测试我们的管道:

客户:url:要求但忽视了即将scrape_configs: - job_name:测试pipeline_stages: -正则表达式:表达式:水平= (? P <水平> \ w +) -标签:水平:" -正则表达式:表达式:\ ((? P < status_code > \ d{3}) \) -标签:status_code: " -正则表达式:表达式:味精= " (? P <消息>。*)"- output: source: message

请注意我们启用调试日志,将stderr重定向到标准输出,并且一个非常简单的应用sed过滤去除一些日志噪声在管道前阶段:

日志。水平=调试2 > & 1 | sed ' s / ^。*期/期/ g’

你也可以一个文件到promtail stdin过程文件。(或从任何过程可以使用stdout !)

——即将也不需要;您可以运行promtail将数据发送到它通过stdin,船行洛基。

我们意识到还有很多改进的空间时设置和调试管道阶段,但我们希望这有助于一点!

429客户重试失败有限

这只适用于客户在洛基回购:

  • Promtail
  • 码头工人记录司机
  • 流利一些
  • Fluentd

现在任何把洛基会见了http响应代码429将重试;以前他们了。

随着我们继续提高限制洛基确保服务器端对行为不端的客户,我们讨论什么客户应该做如果洛基告诉他们后退一点。

最初我们决定解决这个问题通过客户放弃任何日志速率限制。然而,我们已经改变了主意,转而青睐重试这些日志与退避。

这将日志发送到两个地方。首先是重试限制。promtail违约(因此也码头工人记录司机和流利,共享相同的底层代码)将重试429年代和500年代一个指数倒扣长达约8.5分钟在默认配置。(这个可以改变;看到配置文档更多信息)。

第二将日志文件本身。在某种程度上,大多数日志文件卷基于大小或时间。Promtail尝试读一卷的日志文件,但只尝试一次。如果你失去了日志非常敏感,给自己很大的滚动规则和基于日志文件大小增加重试超时。这将保护你从洛基服务器故障或网络问题。

二等奖

max_chunk_age

公关1558年允许配置max_chunk_age将force-flush任何块,达到这个年龄不管它是否空闲。这是有用的限制洛基内存使用以及控制风险损失的事件日志的摄取崩溃。

不过要小心!设置这个值过低会导致很多小块被清空。洛基讨厌小块(我们正在调查的方法来提高)。默认的1 h对大多数人来说可能是好的,但考虑增加2 h,如果您的日志流慢慢写。

例如,如果我们设置chunk_target_size1.5 mb,日志流将日志大约1500字节/秒来填补1.5 mb 1 h。平均ingress-nginx日志是300字节,这意味着我们需要至少5行/秒的速度块完全填充max_chunk_age1 h。

看着我们所有的流,我们发现,他们中的许多人不写速度完全填补这一块,这是进一步降低当标签被添加到流日志文件分解成更小溪流。

这不是一个大问题,如果他们不完全填满。基本上我想说的是:如果你将这个值设置为5米就会有一个坏的时间。

query_ingesters_within

公关1572年添加一个标志告诉查询器跳过查询ingesters请求超过一段时间。这是非常有用的结合上面的max_chunk_age参数,您可以安全地设置query_ingesters_within一个值大于max_chunk_age的摄取和节省不必要的查询数据,他们将不再有。

运行时配置

公关1484年使用新的runtimeconfig包从皮层,洛基可以在运行时重新加载某些配置不重启。可以找到更多的信息文档

Promtail标准流水线计数器

公关1678年允许您配置一个度量阶段,它将输出一个计数器记录的每个流promtail创建:

指标:line_count_total:配置:行动:公司match_all:真正的描述:一个运行计数器与相应的标签类型:所有行计数器

这可以帮助你更好地理解应用程序日志。

Loki-canary DDOS修复

公关1581年修复一个缺陷的loki-canary负责第二DDOS攻击他们在我们的集群。:)

手工检查块

公关1577年附带了一个非常方便的工具,直接打开和检查数据块文件!

升级注意事项

每次让洛基向后兼容,这样升级应该是低风险和低摩擦。

不幸的是洛基软件,软件是困难的,有时候事情并不像我们想要的那么简单。

在版本1.4.0你可能需要额外的步骤,当从先前版本升级。我们已经创建了一个在文档中详细列出这专用页面

主要是你需要担心如果您正在运行一个版本的洛基1.2.0以上!(或者你可以忽略这个1.3.0如果您正在运行版本,可以直接1.4.0)。

想了解更多关于洛基吗?

报名参加我们的介绍洛基网络研讨会定于4月22日上午九时三十分于PT。议程包括洛基是如何工作的概述,基本配置和设置运行洛基和测试出来,如何使用从Grafana洛基,介绍查询和问答与洛基团队成员埃德•韦尔奇西里尔Tovena