Sync DrDump crash handler with TortoiseSVN codebase
[TortoiseGit.git] / ext / CrashServer / CommonLibs / Log / log.h
blob889ed14fd5d69cc0862a073f69465d69779a80ad
1 // Copyright 2014 Idol Software, Inc.
2 //
3 // This file is part of Doctor Dump SDK.
4 //
5 // Doctor Dump SDK is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #ifndef __LOG_H
19 #define __LOG_H
21 #include <windows.h>
22 #include <string>
23 #include <vector>
24 #include <stdarg.h>
25 #include <tchar.h>
26 #include "synchro.h"
27 #include <memory>
29 #pragma warning (disable: 4251) // need dll-linkage
31 void InitializeLog();
32 void FreeLogThreadName();
33 void SetLogThreadName(LPCTSTR pszThreadName);
35 //! Типы сообщений.
36 enum ELogMessageType
38 eLM_Error, //!< "Ошибка" - произошёл сбой в работе, дальнейшее выполнение текущего действия невозможно.
39 eLM_Warning, //!< "Предупреждение" - произошёл сбой в работе, который удалось исправить.
40 eLM_Info, //!< "Информация" - сообщение о выполнении некоторого действия программой.
41 eLM_Debug, //!< "Отладка" - сообщение, содержащее отладочную информацию.
42 eLM_DirectOutput //!< Перенаправление в лог вывода внешнего консольного приложения
45 //! Уровень важности сообщений.
46 enum ELogMessageLevel
48 L0 = 0, //!< Наиболее важный.
49 L1 = 1,
50 L2 = 2,
51 L3 = 3,
52 L4 = 4,
53 L5 = 5,
54 LMAX = 255
57 //! Интерфейс "физического" лога. Осуществляет запись на носитель.
58 class ILogMedia
60 public:
61 virtual ~ILogMedia() {}
62 //! Записывает сообщение.
63 virtual void Write(
64 ELogMessageType type, //!< [in] Тип сообщения.
65 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
66 LPCTSTR pszDate, //!< [in] Дата записи сообщения.
67 LPCTSTR pszTime, //!< [in] Время записи сообщения.
68 LPCTSTR pszThreadId, //!< [in] Идентификатор потока, из которого записано сообщение.
69 LPCTSTR pszThreadName, //!< [in] Имя потока, из которого записано сообщение.
70 LPCTSTR pszModule, //!< [in] Модуль, из которого записано сообщение.
71 LPCTSTR pszMessage //!< [in] Сообщение.
72 ) = 0;
73 //! Разрешает, исключает или модифицирует сообщение.
74 //! \return false - Сообщение игнорируется.
75 virtual bool Check(
76 ELogMessageType type, //!< [in] Тип сообщения.
77 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
78 LPCTSTR pszModule //!< [in] Модуль, из которого записано сообщения.
81 type; nLevel; pszModule;
82 return true;
84 //! Возвращает, работает ли лог.
85 //! Если лог был неудачно создан (например, кривое имя файла), узнать об этом можно здесь.
86 virtual bool IsWorking() const { return true; }
89 typedef std::shared_ptr<ILogMedia> LogMediaPtr;
91 //! Лог-заглушка.
92 class LogMediaProxy: public ILogMedia
94 public:
95 LogMediaProxy(const LogMediaPtr& pLog = LogMediaPtr());
96 ~LogMediaProxy();
97 void SetLog(const LogMediaPtr& pLog);
98 virtual void Write(ELogMessageType type, ELogMessageLevel nLevel, LPCTSTR pszDate, LPCTSTR pszTime, LPCTSTR pszThreadId, LPCTSTR pszThreadName, LPCTSTR pszModule, LPCTSTR pszMessage);
99 virtual bool Check(ELogMessageType type, ELogMessageLevel nLevel, LPCTSTR pszModule);
100 private:
101 LogMediaPtr m_pLog;
102 CriticalSection m_cs;
105 //! Компоновщик "физических" логов.
106 class LogMediaColl: public ILogMedia
108 typedef std::vector<LogMediaPtr> MediaColl;
109 public:
110 LogMediaColl();
111 ~LogMediaColl();
112 void Add(const LogMediaPtr& pMedia);
113 virtual void Write(ELogMessageType type, ELogMessageLevel nLevel, LPCTSTR pszDate, LPCTSTR pszTime, LPCTSTR pszThreadId, LPCTSTR pszThreadName, LPCTSTR pszModule, LPCTSTR pszMessage);
114 virtual bool Check(ELogMessageType type, ELogMessageLevel nLevel, LPCTSTR pszModule);
115 private:
116 MediaColl m_MediaColl;
117 CriticalSection m_cs;
120 //! Интерфейс фильтрации сообщений лога.
121 class IFilter
123 public:
124 virtual ~IFilter() {}
125 //! Разрешает, исключает или модифицирует сообщение.
126 //! \return false - Сообщение игнорируется.
127 virtual bool Check(
128 ELogMessageType& type, //!< [in/out] Тип сообщения.
129 ELogMessageLevel& nLevel, //!< [in/out] Уровень важности (L0 - наиболее важный).
130 LPCTSTR pszModule //!< [in] Модуль, из которого записано сообщения.
131 ) = 0;
134 typedef std::shared_ptr<IFilter> FilterPtr;
136 //! Фильтр по типу и уровню сообщения.
137 //! Разрешает сообщения более приоритетного типа и сообщения указанного типа с важностью не ниже указанной.
138 class TypeLevelFilter: public IFilter
140 ELogMessageType m_type;
141 ELogMessageLevel m_nLevel;
142 public:
143 //! Конструктор.
144 TypeLevelFilter(
145 ELogMessageType type = eLM_Info, //!< [in] Разрешает сообщения приоритетнee type.
146 ELogMessageLevel nLevel = LMAX //!< [in] Разрешает типа type с важностью не ниже nLevel.
147 ): m_type(type), m_nLevel(nLevel) {}
148 virtual bool Check(ELogMessageType& type, ELogMessageLevel& nLevel, LPCTSTR)
150 return type < m_type || (type == m_type && nLevel <= m_nLevel);
154 //! Фильтрующий лог.
155 class FilterLogMedia: public ILogMedia
157 typedef std::vector<FilterPtr> FilterColl;
158 public:
159 //! Конструктор.
160 FilterLogMedia(
161 const LogMediaPtr& pMedia //!< [in] Лог, на который накладывается фильтр.
163 virtual ~FilterLogMedia();
164 //! Добавляет фильтр.
165 void AddFilter(
166 FilterPtr pFilter //!< [in] Фильтр.
168 virtual void Write(ELogMessageType type, ELogMessageLevel nLevel, LPCTSTR pszDate, LPCTSTR pszTime, LPCTSTR pszThreadId, LPCTSTR pszThreadName, LPCTSTR pszModule, LPCTSTR pszMessage);
169 virtual bool Check(ELogMessageType type, ELogMessageLevel nLevel, LPCTSTR pszModule);
171 private:
172 LogMediaPtr m_pMedia;
173 FilterColl m_FilterColl;
174 CriticalSection m_cs;
177 //! Параметры создания лога.
178 struct LogParam
180 LogParam(
181 LogMediaPtr pMedia = LogMediaPtr(), //!< [in]
182 LPCTSTR pszModule = NULL //!< [in]
183 ): m_pMedia(pMedia), m_pszModule(pszModule) {}
184 LogMediaPtr m_pMedia;
185 LPCTSTR m_pszModule;
188 //! "Логический" лог.
189 class LogBase
191 public:
192 virtual ~LogBase();
193 //! Возврашает "физический" лог данного лога.
194 LogMediaPtr GetMedia() const throw() { return m_pMedia; }
196 //! Записывает форматированное сообщение.
197 void Write(
198 ELogMessageType type, //!< [in] Тип сообщения.
199 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
200 LPCTSTR pszMessage, //!< [in] Сообщение.
202 ) throw()
204 va_list ap;
205 va_start(ap, pszMessage);
206 WriteVA(type, nLevel, NULL, pszMessage, ap);
207 va_end(ap);
210 //! Записывает форматированное Unicode-сообщение.
211 void WriteW(
212 ELogMessageType type, //!< [in] Тип сообщения.
213 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
214 LPCWSTR pszModule, //!< [in] Имя модуля. (NULL - имя по умолчанию)
215 LPCWSTR pszMessage, //!< [in] Сообщение.
217 ) throw()
219 va_list ap;
220 va_start(ap, pszMessage);
221 WriteVAW(type, nLevel, pszModule, pszMessage, ap);
222 va_end(ap);
225 //! Записывает форматированное сообщение.
226 virtual void WriteVA(
227 ELogMessageType type, //!< [in] Тип сообщения.
228 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
229 LPCTSTR pszModule, //!< [in] Имя модуля. (NULL - имя по умолчанию)
230 LPCTSTR pszMessage, //!< [in] Сообщение.
231 va_list args
232 ) throw();
234 //! Записывает форматированное Unicode-сообщение.
235 virtual void WriteVAW(
236 ELogMessageType type, //!< [in] Тип сообщения.
237 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
238 LPCWSTR pszModule, //!< [in] Имя модуля. (NULL - имя по умолчанию)
239 LPCWSTR pszMessage, //!< [in] Сообщение.
240 va_list args
241 ) throw();
243 void Debug(LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Debug, L0, NULL, pszMessage, ap); va_end(ap); }
244 void Debug(ELogMessageLevel nLevel, LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Debug, nLevel, NULL, pszMessage, ap); va_end(ap); }
246 void Info(LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Info, L0, NULL, pszMessage, ap); va_end(ap); }
247 void Info(ELogMessageLevel nLevel, LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Info, nLevel, NULL, pszMessage, ap); va_end(ap); }
249 void Warning(LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Warning, L0, NULL, pszMessage, ap); va_end(ap); }
250 void Warning(ELogMessageLevel nLevel, LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Warning, nLevel, NULL, pszMessage, ap); va_end(ap); }
252 void Error(LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Error, L0, NULL, pszMessage, ap); va_end(ap); }
253 void Error(ELogMessageLevel nLevel, LPCTSTR pszMessage, ...) throw() { va_list ap; va_start(ap, pszMessage); WriteVA(eLM_Error, nLevel, NULL, pszMessage, ap); va_end(ap); }
255 //! Проверяет, попадёт ли это сообщение в лог.
256 bool IsFiltered(ELogMessageType type, ELogMessageLevel nLevel);
258 //! Устанавливает название потока.
259 static void SetThreadName(
260 LPCTSTR pszThreadName //!< [in] Имя потока. Указатель должен быть валидным в течении работы потока.
263 //! Возращает устанавленное название потока.
264 static LPCTSTR GetThreadName();
266 //! Возвращает "физический" лог приложения. (Представляет собой LogMediaProxy)
267 static LogMediaPtr GetAppLogMedia();
269 //! Устанавливает "физический" лог приложения.
270 static void SetAppLogMedia(LogMediaPtr pLog);
272 static LogMediaPtr CreateConsoleMedia();
274 static LogMediaPtr CreateFileMedia(
275 LPCTSTR pszFilename, //!< [in] Имя файла.
276 bool bAppend, //!< [in] Флаг добавления в конец.
277 bool bFlush = false, //!< [in] Флаг сброса на диск после каждого Write.
278 bool bNewFileDaily = false
281 enum EDebugMediaStartParams
283 DEBUGMEDIA_NORMAL = 0x1,
284 DEBUGMEDIA_FORCE = 0x2, //!< Создать даже если нет отладчика.
285 DEBUGMEDIA_REPORTERRORS = 0x4, //!< Выводить ошибки через _CrtDbgReport.
287 static LogMediaPtr CreateDebugMedia(
288 DWORD dwParam = DEBUGMEDIA_NORMAL //!< [in] Создать даже если нет отладчика.
291 /*! Создаёт лог из описания в реестре.
292 В указанном ключе могут находится следующие переменные:
293 REG_SZ "TraceHeader" - Первой строкой в лог будет добавлен этот текст
294 REG_SZ "TraceFile" - лог будет подключен к файлу, указанному в значении переменной
295 REG_DWORD "TraceFileAppend" (def: 1) - флаг дописывать в конец файла
296 REG_DWORD "TraceFileFlush" (def: 0) - флаг сброса на диск после каждой записи
297 REG_DWORD "TraceToApp" = 1 - лог будет подключен к логу приложения.
298 REG_DWORD "TraceToConsole" = 1 - лог будет подключен к окну консоли
299 REG_DWORD "TraceToDebug" = 1 - лог будет подключен к логу отладчика (Debug Output).
300 На все эти логи можно наложить фильтр.
301 Возможны следующие фильтры:
302 REG_SZ "TraceType" = ["debug"|"info"|"warning"|"error"] - тип, сообщения ниже которого отображаться не будут.
303 REG_DWORD "TraceLevel" = [0|1|2|...] - уровень типа TraceType, сообщения ниже которого отображаться не будут.
304 Если необходимо накладывать фильтры индивидуально для каждого лога, или необходимо
305 несколько логов одного типа (например, писать в два файла), то в указанном ключе
306 можно завести подключи "Trace1" "Trace2" и т.д. (должны идти последовательно начиная с 1)
307 в которых можно указать дополнительные логи и фильтры.
308 Фильтры в ключе влияют и на подключи тоже!
309 Пример:
310 HLKM\....\SomeComp
311 REG_SZ "TraceFile" = "c:\my.log"
312 HLKM\....\SomeComp\Trace1
313 REG_DWORD "TraceToDebug" = 1
314 REG_SZ "TraceType" = "warning"
315 REG_DWORD "TraceLevel" = 5
316 Означает: писать в файл всё, в дебаг все ошибки и предупреждения уровня 5 и ниже.
319 \return Лог, который можно передать в Log.
321 static LogMediaPtr CreateMediaFromRegistry(
322 HKEY hRoot, //!< [in] Корневой элемент реестра.
323 LPCTSTR pszPath, //!< [in] Путь от корневого элемента, до раздела, содержащего описание лога.
324 bool bAppLog = false //!< [in] Для лога приложения должен быть true. Также устанавливает лог приложения (SetAppLogMedia()).
327 protected:
328 //! Конструктор.
329 LogBase(
330 LogMediaPtr pMedia, //!< [in] Лог.
331 LPCTSTR pszModule //!< [in] Имя модуля.
333 LogMediaPtr m_pMedia;
334 std::basic_string<TCHAR> m_szModule;
337 class LocalLog: public LogBase
339 public:
340 //! Конструктор для под-компонента.
341 LocalLog(
342 const LogParam& param, //!< [in] Параметры создания лога.
343 LPCTSTR pszModule //!< [in] Имя модуля по умолчанию.
345 //! Конструктор.
346 LocalLog(
347 LogMediaPtr pMedia, //!< [in] Лог.
348 LPCTSTR pszModule //!< [in] Имя модуля.
350 //! Конструктор.
351 LocalLog(
352 const LogBase& log, //!< [in] Лог.
353 LPCTSTR pszModule //!< [in] Имя модуля.
355 virtual ~LocalLog();
358 class Log: public LogBase
360 public:
361 //! Конструктор для под-компонента.
362 Log(
363 const LogParam& param, //!< [in] Параметры создания лога.
364 LPCTSTR pszModule //!< [in] Имя модуля по умолчанию.
366 //! Конструктор для главного лога приложения или компонента.
367 Log(
368 LogMediaPtr pMedia, //!< [in] Лог.
369 LPCTSTR pszModule //!< [in] Имя модуля.
371 //! Конструктор для под-компонента.
372 Log(
373 const LogBase& log, //!< [in] Лог.
374 LPCTSTR pszModule //!< [in] Имя модуля.
376 virtual ~Log();
377 void SetParams(
378 LogMediaPtr pMedia, //!< [in] Новый лог.
379 LPCTSTR pszModule = NULL //!< [in] Новое имя модуля. Может быть NULL.
381 //! Записывает форматированное сообщение.
382 virtual void WriteVA(
383 ELogMessageType type, //!< [in] Тип сообщения.
384 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
385 LPCTSTR pszModule, //!< [in] Имя модуля.
386 LPCTSTR pszMessage, //!< [in] Сообщение.
387 va_list args
388 ) throw();
389 //! Записывает форматированное Unicode-сообщение.
390 virtual void WriteVAW(
391 ELogMessageType type, //!< [in] Тип сообщения.
392 ELogMessageLevel nLevel,//!< [in] Уровень важности (L0 - наиболее важный).
393 LPCWSTR pszModule, //!< [in] Имя модуля.
394 LPCWSTR pszMessage, //!< [in] Сообщение.
395 va_list args
396 ) throw();
397 private:
398 CriticalSection m_cs;
402 //! "Логический" лог с фильтрацией.
403 class FilterLog: public Log
405 typedef std::shared_ptr<FilterLogMedia> TFilterLogMediaPtr;
406 TFilterLogMediaPtr GetFilterLogMedia() { return std::static_pointer_cast<FilterLogMedia>(GetMedia()); }
407 public:
408 FilterLog(const LogParam& param, LPCTSTR pszModule): Log(param, pszModule)
410 LogMediaPtr pMedia = GetMedia();
411 if (pMedia)
412 SetParams(LogMediaPtr(new FilterLogMedia(pMedia)));
414 virtual ~FilterLog();
415 void AddFilter(FilterPtr pFilter) { if (GetFilterLogMedia()) GetFilterLogMedia()->AddFilter(pFilter); }
418 #endif