2010-09-11 1 views
1

Я пытаюсь найти достойный способ ведения журнала с C++. Мое текущее решение таково:Функция WriteLog (...) в C++

ostream & GetLog() { if(output == NULL) throw error; return *output; } 

Где выход определен где-то и может быть файлом или чем угодно. Это нормально, но он не позволяет мне ничего делать, кроме как выдать ошибку, если вывод не выделен. Кроме того, моя программа многопоточна, и мне нужно получить блокировку, чтобы правильно проверить, не является ли вывод NULL, а затем записать в него, если это не так. В идеале, любой код, который использует GetLog() должен получить эту блокировку:

{ 
    LockLog lock; 
    if(HasLog()) 
     GetLog() << "My dog ate " << n << " cookies!" << endl; 
} 

Это кажется, что слишком много пустословия мне. Я хотел бы сделать что-то вроде просто

GetLog() << "My dog ate " << n << " cookies!" << endl; 

и он работает без ошибок, когда журнал не выделяется (и с замком), или функция, как

WriteLog("My dog ate " << n << " cookies!" << endl); 

Я знаю, что с C Printf синтаксис это можно сделать с помощью функции переменных аргументов. Есть ли способ сделать это с синтаксисом C++ и без макроса, который заставил бы меня в любом случае разоблачить функции GetLog, HasLog и LockLog?

+0

Если вам нравится 'printf', что мешает вам использовать его? Он находится внутри ''. – zneak

+0

@zneak, очевидно, моя проблема не в том, где найти printf. Я просто привык к синтаксису iostream, и весь мой код написан с его использованием, но в любом случае спасибо. – Scott

ответ

0

Использование log4cxx, который является

достойный способ сделать вход с C++

, что вы вряд ли смогут своевременно соответствовать. Даже если это кажется излишним, вы можете обнаружить, что ваши потребности в диагностике растут по мере того, как ваша система делает, что делает компонент каротажа временем, которое не было предусмотрено в начале.

Я нахожу, что я как сэкономил время, так и научился хорошему дизайну от лучших разработчиков, когда я использую хорошо разработанные, надежные фреймворки, подобные этому (см. Boost, STL).

2

нравится это?

class Log { 
    class buffer { 
     buffer(...); 
     ~buffer() { 
      Lock lock(mutex); 
      // write in destrcutor 
     } 
     string data; 
     Mutex &mutex; 
    }; 
    Mutex mutex; 
... 
}; 

template<class T> 
Log::buffer operator<<(Log& l, T t) { 
    return t; 
} 

template<class T> 
Log::buffer& operator<<(Log::buffer& b, T t) { 
    return b += t; 
} 

Log log; 

log << "blah" << 6; 
+0

Это может плохо работать в среде MT, поскольку вы блокируете только для каждого вызова оператора << << ... – Nick

+0

@ Ник справедливый, дайте мне sec – Anycorn

+0

Не следует блокировать одноэлементный/монопольный вид класса? – Chubsdad

0

Из опыта, я хотел бы написать функцию, которая принимает строку (или список строк), и замки/журналы внутри функции. Оставьте форматирование вне фактической функции ведения журнала, чтобы вы гарантировали, что все будет регистрироваться в одном блоке для одного сообщения логического журнала.

Вы можете сделать что-то вроде того, что я сделал для обработки форматирования, а именно: создать производный от строки класс с конструктором типа printf и использовать его inline.

Так, например:

class PFString : public string 
{ 
public: 
    PFString(const char* pcszFormat, ...) 
    { ... } 
}; 

Log(PFString("something with number %d", 42)); 

Конечно, вы свободны для форматирования строки и другие способы тоже (например: C++ оператор стиль синтаксиса, ресурс строки форматирования и т.д.).