1 /*
2  * Copyright (C) 2019-2021 Ashar Khan <ashar786khan@gmail.com>
3  *
4  * This file is part of CP Editor.
5  *
6  * CP Editor is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * I will not be responsible if CP Editor behaves in unexpected way and
12  * causes your ratings to go down and or lose any important contest.
13  *
14  * Believe Software is "Software" and it isn't immune to bugs.
15  *
16  */
17 
18 /*
19  * The event logger is used for logging events of the editor.
20  * The logs can helps the maintainers find the bug.
21  */
22 
23 #ifndef EVENTLOGGER_HPP
24 #define EVENTLOGGER_HPP
25 
26 #ifdef QT_DEBUG
27 #include <QDebug>
28 #endif
29 #include <QTextStream>
30 
31 class QFile;
32 
33 /**
34  * There are four log levels:
35  * INFO: information, used when everything is normal
36  * WARN: warning, used when something strange happened, but it is not necessarily an error
37  * ERR: error, used when something bad happened
38  * WTF: what a terrible failure, used when it's considered impossible to happen
39  */
40 
41 /*
42  * These NOLINT are placed because macro arguments should be brace enclosed to prevent strange issues. Since, we want a
43  * pure string replacement, we cannot put braces, and hence the no lint.
44  */
45 
46 #define LOG_INFO(stream) Core::Log::log("INFO ", __func__, __LINE__, __FILE__) << stream << Qt::endl; // NOLINT
47 #define LOG_WARN(stream) Core::Log::log("WARN ", __func__, __LINE__, __FILE__) << stream << Qt::endl; // NOLINT
48 #define LOG_ERR(stream) Core::Log::log("ERROR", __func__, __LINE__, __FILE__) << stream << Qt::endl;  // NOLINT
49 #define LOG_WTF(stream) Core::Log::log(" WTF ", __func__, __LINE__, __FILE__) << stream << Qt::endl;  // NOLINT
50 
51 #define LOG_INFO_IF(cond, stream)                                                                                      \
52     if (cond)                                                                                                          \
53     {                                                                                                                  \
54         LOG_INFO(stream)                                                                                               \
55     }
56 
57 #define LOG_WARN_IF(cond, stream)                                                                                      \
58     if (cond)                                                                                                          \
59     {                                                                                                                  \
60         LOG_WARN(stream)                                                                                               \
61     }
62 
63 #define LOG_ERR_IF(cond, stream)                                                                                       \
64     if (cond)                                                                                                          \
65     {                                                                                                                  \
66         LOG_ERR(stream)                                                                                                \
67     }
68 
69 #define LOG_WTF_IF(cond, stream)                                                                                       \
70     if (cond)                                                                                                          \
71     {                                                                                                                  \
72         LOG_WTF(stream)                                                                                                \
73     }
74 
75 #ifdef QT_DEBUG
76 #define LOG_DEV(stream)                                                                                                \
77     {                                                                                                                  \
78         qDebug() << "File: [" __FILE__ "] Func: [" << __func__ << "] Line: [" << __LINE__ << "] "                      \
79                  << stream; /* NOLINT */                                                                               \
80         LOG_WARN(stream);                                                                                              \
81     }
82 #else
83 #define LOG_DEV LOG_WARN
84 #endif
85 
86 #define INFO_OF(variable) "<" #variable ">: [" << (variable) << "], "
87 #define BOOL_INFO_OF(variable) "<" #variable ">: [" << ((variable) ? "true" : "false") << "], "
88 
89 namespace Core
90 {
91 class Log
92 {
93   public:
94     /**
95      * @brief initialize the event logger
96      * @param instance the instance ID provided by SingleApplication, to distinct processes from each other
97      * @param dumptoStderr whether to print the logs into stderr or not
98      * @note this should be called only once before logging anything
99      */
100     static void init(int instance, bool dumptoStderr = false);
101 
102     /**
103      * @brief clear old logs
104      * @note this clears all logs except the current one
105      */
106     static void clearOldLogs();
107 
108     /**
109      * @brief reveal the current log file in the file manager
110      */
111     static void revealInFileManager();
112 
113     static QTextStream &log(const QString &priority, QString funcName, int line, QString fileName);
114 
115   private:
116     static QString dateTimeStamp();
117     static void platformInformation();
118 
119     static QTextStream logStream; // the text stream for logging, writes to logFile
120     static QFile logFile;         // the device for logging, a file or stderr
121 
122     const static int NUMBER_OF_LOGS_TO_KEEP; // Number of log files to keep in Temporary directory
123     const static QString LOG_FILE_NAME;      // Base Name of the log file
124     const static QString LOG_DIR_NAME;       // Directory inside Temp where log files will be stored
125     const static int
126         MAXIMUM_FUNCTION_NAME_SIZE; // Maximum size of function name, it is used to determine spacing in log file
127     const static int MAXIMUM_FILE_NAME_SIZE; // Maximum size of file name, it is used to determine spacing in log file
128 };
129 
130 } // namespace Core
131 
132 #endif // EVENTLOGGER_HPP
133