Skip to content

Commit a0a55d9

Browse files
committed
feat: add eventlogger.hpp header for DDE applications
Add a C++ header-only event logger that can be used by DDE applications to log user behavior events. The logger uses dlopen to dynamically load libdeepin-event-log.so library at runtime. Features: - Header-only implementation, no linking required - Dynamic library loading with QLibrary - System edition check (only UosProfessional enabled by default) - Debug mode macro for testing on other editions - LGPL-3.0-or-later license for easy integration 添加用于DDE应用程序的事件日志头文件。日志记录器使用dlopen在运行时动态加载 libdeepin-event-log.so库。 Log: 添加事件日志头文件 PMS: TASK-388657
1 parent 3999d54 commit a0a55d9

3 files changed

Lines changed: 184 additions & 3 deletions

File tree

Makefile

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ PREFIX = /usr
22
GOBUILD_DIR = gobuild
33
GOPKG_PREFIX = github.com/linuxdeepin/dde-api
44
GOSITE_DIR = ${PREFIX}/share/gocode
5+
CPP_INCLUDE_DIR = ${PREFIX}/include
56
libdir = /lib
67
SYSTEMD_LIB_DIR = ${libdir}
78
SYSTEMD_SERVICE_DIR = ${SYSTEMD_LIB_DIR}/systemd/system/
@@ -83,10 +84,10 @@ ts-to-policy:
8384
deepin-policy-ts-convert ts2policy misc/polkit-action/org.deepin.dde.locale-helper.policy.in misc/ts/org.deepin.dde.locale-helper.policy misc/polkit-action/org.deepin.dde.locale-helper.policy
8485
deepin-policy-ts-convert ts2policy misc/polkit-action/org.deepin.dde.device.unblock-bluetooth-devices.policy.in misc/ts/org.deepin.dde.device.unblock-bluetooth-devices.policy misc/polkit-action/org.deepin.dde.device.unblock-bluetooth-devices.policy
8586

86-
out/bin/%:
87+
out/bin/%: | prepare
8788
${GOBUILD} -o $@ ${GOBUILD_OPTIONS} ${GOPKG_PREFIX}/${@F}
8889

89-
build-binary: prepare $(addprefix out/bin/, ${BINARIES})
90+
build-binary: $(addprefix out/bin/, ${BINARIES})
9091

9192
install-binary:
9293
mkdir -pv ${DESTDIR}${PREFIX}${libdir}/deepin-api
@@ -135,9 +136,14 @@ install/lib/%:
135136
mkdir -pv ${DESTDIR}${GOSITE_DIR}/src/${GOPKG_PREFIX}
136137
cp -R ${CURDIR}/${GOBUILD_DIR}/src/${GOPKG_PREFIX}/${@F} ${DESTDIR}${GOSITE_DIR}/src/${GOPKG_PREFIX}
137138

139+
install-misc:
140+
#Need to copy cpp-include/eventlogger.hpp to /usr/include
141+
mkdir -pv ${DESTDIR}${CPP_INCLUDE_DIR}/dde-api
142+
cp -R cpp-include/eventlogger.hpp ${DESTDIR}${CPP_INCLUDE_DIR}/dde-api
143+
138144
install-dev: ${addprefix install/lib/, ${ININSTALLS}}
139145

140-
install: install-binary install-dev
146+
install: install-binary install-dev install-misc
141147

142148
clean:
143149
rm -rf out/bin gobuild out

cpp-include/eventlogger.hpp

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
2+
//
3+
// SPDX-License-Identifier: LGPL-3.0-or-later
4+
5+
#pragma once
6+
#include <QDebug>
7+
#include <QJsonDocument>
8+
#include <QJsonObject>
9+
#include <QLibrary>
10+
#include <DSysInfo>
11+
12+
#include <mutex>
13+
14+
#include <dlfcn.h>
15+
#include <unistd.h>
16+
17+
// Enable logging for current system version (debug only, remove before release)
18+
// #define DDE_EVENTLOG_DEBUG_ENABLE_CURRENT_VERSION
19+
20+
namespace DDE_EventLogger {
21+
22+
// Check if event logging should be enabled based on system edition
23+
// Only UosProfessional is enabled by default
24+
inline bool shouldEnableEventLog()
25+
{
26+
#ifdef DDE_EVENTLOG_DEBUG_ENABLE_CURRENT_VERSION
27+
// Debug mode: enable for current system version
28+
return true;
29+
#else
30+
// Production mode: only enable for UosProfessional edition
31+
// Note: DSysInfo is in Dtk::Core namespace
32+
return Dtk::Core::DSysInfo::uosEditionType() == Dtk::Core::DSysInfo::UosProfessional;
33+
#endif
34+
}
35+
36+
typedef bool (*Initialize)(const std::string &package_id, bool enable_sig);
37+
typedef void (*WriteEventLog)(const std::string &event_data);
38+
39+
typedef struct _EventLoggerData
40+
{
41+
qint64 tid;
42+
QString target;
43+
QMap<QString, QString> message;
44+
45+
_EventLoggerData()
46+
: tid(0)
47+
, target(QString())
48+
, message(QMap<QString, QString>())
49+
{
50+
}
51+
52+
_EventLoggerData(qint64 tid, const QString &target, const QMap<QString, QString> &message)
53+
: tid(tid)
54+
, target(target)
55+
, message(message)
56+
{
57+
}
58+
59+
_EventLoggerData &operator=(const _EventLoggerData &data)
60+
{
61+
tid = data.tid;
62+
target = data.target;
63+
message = data.message;
64+
return *this;
65+
}
66+
} EventLoggerData;
67+
68+
class EventLogger
69+
{
70+
public:
71+
static EventLogger &instance()
72+
{
73+
static EventLogger instance;
74+
return instance;
75+
}
76+
77+
void writeEventLog(const EventLoggerData &data)
78+
{
79+
if (!shouldEnableEventLog()) {
80+
return;
81+
}
82+
83+
std::lock_guard<std::mutex> lock(m_mutex);
84+
if (!m_initialized) {
85+
return;
86+
}
87+
88+
QJsonDocument json = structToJson(data);
89+
m_writeEventLog(json.toJson(QJsonDocument::Compact).toStdString());
90+
}
91+
92+
void writeEventLog(qint64 tid, const QString &target, const QString &key, const QString &value)
93+
{
94+
writeEventLog(EventLoggerData(tid, target, {{key, value}}));
95+
}
96+
97+
bool init(QString package_id, bool enable_sig)
98+
{
99+
if (!shouldEnableEventLog()) {
100+
return false;
101+
}
102+
103+
std::lock_guard<std::mutex> lock(m_mutex);
104+
105+
if (nullptr == m_initialize || nullptr == m_writeEventLog) {
106+
return false;
107+
}
108+
109+
if (m_initialized) {
110+
return true;
111+
}
112+
113+
m_initialized = m_initialize(package_id.toStdString(), enable_sig);
114+
if (!m_initialized) {
115+
qDebug() << "Failed to initialize event logger";
116+
return false;
117+
}
118+
return true;
119+
}
120+
121+
private:
122+
EventLogger()
123+
: m_initialized(false)
124+
, m_initialize(nullptr)
125+
, m_writeEventLog(nullptr)
126+
, m_library("/usr/lib/libdeepin-event-log.so")
127+
{
128+
// 检查链接库是否成功加载
129+
if (!m_library.load()) {
130+
qDebug() << "Failed to load library:" << m_library.errorString();
131+
return;
132+
}
133+
134+
// 获取链接库中的函数指针
135+
m_initialize = (Initialize)m_library.resolve("Initialize");
136+
m_writeEventLog = (WriteEventLog)m_library.resolve("WriteEventLog");
137+
138+
// 检查函数是否成功获取
139+
if (!m_initialize || !m_writeEventLog) {
140+
qDebug() << "Failed to resolve function";
141+
return;
142+
}
143+
}
144+
145+
~EventLogger() { m_library.unload(); }
146+
147+
EventLogger(const EventLogger &) = delete; // 禁止拷贝构造函数
148+
EventLogger &operator=(const EventLogger &) = delete; // 禁止赋值运算符
149+
150+
// 将结构体转换为 JSON 内容
151+
QJsonDocument structToJson(const EventLoggerData &data)
152+
{
153+
QJsonObject jsonObject;
154+
jsonObject["tid"] = data.tid;
155+
jsonObject["target"] = data.target;
156+
QJsonObject msgJson;
157+
QMapIterator<QString, QString> iterator(data.message);
158+
while (iterator.hasNext()) {
159+
iterator.next();
160+
msgJson[iterator.key()] = iterator.value();
161+
}
162+
163+
jsonObject["message"] = msgJson;
164+
QJsonDocument jsonDocument(jsonObject);
165+
return jsonDocument;
166+
}
167+
168+
std::mutex m_mutex;
169+
bool m_initialized;
170+
Initialize m_initialize;
171+
WriteEventLog m_writeEventLog;
172+
QLibrary m_library;
173+
};
174+
} // namespace DDE_EventLogger

debian/dde-api-dev.install

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/usr/share/gocode/
2+
/usr/include/

0 commit comments

Comments
 (0)