1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "parsethreadkern.h"
#include "qtcompat.h"
#include <QDebug>
#include <QDateTime>
#include <time.h>
using namespace std;
#ifdef QT_DEBUG
Q_LOGGING_CATEGORY(logParseWorkKern, "org.deepin.log.viewer.parse.work.kern")
#else
Q_LOGGING_CATEGORY(logParseWorkKern, "org.deepin.log.viewer.parse.work.kern", QtInfoMsg)
#endif
/**
* @brief ParseThreadKern::ParseThreadKern 构造函数
* @param parent 父对象
*/
ParseThreadKern::ParseThreadKern(QObject *parent)
: ParseThreadBase(parent)
{
}
/**
* @brief ParseThreadKern::~ParseThreadKern 析构函数,停止并销毁process指针
*/
ParseThreadKern::~ParseThreadKern()
{
}
/**
* @brief ParseThreadKern::run 线程执行虚函数
*/
void ParseThreadKern::run()
{
//此线程刚开始把可以继续变量置true,不然下面没法跑
m_canRun = true;
handleKern();
}
/**
* @brief ParseThreadKern::handleKern 处理获取内核日志
*/
void ParseThreadKern::handleKern()
{
QList<QString> dataList;
qint64 gStartLine = m_filter.segementIndex * SEGEMENT_SIZE;
m_FilePath = DLDBusHandler::instance(this)->getFileInfo(m_filter.filePath, false);
for (int i = 0; i < m_FilePath.count(); i++) {
if (!m_FilePath.at(i).contains("txt")) {
QFile file(m_FilePath.at(i)); // add by Airy
if (!file.exists()) {
emit parseFinished(m_threadCount, m_type);
return;
}
}
if (!m_canRun) {
return;
}
if (!Utils::runInCmd) {
initProccess();
if (!m_canRun) {
return;
}
m_process->setProcessChannelMode(QProcess::MergedChannels);
if (!m_canRun) {
return;
}
//共享内存对应变量置true,允许进程内部逻辑运行
ShareMemoryInfo shareInfo;
shareInfo.isStart = true;
SharedMemoryManager::instance()->setRunnableTag(shareInfo);
//启动日志需要提权获取,运行的时候把对应共享内存的名称传进去,方便获取进程拿标记量判断是否继续运行
m_process->start("pkexec", QStringList() << "logViewerAuth"
<< m_FilePath.at(i) << SharedMemoryManager::instance()->getRunnableKey());
m_process->waitForFinished(-1);
//有错则传出空数据
if (m_process->exitCode() != 0) {
emit parseFinished(m_threadCount, m_type, CancelAuth);
return;
}
}
if (!m_canRun) {
return;
}
//如果是压缩文件,对其解压缩
QString filePath = m_FilePath.at(i);
if(QString::compare(QFileInfo(filePath).suffix(), "gz", Qt::CaseInsensitive) == 0){
QStringList filePathList = DLDBusHandler::instance(this)->getFileInfo(filePath);
if(filePathList.size()){
filePath = filePathList.at(0);
}else {
filePath = "";
}
}
qint64 lineCount = DLDBusHandler::instance(this)->getLineCount(filePath);
// 获取全局起始行在当前文件的相对起始行位置
if (gStartLine >= lineCount) {
gStartLine -= lineCount;
continue;
}
qint64 startLine = gStartLine;
QStringList strList = DLDBusHandler::instance(this)->readLogLinesInRange(filePath, startLine, SEGEMENT_SIZE);
for (int j = strList.size() - 1; j >= 0; --j) {
if (!m_canRun) {
return;
}
QString str = strList.at(j);
LOG_MSG_BASE msg;
//删除颜色格式字符
str.replace(REG_EXP("\\#033\\[\\d+(;\\d+){0,2}m"), "");
// 以 "kernel:" 开始分割
int kernelIndex = str.indexOf("kernel:");
if (kernelIndex == -1) {
continue; // 如果没有找到 "kernel:",则跳过该行
}
QString msgContent = str.mid(kernelIndex + 7); // 去掉 "kernel:" 及其前面的部分
str = str.left(kernelIndex); // 取 "kernel:" 前面的部分
QStringList list = str.split(" ", SKIP_EMPTY_PARTS);
if (list.size() < 2)
continue;
//获取内核年份接口已添加,等待系统接口添加年份改变相关日志
QStringList timeList;
QString dateTimeStr = list[0];
bool isNewFormat = dateTimeStr.contains("T");
if (isNewFormat) {
QDateTime dateTime = QDateTime::fromString(dateTimeStr, Qt::ISODate);
if (!dateTime.isValid()) {
dateTime = QDateTime::fromString(dateTimeStr, "yyyy-MM-ddTHH:mm:ss.zzzzzz+hh:mm");
}
timeList << dateTime.toString("yyyy-MM-dd") << dateTime.toString("HH:mm:ss");
iTime = dateTime.toMSecsSinceEpoch();
msg.hostName = list[1];
} else {
if (list[0].contains("-")) {
timeList << list[0] << list[1];
iTime = formatDateTime(list[0], list[1]);
msg.hostName = list[2];
} else {
timeList << list[0] << list[1] << list[2];
iTime = formatDateTime(list[0], list[1], list[2]);
msg.hostName = list[3];
}
}
// 对时间筛选
if (m_filter.timeFilterBegin > 0 && m_filter.timeFilterEnd > 0) {
if (iTime < m_filter.timeFilterBegin || iTime > m_filter.timeFilterEnd)
continue;
}
msg.dateTime = timeList.join(" ");
msg.daemonName = "kernel";
msg.daemonId = "0";
msg.msg = msgContent.trimmed();
dataList.append(QJsonDocument(msg.toJson()).toJson(QJsonDocument::Compact));
if (!m_canRun) {
return;
}
//每获得500个数据就发出信号给控件加载
if (dataList.count() % SINGLE_READ_CNT == 0) {
emit logData(m_threadCount, dataList, m_type);
dataList.clear();
}
if (!m_canRun) {
return;
}
}
}
//最后可能有余下不足500的数据
if (dataList.count() >= 0) {
emit logData(m_threadCount, dataList, m_type);
}
emit parseFinished(m_threadCount, m_type);
}
/**
* @brief ParseThreadKern::formatDateTime 内核日志没有年份 格式为Sep 29 15:53:34 所以需要特殊转换
* @param m 月份字符串
* @param d 日期字符串
* @param t 时间字符串
* @return 时间毫秒数
*/
qint64 ParseThreadKern::formatDateTime(QString m, QString d, QString t)
{
QLocale local(QLocale::English, QLocale::UnitedStates);
QDate curdt = QDate::currentDate();
QString tStr = QString("%1 %2 %3 %4").arg(m).arg(d).arg(curdt.year()).arg(t);
QDateTime dt = local.toDateTime(tStr, "MMM d yyyy hh:mm:ss");
return dt.toMSecsSinceEpoch();
}
/**
* @brief ParseThreadKern::formatDateTime 内核日志有年份 格式为2020-01-05 所以需要特殊转换
* @param y 年月日
* @param t 时间字符串
* @return 时间毫秒数
*/
qint64 ParseThreadKern::formatDateTime(QString y, QString t)
{
//when /var/kern.log have the year
QLocale local(QLocale::English, QLocale::UnitedStates);
QString tStr = QString("%1 %2").arg(y).arg(t);
QDateTime dt = local.toDateTime(tStr, "yyyy-MM-dd hh:mm:ss");
return dt.toMSecsSinceEpoch();
}
|