1 // Copyright 2014 Idol Software, Inc.
3 // This file is part of Doctor Dump SDK.
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.
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/>.
29 #pragma warning (disable: 4251) // need dll-linkage
32 void FreeLogThreadName();
33 void SetLogThreadName(LPCTSTR pszThreadName
);
38 eLM_Error
, //!< "Ошибка" - произошёл сбой в работе, дальнейшее выполнение текущего действия невозможно.
39 eLM_Warning
, //!< "Предупреждение" - произошёл сбой в работе, который удалось исправить.
40 eLM_Info
, //!< "Информация" - сообщение о выполнении некоторого действия программой.
41 eLM_Debug
, //!< "Отладка" - сообщение, содержащее отладочную информацию.
42 eLM_DirectOutput
//!< Перенаправление в лог вывода внешнего консольного приложения
45 //! Уровень важности сообщений.
48 L0
= 0, //!< Наиболее важный.
57 //! Интерфейс "физического" лога. Осуществляет запись на носитель.
61 virtual ~ILogMedia() {}
62 //! Записывает сообщение.
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] Сообщение.
73 //! Разрешает, исключает или модифицирует сообщение.
74 //! \return false - Сообщение игнорируется.
76 ELogMessageType type
, //!< [in] Тип сообщения.
77 ELogMessageLevel nLevel
,//!< [in] Уровень важности (L0 - наиболее важный).
78 LPCTSTR pszModule
//!< [in] Модуль, из которого записано сообщения.
81 type
; nLevel
; pszModule
;
84 //! Возвращает, работает ли лог.
85 //! Если лог был неудачно создан (например, кривое имя файла), узнать об этом можно здесь.
86 virtual bool IsWorking() const { return true; }
89 typedef std::shared_ptr
<ILogMedia
> LogMediaPtr
;
92 class LogMediaProxy
: public ILogMedia
95 LogMediaProxy(const LogMediaPtr
& pLog
= LogMediaPtr());
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
);
102 CriticalSection m_cs
;
105 //! Компоновщик "физических" логов.
106 class LogMediaColl
: public ILogMedia
108 typedef std::vector
<LogMediaPtr
> MediaColl
;
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
);
116 MediaColl m_MediaColl
;
117 CriticalSection m_cs
;
120 //! Интерфейс фильтрации сообщений лога.
124 virtual ~IFilter() {}
125 //! Разрешает, исключает или модифицирует сообщение.
126 //! \return false - Сообщение игнорируется.
128 ELogMessageType
& type
, //!< [in/out] Тип сообщения.
129 ELogMessageLevel
& nLevel
, //!< [in/out] Уровень важности (L0 - наиболее важный).
130 LPCTSTR pszModule
//!< [in] Модуль, из которого записано сообщения.
134 typedef std::shared_ptr
<IFilter
> FilterPtr
;
136 //! Фильтр по типу и уровню сообщения.
137 //! Разрешает сообщения более приоритетного типа и сообщения указанного типа с важностью не ниже указанной.
138 class TypeLevelFilter
: public IFilter
140 ELogMessageType m_type
;
141 ELogMessageLevel m_nLevel
;
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
);
155 class FilterLogMedia
: public ILogMedia
157 typedef std::vector
<FilterPtr
> FilterColl
;
161 const LogMediaPtr
& pMedia
//!< [in] Лог, на который накладывается фильтр.
163 virtual ~FilterLogMedia();
164 //! Добавляет фильтр.
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
);
172 LogMediaPtr m_pMedia
;
173 FilterColl m_FilterColl
;
174 CriticalSection m_cs
;
177 //! Параметры создания лога.
181 LogMediaPtr pMedia
= LogMediaPtr(), //!< [in]
182 LPCTSTR pszModule
= NULL
//!< [in]
183 ): m_pMedia(pMedia
), m_pszModule(pszModule
) {}
184 LogMediaPtr m_pMedia
;
188 //! "Логический" лог.
193 //! Возврашает "физический" лог данного лога.
194 LogMediaPtr
GetMedia() const throw() { return m_pMedia
; }
196 //! Записывает форматированное сообщение.
198 ELogMessageType type
, //!< [in] Тип сообщения.
199 ELogMessageLevel nLevel
,//!< [in] Уровень важности (L0 - наиболее важный).
200 LPCTSTR pszMessage
, //!< [in] Сообщение.
205 va_start(ap
, pszMessage
);
206 WriteVA(type
, nLevel
, NULL
, pszMessage
, ap
);
210 //! Записывает форматированное Unicode-сообщение.
212 ELogMessageType type
, //!< [in] Тип сообщения.
213 ELogMessageLevel nLevel
,//!< [in] Уровень важности (L0 - наиболее важный).
214 LPCWSTR pszModule
, //!< [in] Имя модуля. (NULL - имя по умолчанию)
215 LPCWSTR pszMessage
, //!< [in] Сообщение.
220 va_start(ap
, pszMessage
);
221 WriteVAW(type
, nLevel
, pszModule
, pszMessage
, ap
);
225 //! Записывает форматированное сообщение.
226 virtual void WriteVA(
227 ELogMessageType type
, //!< [in] Тип сообщения.
228 ELogMessageLevel nLevel
,//!< [in] Уровень важности (L0 - наиболее важный).
229 LPCTSTR pszModule
, //!< [in] Имя модуля. (NULL - имя по умолчанию)
230 LPCTSTR pszMessage
, //!< [in] Сообщение.
234 //! Записывает форматированное Unicode-сообщение.
235 virtual void WriteVAW(
236 ELogMessageType type
, //!< [in] Тип сообщения.
237 ELogMessageLevel nLevel
,//!< [in] Уровень важности (L0 - наиболее важный).
238 LPCWSTR pszModule
, //!< [in] Имя модуля. (NULL - имя по умолчанию)
239 LPCWSTR pszMessage
, //!< [in] Сообщение.
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 Фильтры в ключе влияют и на подключи тоже!
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()).
330 LogMediaPtr pMedia
, //!< [in] Лог.
331 LPCTSTR pszModule
//!< [in] Имя модуля.
333 LogMediaPtr m_pMedia
;
334 std::basic_string
<TCHAR
> m_szModule
;
337 class LocalLog
: public LogBase
340 //! Конструктор для под-компонента.
342 const LogParam
& param
, //!< [in] Параметры создания лога.
343 LPCTSTR pszModule
//!< [in] Имя модуля по умолчанию.
347 LogMediaPtr pMedia
, //!< [in] Лог.
348 LPCTSTR pszModule
//!< [in] Имя модуля.
352 const LogBase
& log
, //!< [in] Лог.
353 LPCTSTR pszModule
//!< [in] Имя модуля.
358 class Log
: public LogBase
361 //! Конструктор для под-компонента.
363 const LogParam
& param
, //!< [in] Параметры создания лога.
364 LPCTSTR pszModule
//!< [in] Имя модуля по умолчанию.
366 //! Конструктор для главного лога приложения или компонента.
368 LogMediaPtr pMedia
, //!< [in] Лог.
369 LPCTSTR pszModule
//!< [in] Имя модуля.
371 //! Конструктор для под-компонента.
373 const LogBase
& log
, //!< [in] Лог.
374 LPCTSTR pszModule
//!< [in] Имя модуля.
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] Сообщение.
389 //! Записывает форматированное Unicode-сообщение.
390 virtual void WriteVAW(
391 ELogMessageType type
, //!< [in] Тип сообщения.
392 ELogMessageLevel nLevel
,//!< [in] Уровень важности (L0 - наиболее важный).
393 LPCWSTR pszModule
, //!< [in] Имя модуля.
394 LPCWSTR pszMessage
, //!< [in] Сообщение.
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()); }
408 FilterLog(const LogParam
& param
, LPCTSTR pszModule
): Log(param
, pszModule
)
410 LogMediaPtr pMedia
= GetMedia();
412 SetParams(LogMediaPtr(new FilterLogMedia(pMedia
)));
414 virtual ~FilterLog();
415 void AddFilter(FilterPtr pFilter
) { if (GetFilterLogMedia()) GetFilterLogMedia()->AddFilter(pFilter
); }