1 /*
2 SPDX-FileCopyrightText: 2007 Nicolas Ternisien <nicolas.ternisien@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "syslogAnalyzer.h"
8
9 #include <QDateTime>
10 #include <QStringList>
11
12 #include <KLocalizedString>
13
14 #include "globals.h"
15 #include "ksystemlog_debug.h"
16
17 #include "localLogFileReader.h"
18 #include "logLevel.h"
19 #include "logLine.h"
20 #include "logMode.h"
21 #include "logViewWidget.h"
22
23 #include "logViewModel.h"
24
25 #include "parsingHelper.h"
26
27 #include "ksystemlogConfig.h"
28
SyslogAnalyzer(LogMode * logMode)29 SyslogAnalyzer::SyslogAnalyzer(LogMode *logMode)
30 : FileAnalyzer(logMode)
31 {
32 }
33
~SyslogAnalyzer()34 SyslogAnalyzer::~SyslogAnalyzer()
35 {
36 }
37
initColumns()38 LogViewColumns SyslogAnalyzer::initColumns()
39 {
40 LogViewColumns columns;
41 columns.addColumn(LogViewColumn(i18n("Date"), true, false));
42 columns.addColumn(LogViewColumn(i18n("Host"), true, true));
43 columns.addColumn(LogViewColumn(i18n("Process"), true, true));
44 columns.addColumn(LogViewColumn(i18n("Message"), true, false));
45
46 return columns;
47 }
48
createLogFileReader(const LogFile & logFile)49 LogFileReader *SyslogAnalyzer::createLogFileReader(const LogFile &logFile)
50 {
51 return new LocalLogFileReader(logFile);
52 }
53
logFileSortMode()54 Analyzer::LogFileSortMode SyslogAnalyzer::logFileSortMode()
55 {
56 return Analyzer::AscendingSortedLogFile;
57 }
58
59 /**
60 * TODO Improve speed of this method (with KRegExp class for example)
61 */
parseMessage(const QString & logLine,const LogFile & originalFile)62 LogLine *SyslogAnalyzer::parseMessage(const QString &logLine, const LogFile &originalFile)
63 {
64 // qCDebug(KSYSTEMLOG) << QTime::currentTime() << " : Reading line : " << logLine << " from " <<
65 // originalFile.url.path();
66
67 // 15 is the default date size format
68 if (logLine.length() < 15) {
69 qCDebug(KSYSTEMLOG) << "Too short line";
70 return undefinedLogLine(logLine, originalFile);
71 }
72
73 const int year = QDate::currentDate().year();
74
75 // Month number
76 QString month(logLine.left(3));
77
78 QString line(logLine);
79
80 line.remove(0, 4);
81 const int monthNum = ParsingHelper::instance()->parseSyslogMonth(month);
82
83 // Day number
84 QString day(line.left(2));
85 const int dayNum = day.toInt();
86
87 line.remove(0, 3);
88
89 // Time
90 QString stringTime(line.left(8));
91 const int h = stringTime.leftRef(2).toInt();
92 stringTime.remove(0, 3);
93 const int m = stringTime.leftRef(2).toInt();
94 stringTime.remove(0, 3);
95 const int s = stringTime.leftRef(2).toInt();
96 stringTime.remove(0, 3);
97
98 const QDateTime dateTime(QDate(year, monthNum, dayNum), QTime(h, m, s));
99 if (!dateTime.isValid()) {
100 qCDebug(KSYSTEMLOG) << "Malformed date and time";
101 return undefinedLogLine(logLine, originalFile);
102 }
103
104 line.remove(0, 9);
105
106 QString hostname;
107
108 const int nextSpace = line.indexOf(QLatin1Char(' '));
109 int nextDoubleDot = line.indexOf(QLatin1Char(':'));
110
111 // Normal case or no process name
112 if (nextSpace < nextDoubleDot || nextDoubleDot == -1) {
113 // Host name
114 hostname = line.left(nextSpace);
115 line.remove(0, nextSpace + 1);
116 }
117 // No host name case (very rare)
118 else {
119 // Host name
120 hostname = undefinedHostName();
121 }
122
123 // Refresh double dot once the line has been substr'ed
124 nextDoubleDot = line.indexOf(QLatin1Char(':'));
125
126 QString process;
127 QString message;
128
129 // Process name
130 if (nextDoubleDot != -1) {
131 process = line.left(nextDoubleDot);
132
133 // If the delete process identifier option is enabled
134 if (KSystemLogConfig::deleteProcessIdentifier()) {
135 const int squareBracket = process.indexOf(QLatin1Char('['));
136
137 // If we find a bracket, we remove the useless part
138 if (squareBracket != -1) {
139 process.truncate(squareBracket);
140 }
141 }
142 line.remove(0, nextDoubleDot + 1);
143
144 message = line.remove(0, 1);
145 }
146 // If we can't find any ':' character, it means that this line is a
147 // internal message of syslogd
148 else {
149 if (line.contains(QLatin1String("last message repeated")) || line.contains(QLatin1String("-- MARK --"))) {
150 process = QStringLiteral("syslog");
151 } else {
152 process = undefinedProcess();
153 }
154
155 message = line;
156 }
157
158 QStringList list;
159 list.append(hostname);
160 list.append(process);
161 list.append(message);
162
163 return new LogLine(mLogLineInternalIdGenerator++, dateTime, list, originalFile.url().toLocalFile(), originalFile.defaultLogLevel(), mLogMode);
164 }
165
undefinedLogLine(const QString & message,const LogFile & originalFile)166 inline LogLine *SyslogAnalyzer::undefinedLogLine(const QString &message, const LogFile &originalFile)
167 {
168 QStringList items;
169 items << undefinedHostName() << undefinedProcess() << message;
170 return new LogLine(mLogLineInternalIdGenerator++,
171 QDateTime::currentDateTime(),
172 items,
173 originalFile.url().toLocalFile(),
174 originalFile.defaultLogLevel(),
175 mLogMode);
176 }
177
undefinedHostName()178 inline QString SyslogAnalyzer::undefinedHostName()
179 {
180 // i18nc("Undefined host name", "undefined");
181 return QLatin1String("");
182 }
183
undefinedProcess()184 inline QString SyslogAnalyzer::undefinedProcess()
185 {
186 // i18nc("Undefined process", "undefined");
187 return QLatin1String("");
188 }
189