Skip to content

ref(span-buffer): Introduce multiprocessed flusher - #1

Open
linxia0415 wants to merge 25 commits into
masterfrom
pr-93824
Open

ref(span-buffer): Introduce multiprocessed flusher#1
linxia0415 wants to merge 25 commits into
masterfrom
pr-93824

Conversation

@linxia0415

Copy link
Copy Markdown
Contributor

Refs STREAM-266

Compression helped a lot bring the time on the main thread down. We now think we can scale down the consumers. However, we also need to ensure the flusher can keep up. So let's make the flusher spawn a process per redis shard.

We think this is easier to do than making the process_spans/insert_spans multiprocessed. Over time we can offload mroe things like statistics/metrics to the flusher, and keep the main thread minimal.

code-hawk-sit[bot]

This comment was marked as outdated.

@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 11, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 11, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 11, 2026
@linxia0415 linxia0415 closed this Apr 11, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026

@code-hawk-sit code-hawk-sit Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI代码审查报告

变更概览

本次 PR 涉及 7 个文件,新增 +199 行,删除 -123 行。

功能变更摘要

本 PR 移除了 GitHub Dependabot 配置文件,同时更新了 CLAUDE.md 文档并重构了 Sentry 拓展数据处理流程,重点优化了 spans 数据的消费与刷新逻辑,提升系统稳定性与可维护性。

文件变更摘要

文件 变更 行数 摘要 发现问题
CLAUDE.md 修改 +11/-0 补充 CLAUDE 相关功能说明与使用示例 1 个
src/sentry/consumers/__init__.py 修改 +9/-1 重构消费者初始化逻辑以支持新数据处理流程 1 个
src/sentry/spans/consumers/process/factory.py 修改 +3/-0 新增 spans 处理工厂类以解耦消费逻辑 1 个
src/sentry/spans/consumers/process/flusher.py 修改 +127/-47 重构数据刷新逻辑,增强错误处理与批量提交能力
.github/dependabot.yml 删除 +0/-73 移除 GitHub Dependabot 自动依赖更新配置
tests/sentry/spans/consumers/process/test_consumer.py 修改 +48/-1 新增对消费者处理流程的完整测试用例
tests/sentry/spans/consumers/process/test_flusher.py 修改 +1/-1 修复刷新器测试用例中的断言逻辑

问题严重级别分布

级别 数量 占比
🟡 中危 2 100%

代表性问题(至多 10 条,按严重级别优先)

  1. 🟡 中危 CLAUDE.md L451: line 451 处使用 hasattr() 检查联合类型变量的属性,但 line 456 处改用 isinstance() 进行类型检查。当 x 为 None 时,hasattr(x, 'repla…
  2. 🟡 中危 src/sentry/spans/consumers/process/factory.py L74: line 71 处创建 SpanFlusher 实例时,将 self.produce_to_pipe 作为参数传入 → line 74 处调用 SpanFlusher 构造函数时未检查该参数是否为 N…

CodeHawk 提供支持 · nuwa

@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026

@code-hawk-sit code-hawk-sit Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI代码审查报告

变更概览

本次 PR 涉及 7 个文件,新增 +199 行,删除 -123 行。

功能变更摘要

本 PR 移除了 GitHub Dependabot 配置文件,同时更新了 CLAUDE.md 文档以反映最新开发规范,并对 Sentry 的 spans 处理消费者模块进行了重构,包括新增处理工厂、优化数据刷新逻辑及补充测试用例。

文件变更摘要

文件 变更 行数 摘要 发现问题
CLAUDE.md 修改 +11/-0 更新文档以包含最新的开发与提交规范说明 1 个
src/sentry/consumers/__init__.py 修改 +9/-1 增强消费者初始化逻辑,支持新类型处理流程 1 个
src/sentry/spans/consumers/process/factory.py 修改 +3/-0 新增 spans 处理消费工厂类用于动态实例化处理器 1 个
src/sentry/spans/consumers/process/flusher.py 修改 +127/-47 重构数据刷新逻辑,提升处理效率并优化错误恢复机制
.github/dependabot.yml 删除 +0/-73 移除 GitHub Dependabot 自动依赖更新配置
tests/sentry/spans/consumers/process/test_consumer.py 修改 +48/-1 新增消费者功能测试,覆盖多种处理场景和异常路径
tests/sentry/spans/consumers/process/test_flusher.py 修改 +1/-1 修复测试断言以匹配刷新器行为变更

问题严重级别分布

级别 数量 占比
🟡 中危 1 100%

代表性问题(至多 10 条,按严重级别优先)

  1. 🟡 中危 CLAUDE.md L451: line 451 处使用 hasattr() 检查类型联合变量 x 的方法存在缺陷,但 line 452 处直接调用 replace 方法未做空值或类型验证。当 x 为 None 时,hasattr(…

CodeHawk 提供支持 · nuwa

@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026

@code-hawk-sit code-hawk-sit Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI代码审查报告

变更概览

本次 PR 涉及 7 个文件,新增 +199 行,删除 -123 行。

功能变更摘要

本 PR 移除了 GitHub Dependabot 配置,同时更新了 CLAUDE.md 文档以反映最新变更,并对 Sentry 的 spans 消费者模块进行了重构,重点优化了数据处理与刷新逻辑,提升系统稳定性与可维护性。

文件变更摘要

文件 变更 行数 摘要 发现问题
CLAUDE.md 修改 +11/-0 更新文档以包含最新的功能说明和变更记录 1 个
src/sentry/consumers/__init__.py 修改 +9/-1 重构消费者初始化逻辑,增强模块可扩展性 1 个
src/sentry/spans/consumers/process/factory.py 修改 +3/-0 新增处理工厂的创建逻辑,支持动态消费策略 1 个
src/sentry/spans/consumers/process/flusher.py 修改 +127/-47 重构数据刷新逻辑,优化性能并增强错误处理能力
.github/dependabot.yml 删除 +0/-73 移除 GitHub Dependabot 自动依赖更新配置
tests/sentry/spans/consumers/process/test_consumer.py 修改 +48/-1 补充消费者处理流程的测试用例,覆盖新逻辑分支
tests/sentry/spans/consumers/process/test_flusher.py 修改 +1/-1 修复刷新器测试中的断言逻辑,确保边界条件验证

问题严重级别分布

级别 数量 占比
🟡 中危 2 100%

代表性问题(至多 10 条,按严重级别优先)

  1. 🟡 中危 CLAUDE.md L451: line 451 处使用 hasattr(x, "replace") 判断变量是否为字符串类型,但该方法在 xNone 时仍会返回 True(因为 None 有 `class
  2. 🟡 中危 src/sentry/consumers/__init__.py L430: 延迟错误处理模式:line 430 处新增 click.Option 配置,但未在 get_stream_processor 函数中对 cmd_context.params 的有效性进行校…

CodeHawk 提供支持 · nuwa

@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@LX-CodeReview LX-CodeReview deleted a comment from code-hawk-sit Bot Apr 13, 2026
@linxia0415 linxia0415 closed this Apr 13, 2026
@linxia0415 linxia0415 reopened this Apr 13, 2026

@code-hawk-sit code-hawk-sit Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI代码审查报告

变更概览

本次 PR 涉及 7 个文件,新增 +199 行,删除 -123 行。

功能变更摘要

本PR重构了Span处理消费者的刷新逻辑,增强了缓冲管理与错误处理能力,并补充了相关单元测试。同时移除了Dependabot自动更新配置并更新了开发文档。

文件变更摘要

文件 变更 行数 摘要 发现问题
src/sentry/spans/consumers/process/flusher.py 修改 +127/-47 重构flusher缓冲刷新与批次处理逻辑 6 个
.github/dependabot.yml 删除 +0/-73 删除Dependabot自动依赖更新配置
tests/sentry/spans/consumers/process/test_consumer.py 修改 +48/-1 补充Span消费者完整流程测试用例
CLAUDE.md 修改 +11/-0 补充Span消费者flusher功能的相关说明文档
src/sentry/consumers/__init__.py 修改 +9/-1 新增Span处理消费者模块的注册逻辑
src/sentry/spans/consumers/process/factory.py 修改 +3/-0 为Span处理工厂新增缓冲刷新相关配置
tests/sentry/spans/consumers/process/test_flusher.py 修改 +1/-1 调整flusher测试以适配新逻辑

问题严重级别分布

级别 数量 占比
🟡 中危 6 100%

代表性问题(至多 10 条,按严重级别优先)

  1. 🟡 中危 src/sentry/spans/consumers/process/flusher.py L127: 增加代码维护负担;误导开发者认为存在按单个 shard 重启进程的能力。
  2. 🟡 中危 src/sentry/spans/consumers/process/flusher.py L199: 监控数据分散,无法正确聚合跨代码路径的指标;可能导致告警遗漏或误报;增加运维排查难度。
  3. 🟡 中危 src/sentry/spans/consumers/process/flusher.py L222: 代码可读性降低;如果 process 对象实现了 bool 方法,可能导致意外的行为。
  4. 🟡 中危 src/sentry/spans/consumers/process/flusher.py L253: 静态类型检查可能失败;代码维护者可能对类型关系产生困惑。
  5. 🟡 中危 src/sentry/spans/consumers/process/flusher.py L259: 进程重启失败时,self.processes 中保留无效引用;后续调用 _ensure_processes_alive 时可能操作已失效的进程对象。
  6. 🟡 中危 src/sentry/spans/consumers/process/flusher.py L346: Thread 类型的进程在 join 后没有明确清理,可能导致资源泄漏;类型检查不一致。

CodeHawk 提供支持 · nuwa

self.processes[process_index] = process
self.buffers[process_index] = shard_buffer

def _create_process_for_shard(self, shard: int):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

_create_process_for_shard 方法在 line 127-132 定义,但搜索整个文件发现该方法从未被调用。这是一个死代码(dead code),可能是重构过程中遗漏的未使用方法。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 127

💬 详细说明:

  • 增加代码维护负担;误导开发者认为存在按单个 shard 重启进程的能力。

📝 问题代码:

def _create_process_for_shard(self, shard: int):

💡 修复建议:

如果确实不需要按单个 shard 重启进程,应删除此方法;如果需要,应确保在适当的地方调用。

✅ 修复示例:

# 建议删除此方法,或添加调用逻辑

🔗 参考链接

produce(kafka_payload)

with metrics.timer("spans.buffer.flusher.wait_produce"):
with metrics.timer("spans.buffer.flusher.wait_produce", tags={"shards": shard_tag}):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

metrics.timer 的 tags 参数键名不一致:line 185 使用 'shard'(单数),line 199 使用 'shards'(复数)。这会导致同一指标在不同代码路径下产生不同的标签键,破坏指标聚合的一致性,使监控和告警配置变得困难。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 199

💬 详细说明:

  • 监控数据分散,无法正确聚合跨代码路径的指标;可能导致告警遗漏或误报;增加运维排查难度。

📝 问题代码:

with metrics.timer("spans.buffer.flusher.wait_produce", tags={"shards": shard_tag}):

💡 修复建议:

统一 tags 键名,建议都使用 'shard'(单数)以保持一致性。

✅ 修复示例:

with metrics.timer("spans.buffer.flusher.wait_produce", tags={"shard": shard_tag}):

🔗 参考链接

if self.process_restarts > MAX_PROCESS_RESTARTS:
raise RuntimeError(f"flusher process crashed repeatedly ({cause}), restarting consumer")
for process_index, process in self.processes.items():
if not process:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

line 222 检查 process 是否为 falsy 值,但 process 的类型是 multiprocessing.context.SpawnProcess | threading.Thread。这种检查方式不够明确,应该使用 'process is None' 来明确检查 process 是否未初始化,避免潜在的类型混淆问题。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 222

💬 详细说明:

  • 代码可读性降低;如果 process 对象实现了 bool 方法,可能导致意外的行为。

📝 问题代码:

if not process:

💡 修复建议:

将 'if not process:' 改为 'if process is None:' 以明确表达检查意图。

✅ 修复示例:

if process is None:
    continue

🔗 参考链接


self.process_restarts += 1
self._create_process()
try:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

line 253 使用 isinstance(process, multiprocessing.Process) 检查进程类型,但 process 的实际类型可能是 multiprocessing.context.SpawnProcess(line 68 的类型注解)。虽然 SpawnProcess 是 Process 的子类,但代码中 line 110 创建的是 mp_context.Process,其返回类型是 SpawnProcess。这种类型检查在运行时可能工作,但类型注解和实际检查不一致,可能导致静态类型检查器报错。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 253

💬 详细说明:

  • 静态类型检查可能失败;代码维护者可能对类型关系产生困惑。

📝 问题代码:

if isinstance(process, multiprocessing.Process):

💡 修复建议:

统一使用 mp_context.Process 或明确使用 multiprocessing.context.SpawnProcess 进行类型检查,确保类型注解和运行时检查一致。

✅ 修复示例:

if isinstance(process, multiprocessing.context.SpawnProcess):

🔗 参考链接

except (ValueError, AttributeError):
pass # Process already closed, ignore

self._create_process_for_shards(process_index, shards)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

在 _ensure_processes_alive 方法中,当进程不健康需要重启时(line 259),会调用 _create_process_for_shards 重新创建进程。但是,在重启之前,旧的 process 对象虽然被 kill(line 255),但没有从 self.processes 字典中移除。如果 _create_process_for_shards 失败,会导致字典中保留无效的进程引用。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 259

💬 详细说明:

  • 进程重启失败时,self.processes 中保留无效引用;后续调用 _ensure_processes_alive 时可能操作已失效的进程对象。

📝 问题代码:

self._create_process_for_shards(process_index, shards)

💡 修复建议:

在调用 _create_process_for_shards 之前,先从 self.processes 中移除旧的进程引用;或者确保 _create_process_for_shards 成功后再更新字典。

✅ 修复示例:

try:
    if isinstance(process, multiprocessing.Process):
        process.kill()
except (ValueError, AttributeError):
    pass

# 移除旧引用
del self.processes[process_index]
del self.buffers[process_index]

self.process_restarts[process_index] += 1
self._create_process_for_shards(process_index, shards)

🔗 参考链接


if isinstance(self.process, multiprocessing.Process):
self.process.terminate()
if isinstance(process, multiprocessing.Process):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 AI 代码审查发现问题

📋 问题概述

line 346 同样存在类型检查不一致的问题,与 line 253 类似。此外,在 join 方法中,当 process 是 threading.Thread 时,没有调用任何终止或清理操作,可能导致线程资源泄漏。

📍 问题详情

🟡 问题 1 | 严重程度: MEDIUM | 行号: 346

💬 详细说明:

  • Thread 类型的进程在 join 后没有明确清理,可能导致资源泄漏;类型检查不一致。

📝 问题代码:

if isinstance(process, multiprocessing.Process):

💡 修复建议:

  1. 统一类型检查;2. 对于 Thread 类型,考虑是否需要调用 join 等待其完成或设置 daemon 标志确保退出。

✅ 修复示例:

if isinstance(process, multiprocessing.context.SpawnProcess):
    process.terminate()
elif isinstance(process, threading.Thread):
    # Thread is daemon=True, will exit when main process exits
    pass

🔗 参考链接

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants