使用共享DLL进行日志记录的体系结构

时间:2019-05-14 08:02:14

标签: c++ windows logging dll

我一直在为我们的产品编写日志记录代码,但遇到体系结构问题。我们有两个用C ++为Window编写的命令行可执行文件,分别称为Foo和Bar,它们依赖于一个我们称为Core的DLL。我想从Core内登录。

问题是,这些日志条目应该在哪里结束?如果我运行Foo,我想在Foo.log中看到它们,如果我运行Bar,它们应该在Bar.log中。如果我同时运行Foo和Bar,该怎么办? (我认为我已经整理了运行Foo或Bar的多个副本的情况,有效地锁定了日志文件。)

一个想法是,Core可以保留“当有人发出记录请求时我需要调用的所有记录器”的列表。这意味着要编写一个全新的API,并且DLL中的日志记录与exes或静态库中的日志记录不同。那不理想。如果它在lib中,我什至不知道代码在哪里结束!

我已经研究过log4cplus,并增强了日志记录功能,但是对于如何将其与这些组件结合使用也没有任何吸引力,因此有些想法被困住了。这当然可以解决吗?!

1 个答案:

答案 0 :(得分:-1)

功能指针是IMO的关键。

我通常在.exe代码的最顶层实现记录器,而在启动时,我会一直向下传递函数指针。这是一个例子。

enum struct eLogLevel : uint8_t
{
    Error,
    Warning,
    Info,
    Debug
};
// C function pointer to write messages to arbitrary destination. Messages are better to be UTF8.
using pfnLogMessage = void( *)( eLogLevel lvl, const char* msg );

// DLL API, call this once, immediately after loading your DLL. Keep the level + function pointer in static variables. 
// Unless messing with DLL segments, static variables are per-process, i.e. two processes will have different copy of these variables.
// Good idea to also call on shutdown, passing nullptr, before closing the underlying implementation stream.
void initializeLogging( eLogLevel maxLevelToLog, pfnLogMessage fnLogMessage );

// Invoke that function pointer to actually log stuff.
void logMessage( eLogLevel lvl, const CStringA& msg );

// Convenience wrappers to format and write various messages.
// Moar examples: https://github.com/Const-me/vis_avs_dx/blob/master/avs_dx/DxVisuals/Utils/logger.h
inline void logMessageV( eLogLevel lvl, const char* pszFormat, va_list args )
{
    CStringA str;
    str.FormatV( pszFormat, args );
    logMessage( lvl, str );
}

#define LOG_MESSAGE_FORMAT( lvl ) va_list args; va_start( args, pszFormat ); logMessageV( lvl, pszFormat, args ); va_end( args );

inline void logError( const char* pszFormat, ... )
{
    LOG_MESSAGE_FORMAT( eLogLevel::Error );
}