간단한 대답은 하나도 없습니다. 그것은 응용 프로그램에 따라 다릅니다. 난 많은 하위 프로젝트에 대한 로깅 을 다르게 구성 할 수있는 매우 큰 프로젝트에서 작업했습니다. 그러한 시스템은 작은 응용 프로그램 인 에서 과도 할 것입니다. 또한 응용 프로그램 이 장기간 동안 계속 있어야하는 경우에도 차이가 있습니다. 이 경우 응용 프로그램을 중지하지 않고 로그를 재구성하는 것이 좋습니다.
그러나 일반적으로 로그 구성 파일 의 로깅 수준을 지정하고 로그 메시지로 수행 할 작업이 필요합니다. 또한 로깅이 없을 때 최소한 의 작업을 수행해야합니다. 내가 사용한 한 가지 해결책은 사용 가능한 각 작업 (파일에 쓰기, 이메일 보내기, 또는 syslog로 보내기)마다 다양한 streambufs를 유지하는 것입니다. 그러면 ostream * 테이블에 로그 수준으로 색인이 생성됩니다. 해당 레벨에 대한 로깅이 있다면 필요한 모든 작업 streambufs로 전달하는 streambuf를 만들고 테이블에 사용하는 ostream의 주소를 으로 지정합니다. 이 특별한 streambuf에는 각 로깅 레코드를 시작하고 중지하는 기능도 있습니다. 레코드를 시작하는 레코드는 파일 이름과 라인 번호 으로 호출되며 레코드를 중지하는 레코드는 각 관리되는 스트림을 플러시합니다. 주어진 레벨에서 로깅이없는 경우 ostream 포인터는 null입니다.
기본 로거는 다음과 같습니다
이
class Logger
{
std::ostream* myDest;
int* myUseCount;
public:
Logger(int level, char const* filename, int lineNumber)
: myDest(ourLogTable[level])
, myUseCount(new int(1))
{
if (myDest != NULL) {
myDest->rdbuf()->startLogRecord(filename, lineNumber);
}
}
Logger(Logger const& other)
: myDest(other.myDest)
, myUseCount(other.myUseCount)
{
++ *myUseCount;
}
~Logger()
{
-- *myUseCount;
if (*myUseCount == 0 && myDest != NULL) {
myDest->flush();
}
}
template <typename T>
Logger& operator<<(T const& obj)
{
if (myDest != NULL) {
*myDest << obj;
}
}
};
(.. C++ 11, 당신이 내 참조 계산보다는 이동의 의미를 사용해야 훨씬 더 간단) 마지막으로
, 당신은 로거를 호출 매크로를 통해 :
#define LOG(level) Logger(level, __FILE__, __LINE__)
자동 파일 이름과 줄 번호를 삽입 할 경우 매크로의 사용이 필요하다.
[이 질문에 대한 답변] (http://stackoverflow.com/questions/696321/best-logging-framework-for-native-c) –