Skip to content

fix: optimize dpkg log time filtering with file-level pre-filtering - #541

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wangrong1069:agent/pms-bug-bot/2685b386cc00
Oct 14, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wangrong1069:agent/pms-bug-bot/2685b386cc00

Conversation

@wangrong1069

@wangrong1069 wangrong1069 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Root Cause Analysis

handleDkpg() in logauththread.cpp lacks file-level time pre-filtering. When the user selects "today" (or any time range) and no dpkg log entries match, the function still reads every file via DBus and parses all lines through regex/split/QDateTime, only to discard them. This takes 31-69 seconds (per test logs) before the spinner stops with empty content. Key evidence: logauththread.cpp:698 time filter discards all entries → dList empty → displaycontent.cpp:2048 !list.isEmpty() blocks early spinner stop.

Fix

Three optimizations in handleDkpg():

  1. mtime fast path (before DBus read): skip original (non-txt) log files whose lastModified() precedes timeFilterBegin — avoids DBus read entirely for stale files.
  2. Content pre-filter (after DBus read, before line-by-line parsing): parse first/last line timestamps to get file time range; if it doesn't intersect the filter range, skip line-by-line parsing. Falls back to line-by-line when timestamps can't be parsed.
  3. Regex extraction: QRegularExpression construction moved from inner loop (constructed per line) to function-level const variable.
  4. Early return signal fix: add emit dpkgFinished(m_threadCount) before return in the "file does not exist" early return path.

Change Safety Assessment

Code Safety

  • Risk Level: Low
  • handleDkpg() signature unchanged; pre-filter logic conservatively falls back to line-by-line parsing when file time range can't be determined — no behavior change in those cases
  • No regression risk with related PMS bug 340567 (datetime format fix) — pre-filter uses same "yyyy-MM-dd hh:mm:ss" format

Business Impact Scope

Affects dpkg log viewing with time filter (e.g., "today", "custom range"). When no entries match the selected time range, the spinner stops quickly instead of running for 30-70 seconds. No impact when time filter is inactive ("all") or when file time range cannot be determined.

Verification Suggestion

Test dpkg log viewing with "today" filter (original bug scenario — verify fast response with content or quick empty display), "all" filter (no regression), and custom time range (correct filtering).


根因分析

logauththread.cpp 中 handleDkpg() 缺少文件级时间预过滤。用户选择"今天"(或任意时间段)且无 dpkg 日志条目匹配时,函数仍通过 DBus 读取每个文件并逐行解析(regex/split/QDateTime),最终全部丢弃。测试日志显示耗时 31-69 秒后转圈停止且无内容显示。关键证据:logauththread.cpp:698 时间过滤丢弃所有条目 → dList 为空 → displaycontent.cpp:2048 !list.isEmpty() 阻止 spinner 提前停止。

修复方案

在 handleDkpg() 中做三项优化:

  1. mtime 快速通道(DBus 读取前):原始日志文件(非解压 txt)的 lastModified() 早于筛选起点 → 整文件跳过,省掉 DBus 读取
  2. 内容预筛(DBus 读取后、逐行解析前):取首尾行时间戳为文件时间区间,与筛选区间无交集则跳过逐行解析;无法确定区间时保守回退逐行
  3. 正则外提:QRegularExpression 从内层循环每次构造改为函数内一次构造
  4. 提前返回补发信号:文件不存在提前返回路径补加 emit dpkgFinished(m_threadCount)

改动安全评估

代码安全评估

  • 风险等级: 低风险
  • handleDkpg() 函数签名未变;预过滤逻辑在无法确定文件时间区间时保守回退逐行解析,行为不变
  • 与关联 PMS bug 340567(日期时间格式修复)无冲突——预过滤使用相同的 "yyyy-MM-dd hh:mm:ss" 格式

业务影响范围

影响 dpkg 日志按时间筛选查看功能(如"今天"、"自定义时间段")。无匹配日志时转圈快速停止而非等待 30-70 秒。无时间过滤("全部")或无法确定文件时间区间时行为不变。

验证建议

测试选择"今天"查看 dpkg 日志(原 bug 场景——验证快速响应或有内容显示)、"全部"(无回归)、自定义时间段(过滤结果正确)。

Summary by Sourcery

Optimize dpkg log retrieval so time-filtered searches skip irrelevant files and complete faster.

Bug Fixes:

  • Stop dpkg log processing promptly when files are missing or when their contents cannot intersect the selected time range.

Enhancements:

  • Optimize dpkg log time filtering with file-level modification-time and content-range pre-filtering, while reusing the ANSI escape-sequence regular expression during line parsing.

@sourcery-ai

sourcery-ai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Reviewer's Guide

Optimizes dpkg log time-filtering by rejecting stale or non-overlapping files before expensive parsing, while preserving conservative fallback behavior; also reuses the ANSI regex and fixes completion signaling on the missing-file early-return path.

Sequence diagram for optimized dpkg log time filtering

sequenceDiagram
    participant T as LogAuthThread
    participant FS as FileSystem
    participant DB as DLDBusHandler
    participant P as DpkgParser

    T->>FS: lastModified()
    alt mtime before filter begin
        T-->>T: Skip file
    else file may overlap filter
        T->>DB: readLog(filePath)
        T->>P: dpkgFileOutOfTimeRange(lines, filterBegin, filterEnd)
        alt content outside filter range
            T-->>T: Skip line parsing
        else range overlaps or cannot be determined
            loop each log line
                T->>P: dpkgLineTime(line)
                T->>P: Apply existing line filters
            end
        end
    end
Loading

Flow diagram for dpkg log file-level time pre-filtering

flowchart TD
    A[handleDkpg] --> B{Time filter active?}
    B -- No --> C[readLog]
    B -- Yes --> D{Original file mtime before filter begin?}
    D -- Yes --> E[Skip file]
    D -- No --> C
    C --> F{File content time range overlaps filter?}
    F -- No --> E
    F -- Yes --> G[Parse lines and apply existing filters]
    F -- Unknown --> G
    G --> H[Emit filtered dpkg results]
    E --> I{More files?}
    H --> I
    I -- Yes --> B
    I -- No --> J[Complete processing]
Loading

File-Level Changes

Change Details Files
Adds file-level time filtering to avoid unnecessary dpkg log parsing.
  • Skips non-text files before DBus reads when modification time is earlier than the filter start.
  • Uses the first and last parseable line timestamps to skip files outside the selected interval, with conservative fallback to line parsing.
  • Keeps the existing per-line filtering path for files that may overlap the interval.
application/logauththread.cpp
Reduces per-line processing overhead and improves completion signaling.
  • Hoists ANSI escape-sequence regex construction outside the line-processing loop.
  • Emits the completion signal when a referenced dpkg log file is missing before returning.
application/logauththread.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai 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.

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="application/logauththread.cpp" line_range="715" />
<code_context>
+        if (m_dkpgFilters.timeFilterBegin > 0 && m_dkpgFilters.timeFilterEnd > 0
+            && !m_FilePath.at(i).contains("txt")) {
+            QFileInfo fileInfo(m_FilePath.at(i));
+            if (fileInfo.lastModified().toMSecsSinceEpoch() < m_dkpgFilters.timeFilterBegin) {
+                qCDebug(logApp) << "Skipping dpkg file (mtime before filter range):" << m_FilePath.at(i);
+                continue;
</code_context>
<issue_to_address>
**Matching entries are skipped**

When a non-`txt` dpkg log has an old modification time but contains timestamps in the selected range, `handleDkpg()` uses the file’s modification time to skip the log before reading it, so matching entries never reach the per-line filter and the user sees incomplete results.

Do not use modification time alone to skip a log; read it and apply the timestamp filter to its entries.

Also at `application/logauththread.cpp:686-687`, `application/logauththread.cpp:716-718`.
</issue_to_address>

### Comment 2
<location path="application/logauththread.cpp" line_range="686-687" />
<code_context>
+    if (!fileEarliest.isValid() || !fileLatest.isValid())
+        return false;
+
+    return fileLatest.toMSecsSinceEpoch() < filterBegin
+           || fileEarliest.toMSecsSinceEpoch() > filterEnd;
+}
+
</code_context>
<issue_to_address>
**Matching entries are skipped**

When a dpkg log has non-monotonic timestamps, with its first and last valid timestamps outside the selected range while an interior timestamp matches, `dpkgFileOutOfTimeRange()` treats the first and last valid timestamps as the file’s bounds, so `handleDkpg()` skips the whole file before per-line filtering and the matching entry disappears.

Avoid using the first and last timestamps as the file’s bounds; determine whether any entry matches or rely on per-line filtering.

Also at `application/logauththread.cpp:712-718`.
</issue_to_address>

### Comment 3
<location path="application/logauththread.cpp" line_range="703" />
<code_context>
             QFile file(m_FilePath.at(i)); // if not,maybe crash
             if (!file.exists()) {
                 qCWarning(logApp) << "DPKG log file does not exist:" << m_FilePath.at(i);
+                emit dpkgFinished(m_threadCount);
                 return;
             }
</code_context>
<issue_to_address>
**Buffered entries are lost**

When a listed file is missing after earlier files have added fewer than one batch of entries to `dList`, `handleDkpg()` emits `dpkgFinished` and returns without sending the buffered `dList`, so the caller marks loading complete with those entries missing.

Emit any remaining `dList` entries before returning and signaling completion.
</issue_to_address>

### Comment 4
<location path="application/logauththread.cpp" line_range="653" />
<code_context>
+static QDateTime dpkgLineTime(const QString &line)
+{
+    // dpkg 日志行格式为 "yyyy-MM-dd hh:mm:ss ...",取前 19 字符即可得到时间戳部分
+    return QDateTime::fromString(line.trimmed().left(19), "yyyy-MM-dd hh:mm:ss");
+}
+
</code_context>
<issue_to_address>
**ANSI-prefixed entries are skipped**

When an ANSI escape prefix affects a timestamp that matches the filter, while the helper’s other parseable timestamps place the file outside the range, `dpkgLineTime()` parses the raw line before ANSI escapes are removed, so `dpkgFileOutOfTimeRange()` can skip the file before the per-line parser gets a chance to match that entry.

Remove ANSI escapes before parsing timestamps in `dpkgLineTime()`.

Also at `application/logauththread.cpp:654`, `application/logauththread.cpp:747`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread application/logauththread.cpp Resolved
Comment thread application/logauththread.cpp Resolved
Comment thread application/logauththread.cpp Resolved
Comment thread application/logauththread.cpp Resolved
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 95 分 (通过阈值: 70分)

Fail


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交为 dpkg 日志时间过滤性能优化,新增两个静态辅助函数 dpkgLineTime() 和 dpkgFileOutOfTimeRange(),并在 handleDkpg() 中添加 mtime 快速通道、内容预筛和正则外提三项优化。代码注释完整、逻辑清晰、边界处理保守(无法确定时间范围时回退逐行解析),修复了文件不存在路径未发射 dpkgFinished 信号的问题。未发现安全漏洞,性能优化设计合理。扣分项为 dpkgFileOutOfTimeRange 函数在极端情况下存在 O(2n) 遍历的轻微优化空间。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: []


2. 代码质量 ✅

评价: 良好 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['建议在 dpkgFileOutOfTimeRange 中添加最大扫描行数限制(如前100行和后100行),避免极端情况下遍历整个文件']


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['mtime 快速通道有效避免了不必要的 DBus 读取,内容预筛有效减少了逐行解析开销,正则外提避免了循环内重复构造,三项优化设计合理']


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 修复安全漏洞,加强输入验证


💡 改进建议代码示例

// 暂无代码示例

本报告由 AI 代码审查工具自动生成

1. Root cause: handleDkpg() lacks file-level time pre-filtering; when
   filtering by time period (e.g. "today") with no matching entries,
   every file is still read via DBus and parsed line-by-line through
   regex/split/QDateTime, causing long spinner with no content shown
2. Fix: add mtime fast path to skip original files whose lastModified
   precedes filter begin (before DBus read); add content pre-filter to
   skip files whose first/last timestamp range does not intersect the
   filter range (after DBus read, before line-by-line parsing); extract
   QRegularExpression construction out of the inner loop to once per
   function call; add missing emit dpkgFinished on early return when
   log file does not exist
3. Refactor: extract content pre-filtering into dpkgLineTime() and
   dpkgFileOutOfTimeRange() functions for readability; add qCDebug logs
   at key skip points (mtime fast path, content pre-filter); add
   comments to key code blocks
4. Impact: dpkg log viewing with time filter is significantly faster;
   no behavior change when time filter is inactive or when file time
   range cannot be determined (conservatively falls back to line-by-line)

Log: Optimize dpkg log time filtering to avoid long spinner

Influence:
1. Test dpkg log viewing with "today" filter - verify fast response
2. Test dpkg log viewing with "all" filter - verify no regression
3. Test dpkg log viewing with custom time range - verify correct results
4. Test across multiple log files including .gz compressed files

fix: 优化dpkg日志时间过滤,增加文件级预过滤

1. 根因:handleDkpg() 缺少文件级时间预过滤,按时间段筛选(如"今天")
   且无匹配条目时,仍对每个文件执行 DBus 读取和逐行 regex/split/
   QDateTime 解析,导致长时间转圈且无内容显示
2. 方案:新增 mtime 快速通道,原始日志文件 lastModified 早于筛选
   起点则整文件跳过(DBus 读取前);新增内容预筛,取首尾行时间戳
   为文件时间区间,与筛选区间无交集则跳过逐行解析(DBus 读取后);
   正则外提为函数内一次构造;文件不存在提前返回时补发 dpkgFinished
   信号
3. 重构:将内容预筛逻辑封装为 dpkgLineTime() 和
   dpkgFileOutOfTimeRange() 函数,提升可读性;在关键跳过位置
   (mtime 快速通道、内容预筛)添加 qCDebug 日志;为关键代码块
   添加注释
4. 影响:dpkg 日志按时间筛选时响应速度大幅提升;无时间过滤或无法
   确定文件时间区间时保守回退逐行解析,行为不变

Log: 优化dpkg日志时间过滤,避免长时间转圈无内容

Influence:
1. 测试选择"今天"查看dpkg日志,验证响应快速且有内容显示
2. 测试选择"全部"查看dpkg日志,验证无回归
3. 测试自定义时间段筛选dpkg日志,验证过滤结果正确
4. 测试跨多个日志文件场景,包含.gz压缩文件

PMS: BUG-369163
@wangrong1069
wangrong1069 force-pushed the agent/pms-bug-bot/2685b386cc00 branch from 7bcf99c to dbd8653 Compare October 13, 2026 13:44
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, wangrong1069

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@wangrong1069

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit f49e7a1 into linuxdeepin:master Oct 14, 2026
17 checks passed
@wangrong1069
wangrong1069 deleted the agent/pms-bug-bot/2685b386cc00 branch October 14, 2026 01:31
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.

3 participants