Index: src/ch/AsyncHttpFile.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/AsyncHttpFile.cpp	(.../AsyncHttpFile.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/ch/AsyncHttpFile.cpp	(.../AsyncHttpFile.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -353,11 +353,12 @@
 	if(!pRequest || !pRequest->pHttpFile)
 		return;
 
+	chcore::TLoggerPtr spLog = GetLogFactory()->CreateLogger(L"AsyncHttpFile");
 	CString strMsg;
 	strMsg.Format(_T("[CAsyncHttpFile::InternetStatusCallback] hInternet: %p, dwContext: %Iu (operation: %lu), dwInternetStatus: %lu, lpvStatusInformation: %p, dwStatusInformationLength: %lu\n"),
 		hInternet, (size_t)dwContext, pRequest->eOperationType, dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
 	ATLTRACE(L"%s\n", strMsg);
-	LOG_DEBUG(GetLogger()) << strMsg;
+	LOG_DEBUG(spLog) << strMsg;
 
 	switch(dwInternetStatus)
 	{
@@ -400,7 +401,6 @@
 	pRequest->pHttpFile->SetCompletionStatus(dwInternetStatus);
 }
 
-
 // ============================================================================
 /// CAsyncHttpFile::SetUrlHandle
 /// @date 2009/04/18
Index: src/ch/MainWnd.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -80,7 +80,8 @@
 /////////////////////////////////////////////////////////////////////////////
 // CMainWnd construction/destruction
 CMainWnd::CMainWnd() :
-	m_spTaskMgrStats(new chcore::TTaskManagerStatsSnapshot)
+	m_spTaskMgrStats(new chcore::TTaskManagerStatsSnapshot),
+	m_spLog(GetLogFactory()->CreateLogger(L"MainWnd"))
 {
 }
 
@@ -188,7 +189,7 @@
 
 		if(!LoadTaskManager())
 		{
-			LOG_ERROR(GetLogger()) << _T("Couldn't load task manager data. User did not allow re-creation of the database.");
+			LOG_ERROR(m_spLog) << _T("Couldn't load task manager data. User did not allow re-creation of the database.");
 			return -1;
 		}
 
@@ -200,7 +201,7 @@
 		m_spTasks->TasksRetryProcessing();
 
 		// start clipboard monitoring
-		LOG_INFO(GetLogger()) << _T("Starting clipboard monitor...");
+		LOG_INFO(m_spLog) << _T("Starting clipboard monitor...");
 		CClipboardMonitor::StartMonitor(m_spTasks);
 
 		CheckForUpdates();
@@ -229,7 +230,7 @@
 
 	if(bCaughtError)
 	{
-		LOG_ERROR(GetLogger()) << szErrInfo.get();
+		LOG_ERROR(m_spLog) << szErrInfo.get();
 		return -1;
 	}
 	return 0;
@@ -243,10 +244,11 @@
 	CString strTasksDir = GetTasksDirectory();
 	TSQLiteSerializerFactoryPtr spSerializerFactory(new TSQLiteSerializerFactory(PathFromString(strTasksDir)));
 	IFeedbackHandlerFactoryPtr spFeedbackFactory(new CFeedbackHandlerFactory);
+	TMultiLoggerConfigPtr spLoggerConfig = std::make_shared<TMultiLoggerConfig>();	// #todo
 
 	try
 	{
-		m_spTasks.reset(new chcore::TTaskManager(spSerializerFactory, spFeedbackFactory, PathFromString(strTasksDir)));
+		m_spTasks.reset(new chcore::TTaskManager(spSerializerFactory, spFeedbackFactory, PathFromString(strTasksDir), spLoggerConfig));
 	}
 	catch(const std::exception& e)
 	{
@@ -257,14 +259,14 @@
 	{
 		if(MsgBox(IDS_TASKMANAGER_LOAD_FAILED, MB_ICONERROR | MB_OKCANCEL) == IDOK)
 		{
-			m_spTasks.reset(new chcore::TTaskManager(spSerializerFactory, spFeedbackFactory, PathFromString(strTasksDir), true));
+			m_spTasks.reset(new chcore::TTaskManager(spSerializerFactory, spFeedbackFactory, PathFromString(strTasksDir), spLoggerConfig, true));
 		}
 		else
 			return false;
 	}
 
 	// load last state
-	LOG_INFO(GetLogger()) << _T("Loading existing tasks...");
+	LOG_INFO(m_spLog) << _T("Loading existing tasks...");
 
 	// load tasks
 	m_spTasks->Load();
@@ -405,7 +407,7 @@
 
 	if(!strMessage.IsEmpty())
 	{
-		LOG_ERROR(GetLogger()) << L"Failed to finalize tasks before exiting Copy Handler. Error: " + strMessage;
+		LOG_ERROR(m_spLog) << L"Failed to finalize tasks before exiting Copy Handler. Error: " + strMessage;
 
 		ictranslate::CFormat fmt;
 
@@ -437,7 +439,7 @@
 				fmt.SetFormat(_T("Failed to autosave task. Error: %err."));
 				fmt.SetParam(_T("%err"), (PCTSTR)strError);
 
-				LOG_ERROR(GetLogger()) << fmt;
+				LOG_ERROR(m_spLog) << fmt;
 			}
 
 			SetTimer(1023, GetPropValue<PP_PAUTOSAVEINTERVAL>(GetConfig()), nullptr);
@@ -518,7 +520,7 @@
 				fmt.SetParam(_T("%xml"), wstrData.c_str());
 				fmt.SetParam(_T("%err"), (PCTSTR)strError);
 
-				LOG_ERROR(GetLogger()) << fmt;
+				LOG_ERROR(m_spLog) << fmt;
 
 				fmt.SetFormat(GetResManager().LoadString(IDS_SHELLEXT_XML_IMPORT_FAILED));
 				fmt.SetParam(_T("%err"), (PCTSTR)strError);
@@ -628,7 +630,7 @@
 				fmt.SetParam(_T("%path"), strPath.ToString());
 				fmt.SetParam(_T("%err"), szBuffer.get());
 
-				LOG_ERROR(GetLogger()) << fmt;
+				LOG_ERROR(m_spLog) << fmt;
 
 				fmt.SetFormat(GetResManager().LoadString(IDS_TASK_IMPORT_FAILED));
 				fmt.SetParam(_T("%path"), strPath.ToString());
@@ -899,7 +901,7 @@
 				_ASSERTE(FALSE);
 				CString strMsg;
 				strMsg.Format(L"Encountered problem trying to retrieve shell ext configuration.\nReason: %S", e.what());
-				LOG_ERROR(GetLogger()) << strMsg;
+				LOG_ERROR(m_spLog) << strMsg;
 
 				return FALSE;
 			}
@@ -1062,7 +1064,7 @@
 		// perform checking for updates only when the minimal interval has passed
 		if(ullCurrentStamp - ullTimestamp >= ullMinInterval)
 		{
-			LOG_INFO(GetLogger()) << _T("Checking for updates...");
+			LOG_INFO(m_spLog) << _T("Checking for updates...");
 
 			CUpdaterDlg* pDlg = new CUpdaterDlg(true);
 			pDlg->m_bAutoDelete = true;
@@ -1076,7 +1078,7 @@
 			}
 			catch(const std::exception& /*e*/)
 			{
-				LOG_ERROR(GetLogger()) << _T("Storing last update check timestamp in configuration failed");
+				LOG_ERROR(m_spLog) << _T("Storing last update check timestamp in configuration failed");
 			}
 		}
 	}
Index: src/ch/MainWnd.h
===================================================================
diff -u -N -r4fe995b304ea342b50293f92d3c1992b43b820f7 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/MainWnd.h	(.../MainWnd.h)	(revision 4fe995b304ea342b50293f92d3c1992b43b820f7)
+++ src/ch/MainWnd.h	(.../MainWnd.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -86,6 +86,8 @@
 
 	DWORD m_dwLastTime = 0;
 	UINT m_uiTaskbarRestart = 0;
+
+	chcore::TLoggerPtr m_spLog;
 };
 
 #endif
Index: src/ch/UpdaterDlg.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/UpdaterDlg.cpp	(.../UpdaterDlg.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/ch/UpdaterDlg.cpp	(.../UpdaterDlg.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -23,15 +23,14 @@
 	ON_WM_TIMER()
 END_MESSAGE_MAP()
 
-
 // CUpdaterDlg dialog
-
 IMPLEMENT_DYNAMIC(CUpdaterDlg, ictranslate::CLanguageDialog)
 
 CUpdaterDlg::CUpdaterDlg(bool bBackgroundMode, CWnd* pParent /*=nullptr*/) :
 	ictranslate::CLanguageDialog(IDD_UPDATER_DIALOG, pParent),
 	m_eLastState(CUpdateChecker::eResult_Undefined),
-	m_bBackgroundMode(bBackgroundMode)
+	m_bBackgroundMode(bBackgroundMode),
+	m_spLog(GetLogFactory()->CreateLogger(L"UpdaterDlg"))
 {
 	RegisterStaticExControl(AfxGetInstanceHandle());
 }
@@ -87,13 +86,13 @@
 	{
 		CString str;
 		str.Format(_T("Opening a browser with address %s..."), (PCTSTR)strDownloadAddr);
-		LOG_DEBUG(GetLogger()) << str;
+		LOG_DEBUG(m_spLog) << str;
 
 		str.Format(_T("url.dll,FileProtocolHandler %s"), (PCTSTR)strDownloadAddr);
 		ULONG_PTR ulRes = (ULONG_PTR)ShellExecute(nullptr, _T("open"), _T("rundll32.exe"), str, nullptr, SW_SHOW);
 
 		str.Format(_T("ShellExecute returned %I64u"), (unsigned long long)ulRes);
-		LOG_DEBUG(GetLogger()) << str;
+		LOG_DEBUG(m_spLog) << str;
 
 		// close the dialog if succeeded; 32 is some arbitrary value from ms docs
 		if(ulRes > 32)
@@ -389,7 +388,7 @@
 
 	if(!strError.IsEmpty())
 	{
-		LOG_ERROR(GetLogger()) << strError;
+		LOG_ERROR(m_spLog) << strError;
 	}
 }
 
Index: src/ch/UpdaterDlg.h
===================================================================
diff -u -N -r8068e0c351055554340ac9755d1bc846893bf2b8 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/UpdaterDlg.h	(.../UpdaterDlg.h)	(revision 8068e0c351055554340ac9755d1bc846893bf2b8)
+++ src/ch/UpdaterDlg.h	(.../UpdaterDlg.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -58,5 +58,8 @@
 
 	CUpdateChecker m_ucChecker;
 	CUpdateChecker::ECheckResult m_eLastState;
+
 	bool m_bBackgroundMode;		///< Do we operate in standard mode (false), or in background mode (true)
+
+	chcore::TLoggerPtr m_spLog;
 };
Index: src/ch/ch.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/ch.cpp	(.../ch.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/ch/ch.cpp	(.../ch.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -98,8 +98,7 @@
 }
 
 CCopyHandlerApp::CCopyHandlerApp() :
-	m_pMainWindow(nullptr),
-	m_log(L"CH")
+	m_pMainWindow(nullptr)
 {
 	// this is the one-instance application
 	InitProtection();
@@ -301,37 +300,43 @@
 	// read the configuration
 	try
 	{
-		GetConfig().Read(strCfgPath);
+		rCfg.Read(strCfgPath);
 	}
 	catch(...)
 	{
 	}
 
 	// ================================= Logging ========================================
+	m_logInitializer.Init(5, 1 * 1024 * 1024);	// #todo
+	m_chEngine.Init(5, 1 * 1024 * 1024);
+
+	chcore::TMultiLoggerConfigPtr spLoggerConfig = std::make_shared<chcore::TMultiLoggerConfig>();	// #todo
+
 	// initialize the global log file if it is requested by configuration file
 	CString strLogPath = strPath + _T("\\ch.log");
 
-	m_log.SetLogPath(strLogPath);
+	m_spLogFactory.reset(new chcore::TLoggerFactory(chcore::PathFromString(strLogPath), spLoggerConfig));
+	m_spLog = m_spLogFactory->CreateLogger(L"App");
 
-	LOG_INFO(m_log) << _T("============================ Initializing Copy Handler ============================");
-	LOG_INFO(m_log) << _T("");
+	LOG_INFO(m_spLog) << _T("============================ Initializing Copy Handler ============================");
+	LOG_INFO(m_spLog) << _T("");
 
 	// ================================= COM ========================================
-	LOG_INFO(m_log) << _T("Initializing COM");
+	LOG_INFO(m_spLog) << _T("Initializing COM");
 
 	HRESULT hResult = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
 	if(FAILED(hResult))
 	{
 		CString strMsg;
 		strMsg.Format(_T("Cannot initialize COM, the application will now exit (result = 0x%lx)"), hResult);
 
-		LOG_ERROR(m_log) << strMsg;
+		LOG_ERROR(m_spLog) << strMsg;
 		AfxMessageBox(strMsg, MB_ICONERROR | MB_OK);
 		return FALSE;
 	}
 
 	// ================================= Resource manager ========================================
-	LOG_INFO(m_log) << _T("Initializing resource manager...");
+	LOG_INFO(m_spLog) << _T("Initializing resource manager...");
 
 	ictranslate::CResourceManager& rResManager = ictranslate::CResourceManager::Acquire();
 
@@ -344,7 +349,7 @@
 	{
 		TCHAR szData[2048];
 		_sntprintf(szData, 2048, _T("Couldn't find the language file specified in configuration file:\n%s\nPlease correct this path to point the language file to use.\nProgram will now exit."), (PCTSTR)strPath);
-		LOG_ERROR(m_log) << szData;
+		LOG_ERROR(m_spLog) << szData;
 		AfxMessageBox(szData, MB_ICONSTOP | MB_OK);
 		return FALSE;
 	}
@@ -369,7 +374,7 @@
 
 	// ================================= Checking for running instances of CH ========================================
 	// check instance - return false if it's the second one
-	LOG_INFO(m_log) << _T("Checking for other running instances of Copy Handler");
+	LOG_INFO(m_spLog) << _T("Checking for other running instances of Copy Handler");
 	if(!IsFirstInstance())
 	{
 		// if there is a command line specified, send it to the existing instance
@@ -379,7 +384,7 @@
 			if(hWnd == nullptr)
 			{
 				// cannot pass command line to running ch
-				LOG_ERROR(m_log) << _T("Cannot determine running CH's window. Cannot pass command line there.");
+				LOG_ERROR(m_spLog) << _T("Cannot determine running CH's window. Cannot pass command line there.");
 				MsgBox(IDS_COMMAND_LINE_FAILED_STRING, MB_OK | MB_ICONERROR);
 				return FALSE;
 			}
@@ -394,22 +399,22 @@
 			// send a message to ch
 			if(::SendMessage(hWnd, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cds)) == 0)
 			{
-				LOG_ERROR(m_log) << _T("Command line was not processed properly at the running CH's instance.");
+				LOG_ERROR(m_spLog) << _T("Command line was not processed properly at the running CH's instance.");
 				MsgBox(IDS_COMMAND_LINE_FAILED_STRING, MB_OK | MB_ICONERROR);
 			}
 
 			return FALSE;
 		}
 		else
 		{
-			LOG_WARNING(m_log) << _T("Other instance of Copy Handler is already running. Exiting.");
+			LOG_WARNING(m_spLog) << _T("Other instance of Copy Handler is already running. Exiting.");
 			MsgBox(IDS_ONECOPY_STRING, MB_OK | MB_ICONWARNING);
 			return FALSE;
 		}
 	}
 
 	// ================================= Common controls ========================================
-	LOG_INFO(m_log) << _T("Initializing GUI common controls");
+	LOG_INFO(m_spLog) << _T("Initializing GUI common controls");
 
 	// InitCommonControlsEx() is required on Windows XP if an application
 	// manifest specifies use of ComCtl32.dll version 6 or later to enable
@@ -421,25 +426,25 @@
 	InitCtrls.dwICC = ICC_WIN95_CLASSES;
 	if(!InitCommonControlsEx(&InitCtrls))
 	{
-		LOG_ERROR(m_log) << _T("Cannot initialize common controls.");
+		LOG_ERROR(m_spLog) << _T("Cannot initialize common controls.");
 		MsgBox(IDS_ERROR_INITIALIZING_COMMON_CONTROLS, MB_OK | MB_ICONERROR);
 		return FALSE;
 	}
 
 	if(!AfxInitRichEdit2())
 	{
-		LOG_ERROR(m_log) << _T("Cannot initialize rich edit control.");
+		LOG_ERROR(m_spLog) << _T("Cannot initialize rich edit control.");
 		MsgBox(IDS_ERROR_INITIALIZING_RICH_EDIT_CONTROL, MB_OK | MB_ICONERROR);
 		return FALSE;
 	}
 
 	// ================================= Shell extension ========================================
-	LOG_INFO(m_log) << _T("Checking shell extension compatibility");
+	LOG_INFO(m_spLog) << _T("Checking shell extension compatibility");
 
 	InitShellExtension();
 
 	// ================================= Initial settings ========================================
-	LOG_INFO(m_log) << _T("Applying initial settings");
+	LOG_INFO(m_spLog) << _T("Applying initial settings");
 
 	// set this process priority class
 	HANDLE hProcess = GetCurrentProcess();
@@ -451,7 +456,7 @@
 #endif
 
 	// ================================= Main window ========================================
-	LOG_INFO(m_log) << _T("Creating main application window");
+	LOG_INFO(m_spLog) << _T("Creating main application window");
 	// create main window
 	m_pMainWindow=new CMainWnd;
 	if (!((CMainWnd*)m_pMainWindow)->Create())
@@ -460,7 +465,7 @@
 	m_pMainWnd = m_pMainWindow;
 	CWinApp::InitInstance();
 
-	LOG_INFO(m_log) << _T("Copy Handler initialized successfully");
+	LOG_INFO(m_spLog) << _T("Copy Handler initialized successfully");
 
 	return TRUE;
 #endif
@@ -509,7 +514,7 @@
 	{
 		CString strMsg;
 		strMsg.Format(_T("Shell extension is not registered."));
-		LOG_WARNING(m_log) << strMsg;
+		LOG_WARNING(m_spLog) << strMsg;
 
 		switch(iDoNotShowAgain_Unregistered)
 		{
@@ -534,7 +539,7 @@
 	{
 		CString strMsg;
 		strMsg.Format(_T("Shell extension has different version (0x%lx) than Copy Handler (0x%lx)."), (unsigned long)lExtensionVersion, (unsigned long)(PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4));
-		LOG_WARNING(m_log) << strMsg;
+		LOG_WARNING(m_spLog) << strMsg;
 
 		switch(iDoNotShowAgain_VersionMismatch)
 		{
@@ -567,9 +572,9 @@
 	}
 }
 
-TLogger& CCopyHandlerApp::GetLogger()
+chcore::TLoggerFactoryPtr CCopyHandlerApp::GetLogFactory()
 {
-	return m_log;
+	return m_spLogFactory;
 }
 
 void CCopyHandlerApp::RegisterShellExtension() 
@@ -602,7 +607,7 @@
 		// registered ok, but incompatible versions - probably restart required
 		CString strMsg;
 		strMsg.Format(_T("Registration succeeded, but still the shell extension has different version (0x%lx) than Copy Handler (0x%lx)."), (unsigned long)lExtensionVersion, (unsigned long)(PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4));
-		LOG_WARNING(m_log) << strMsg;
+		LOG_WARNING(m_spLog) << strMsg;
 
 		MsgBox(IDS_SHELL_EXTENSION_REGISTERED_MISMATCH_STRING, MB_ICONWARNING | MB_OK);
 	}
@@ -753,14 +758,14 @@
 
 int CCopyHandlerApp::ExitInstance()
 {
-	LOG_INFO(m_log) << _T("Pre-exit step - releasing shell extension");
+	LOG_INFO(m_spLog) << _T("Pre-exit step - releasing shell extension");
 
 	m_tShellExtClient.Close();
 
-	LOG_INFO(m_log) << _T("Pre-exit step - uninitializing COM");
+	LOG_INFO(m_spLog) << _T("Pre-exit step - uninitializing COM");
 	CoUninitialize();
 
-	LOG_INFO(m_log) << _T("============================ Leaving Copy Handler ============================");
+	LOG_INFO(m_spLog) << _T("============================ Leaving Copy Handler ============================");
 
 	return __super::ExitInstance();
 }
Index: src/ch/ch.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/ch.h	(.../ch.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/ch/ch.h	(.../ch.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -27,6 +27,7 @@
 #include "../common/TLogger.h"
 #include "../common/TLoggerInitializer.h"
 #include "../libchcore/TCoreEngine.h"
+#include "../common/TLoggerFactory.h"
 
 class CCopyHandlerApp : public CWinApp, public CAppHelper
 {
@@ -47,7 +48,7 @@
 	static ictranslate::CResourceManager& GetResManager();
 	static chcore::TConfig& GetConfig();
 
-	TLogger& GetLogger();
+	chcore::TLoggerFactoryPtr GetLogFactory();
 
 	void RegisterShellExtension();
 	void UnregisterShellExtension();
@@ -70,7 +71,8 @@
 
 	chcore::TCoreEngine m_chEngine;
 	TLoggerInitializer m_logInitializer;
-	TLogger m_log;
+	chcore::TLoggerFactoryPtr m_spLogFactory;
+	chcore::TLoggerPtr m_spLog;
 
 	CWnd *m_pMainWindow;
 
@@ -82,9 +84,9 @@
 	return GetApplication();
 }
 
-inline TLogger& GetLogger()
+inline chcore::TLoggerFactoryPtr GetLogFactory()
 {
-	return GetApp().GetLogger();
+	return GetApp().GetLogFactory();
 }
 
 inline ictranslate::CResourceManager& GetResManager()
Index: src/ch/ch.vc140.vcxproj
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/ch.vc140.vcxproj	(.../ch.vc140.vcxproj)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/ch/ch.vc140.vcxproj	(.../ch.vc140.vcxproj)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -511,8 +511,15 @@
     <ClInclude Include="..\Common\ipcstructs.h" />
     <ClInclude Include="..\common\targetver.h" />
     <ClInclude Include="..\common\TLogger.h" />
+    <ClInclude Include="..\common\TLoggerFactory.h" />
     <ClInclude Include="..\common\TLoggerInitializer.h" />
+    <ClInclude Include="..\common\TLoggerLevelConfig.h" />
+    <ClInclude Include="..\common\TLoggerLocationConfig.h" />
+    <ClInclude Include="..\common\TLogRotator.h" />
+    <ClInclude Include="..\common\TLogSink.h" />
+    <ClInclude Include="..\common\TLogSinkCollection.h" />
     <ClInclude Include="..\common\TMultiFileBackend.h" />
+    <ClInclude Include="..\common\TMultiLoggerConfig.h" />
     <ClInclude Include="..\common\TShellExtMenuConfig.h" />
     <ClInclude Include="..\common\version.h" />
     <ClInclude Include="AsyncHttpFile.h" />
@@ -775,8 +782,15 @@
       <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4512;4714</DisableSpecificWarnings>
       <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">4512;4714</DisableSpecificWarnings>
     </ClCompile>
+    <ClCompile Include="..\common\TLoggerFactory.cpp" />
     <ClCompile Include="..\common\TLoggerInitializer.cpp" />
+    <ClCompile Include="..\common\TLoggerLevelConfig.cpp" />
+    <ClCompile Include="..\common\TLoggerLocationConfig.cpp" />
+    <ClCompile Include="..\common\TLogRotator.cpp" />
+    <ClCompile Include="..\common\TLogSink.cpp" />
+    <ClCompile Include="..\common\TLogSinkCollection.cpp" />
     <ClCompile Include="..\common\TMultiFileBackend.cpp" />
+    <ClCompile Include="..\common\TMultiLoggerConfig.cpp" />
     <ClCompile Include="..\common\TShellExtMenuConfig.cpp" />
     <ClCompile Include="AsyncHttpFile.cpp" />
     <ClCompile Include="CDragDropComboEx.cpp" />
Index: src/ch/ch.vc140.vcxproj.filters
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/ch/ch.vc140.vcxproj.filters	(.../ch.vc140.vcxproj.filters)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/ch/ch.vc140.vcxproj.filters	(.../ch.vc140.vcxproj.filters)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -257,6 +257,27 @@
     <ClInclude Include="..\common\TMultiFileBackend.h">
       <Filter>Source Files\Shared\Logging</Filter>
     </ClInclude>
+    <ClInclude Include="..\common\TLogRotator.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLogSink.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLogSinkCollection.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLoggerFactory.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLoggerLevelConfig.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLoggerLocationConfig.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TMultiLoggerConfig.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\common\TShellExtMenuConfig.cpp">
@@ -439,6 +460,27 @@
     <ClCompile Include="..\common\TMultiFileBackend.cpp">
       <Filter>Source Files\Shared\Logging</Filter>
     </ClCompile>
+    <ClCompile Include="..\common\TLogRotator.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLogSink.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLogSinkCollection.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLoggerFactory.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLoggerLevelConfig.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLoggerLocationConfig.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TMultiLoggerConfig.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\ch.rc2">
Index: src/common/TLogRotator.cpp
===================================================================
diff -u -N
--- src/common/TLogRotator.cpp	(revision 0)
+++ src/common/TLogRotator.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,96 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TLogRotator.h"
+#include <boost\date_time\posix_time\ptime.hpp>
+#include <boost\date_time\posix_time\posix_time_io.hpp>
+#include "..\libchcore\TString.h"
+#include "TLogSinkCollection.h"
+#include "..\libchcore\TFileException.h"
+
+namespace chcore
+{
+	TLogRotator::TLogRotator(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize) :
+		m_uiMaxRotatedFiles(uiMaxRotatedFiles),
+		m_ullMaxLogSize(ullMaxLogSize)
+	{
+	}
+
+	void TLogRotator::SetLimits(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize)
+	{
+		m_uiMaxRotatedFiles = uiMaxRotatedFiles;
+		m_ullMaxLogSize = ullMaxLogSize;
+	}
+
+	void TLogRotator::RotateFile(const TSmartPath& pathLog, TLogSink& sinkData, size_t stRequiredSpace)
+	{
+		unsigned long long ullCurrentLogSize = sinkData.GetCurrentLogSize();
+		unsigned long long ullNewSize = ullCurrentLogSize + stRequiredSpace;
+		if (ullCurrentLogSize == 0 || ullNewSize < m_ullMaxLogSize)
+			return;
+
+		sinkData.CloseLogFile();
+
+		TString pathNew = pathLog.ToWString();
+		if (pathNew.EndsWithNoCase(L".log"))
+			pathNew.LeftSelf(pathNew.GetLength() - 4);
+
+		boost::posix_time::ptime timeNow = boost::posix_time::second_clock::local_time();
+		boost::posix_time::time_facet* facet = new boost::posix_time::time_facet();
+		facet->format("%Y%m%d%H%M%S");
+		std::wstringstream stream;
+		stream.imbue(std::locale(std::locale::classic(), facet));
+		stream << time;
+		pathNew.Append(L".");
+		pathNew.Append(stream.str().c_str());
+		pathNew.Append(L".log");
+
+		if (!MoveFile(pathLog.ToString(), pathNew.c_str()))
+			throw TFileException(eErr_CannotFastMove, GetLastError(), pathLog, L"Cannot rotate file", LOCATION);
+
+		sinkData.AddRotatedFile(PathFromWString(pathNew));
+		sinkData.RemoveObsoleteRotatedLogs(m_uiMaxRotatedFiles);
+	}
+
+	void TLogRotator::ScanForLogs(const TSmartPath& pathDir, TLogSinkCollection& rCollection)
+	{
+		TSmartPath pathSearch = pathDir;
+		pathSearch += PathFromString(L"*.log");
+
+		std::vector<TSmartPath> vPaths;
+		WIN32_FIND_DATA wfd = { 0 };
+
+		HANDLE hFind = FindFirstFile(pathSearch.ToString(), &wfd);
+		BOOL bFound = (hFind != INVALID_HANDLE_VALUE);
+		while (bFound)
+		{
+			TSmartPath pathFound = pathDir + PathFromString(wfd.cFileName);
+			vPaths.push_back(pathFound);
+
+			bFound = FindNextFile(hFind, &wfd);
+		}
+
+		std::sort(vPaths.begin(), vPaths.end(), [](const TSmartPath& path1, const TSmartPath& path2) { return path2 > path1; });
+
+		for (const TSmartPath& rPath : vPaths)
+		{
+			rCollection.AddPath(rPath);
+		}
+	}
+}
Index: src/common/TLogRotator.h
===================================================================
diff -u -N
--- src/common/TLogRotator.h	(revision 0)
+++ src/common/TLogRotator.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,45 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TLOGROTATOR_H__
+#define __TLOGROTATOR_H__
+
+#include "..\libchcore\TPath.h"
+#include "TLogSink.h"
+
+namespace chcore
+{
+	class TLogSinkCollection;
+
+	class TLogRotator
+	{
+	public:
+		TLogRotator(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize);
+
+		void SetLimits(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize);
+
+		void RotateFile(const TSmartPath& pathLog, TLogSink& sinkData, size_t stRequiredSpace);
+		static void ScanForLogs(const TSmartPath& pathDir, TLogSinkCollection& rCollection);
+
+	private:
+		unsigned int m_uiMaxRotatedFiles = 0;
+		unsigned long long m_ullMaxLogSize = 0;
+	};
+}
+
+#endif
Index: src/common/TLogSink.cpp
===================================================================
diff -u -N
--- src/common/TLogSink.cpp	(revision 0)
+++ src/common/TLogSink.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,78 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TLogSink.h"
+#include "..\libchcore\TFileException.h"
+
+namespace chcore
+{
+	TLogSink::TLogSink(const chcore::TSmartPath& pathLog)
+		: m_pathLog(pathLog)
+	{
+	}
+
+	HANDLE TLogSink::GetFileHandle()
+	{
+		if (m_handleFile != INVALID_HANDLE_VALUE)
+			return m_handleFile;
+
+		m_handleFile = CreateFile(m_pathLog.ToString(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+		if (m_handleFile == INVALID_HANDLE_VALUE)
+			throw TFileException(eErr_CannotOpenFile, GetLastError(), m_pathLog, L"Cannot open log file", LOCATION);
+
+		return m_handleFile;
+	}
+
+	unsigned long long TLogSink::GetCurrentLogSize()
+	{
+		LARGE_INTEGER liSize = { 0 };
+		if (!GetFileSizeEx(GetFileHandle(), &liSize))
+			throw new TFileException(eErr_CannotGetFileInfo, GetLastError(), m_pathLog, L"Cannot determine current log size", LOCATION);
+
+		return liSize.QuadPart;
+	}
+
+	void TLogSink::AddRotatedFile(const TSmartPath& rPath)
+	{
+		m_setRotatedFiles.insert(rPath);
+	}
+
+	void TLogSink::RemoveObsoleteRotatedLogs(unsigned int uiMaxRotatedFiles)
+	{
+		while (m_setRotatedFiles.size() > uiMaxRotatedFiles)
+		{
+			auto iterRotatedFile = m_setRotatedFiles.begin();
+			if (!DeleteFile(iterRotatedFile->ToString()))
+				break;
+
+			m_setRotatedFiles.erase(iterRotatedFile);
+		}
+	}
+
+	void chcore::TLogSink::CloseLogFile()
+	{
+		m_handleFile.Close();
+	}
+
+	void chcore::TLogSink::CloseIfTimedOut(unsigned long long ullCurrentTimestamp, unsigned long long ullMaxHandleCacheTime)
+	{
+		if (ullCurrentTimestamp - m_ullLastUsageTimestamp > ullMaxHandleCacheTime)
+			CloseLogFile();
+	}
+}
Index: src/common/TLogSink.h
===================================================================
diff -u -N
--- src/common/TLogSink.h	(revision 0)
+++ src/common/TLogSink.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,50 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TLOGSINK_H__
+#define __TLOGSINK_H__
+
+#include "..\libchcore\TPath.h"
+#include "..\libchcore\TAutoHandles.h"
+#include <set>
+
+namespace chcore
+{
+	class TLogSink
+	{
+	public:
+		TLogSink(const chcore::TSmartPath& pathLog);
+
+		HANDLE GetFileHandle();
+		unsigned long long GetCurrentLogSize();
+
+		void CloseLogFile();
+		void CloseIfTimedOut(unsigned long long ullCurrentTimestamp, unsigned long long ullMaxHandleCacheTime);
+
+		void AddRotatedFile(const TSmartPath& rPath);
+		void RemoveObsoleteRotatedLogs(unsigned int uiMaxRotatedFiles);
+
+	private:
+		chcore::TSmartPath m_pathLog;
+		chcore::TAutoFileHandle m_handleFile;
+		unsigned long long m_ullLastUsageTimestamp = 0;
+		std::set<chcore::TSmartPath> m_setRotatedFiles;
+	};
+}
+
+#endif
Index: src/common/TLogSinkCollection.cpp
===================================================================
diff -u -N
--- src/common/TLogSinkCollection.cpp	(revision 0)
+++ src/common/TLogSinkCollection.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,80 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TLogSinkCollection.h"
+#include "..\libchcore\TStringArray.h"
+
+namespace chcore
+{
+	TLogSinkCollection::TLogSinkCollection()
+	{
+
+	}
+
+	void TLogSinkCollection::AddPath(const TSmartPath& rPath)
+	{
+		TStringArray arrComponents;
+		TSmartPath pathToFileWithoutExtension = rPath.GetFileTitle();
+		pathToFileWithoutExtension.ToWString().Split(L".", arrComponents);
+
+		switch (arrComponents.GetCount())
+		{
+		case 0:
+			break;
+		case 1:
+		{
+			GetSinkData(rPath);
+			break;
+		}
+		default:
+		{
+			TSmartPath pathBase = rPath.GetFileDir() + pathToFileWithoutExtension.GetFileTitle();
+			TLogSink& rSinkData = GetSinkData(pathBase);
+
+			std::wstring strRotateInfo = arrComponents.GetAt(arrComponents.GetCount() - 1).c_str();
+			if (std::all_of(strRotateInfo.begin(), strRotateInfo.end(), isdigit))
+			{
+				rSinkData.AddRotatedFile(rPath);
+			}
+		}
+		}
+	}
+
+	TLogSink& TLogSinkCollection::GetSinkData(const TSmartPath& path)
+	{
+		auto iterFind = m_mapLogs.find(path);
+		if (iterFind == m_mapLogs.end())
+			iterFind = m_mapLogs.insert(std::make_pair(path, TLogSink(path))).first;
+
+		return iterFind->second;
+	}
+
+	void TLogSinkCollection::Clear()
+	{
+		m_mapLogs.clear();
+	}
+
+	void TLogSinkCollection::CloseExpiredFiles(unsigned long long ullCurrentTimestamp, unsigned long long ullMaxHandleCacheTime)
+	{
+		for (auto& pairSink : m_mapLogs)
+		{
+			pairSink.second.CloseIfTimedOut(ullCurrentTimestamp, ullMaxHandleCacheTime);
+		}
+	}
+}
Index: src/common/TLogSinkCollection.h
===================================================================
diff -u -N
--- src/common/TLogSinkCollection.h	(revision 0)
+++ src/common/TLogSinkCollection.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,45 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TLOGSINKCOLLECTION_H__
+#define __TLOGSINKCOLLECTION_H__
+
+#include <map>
+#include "..\libchcore\TPath.h"
+#include "TLogSink.h"
+
+namespace chcore
+{
+	class TLogSinkCollection
+	{
+	public:
+		TLogSinkCollection();
+
+		void AddPath(const TSmartPath& rPath);
+		TLogSink& GetSinkData(const TSmartPath& path);
+
+		void Clear();
+
+		void CloseExpiredFiles(unsigned long long ullCurrentTimestamp, unsigned long long ullMaxHandleCacheTime);
+
+	private:
+		std::map<TSmartPath, TLogSink> m_mapLogs;
+	};
+}
+
+#endif
Index: src/common/TLogger.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/common/TLogger.cpp	(.../TLogger.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/common/TLogger.cpp	(.../TLogger.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -19,23 +19,25 @@
 #include "stdafx.h"
 #include "TLogger.h"
 #include <boost/log/attributes/constant.hpp>
+#include "../libchcore/TCoreException.h"
 
 namespace keywords = boost::log::keywords;
 
-TLogger::TLogger(PCTSTR pszChannel) :
-	Logger(keywords::channel = pszChannel)
+namespace chcore
 {
-}
+	TLogger::TLogger(const TLoggerLevelConfigPtr& spLoggerConfig, const TLoggerLocationConfigPtr& spLogLocation, PCTSTR pszChannel) :
+		Logger(keywords::channel = pszChannel)
+	{
+		if (!spLoggerConfig)
+			throw TCoreException(eErr_InvalidArgument, L"spLoggerConfig", LOCATION);
+		if (!spLogLocation)
+			throw TCoreException(eErr_InvalidArgument, L"spLogLocation", LOCATION);
 
-TLogger::TLogger(PCTSTR pszLogPath, PCTSTR pszChannel) :
-	TLogger(pszChannel)
-{
-	m_iterLogPath = add_attribute("LogPath", boost::log::attributes::constant< std::wstring >(pszLogPath)).first;
-}
+		m_iterLogPath = add_attribute("LogPath", boost::log::attributes::constant<TLoggerLocationConfigPtr>(spLogLocation)).first;
+	}
 
-void TLogger::SetLogPath(PCTSTR pszLogPath)
-{
-	if(m_iterLogPath != boost::log::attribute_set::iterator())
-		remove_attribute(m_iterLogPath);
-	m_iterLogPath = add_attribute("LogPath", boost::log::attributes::constant< std::wstring >(pszLogPath)).first;
+	severity_level TLogger::GetMinSeverity() const
+	{
+		return m_spLoggerConfig->GetMinSeverityLevel();
+	}
 }
Index: src/common/TLogger.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/common/TLogger.h	(.../TLogger.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/common/TLogger.h	(.../TLogger.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -21,27 +21,38 @@
 
 #include <boost/log/trivial.hpp>
 #include <boost/log/sources/severity_channel_logger.hpp>
+#include "TLoggerLevelConfig.h"
+#include "TLoggerLocationConfig.h"
+#include <memory>
 
 using boost::log::trivial::severity_level;
 using Logger = boost::log::sources::wseverity_channel_logger_mt<severity_level, std::wstring>;
 
-class TLogger : public Logger
+namespace chcore
 {
-public:
-	TLogger(PCTSTR pszChannel);
-	TLogger(PCTSTR pszLogPath, PCTSTR pszChannel);
+	class TLogger : public Logger
+	{
+	private:
+		TLogger(const TLoggerLevelConfigPtr& spLoggerConfig, const TLoggerLocationConfigPtr& spLogLocation, PCTSTR pszChannel);
 
-	void SetLogPath(PCTSTR pszLogPath);
+	public:
+		severity_level GetMinSeverity() const;
 
-private:
-	boost::log::attribute_set::iterator m_iterLogPath;
-};
+	private:
+		boost::log::attribute_set::iterator m_iterLogPath;
+		TLoggerLevelConfigPtr m_spLoggerConfig;
 
-#define LOG_TRACE(logger) BOOST_LOG_SEV(logger, boost::log::trivial::trace)
-#define LOG_DEBUG(logger) BOOST_LOG_SEV(logger, boost::log::trivial::debug)
-#define LOG_INFO(logger) BOOST_LOG_SEV(logger, boost::log::trivial::info)
-#define LOG_WARNING(logger) BOOST_LOG_SEV(logger, boost::log::trivial::warning)
-#define LOG_ERROR(logger) BOOST_LOG_SEV(logger, boost::log::trivial::error)
-#define LOG_FATAL(logger) BOOST_LOG_SEV(logger, boost::log::trivial::fatal)
+		friend class TLoggerFactory;
+	};
 
+	using TLoggerPtr = std::unique_ptr<TLogger>;
+}
+
+#define LOG_TRACE(logger) if(boost::log::trivial::trace >= (logger)->GetMinSeverity()) BOOST_LOG_SEV((*logger), boost::log::trivial::trace)
+#define LOG_DEBUG(logger) if(boost::log::trivial::debug >= (logger)->GetMinSeverity()) BOOST_LOG_SEV((*logger), boost::log::trivial::debug)
+#define LOG_INFO(logger) if(boost::log::trivial::info >= (logger)->GetMinSeverity()) BOOST_LOG_SEV((*logger), boost::log::trivial::info)
+#define LOG_WARNING(logger) if(boost::log::trivial::warning >= (logger)->GetMinSeverity()) BOOST_LOG_SEV((*logger), boost::log::trivial::warning)
+#define LOG_ERROR(logger) if(boost::log::trivial::error >= (logger)->GetMinSeverity()) BOOST_LOG_SEV((*logger), boost::log::trivial::error)
+#define LOG_FATAL(logger) if(boost::log::trivial::fatal >= (logger)->GetMinSeverity()) BOOST_LOG_SEV((*logger), boost::log::trivial::fatal)
+
 #endif
Index: src/common/TLoggerFactory.cpp
===================================================================
diff -u -N
--- src/common/TLoggerFactory.cpp	(revision 0)
+++ src/common/TLoggerFactory.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,38 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TLoggerFactory.h"
+#include "..\libchcore\TCoreException.h"
+
+namespace chcore
+{
+	TLoggerFactory::TLoggerFactory(const TSmartPath& pathLog, const TMultiLoggerConfigPtr& spMultiLoggerConfig) :
+		m_spMultiLoggerConfig(spMultiLoggerConfig),
+		m_spLogLocation(std::make_shared<TLoggerLocationConfig>(pathLog))
+	{
+		if (!spMultiLoggerConfig)
+			throw TCoreException(eErr_InvalidArgument, L"spMultiLoggerConfig", LOCATION);
+	}
+
+	std::unique_ptr<TLogger> TLoggerFactory::CreateLogger(PCTSTR pszChannel)
+	{
+		TLoggerLevelConfigPtr spConfig = m_spMultiLoggerConfig->GetLoggerConfig(pszChannel);
+		return std::unique_ptr<TLogger>(new TLogger(spConfig, m_spLogLocation, pszChannel));
+	}
+}
Index: src/common/TLoggerFactory.h
===================================================================
diff -u -N
--- src/common/TLoggerFactory.h	(revision 0)
+++ src/common/TLoggerFactory.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,44 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TLOGGERFACTORY_H__
+#define __TLOGGERFACTORY_H__
+
+#include "TMultiLoggerConfig.h"
+#include "TLogger.h"
+#include "TLoggerLocationConfig.h"
+#include <memory>
+
+namespace chcore
+{
+	class TLoggerFactory
+	{
+	public:
+		TLoggerFactory(const TSmartPath& pathLog, const TMultiLoggerConfigPtr& spMultiLoggerConfig);
+
+		std::unique_ptr<TLogger> CreateLogger(PCTSTR pszChannel);
+
+	private:
+		TMultiLoggerConfigPtr m_spMultiLoggerConfig;
+		TLoggerLocationConfigPtr m_spLogLocation;
+	};
+
+	using TLoggerFactoryPtr = std::shared_ptr<TLoggerFactory>;
+}
+
+#endif
Index: src/common/TLoggerInitializer.cpp
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/common/TLoggerInitializer.cpp	(.../TLoggerInitializer.cpp)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/common/TLoggerInitializer.cpp	(.../TLoggerInitializer.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -49,15 +49,14 @@
 TLoggerInitializer::TLoggerInitializer() :
 	m_spData(new InternalData)
 {
-	InitSink();
 }
 
 TLoggerInitializer::~TLoggerInitializer()
 {
 	Uninit();
 }
 
-void TLoggerInitializer::InitSink()
+void TLoggerInitializer::Init(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize)
 {
 	if(m_bWasInitialized)
 		return;
@@ -67,7 +66,7 @@
 	logging::add_common_attributes();
 
 	// sink BACKEND
-	boost::shared_ptr<Backend> backend = boost::make_shared<Backend>();
+	boost::shared_ptr<Backend> backend = boost::make_shared<Backend>(nullptr, uiMaxRotatedFiles, ullMaxLogSize);
 
 /*
 	// Set up the file naming pattern
Index: src/common/TLoggerInitializer.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/common/TLoggerInitializer.h	(.../TLoggerInitializer.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/common/TLoggerInitializer.h	(.../TLoggerInitializer.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -25,12 +25,10 @@
 	TLoggerInitializer();
 	~TLoggerInitializer();
 
+	void Init(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize);
 	void Uninit();
 
 private:
-	void InitSink();
-
-private:
 	struct InternalData;
 	std::unique_ptr<InternalData> m_spData;
 	bool m_bWasInitialized = false;
Index: src/common/TLoggerLevelConfig.cpp
===================================================================
diff -u -N
--- src/common/TLoggerLevelConfig.cpp	(revision 0)
+++ src/common/TLoggerLevelConfig.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,33 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TLoggerLevelConfig.h"
+
+namespace chcore
+{
+	void TLoggerLevelConfig::SetMinSeverityLevel(boost::log::trivial::severity_level eLevel)
+	{
+		m_eMinSeverity = eLevel;
+	}
+
+	boost::log::trivial::severity_level TLoggerLevelConfig::GetMinSeverityLevel() const
+	{
+		return m_eMinSeverity;
+	}
+}
Index: src/common/TLoggerLevelConfig.h
===================================================================
diff -u -N
--- src/common/TLoggerLevelConfig.h	(revision 0)
+++ src/common/TLoggerLevelConfig.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,39 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TLOGGERCONFIG_H__
+#define __TLOGGERCONFIG_H__
+
+#include <boost/log/trivial.hpp>
+
+namespace chcore
+{
+	class TLoggerLevelConfig
+	{
+	public:
+		void SetMinSeverityLevel(boost::log::trivial::severity_level eLevel);
+		boost::log::trivial::severity_level GetMinSeverityLevel() const;
+
+	private:
+		boost::log::trivial::severity_level m_eMinSeverity = boost::log::trivial::trace;
+	};
+
+	using TLoggerLevelConfigPtr = std::shared_ptr<TLoggerLevelConfig>;
+}
+
+#endif
Index: src/common/TLoggerLocationConfig.cpp
===================================================================
diff -u -N
--- src/common/TLoggerLocationConfig.cpp	(revision 0)
+++ src/common/TLoggerLocationConfig.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,32 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TLoggerLocationConfig.h"
+
+namespace chcore
+{
+	TLoggerLocationConfig::TLoggerLocationConfig(const TSmartPath& pathLog) : m_pathLog(pathLog)
+	{
+	}
+
+	chcore::TSmartPath TLoggerLocationConfig::GetLogPath() const
+	{
+		return m_pathLog;
+	}
+}
Index: src/common/TLoggerLocationConfig.h
===================================================================
diff -u -N
--- src/common/TLoggerLocationConfig.h	(revision 0)
+++ src/common/TLoggerLocationConfig.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,40 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TLOGGERLOCATIONCONFIG_H__
+#define __TLOGGERLOCATIONCONFIG_H__
+
+#include "..\libchcore\TPath.h"
+
+namespace chcore
+{
+	class TLoggerLocationConfig
+	{
+	public:
+		TLoggerLocationConfig(const TSmartPath& pathLog);
+
+		TSmartPath GetLogPath() const;
+
+	private:
+		TSmartPath m_pathLog;
+	};
+
+	using TLoggerLocationConfigPtr = std::shared_ptr<TLoggerLocationConfig>;
+}
+
+#endif
Index: src/common/TMultiFileBackend.cpp
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/common/TMultiFileBackend.cpp	(.../TMultiFileBackend.cpp)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/common/TMultiFileBackend.cpp	(.../TMultiFileBackend.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -18,17 +18,76 @@
 // ============================================================================
 #include "stdafx.h"
 #include "TMultiFileBackend.h"
+#include "..\libchcore\TTimestampProviderTickCount.h"
+#include <boost\algorithm\string\case_conv.hpp>
+#include <boost/log/utility/value_ref.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost\date_time\posix_time\posix_time_io.hpp>
+#include <sstream>
+#include "..\libchcore\TStringArray.h"
+#include "TLoggerLocationConfig.h"
 
 namespace chcore
 {
-	TMultiFileBackend::TMultiFileBackend()
+	TMultiFileBackend::TMultiFileBackend(ITimestampProviderPtr spTimestampProvider, unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize) :
+		m_spTimestampProvider(spTimestampProvider),
+		m_logRotator(uiMaxRotatedFiles, ullMaxLogSize)
 	{
+		if (!m_spTimestampProvider)
+			m_spTimestampProvider.reset(new TTimestampProviderTickCount);
+	}
 
+	void TMultiFileBackend::Init(const TSmartPath& pathDirectory, unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize)
+	{
+		SetDirectory(pathDirectory);
+		m_logRotator.SetLimits(uiMaxRotatedFiles, ullMaxLogSize);
 	}
 
-	void TMultiFileBackend::consume(boost::log::record_view const& /*rec*/, string_type const& /*formatted_message*/)
+	void TMultiFileBackend::consume(const boost::log::record_view& rec, const string_type& formatted_message)
 	{
+		if (!m_bInitialized)
+			return;
 
+		TSmartPath pathLog = GetLogName(rec);
+		if (pathLog.IsEmpty())
+			return;
+
+		TLogSink& sinkData = m_mapLogs.GetSinkData(pathLog);
+
+		HANDLE hFile = GetLogFile(pathLog, sinkData, formatted_message.length());
+		if (hFile == INVALID_HANDLE_VALUE)
+			return;
+
+		DWORD dwToWrite = boost::numeric_cast<DWORD>(formatted_message.length() * sizeof(wchar_t));
+		DWORD dwWritten = 0;
+		WriteFile(hFile, formatted_message.c_str(), dwToWrite, &dwWritten, nullptr);
 	}
 
+	TSmartPath TMultiFileBackend::GetLogName(const boost::log::record_view &rec)
+	{
+		auto attrLogPath = rec.attribute_values().find("LogPath");
+		if (attrLogPath == rec.attribute_values().end())
+			return TSmartPath();
+
+		boost::log::value_ref<TLoggerLocationConfigPtr> val = boost::log::extract<TLoggerLocationConfigPtr>(attrLogPath->second);
+		if (!val)
+			return TSmartPath();
+
+		return val.get()->GetLogPath();
+	}
+
+	HANDLE TMultiFileBackend::GetLogFile(const TSmartPath& pathLog, TLogSink& sinkData, size_t stRequiredSpace)
+	{
+		m_logRotator.RotateFile(pathLog, sinkData, stRequiredSpace);
+
+		return sinkData.GetFileHandle();
+	}
+
+	void TMultiFileBackend::SetDirectory(const TSmartPath& pathDirectory)
+	{
+		m_mapLogs.Clear();
+		m_logRotator.ScanForLogs(pathDirectory, m_mapLogs);
+		m_bInitialized = true;
+	}
+
 }
Index: src/common/TMultiFileBackend.h
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/common/TMultiFileBackend.h	(.../TMultiFileBackend.h)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/common/TMultiFileBackend.h	(.../TMultiFileBackend.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -20,22 +20,40 @@
 #define __TMULTIFILEBACKEND_H__
 
 #include <boost/log/sinks/basic_sink_backend.hpp>
+#include "../libchcore/TAutoHandles.h"
+#include "../libchcore/ITimestampProvider.h"
+#include "../libchcore/TPath.h"
+#include "TLogSink.h"
+#include "TLogSinkCollection.h"
+#include "TLogRotator.h"
 
 namespace chcore
 {
-	class TMultiFileBackend : public boost::log::sinks::basic_formatted_sink_backend< char >
+	class TMultiFileBackend : public boost::log::sinks::basic_formatted_sink_backend<char>
 	{
 	public:
-		TMultiFileBackend();
+		const unsigned int MaxHandleCacheTime = 60000;
 
-		void consume(boost::log::record_view const& rec, string_type const& formatted_message);
+	public:
+		TMultiFileBackend(ITimestampProviderPtr spTimestampProvider, unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize);
 
+		void Init(const TSmartPath& pathDirectory, unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize);
+
+		void consume(const boost::log::record_view& rec, const string_type& formatted_message);
+
 	private:
-		unsigned long long m_ullRotateSize;
-		unsigned int m_uiMaxRotatedFiles;
-		unsigned int m_uiHandleCacheTime;
+		void SetDirectory(const TSmartPath& pathDirectory);
 
-		// map<logname, <handle, last-write-time, list<rotated-files>>>
+		static TSmartPath GetLogName(const boost::log::record_view &rec);
+		HANDLE GetLogFile(const TSmartPath& pathLog, TLogSink& sinkData, size_t stRequiredSpace);
+
+	private:
+		unsigned int m_uiHandleCacheTime = MaxHandleCacheTime;
+
+		TLogSinkCollection m_mapLogs;
+		TLogRotator m_logRotator;
+		ITimestampProviderPtr m_spTimestampProvider;
+		bool m_bInitialized = false;
 	};
 }
 
Index: src/common/TMultiLoggerConfig.cpp
===================================================================
diff -u -N
--- src/common/TMultiLoggerConfig.cpp	(revision 0)
+++ src/common/TMultiLoggerConfig.cpp	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,32 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TMultiLoggerConfig.h"
+
+namespace chcore
+{
+	TLoggerLevelConfigPtr TMultiLoggerConfig::GetLoggerConfig(PCTSTR pszChannel)
+	{
+		auto iterConfig = m_mapConfigs.find(pszChannel);
+		if (iterConfig == m_mapConfigs.end())
+			iterConfig = m_mapConfigs.insert(std::make_pair(pszChannel, std::make_shared<TLoggerLevelConfig>())).first;
+
+		return iterConfig->second;
+	}
+}
Index: src/common/TMultiLoggerConfig.h
===================================================================
diff -u -N
--- src/common/TMultiLoggerConfig.h	(revision 0)
+++ src/common/TMultiLoggerConfig.h	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -0,0 +1,39 @@
+// ============================================================================
+//  Copyright (C) 2001-2016 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#ifndef __TMULTILOGGERCONFIG_H__
+#define __TMULTILOGGERCONFIG_H__
+
+#include <map>
+#include "TLoggerLevelConfig.h"
+
+namespace chcore
+{
+	class TMultiLoggerConfig
+	{
+	public:
+		TLoggerLevelConfigPtr GetLoggerConfig(PCTSTR pszChannel);
+
+	private:
+		std::map<std::wstring, TLoggerLevelConfigPtr> m_mapConfigs;	// channel, config
+	};
+
+	using TMultiLoggerConfigPtr = std::shared_ptr<TMultiLoggerConfig>;
+}
+
+#endif
Index: src/libchcore/TCoreEngine.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TCoreEngine.cpp	(.../TCoreEngine.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TCoreEngine.cpp	(.../TCoreEngine.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -30,6 +30,12 @@
 		Uninitialize();
 	}
 
+
+	void TCoreEngine::Init(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize)
+	{
+		m_loggerInitializer.Init(uiMaxRotatedFiles, ullMaxLogSize);
+	}
+
 	void TCoreEngine::Uninitialize()
 	{
 		m_loggerInitializer.Uninit();
Index: src/libchcore/TCoreEngine.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TCoreEngine.h	(.../TCoreEngine.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TCoreEngine.h	(.../TCoreEngine.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -30,6 +30,7 @@
 		TCoreEngine();
 		~TCoreEngine();
 
+		void Init(unsigned int uiMaxRotatedFiles, unsigned long long ullMaxLogSize);
 		void Uninitialize();
 
 	private:
Index: src/libchcore/TFilesystemFeedbackWrapper.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TFilesystemFeedbackWrapper.cpp	(.../TFilesystemFeedbackWrapper.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TFilesystemFeedbackWrapper.cpp	(.../TFilesystemFeedbackWrapper.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -25,10 +25,10 @@
 
 namespace chcore
 {
-	TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, const TSmartPath& pathLogger, TWorkerThreadController& rThreadController) :
+	TFilesystemFeedbackWrapper::TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, const TLoggerFactoryPtr& spLogFactory, TWorkerThreadController& rThreadController) :
 		m_spFeedbackHandler(spFeedbackHandler),
 		m_spFilesystem(spFilesystem),
-		m_log(pathLogger.ToString(), L"Filesystem"),
+		m_spLog(spLogFactory->CreateLogger(L"Filesystem")),
 		m_rThreadController(rThreadController)
 	{
 		if (!spFilesystem)
@@ -61,7 +61,7 @@
 			strFormat = _T("Error %errno while calling CreateDirectory %path (ProcessFiles)");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), pathDirectory.ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathDirectory.ToWString(), TString(), EFileError::eCreateError, dwLastError);
 			switch (frResult.GetResult())
@@ -109,7 +109,7 @@
 		{
 			bRetry = false;
 
-			LOG_INFO(m_log) << _T("Checking for free space on destination disk...");
+			LOG_INFO(m_spLog) << _T("Checking for free space on destination disk...");
 
 			// get free space
 			DWORD dwLastError = ERROR_SUCCESS;
@@ -130,7 +130,7 @@
 				strFormat = _T("Error %errno while checking free space at %path");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), pathDestination.ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				frResult = m_spFeedbackHandler->FileError(pathDestination.ToWString(), TString(), EFileError::eCheckForFreeSpace, dwLastError);
 				switch (frResult.GetResult())
@@ -159,22 +159,22 @@
 				TString strFormat = _T("Not enough free space on disk - needed %needsize bytes for data, available: %availablesize bytes.");
 				strFormat.Replace(_T("%needsize"), boost::lexical_cast<std::wstring>(ullNeededSize).c_str());
 				strFormat.Replace(_T("%availablesize"), boost::lexical_cast<std::wstring>(ullAvailableSize).c_str());
-				LOG_WARNING(m_log) << strFormat.c_str();
+				LOG_WARNING(m_spLog) << strFormat.c_str();
 
 				frResult = m_spFeedbackHandler->NotEnoughSpace(pathFirstSrc.ToWString(), pathDestination.ToWString(), ullNeededSize);
 				switch (frResult.GetResult())
 				{
 				case EFeedbackResult::eResult_Cancel:
-					LOG_INFO(m_log) << _T("Cancel request while checking for free space on disk.");
+					LOG_INFO(m_spLog) << _T("Cancel request while checking for free space on disk.");
 					return TSubTaskBase::eSubResult_CancelRequest;
 
 				case EFeedbackResult::eResult_Retry:
-					LOG_INFO(m_log) << _T("Retrying to read drive's free space...");
+					LOG_INFO(m_spLog) << _T("Retrying to read drive's free space...");
 					bRetry = true;
 					break;
 
 				case EFeedbackResult::eResult_Ignore:
-					LOG_INFO(m_log) << _T("Ignored warning about not enough place on disk to copy data.");
+					LOG_INFO(m_spLog) << _T("Ignored warning about not enough place on disk to copy data.");
 					return TSubTaskBase::eSubResult_Continue;
 
 				default:
@@ -220,13 +220,13 @@
 			TString strFormat = _T("Error #%errno while deleting folder %path");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError);
 			switch (frResult.GetResult())
 			{
 			case EFeedbackResult::eResult_Cancel:
-				LOG_INFO(m_log) << _T("Cancel request while deleting file.");
+				LOG_INFO(m_spLog) << _T("Cancel request while deleting file.");
 				return TSubTaskBase::eSubResult_CancelRequest;
 
 			case EFeedbackResult::eResult_Retry:
@@ -281,13 +281,13 @@
 			TString strFormat = _T("Error #%errno while deleting file %path");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(spFileInfo->GetFullFilePath().ToWString(), TString(), EFileError::eDeleteError, dwLastError);
 			switch (frResult.GetResult())
 			{
 			case EFeedbackResult::eResult_Cancel:
-				LOG_INFO(m_log) << _T("Cancel request while deleting file.");
+				LOG_INFO(m_spLog) << _T("Cancel request while deleting file.");
 				return TSubTaskBase::eSubResult_CancelRequest;
 
 			case EFeedbackResult::eResult_Retry:
@@ -346,7 +346,7 @@
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%srcpath"), spFileInfo->GetFullFilePath().ToString());
 			strFormat.Replace(_T("%dstpath"), pathDestination.ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathSrc.ToWString(), pathDestination.ToWString(), EFileError::eFastMoveError, dwLastError);
 			switch (frResult.GetResult())
Index: src/libchcore/TFilesystemFeedbackWrapper.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TFilesystemFeedbackWrapper.h	(.../TFilesystemFeedbackWrapper.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TFilesystemFeedbackWrapper.h	(.../TFilesystemFeedbackWrapper.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -22,16 +22,16 @@
 #include "IFilesystem.h"
 #include "TSubTaskBase.h"
 #include "../common/TLogger.h"
+#include "../common/TLoggerFactory.h"
 
 namespace chcore
 {
 	class TWorkerThreadController;
-	class log_file;
 
 	class TFilesystemFeedbackWrapper
 	{
 	public:
-		TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, const TSmartPath& pathLogger, TWorkerThreadController& rThreadController);
+		TFilesystemFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const IFilesystemPtr& spFilesystem, const TLoggerFactoryPtr& spLogFactory, TWorkerThreadController& rThreadController);
 		TFilesystemFeedbackWrapper& operator=(const TFilesystemFeedbackWrapper&) = delete;
 
 		TSubTaskBase::ESubOperationResult CreateDirectoryFB(const TSmartPath& pathDirectory);
@@ -52,7 +52,7 @@
 	private:
 		IFeedbackHandlerPtr m_spFeedbackHandler;
 		IFilesystemPtr m_spFilesystem;
-		TLogger m_log;
+		TLoggerPtr m_spLog;
 		TWorkerThreadController& m_rThreadController;
 	};
 }
Index: src/libchcore/TFilesystemFileFeedbackWrapper.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TFilesystemFileFeedbackWrapper.cpp	(.../TFilesystemFileFeedbackWrapper.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TFilesystemFileFeedbackWrapper.cpp	(.../TFilesystemFileFeedbackWrapper.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -26,9 +26,9 @@
 
 namespace chcore
 {
-	TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathLogger, TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem) :
+	TFilesystemFileFeedbackWrapper::TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const TLoggerFactoryPtr& spLogFactory, TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem) :
 		m_spFeedbackHandler(spFeedbackHandler),
-		m_log(pathLogger.ToString(), L"Filesystem-File"),
+		m_spLog(spLogFactory->CreateLogger(L"Filesystem-File")),
 		m_rThreadController(rThreadController),
 		m_spFilesystem(spFilesystem)
 	{
@@ -70,7 +70,7 @@
 				TString strFormat = _T("Cancel request [error %errno] while opening source file %path (OpenSourceFileFB)");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), fileSrc->GetFilePath().ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				return TSubTaskBase::eSubResult_CancelRequest;
 			}
@@ -84,7 +84,7 @@
 				TString strFormat = _T("Retrying [error %errno] to open source file %path (OpenSourceFileFB)");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), fileSrc->GetFilePath().ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				bRetry = true;
 				break;
@@ -157,7 +157,7 @@
 				TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				bRetry = true;
 				break;
@@ -168,7 +168,7 @@
 				TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				return TSubTaskBase::eSubResult_CancelRequest;
 			}
@@ -260,7 +260,7 @@
 					// log
 					TString strFormat = _T("Cancel request while checking result of dialog before opening source file %path (CustomCopyFileFB)");
 					strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString());
-					LOG_INFO(m_log) << strFormat.c_str();
+					LOG_INFO(m_spLog) << strFormat.c_str();
 
 					return TSubTaskBase::eSubResult_CancelRequest;
 				}
@@ -282,7 +282,7 @@
 				TString strFormat = _T("Retrying [error %errno] to open destination file %path (CustomCopyFileFB)");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				bRetry = true;
 
@@ -294,7 +294,7 @@
 				TString strFormat = _T("Cancel request [error %errno] while opening destination file %path (CustomCopyFileFB)");
 				strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 				strFormat.Replace(_T("%path"), fileDst->GetFilePath().ToString());
-				LOG_ERROR(m_log) << strFormat.c_str();
+				LOG_ERROR(m_spLog) << strFormat.c_str();
 
 				return TSubTaskBase::eSubResult_CancelRequest;
 			}
@@ -341,7 +341,7 @@
 			TString strFormat = _T("Error %errno while truncating file %path to 0");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), pathFile.ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eResizeError, dwLastError);
 			switch (frResult.GetResult())
@@ -397,7 +397,7 @@
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetRequestedDataSize()).c_str());
 			strFormat.Replace(_T("%path"), pathFile.ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eReadError, dwLastError);
 			switch (frResult.GetResult())
@@ -454,7 +454,7 @@
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetBytesTransferred()).c_str());
 			strFormat.Replace(_T("%path"), pathFile.ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError);
 			switch (frResult.GetResult())
@@ -510,7 +510,7 @@
 			TString strFormat = _T("Error %errno while trying to finalize file %path (CustomCopyFileFB)");
 			strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 			strFormat.Replace(_T("%path"), pathFile.ToString());
-			LOG_ERROR(m_log) << strFormat.c_str();
+			LOG_ERROR(m_spLog) << strFormat.c_str();
 
 			TFeedbackResult frResult = m_spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eFinalizeError, dwLastError);
 			switch (frResult.GetResult())
Index: src/libchcore/TFilesystemFileFeedbackWrapper.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TFilesystemFileFeedbackWrapper.h	(.../TFilesystemFileFeedbackWrapper.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TFilesystemFileFeedbackWrapper.h	(.../TFilesystemFileFeedbackWrapper.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -24,16 +24,16 @@
 #include "IFeedbackHandler.h"
 #include "IFilesystem.h"
 #include "../common/TLogger.h"
+#include "../common/TLoggerFactory.h"
 
 namespace chcore
 {
 	class TWorkerThreadController;
-	class log_file;
 
 	class TFilesystemFileFeedbackWrapper
 	{
 	public:
-		TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const TSmartPath& pathLogger, TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem);
+		TFilesystemFileFeedbackWrapper(const IFeedbackHandlerPtr& spFeedbackHandler, const TLoggerFactoryPtr& spLogFactory, TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem);
 		TFilesystemFileFeedbackWrapper& operator=(const TFilesystemFileFeedbackWrapper&) = delete;
 
 		TSubTaskBase::ESubOperationResult OpenSourceFileFB(const IFilesystemFilePtr& fileSrc);
@@ -58,7 +58,7 @@
 	private:
 		IFeedbackHandlerPtr m_spFeedbackHandler;
 		IFilesystemPtr m_spFilesystem;
-		TLogger m_log;
+		TLoggerPtr m_spLog;
 		TWorkerThreadController& m_rThreadController;
 	};
 }
Index: src/libchcore/TSubTaskContext.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskContext.cpp	(.../TSubTaskContext.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskContext.cpp	(.../TSubTaskContext.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -30,20 +30,22 @@
 {
 	TSubTaskContext::TSubTaskContext(TConfig& rConfig, const TBasePathDataContainerPtr& spBasePaths,
 		const TFileFiltersArray& rFilters,
-		TTaskConfigTracker& rCfgTracker, const TSmartPath& rPathLogFile,
+		TTaskConfigTracker& rCfgTracker, const TLoggerFactoryPtr& spLoggerFactory,
 		TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem) :
 		m_rConfig(rConfig),
 		m_eOperationType(eOperation_None),
 		m_spBasePaths(spBasePaths),
 		m_pathDestination(),
 		m_rCfgTracker(rCfgTracker),
-		m_pathLogFile(rPathLogFile),
+		m_spLoggerFactory(spLoggerFactory),
 		m_rThreadController(rThreadController),
 		m_spFilesystem(spFilesystem),
 		m_rFilters(rFilters)
 	{
 		if (!spFilesystem)
 			throw TCoreException(eErr_InvalidArgument, L"spFilesystem", LOCATION);
+		if (!spLoggerFactory)
+			throw TCoreException(eErr_InvalidArgument, L"spLoggerFactory", LOCATION);
 	}
 
 	TSubTaskContext::~TSubTaskContext()
@@ -105,16 +107,11 @@
 		return m_rCfgTracker;
 	}
 
-	TSmartPath TSubTaskContext::GetLogPath() const
+	TLoggerFactoryPtr TSubTaskContext::GetLogFactory() const
 	{
-		return m_pathLogFile;
+		return m_spLoggerFactory;
 	}
 
-	void TSubTaskContext::SetLogPath(const TSmartPath& pathLog)
-	{
-		m_pathLogFile = pathLog;
-	}
-
 	TWorkerThreadController& TSubTaskContext::GetThreadController()
 	{
 		return m_rThreadController;
Index: src/libchcore/TSubTaskContext.h
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskContext.h	(.../TSubTaskContext.h)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/libchcore/TSubTaskContext.h	(.../TSubTaskContext.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -29,10 +29,10 @@
 #include "TBasePathData.h"
 #include "TFileInfoArray.h"
 #include "IFilesystem.h"
+#include "..\common\TLoggerFactory.h"
 
 namespace chcore
 {
-	class log_file;
 	class TWorkerThreadController;
 	class TTaskConfigTracker;
 	class TConfig;
@@ -46,7 +46,7 @@
 	public:
 		TSubTaskContext(TConfig& rConfig, const TBasePathDataContainerPtr& spBasePaths,
 			const TFileFiltersArray& rFilters,
-			TTaskConfigTracker& rCfgTracker, const TSmartPath& rPathLogFile,
+			TTaskConfigTracker& rCfgTracker, const TLoggerFactoryPtr& spLoggerFactory,
 			TWorkerThreadController& rThreadController, const IFilesystemPtr& spFilesystem);
 		~TSubTaskContext();
 
@@ -68,8 +68,7 @@
 		TTaskConfigTracker& GetCfgTracker();
 		const TTaskConfigTracker& GetCfgTracker() const;
 
-		TSmartPath GetLogPath() const;
-		void SetLogPath(const TSmartPath& pathLog);
+		TLoggerFactoryPtr GetLogFactory() const;
 
 		TWorkerThreadController& GetThreadController();
 		const TWorkerThreadController& GetThreadController() const;
@@ -105,11 +104,9 @@
 #pragma warning(push)
 #pragma warning(disable: 4251)
 		IFilesystemPtr m_spFilesystem;
+		TLoggerFactoryPtr m_spLoggerFactory;
 #pragma warning(pop)
 
-		// additional data
-		TSmartPath m_pathLogFile;
-
 		// thread control
 		TWorkerThreadController& m_rThreadController;
 	};
Index: src/libchcore/TSubTaskCopyMove.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -68,7 +68,7 @@
 	TSubTaskCopyMove::TSubTaskCopyMove(TSubTaskContext& rContext) :
 		TSubTaskBase(rContext),
 		m_tSubTaskStats(eSubOperation_Copying),
-		m_log(rContext.GetLogPath().ToString(), L"ST-CopyMove")
+		m_spLog(rContext.GetLogFactory()->CreateLogger(L"ST-CopyMove"))
 	{
 	}
 
@@ -109,10 +109,10 @@
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 		TBasePathDataContainerPtr spSrcPaths = GetContext().GetBasePaths();
 
-		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogPath(), rThreadController);
+		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogFactory(), rThreadController);
 
 		// log
-		LOG_INFO(m_log) << _T("Processing files/folders (ProcessFiles)");
+		LOG_INFO(m_spLog) << _T("Processing files/folders (ProcessFiles)");
 
 		// initialize stats if not resuming (when resuming we have already initialized
 		// the stats once - it is being restored in Load() too).
@@ -165,15 +165,15 @@
 		strFormat.Replace(_T("%dstpath"), pathDestination.ToString());
 		strFormat.Replace(_T("%currindex"), boost::lexical_cast<std::wstring>(fcIndex).c_str());
 
-		LOG_INFO(m_log) << strFormat.c_str();
+		LOG_INFO(m_spLog) << strFormat.c_str();
 
 		for(; fcIndex < fcSize; fcIndex++)
 		{
 			// should we kill ?
 			if(rThreadController.KillRequested())
 			{
 				// log
-				LOG_INFO(m_log) << _T("Kill request while processing file in ProcessFiles");
+				LOG_INFO(m_spLog) << _T("Kill request while processing file in ProcessFiles");
 				return TSubTaskBase::eSubResult_KillRequest;
 			}
 
@@ -252,7 +252,7 @@
 		bool bUpdateDirTimes = GetTaskPropValue<eTO_SetDestinationDateTime>(rConfig);
 		if(bUpdateDirTimes)
 		{
-			LOG_INFO(m_log) << _T("Setting directory attributes");
+			LOG_INFO(m_spLog) << _T("Setting directory attributes");
 
 			// iterate backwards
 			for(file_count_t fcAttrIndex = fcSize; fcAttrIndex != 0; --fcAttrIndex)
@@ -261,7 +261,7 @@
 				if(rThreadController.KillRequested())
 				{
 					// log
-					LOG_INFO(m_log) << _T("Kill request while processing file in ProcessFiles");
+					LOG_INFO(m_spLog) << _T("Kill request while processing file in ProcessFiles");
 					return TSubTaskBase::eSubResult_KillRequest;
 				}
 
@@ -281,7 +281,7 @@
 		m_tSubTaskStats.SetCurrentPath(TString());
 
 		// log
-		LOG_INFO(m_log) << _T("Finished processing in ProcessFiles");
+		LOG_INFO(m_spLog) << _T("Finished processing in ProcessFiles");
 
 		return TSubTaskBase::eSubResult_Continue;
 	}
@@ -336,7 +336,7 @@
 		const TConfig& rConfig = GetContext().GetConfig();
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 
-		TFilesystemFileFeedbackWrapper tFileFBWrapper(spFeedbackHandler, GetContext().GetLogPath(), rThreadController, spFilesystem);
+		TFilesystemFileFeedbackWrapper tFileFBWrapper(spFeedbackHandler, GetContext().GetLogFactory(), rThreadController, spFilesystem);
 
 		TString strFormat;
 		TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue;
@@ -406,7 +406,7 @@
 					strFormat = _T("Kill request while main copying file %srcpath -> %dstpath");
 					strFormat.Replace(_T("%srcpath"), pData->spSrcFile->GetFullFilePath().ToString());
 					strFormat.Replace(_T("%dstpath"), pData->pathDstFile.ToString());
-					LOG_INFO(m_log) << strFormat.c_str();
+					LOG_INFO(m_spLog) << strFormat.c_str();
 
 					eResult = TSubTaskBase::eSubResult_KillRequest;
 					bStopProcessing = true;
@@ -806,7 +806,7 @@
 			strFormat.Replace(_T("%lansize2"), boost::lexical_cast<std::wstring>(rBufferSizes.GetLANSize()).c_str());
 			strFormat.Replace(_T("%cnt"), boost::lexical_cast<std::wstring>(rBufferSizes.GetBufferCount()).c_str());
 
-			LOG_INFO(m_log) << strFormat.c_str();
+			LOG_INFO(m_spLog) << strFormat.c_str();
 
 			rBuffer.ReinitializeBuffers(rBufferSizes.GetBufferCount(), rBufferSizes.GetMaxSize());
 
@@ -830,7 +830,7 @@
 		strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(dwLastError).c_str());
 		strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetRequestedDataSize()).c_str());
 		strFormat.Replace(_T("%path"), pathFile.ToString());
-		LOG_ERROR(m_log) << strFormat.c_str();
+		LOG_ERROR(m_spLog) << strFormat.c_str();
 
 		TFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eReadError, dwLastError);
 		switch(frResult.GetResult())
@@ -868,7 +868,7 @@
 		strFormat.Replace(_T("%errno"), boost::lexical_cast<std::wstring>(rBuffer.GetErrorCode()).c_str());
 		strFormat.Replace(_T("%count"), boost::lexical_cast<std::wstring>(rBuffer.GetBytesTransferred()).c_str());
 		strFormat.Replace(_T("%path"), pathFile.ToString());
-		LOG_ERROR(m_log) << strFormat.c_str();
+		LOG_ERROR(m_spLog) << strFormat.c_str();
 
 		TFeedbackResult frResult = spFeedbackHandler->FileError(pathFile.ToWString(), TString(), EFileError::eWriteError, dwLastError);
 		switch (frResult.GetResult())
Index: src/libchcore/TSubTaskCopyMove.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskCopyMove.h	(.../TSubTaskCopyMove.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskCopyMove.h	(.../TSubTaskCopyMove.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -82,7 +82,7 @@
 #pragma warning(push)
 #pragma warning(disable: 4251)
 		TSubTaskStatsInfo m_tSubTaskStats;
-		TLogger m_log;
+		TLoggerPtr m_spLog;
 #pragma warning(pop)
 	};
 }
Index: src/libchcore/TSubTaskDelete.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskDelete.cpp	(.../TSubTaskDelete.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -47,7 +47,7 @@
 	TSubTaskDelete::TSubTaskDelete(TSubTaskContext& rContext) :
 		TSubTaskBase(rContext),
 		m_tSubTaskStats(eSubOperation_Deleting),
-		m_log(rContext.GetLogPath().ToString(), L"ST-Delete")
+		m_spLog(rContext.GetLogFactory()->CreateLogger(L"ST-Delete"))
 	{
 	}
 
@@ -85,10 +85,10 @@
 		TWorkerThreadController& rThreadController = GetContext().GetThreadController();
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 
-		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogPath(), rThreadController);
+		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogFactory(), rThreadController);
 
 		// log
-		LOG_INFO(m_log) << _T("Deleting files (DeleteFiles)...");
+		LOG_INFO(m_spLog) << _T("Deleting files (DeleteFiles)...");
 
 		// new stats
 		m_tSubTaskStats.SetCurrentBufferIndex(TBufferSizes::eBuffer_Default);
@@ -118,7 +118,7 @@
 			if (rThreadController.KillRequested())
 			{
 				// log
-				LOG_INFO(m_log) << _T("Kill request while deleting files (Delete Files)");
+				LOG_INFO(m_spLog) << _T("Kill request while deleting files (Delete Files)");
 				return TSubTaskBase::eSubResult_KillRequest;
 			}
 
@@ -146,7 +146,7 @@
 		m_tSubTaskStats.SetCurrentPath(TString());
 
 		// log
-		LOG_INFO(m_log) << _T("Deleting files finished");
+		LOG_INFO(m_spLog) << _T("Deleting files finished");
 
 		return TSubTaskBase::eSubResult_Continue;
 	}
Index: src/libchcore/TSubTaskDelete.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskDelete.h	(.../TSubTaskDelete.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskDelete.h	(.../TSubTaskDelete.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -54,7 +54,7 @@
 #pragma warning(push)
 #pragma warning(disable: 4251)
 		TSubTaskStatsInfo m_tSubTaskStats;
-		TLogger m_log;
+		TLoggerPtr m_spLog;
 #pragma warning(pop)
 	};
 }
Index: src/libchcore/TSubTaskFastMove.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskFastMove.cpp	(.../TSubTaskFastMove.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskFastMove.cpp	(.../TSubTaskFastMove.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -46,7 +46,7 @@
 	TSubTaskFastMove::TSubTaskFastMove(TSubTaskContext& rContext) :
 		TSubTaskBase(rContext),
 		m_tSubTaskStats(eSubOperation_FastMove),
-		m_log(rContext.GetLogPath().ToString(), L"ST-FastMove")
+		m_spLog(rContext.GetLogFactory()->CreateLogger(L"ST-FastMove"))
 	{
 	}
 
@@ -91,9 +91,9 @@
 		const TFileFiltersArray& rafFilters = GetContext().GetFilters();
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 
-		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogPath(), rThreadController);
+		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogFactory(), rThreadController);
 
-		LOG_INFO(m_log) << _T("Performing initial fast-move operation...");
+		LOG_INFO(m_spLog) << _T("Performing initial fast-move operation...");
 
 		// new stats
 		m_tSubTaskStats.SetCurrentBufferIndex(TBufferSizes::eBuffer_Default);
@@ -172,7 +172,7 @@
 			if (rThreadController.KillRequested())
 			{
 				// log
-				LOG_INFO(m_log) << _T("Kill request while fast moving items");
+				LOG_INFO(m_spLog) << _T("Kill request while fast moving items");
 				return eSubResult_KillRequest;
 			}
 		}
@@ -182,7 +182,7 @@
 		m_tSubTaskStats.SetCurrentPath(TString());
 
 		// log
-		LOG_INFO(m_log) << _T("Fast moving finished");
+		LOG_INFO(m_spLog) << _T("Fast moving finished");
 
 		return eSubResult_Continue;
 	}
Index: src/libchcore/TSubTaskFastMove.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskFastMove.h	(.../TSubTaskFastMove.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskFastMove.h	(.../TSubTaskFastMove.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -57,7 +57,7 @@
 #pragma warning(push)
 #pragma warning(disable: 4251)
 		TSubTaskStatsInfo m_tSubTaskStats;
-		TLogger m_log;
+		TLoggerPtr m_spLog;
 #pragma warning(pop)
 	};
 }
Index: src/libchcore/TSubTaskScanDirectory.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskScanDirectory.cpp	(.../TSubTaskScanDirectory.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -28,7 +28,6 @@
 #include "TBasePathData.h"
 #include "TWorkerThreadController.h"
 #include "TTaskLocalStats.h"
-#include <boost\smart_ptr\make_shared.hpp>
 #include "TFileInfoArray.h"
 #include "TFileInfo.h"
 #include "TCoreException.h"
@@ -47,7 +46,7 @@
 	TSubTaskScanDirectories::TSubTaskScanDirectories(TSubTaskContext& rContext) :
 		TSubTaskBase(rContext),
 		m_tSubTaskStats(eSubOperation_Scanning),
-		m_log(rContext.GetLogPath().ToString(), L"ST-ScanDirs")
+		m_spLog(rContext.GetLogFactory()->CreateLogger(L"ST-ScanDirs"))
 	{
 	}
 
@@ -92,9 +91,9 @@
 		const TFileFiltersArray& rafFilters = GetContext().GetFilters();
 		IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem();
 
-		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogPath(), rThreadController);
+		TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogFactory(), rThreadController);
 
-		LOG_INFO(m_log) << _T("Searching for files...");
+		LOG_INFO(m_spLog) << _T("Searching for files...");
 
 		// reset progress
 		rFilesCache.SetComplete(false);
@@ -147,7 +146,7 @@
 			// log
 			strFormat = _T("Adding file/folder (clipboard) : %path ...");
 			strFormat.Replace(_T("%path"), pathCurrent.ToString());
-			LOG_INFO(m_log) << strFormat.c_str();
+			LOG_INFO(m_spLog) << strFormat.c_str();
 
 			// add if needed
 			if (spFileInfo->IsDirectory())
@@ -161,22 +160,22 @@
 					// log
 					strFormat = _T("Added folder %path");
 					strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
-					LOG_INFO(m_log) << strFormat.c_str();
+					LOG_INFO(m_spLog) << strFormat.c_str();
 				}
 
 				// don't add folder contents when moving inside one disk boundary
 				// log
 				strFormat = _T("Recursing folder %path");
 				strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
-				LOG_INFO(m_log) << strFormat.c_str();
+				LOG_INFO(m_spLog) << strFormat.c_str();
 
 				ScanDirectory(spFileInfo->GetFullFilePath(), spBasePath, true, !bIgnoreDirs || bForceDirectories, rafFilters);
 
 				// check for kill need
 				if (rThreadController.KillRequested())
 				{
 					// log
-					LOG_INFO(m_log) << _T("Kill request while adding data to files array (RecurseDirectories)");
+					LOG_INFO(m_spLog) << _T("Kill request while adding data to files array (RecurseDirectories)");
 					rFilesCache.Clear();
 					return eSubResult_KillRequest;
 				}
@@ -190,7 +189,7 @@
 				// log
 				strFormat = _T("Added file %path");
 				strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString());
-				LOG_INFO(m_log) << strFormat.c_str();
+				LOG_INFO(m_spLog) << strFormat.c_str();
 			}
 		}
 
@@ -202,7 +201,7 @@
 		rFilesCache.SetComplete(true);
 
 		// log
-		LOG_INFO(m_log) << _T("Searching for files finished");
+		LOG_INFO(m_spLog) << _T("Searching for files finished");
 
 		return eSubResult_Continue;
 	}
Index: src/libchcore/TSubTaskScanDirectory.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TSubTaskScanDirectory.h	(.../TSubTaskScanDirectory.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TSubTaskScanDirectory.h	(.../TSubTaskScanDirectory.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -62,7 +62,7 @@
 #pragma warning(push)
 #pragma warning(disable: 4251)
 		TSubTaskStatsInfo m_tSubTaskStats;
-		TLogger m_log;
+		TLoggerPtr m_spLog;
 #pragma warning(pop)
 	};
 }
Index: src/libchcore/TTask.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTask.cpp	(.../TTask.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TTask.cpp	(.../TTask.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -47,14 +47,15 @@
 	////////////////////////////////////////////////////////////////////////////
 	// TTask members
 
-	TTask::TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskDefinition& rTaskDefinition, const TSmartPath& rLogPath) :
-		m_log(rLogPath.ToString(), L"Task"),
+	TTask::TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler,
+		const TTaskDefinition& rTaskDefinition, const TSmartPath& rLogPath, const TMultiLoggerConfigPtr& spLoggerConfig) :
+		m_spLogFactory(new TLoggerFactory(rLogPath, spLoggerConfig)),
 		m_spInternalFeedbackHandler(spFeedbackHandler),
 		m_spSrcPaths(new TBasePathDataContainer),
 		m_bForce(false),
 		m_bContinue(false),
 		m_tSubTaskContext(m_tConfiguration, m_spSrcPaths, m_afFilters,
-			m_cfgTracker, rLogPath, m_workerThread,
+			m_cfgTracker, m_spLogFactory, m_workerThread,
 			std::make_shared<TLocalFilesystem>()),
 		m_tSubTasksArray(m_tSubTaskContext),
 		m_spSerializer(spSerializer)
@@ -64,18 +65,19 @@
 		if(!spSerializer)
 			throw TCoreException(eErr_InvalidArgument, L"spSerializer", LOCATION);
 
+		m_spLog = m_spLogFactory->CreateLogger(L"Task");
 		m_tBaseData.SetLogPath(rLogPath);
 		SetTaskDefinition(rTaskDefinition);
 	}
 
-	TTask::TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskBaseData& rBaseTaskData) :
-		m_log(rBaseTaskData.GetLogPath().ToString(), L"Task"),
+	TTask::TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskBaseData& rBaseTaskData, const TMultiLoggerConfigPtr& spLoggerConfig) :
+		m_spLogFactory(new TLoggerFactory(rBaseTaskData.GetLogPath(), spLoggerConfig)),
 		m_spInternalFeedbackHandler(spFeedbackHandler),
 		m_spSrcPaths(new TBasePathDataContainer),
 		m_bForce(false),
 		m_bContinue(false),
 		m_tSubTaskContext(m_tConfiguration, m_spSrcPaths, m_afFilters,
-			m_cfgTracker, rBaseTaskData.GetLogPath(), m_workerThread,
+			m_cfgTracker, m_spLogFactory, m_workerThread,
 			std::make_shared<TLocalFilesystem>()),
 		m_tSubTasksArray(m_tSubTaskContext),
 		m_spSerializer(spSerializer)
@@ -84,6 +86,8 @@
 			throw TCoreException(eErr_InvalidArgument, L"spFeedbackHandler", LOCATION);
 		if(!spSerializer)
 			throw TCoreException(eErr_InvalidArgument, L"spSerializer", LOCATION);
+
+		m_spLog = m_spLogFactory->CreateLogger(L"Task");
 	}
 
 	TTask::~TTask()
@@ -207,7 +211,7 @@
 			{
 				if (bLogPathLoaded)
 				{
-					LOG_ERROR(m_log) << szErr;
+					LOG_ERROR(m_spLog) << szErr;
 				}
 			}
 			catch (const std::exception&)
@@ -216,13 +220,13 @@
 		}
 	}
 
-	TTaskPtr TTask::Load(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler)
+	TTaskPtr TTask::Load(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TMultiLoggerConfigPtr& spLoggerConfig)
 	{
 		TTaskBaseData tBaseData;
 		ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("task"));
 		tBaseData.Load(spContainer);
 
-		TTaskPtr spTask = std::shared_ptr<TTask>(new TTask(spSerializer, spFeedbackHandler, tBaseData));
+		TTaskPtr spTask = std::shared_ptr<TTask>(new TTask(spSerializer, spFeedbackHandler, tBaseData, spLoggerConfig));
 		spTask->Load(tBaseData);
 
 		return spTask;
@@ -307,7 +311,7 @@
 
 	void TTask::BeginProcessing()
 	{
-		LOG_INFO(m_log) << _T("Requested task to begin processing");
+		LOG_INFO(m_spLog) << _T("Requested task to begin processing");
 
 		boost::unique_lock<boost::shared_mutex> lock(m_lock);
 		if (m_tBaseData.GetCurrentState() != eTaskState_LoadError)
@@ -319,7 +323,7 @@
 		// the same as retry but less demanding
 		if (GetTaskState() == eTaskState_Paused)
 		{
-			LOG_INFO(m_log) << _T("Requested task resume");
+			LOG_INFO(m_spLog) << _T("Requested task resume");
 			SetTaskState(eTaskState_Processing);
 			BeginProcessing();
 		}
@@ -353,7 +357,7 @@
 
 	void TTask::RestartProcessing()
 	{
-		LOG_INFO(m_log) << _T("Requested task restart");
+		LOG_INFO(m_spLog) << _T("Requested task restart");
 		KillThread();
 
 		SetTaskState(eTaskState_None);
@@ -378,7 +382,7 @@
 	{
 		if (GetTaskState() != eTaskState_Finished && GetTaskState() != eTaskState_Cancelled)
 		{
-			LOG_INFO(m_log) << _T("Requested task pause");
+			LOG_INFO(m_spLog) << _T("Requested task pause");
 			KillThread();
 			SetTaskState(eTaskState_Paused);
 		}
@@ -389,7 +393,7 @@
 		// change to ST_CANCELLED
 		if (GetTaskState() != eTaskState_Finished)
 		{
-			LOG_INFO(m_log) << _T("Requested task cancel");
+			LOG_INFO(m_spLog) << _T("Requested task cancel");
 			KillThread();
 			SetTaskState(eTaskState_Cancelled);
 		}
@@ -527,7 +531,7 @@
 				SetTaskState(eTaskState_Processing);
 				bContinue = true;
 
-				LOG_INFO(m_log) << _T("Finished waiting for begin permission");
+				LOG_INFO(m_spLog) << _T("Finished waiting for begin permission");
 
 				//			return; // skips sleep and kill flag checking
 			}
@@ -537,7 +541,7 @@
 			if (m_workerThread.KillRequested())
 			{
 				// log
-				LOG_INFO(m_log) << _T("Kill request while waiting for begin permission (wait state)");
+				LOG_INFO(m_spLog) << _T("Kill request while waiting for begin permission (wait state)");
 				return TSubTaskBase::eSubResult_KillRequest;
 			}
 		}
@@ -575,7 +579,7 @@
 			m_tConfiguration.ConnectToNotifier(TTask::OnCfgOptionChanged, this);
 
 			// verify configuration is valid
-			TTaskConfigVerifier::VerifyAndUpdate(m_tConfiguration, &m_log);
+			TTaskConfigVerifier::VerifyAndUpdate(m_tConfiguration, m_spLog);
 
 			// set thread options
 			HANDLE hThread = GetCurrentThread();
@@ -672,7 +676,7 @@
 
 		// log
 		TString strMsg = TString(L"Caught exception in ThrdProc: ") + upExceptionInfoBuffer.get();
-		LOG_ERROR(m_log) << strMsg.c_str();
+		LOG_ERROR(m_spLog) << strMsg.c_str();
 
 		// let others know some error happened
 		spFeedbackHandler->OperationError();
@@ -697,7 +701,7 @@
 		strFormat.Replace(_T("%hour"), boost::lexical_cast<std::wstring>(tm.GetHour()).c_str());
 		strFormat.Replace(_T("%minute"), boost::lexical_cast<std::wstring>(tm.GetMinute()).c_str());
 		strFormat.Replace(_T("%second"), boost::lexical_cast<std::wstring>(tm.GetSecond()).c_str());
-		LOG_INFO(m_log) << strFormat.c_str();
+		LOG_INFO(m_spLog) << strFormat.c_str();
 	}
 
 	void TTask::OnEndOperation()
@@ -711,7 +715,7 @@
 		strFormat.Replace(_T("%hour"), boost::lexical_cast<std::wstring>(tm.GetHour()).c_str());
 		strFormat.Replace(_T("%minute"), boost::lexical_cast<std::wstring>(tm.GetMinute()).c_str());
 		strFormat.Replace(_T("%second"), boost::lexical_cast<std::wstring>(tm.GetSecond()).c_str());
-		LOG_INFO(m_log) << strFormat.c_str();
+		LOG_INFO(m_spLog) << strFormat.c_str();
 	}
 
 	void TTask::RequestStopThread()
Index: src/libchcore/TTask.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTask.h	(.../TTask.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TTask.h	(.../TTask.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -35,6 +35,7 @@
 #include <mutex>
 #include "IFilesystem.h"
 #include "..\Common\TLogger.h"
+#include "..\common\TLoggerFactory.h"
 
 namespace chcore
 {
@@ -48,8 +49,8 @@
 	class LIBCHCORE_API TTask
 	{
 	private:
-		TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskBaseData& rBaseTaskData);
-		TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskDefinition& rTaskDefinition, const TSmartPath& rLogPath);
+		TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskBaseData& rBaseTaskData, const TMultiLoggerConfigPtr& spLoggerConfig);
+		TTask(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TTaskDefinition& rTaskDefinition, const TSmartPath& rLogPath, const TMultiLoggerConfigPtr& spLoggerConfig);
 
 	public:
 		~TTask();
@@ -69,7 +70,7 @@
 		// thread
 		void SetPriority(int nPriority);
 
-		static TTaskPtr Load(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler);
+		static TTaskPtr Load(const ISerializerPtr& spSerializer, const IFeedbackHandlerPtr& spFeedbackHandler, const TMultiLoggerConfigPtr& spLoggerConfig);
 		void Store(bool bForce);
 
 		void BeginProcessing();
@@ -142,9 +143,10 @@
 		// base data
 		TTaskBaseData m_tBaseData;
 
-		// basic information
 #pragma warning(push)
 #pragma warning(disable: 4251)
+		TLoggerFactoryPtr m_spLogFactory;
+		TLoggerPtr m_spLog;				///< Log file where task information will be stored
 		TBasePathDataContainerPtr m_spSrcPaths;
 #pragma warning(pop)
 
@@ -165,12 +167,6 @@
 		bool m_bForce;						// if the continuation of tasks should be independent of max concurrently running task limit
 		bool m_bContinue;					// allows task to continue
 
-		// other helpers
-#pragma warning(push)
-#pragma warning(disable: 4251)
-		TLogger m_log;				///< Log file where task information will be stored
-#pragma warning(pop)
-
 		/// Thread controlling object
 		TWorkerThreadController m_workerThread;
 
Index: src/libchcore/TTaskConfigVerifier.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTaskConfigVerifier.cpp	(.../TTaskConfigVerifier.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TTaskConfigVerifier.cpp	(.../TTaskConfigVerifier.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -24,15 +24,15 @@
 
 namespace chcore
 {
-	void TTaskConfigVerifier::VerifyAndUpdate(TConfig& rConfig, TLogger* pLog)
+	void TTaskConfigVerifier::VerifyAndUpdate(TConfig& rConfig, const TLoggerPtr& spLog)
 	{
 		TString strFirstFormat = GetTaskPropValue<eTO_AlternateFilenameFormatString_First>(rConfig);
 		if(strFirstFormat.Find(L"%name") == TString::npos || strFirstFormat.Find(L"%ext") == TString::npos)
 		{
 			TString strDefaultFormat = TaskPropData<eTO_AlternateFilenameFormatString_First>::GetDefaultValue();
-			if(pLog)
+			if(spLog)
 			{
-				LOG_WARNING(*pLog) << boost::str(boost::wformat(L"First alternate filename format string (%1%) does not contain %%name placeholder. Switching to default (%2%).")
+				LOG_WARNING(spLog) << boost::str(boost::wformat(L"First alternate filename format string (%1%) does not contain %%name placeholder. Switching to default (%2%).")
 						% strFirstFormat.c_str()
 						% strDefaultFormat.c_str()).c_str();
 			}
@@ -45,9 +45,9 @@
 			|| strSubsequentFormat.Find(L"%ext") == TString::npos)
 		{
 			TString strDefaultFormat = TaskPropData<eTO_AlternateFilenameFormatString_AfterFirst>::GetDefaultValue();
-			if(pLog)
+			if(spLog)
 			{
-				LOG_WARNING(*pLog) <<
+				LOG_WARNING(spLog) <<
 					boost::str(boost::wformat(L"Subsequent alternate filename format string (%1%) does not contain %%name or %%count placeholder. Switching to default (%2%).")
 						% strSubsequentFormat.c_str()
 						% strDefaultFormat.c_str()).c_str();
Index: src/libchcore/TTaskConfigVerifier.h
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTaskConfigVerifier.h	(.../TTaskConfigVerifier.h)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TTaskConfigVerifier.h	(.../TTaskConfigVerifier.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -19,7 +19,7 @@
 #ifndef __TTASKCONFIGVERIFIER_H__
 #define __TTASKCONFIGVERIFIER_H__
 
-class TLogger;
+#include "..\common\TLogger.h"
 
 namespace chcore
 {
@@ -28,7 +28,7 @@
 	class TTaskConfigVerifier
 	{
 	public:
-		static void VerifyAndUpdate(TConfig& rConfig, TLogger* pLog);
+		static void VerifyAndUpdate(TConfig& rConfig, const TLoggerPtr& spLog);
 	};
 }
 
Index: src/libchcore/TTaskManager.cpp
===================================================================
diff -u -N -r6f8b891b60eb0f33199fd29db75d4d9f4a22c248 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTaskManager.cpp	(.../TTaskManager.cpp)	(revision 6f8b891b60eb0f33199fd29db75d4d9f4a22c248)
+++ src/libchcore/TTaskManager.cpp	(.../TTaskManager.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -36,15 +36,19 @@
 	TTaskManager::TTaskManager(const ISerializerFactoryPtr& spSerializerFactory,
 		const IFeedbackHandlerFactoryPtr& spFeedbackHandlerFactory,
 		const TSmartPath& pathLogDir,
+		const TMultiLoggerConfigPtr& spMultiLoggerConfig,
 		bool bForceRecreateSerializer) :
 		m_spSerializerFactory(spSerializerFactory),
 		m_spFeedbackFactory(spFeedbackHandlerFactory),
-		m_pathLogDir(pathLogDir)
+		m_pathLogDir(pathLogDir),
+		m_spMultiLoggerConfig(spMultiLoggerConfig)
 	{
 		if(!spFeedbackHandlerFactory)
 			throw TCoreException(eErr_InvalidPointer, L"spFeedbackHandlerFactory", LOCATION);
-		if(!spSerializerFactory)
+		if (!spSerializerFactory)
 			throw TCoreException(eErr_InvalidPointer, L"spSerializerFactory", LOCATION);
+		if (!spMultiLoggerConfig)
+			throw TCoreException(eErr_InvalidPointer, L"spMultiLoggerConfig", LOCATION);
 		m_spSerializer = m_spSerializerFactory->CreateTaskManagerSerializer(bForceRecreateSerializer);
 	}
 
@@ -58,7 +62,7 @@
 		IFeedbackHandlerPtr spHandler = m_spFeedbackFactory->Create();
 		ISerializerPtr spSerializer = m_spSerializerFactory->CreateTaskSerializer(tTaskDefinition.GetTaskName());
 
-		TTaskPtr spTask(new TTask(spSerializer, spHandler, tTaskDefinition, CreateTaskLogPath(tTaskDefinition.GetTaskName())));
+		TTaskPtr spTask(new TTask(spSerializer, spHandler, tTaskDefinition, CreateTaskLogPath(tTaskDefinition.GetTaskName()), m_spMultiLoggerConfig));
 
 		spTask->Store(true);
 
@@ -522,7 +526,7 @@
 			if (!spSerializer)
 				spSerializer = std::make_shared<TFakeFileSerializer>(rInfo.second);
 
-			TTaskPtr spTask = TTask::Load(spSerializer, spHandler);
+			TTaskPtr spTask = TTask::Load(spSerializer, spHandler, m_spMultiLoggerConfig);
 
 			boost::unique_lock<boost::shared_mutex> lock(m_lock);
 
Index: src/libchcore/TTaskManager.h
===================================================================
diff -u -N -r4fe995b304ea342b50293f92d3c1992b43b820f7 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTaskManager.h	(.../TTaskManager.h)	(revision 4fe995b304ea342b50293f92d3c1992b43b820f7)
+++ src/libchcore/TTaskManager.h	(.../TTaskManager.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -27,6 +27,7 @@
 #include "ISerializer.h"
 #include "ISerializerFactory.h"
 #include "TObsoleteFiles.h"
+#include "..\common\TMultiLoggerConfig.h"
 
 namespace chcore
 {
@@ -42,6 +43,7 @@
 		TTaskManager(const ISerializerFactoryPtr& spSerializerFactory,
 			const IFeedbackHandlerFactoryPtr& spFeedbackHandlerFactory,
 			const TSmartPath& pathLogDir,
+			const TMultiLoggerConfigPtr& spMultiLoggerConfig,
 			bool bForceRecreateSerializer = false);
 
 		~TTaskManager();
@@ -101,6 +103,7 @@
 		IFeedbackHandlerFactoryPtr m_spFeedbackFactory;
 		ISerializerPtr m_spSerializer;
 		ISerializerFactoryPtr m_spSerializerFactory;
+		TMultiLoggerConfigPtr m_spMultiLoggerConfig;
 #pragma warning(pop)
 	};
 
Index: src/libchcore/TTimestampProviderTickCount.h
===================================================================
diff -u -N -r4fe995b304ea342b50293f92d3c1992b43b820f7 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/TTimestampProviderTickCount.h	(.../TTimestampProviderTickCount.h)	(revision 4fe995b304ea342b50293f92d3c1992b43b820f7)
+++ src/libchcore/TTimestampProviderTickCount.h	(.../TTimestampProviderTickCount.h)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -20,10 +20,11 @@
 #define __TTIMESTAMPPROVIDERTICKCOUNT_H__
 
 #include "ITimestampProvider.h"
+#include "libchcore.h"
 
 namespace chcore
 {
-	class TTimestampProviderTickCount : public ITimestampProvider
+	class LIBCHCORE_API TTimestampProviderTickCount : public ITimestampProvider
 	{
 	public:
 		TTimestampProviderTickCount();
Index: src/libchcore/Tests/TestsTTaskConfigVerifier.cpp
===================================================================
diff -u -N -r3526dc60304e69e55a129472a71594d4dacda5b2 -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/Tests/TestsTTaskConfigVerifier.cpp	(.../TestsTTaskConfigVerifier.cpp)	(revision 3526dc60304e69e55a129472a71594d4dacda5b2)
+++ src/libchcore/Tests/TestsTTaskConfigVerifier.cpp	(.../TestsTTaskConfigVerifier.cpp)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -51,7 +51,6 @@
 
 TEST(TestsTTaskConfigVerifier, VerifyAndUpdate_NextAlternateFilenameFormat_Valid)
 {
-	log_file log;
 	TConfig config;
 
 	SetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(config, L"Subsequent copy of %name (%count)%ext");
@@ -66,7 +65,6 @@
 
 TEST(TestsTTaskConfigVerifier, VerifyAndUpdate_NextAlternateFilenameFormat_InvalidCount)
 {
-	log_file log;
 	TConfig config;
 
 	SetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(config, L"Subsequent copy of %name (%cout)%ext");
@@ -96,7 +94,6 @@
 
 TEST(TestsTTaskConfigVerifier, VerifyAndUpdate_NextAlternateFilenameFormat_InvalidName)
 {
-	log_file log;
 	TConfig config;
 
 	SetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(config, L"Subsequent copy of %ame (%count)%ext");
Index: src/libchcore/libchcore.vc140.vcxproj
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/libchcore.vc140.vcxproj	(.../libchcore.vc140.vcxproj)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/libchcore/libchcore.vc140.vcxproj	(.../libchcore.vc140.vcxproj)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -456,8 +456,15 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClInclude Include="..\common\TLogger.h" />
+    <ClInclude Include="..\common\TLoggerLevelConfig.h" />
+    <ClInclude Include="..\common\TLoggerFactory.h" />
     <ClInclude Include="..\common\TLoggerInitializer.h" />
+    <ClInclude Include="..\common\TLoggerLocationConfig.h" />
+    <ClInclude Include="..\common\TLogRotator.h" />
+    <ClInclude Include="..\common\TLogSink.h" />
+    <ClInclude Include="..\common\TLogSinkCollection.h" />
     <ClInclude Include="..\common\TMultiFileBackend.h" />
+    <ClInclude Include="..\common\TMultiLoggerConfig.h" />
     <ClInclude Include="CommonDataTypes.h" />
     <ClInclude Include="ConfigNode.h" />
     <ClInclude Include="ConfigNodeContainer.h" />
@@ -600,8 +607,15 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">NotUsing</PrecompiledHeader>
     </ClCompile>
     <ClCompile Include="..\common\TLogger.cpp" />
+    <ClCompile Include="..\common\TLoggerLevelConfig.cpp" />
+    <ClCompile Include="..\common\TLoggerFactory.cpp" />
     <ClCompile Include="..\common\TLoggerInitializer.cpp" />
+    <ClCompile Include="..\common\TLoggerLocationConfig.cpp" />
+    <ClCompile Include="..\common\TLogRotator.cpp" />
+    <ClCompile Include="..\common\TLogSink.cpp" />
+    <ClCompile Include="..\common\TLogSinkCollection.cpp" />
     <ClCompile Include="..\common\TMultiFileBackend.cpp" />
+    <ClCompile Include="..\common\TMultiLoggerConfig.cpp" />
     <ClCompile Include="ConfigNode.cpp" />
     <ClCompile Include="ConfigNodeContainer.cpp" />
     <ClCompile Include="IColumnsDefinition.cpp" />
Index: src/libchcore/libchcore.vc140.vcxproj.filters
===================================================================
diff -u -N -r205f3bfeed0082edb35430a9a0968699e5cc7fea -r62d767936f1675e1db51174f53c91484fe691937
--- src/libchcore/libchcore.vc140.vcxproj.filters	(.../libchcore.vc140.vcxproj.filters)	(revision 205f3bfeed0082edb35430a9a0968699e5cc7fea)
+++ src/libchcore/libchcore.vc140.vcxproj.filters	(.../libchcore.vc140.vcxproj.filters)	(revision 62d767936f1675e1db51174f53c91484fe691937)
@@ -473,6 +473,27 @@
     <ClInclude Include="..\common\TMultiFileBackend.h">
       <Filter>Source Files\Shared\Logging</Filter>
     </ClInclude>
+    <ClInclude Include="..\common\TLogRotator.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLogSink.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLogSinkCollection.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLoggerFactory.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TMultiLoggerConfig.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLoggerLevelConfig.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TLoggerLocationConfig.h">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="TSubTaskArray.cpp">
@@ -859,11 +880,32 @@
     <ClCompile Include="..\common\TLoggerInitializer.cpp">
       <Filter>Source Files\Shared\Logging</Filter>
     </ClCompile>
+    <ClCompile Include="..\common\TMultiFileBackend.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLogRotator.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLogSink.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLogSinkCollection.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
     <ClCompile Include="TCoreEngine.cpp">
-      <Filter>Source Files</Filter>
+      <Filter>Source Files\Library files</Filter>
     </ClCompile>
-    <ClCompile Include="..\common\TMultiFileBackend.cpp">
+    <ClCompile Include="..\common\TLoggerFactory.cpp">
       <Filter>Source Files\Shared\Logging</Filter>
     </ClCompile>
+    <ClCompile Include="..\common\TMultiLoggerConfig.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLoggerLevelConfig.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
+    <ClCompile Include="..\common\TLoggerLocationConfig.cpp">
+      <Filter>Source Files\Shared\Logging</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file