feat(dock): add app launch event reporting for taskbar icons#1606
Open
Ivy233 wants to merge 1 commit into
Open
feat(dock): add app launch event reporting for taskbar icons#1606Ivy233 wants to merge 1 commit into
Ivy233 wants to merge 1 commit into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Ivy233 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
35405ee to
0b79013
Compare
|
TAG Bot New tag: 2.0.43 |
1. Implement LaunchDurationReporter to report event 1000610003 when taskbar icons appear 2. Report app metadata: name, launch type, version, unique ID, timestamp, and package type 3. Query Application Manager via DBus for instance information 4. Detect package type using ll-cli for linglong apps and dpkg-query for deb packages 5. Implement cache with 30-minute TTL for linglong and deb packages 6. Async D-Bus query execution for better performance Log: Report app launch events when taskbar icons appear for analytics Influence: 1. Verify event 1000610003 triggers when new taskbar icons appear 2. Verify correct version reporting for linglong and deb packages feat(dock): 添加任务栏图标出现时的应用启动事件上报 1. 实现 LaunchDurationReporter 在任务栏图标出现时上报 1000610003 事件 2. 上报应用元数据:名称、启动类型、版本、唯一 ID、时间戳和包类型 3. 通过 DBus 查询应用管理器获取实例信息 4. 使用 ll-cli 检测玲珑应用,使用 dpkg-query 检测 deb 包 5. 实现 30 分钟 TTL 的玲珑和 deb 包缓存 6. D-Bus 查询异步执行,提升性能 Log: 任务栏图标出现时上报应用启动事件用于分析 Influence: 1. 验证新图标出现时触发 1000610003 事件 2. 验证玲珑和 deb 包版本正确上报 PMS: TASK-389405
0b79013 to
2e0b988
Compare
deepin pr auto review这份代码实现了一个应用启动时长上报器,通过 D-Bus 查询应用实例信息,结合 但在语法逻辑、代码质量、性能和安全性方面存在一些需要改进的地方。以下是详细的审查意见: 1. 语法与逻辑问题
2. 代码性能
3. 代码安全
4. 代码质量与可维护性
改进后的代码示例针对以上核心问题,以下是修改后的 // ... 头部保持不变,建议修改年份 ...
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
namespace {
// ... 常量定义增加 ...
constexpr auto kAmService = "org.desktopspec.ApplicationManager1";
constexpr auto kApplicationIface = "org.desktopspec.ApplicationManager1.Application";
constexpr auto kInstanceIface = "org.desktopspec.ApplicationManager1.Instance";
constexpr int kLinglongCacheTTLSeconds = 1800;
constexpr int kDebCacheTTLSeconds = 1800;
constexpr int kDbusTimeoutMs = 1000;
constexpr int kSubprocessTimeoutMs = 3000;
QList<InstanceInfo> queryInstances(const QString &desktopId)
{
QList<InstanceInfo> result;
auto appPath = QStringLiteral("/org/desktopspec/ApplicationManager1/%1").arg(escapeToObjectPath(desktopId));
QDBusInterface appIface(QString::fromUtf8(kAmService),
appPath,
QStringLiteral("org.freedesktop.DBus.Properties"),
QDBusConnection::sessionBus());
appIface.setTimeout(kDbusTimeoutMs);
QDBusReply<QVariant> reply = appIface.call(QStringLiteral("Get"),
QString::fromUtf8(kApplicationIface),
QStringLiteral("Instances"));
if (!reply.isValid()) {
qCDebug(launchDurationReporter) << "[DockIconTiming] queryInstances failed for" << desktopId << ":" << reply.error().message();
return result;
}
const auto paths = qdbus_cast<QList<QDBusObjectPath>>(reply.value());
for (const auto &path : paths) {
QDBusInterface instIface(QString::fromUtf8(kAmService),
path.path(),
QStringLiteral("org.freedesktop.DBus.Properties"),
QDBusConnection::sessionBus());
instIface.setTimeout(kDbusTimeoutMs);
InstanceInfo info;
info.instanceId = path.path().section(QLatin1Char('/'), -1);
// 优化:使用 QDBusReply 简化提取逻辑
QDBusReply<QVariant> launchTypeReply = instIface.call(QStringLiteral("Get"),
QString::fromUtf8(kInstanceIface),
QStringLiteral("LaunchType"));
if (launchTypeReply.isValid()) {
info.launchType = launchTypeReply.value().toString();
}
if (info.launchType.isEmpty()) {
info.launchType = QStringLiteral("unknown");
}
result.append(info);
}
return result;
}
QHash<QString, QString> loadAllLinglongVersions()
{
QHash<QString, QString> result;
QProcess proc;
// 建议:如果 ll-cli 支持 --json,请使用 JSON 解析代替字符串分割
proc.start(QStringLiteral("ll-cli"), {QStringLiteral("list"), QStringLiteral("--type"), QStringLiteral("app")});
if (!proc.waitForFinished(kSubprocessTimeoutMs)) {
qCWarning(launchDurationReporter) << "ll-cli list timeout";
proc.kill();
proc.waitForFinished();
return result;
}
if (proc.exitCode() != 0) {
qCWarning(launchDurationReporter) << "ll-cli list failed, exitCode:" << proc.exitCode();
return result;
}
QString output = QString::fromUtf8(proc.readAllStandardOutput());
QStringList lines = output.split(QLatin1Char('\n'), Qt::SkipEmptyParts);
// Skip header line
for (int i = 1; i < lines.size(); ++i) {
// 优化:使用正则匹配连续空格,防止单元格内包含空格导致错位
QStringList columns = lines[i].simplified().split(QRegularExpression("\\s+"));
if (columns.size() >= 3) {
QString name = columns[1];
QString version = columns[2];
if (!name.isEmpty()) {
result.insert(name, version);
}
}
}
return result;
}
// 正则表达式验证包名合法性,防止注入或异常字符
static bool isValidDesktopId(const QString &desktopId) {
static QRegularExpression validNameRegex("^[a-z0-9][a-z0-9+.-]+$");
return validNameRegex.match(desktopId).hasMatch();
}
} // namespace
namespace dock {
// ... 构造和析构保持不变 ...
void LaunchDurationReporter::reportWindowAppeared(const QString &desktopId)
{
if (desktopId.isEmpty() || !isValidDesktopId(desktopId)) {
return;
}
// 不需要接收 future 则不接收,避免 Q_UNUSED
QtConcurrent::run(&m_workerPool, [this, desktopId]() {
auto instances = queryInstances(desktopId);
QString uniqueId;
QString launchType = QStringLiteral("unknown");
if (!instances.isEmpty()) {
const auto &latest = instances.constLast();
uniqueId = latest.instanceId;
launchType = latest.launchType;
}
if (uniqueId.isEmpty()) {
return;
}
QString version;
QString pakType;
{
QMutexLocker locker(&m_cacheMutex);
qint64 currentTime = QDateTime::currentSecsSinceEpoch();
if ((currentTime - m_linglongCacheTime) > kLinglongCacheTTLSeconds) {
m_linglongCache = loadAllLinglongVersions();
m_linglongCacheTime = currentTime;
}
if (m_linglongCache.contains(desktopId)) {
version = m_linglongCache.value(desktopId);
pakType = QStringLiteral("linglong");
} else if (m_debCache.contains(desktopId)) {
const auto &entry = m_debCache.value(desktopId);
if ((currentTime - entry.timestamp) <= kDebCacheTTLSeconds) {
version = entry.version;
pakType = entry.pakType;
}
}
}
if (pakType.isEmpty()) {
QProcess proc;
proc.start(QStringLiteral("dpkg-query"), {QStringLiteral("-W"), QStringLiteral("-f=${Version}"), desktopId});
proc.waitForFinished(kDbusTimeoutMs); // 复用超时常量
if (proc.exitCode() == 0) {
version = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
pakType = QStringLiteral("deb");
} else {
qCDebug(launchDurationReporter) << "dpkg-query failed for" << desktopId << "exitCode:" << proc.exitCode();
pakType = QStringLiteral("unknown");
}
QMutexLocker locker(&m_cacheMutex);
m_debCache.insert(desktopId, {version, pakType, QDateTime::currentSecsSinceEpoch()});
}
QMetaObject::invokeMethod(this, [this, desktopId, uniqueId, launchType, version, pakType]() {
doReport(desktopId, uniqueId, launchType, version, pakType);
}, Qt::QueuedConnection);
});
}
// ... doReport 保持不变 ...
} // namespace dock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Log: Report app launch events when taskbar icons appear for analytics
Influence:
feat(dock): 添加任务栏图标出现时的应用启动事件上报
Log: 任务栏图标出现时上报应用启动事件用于分析
Influence:
PMS: TASK-389405