Перенаправление ostream в файл не работает - PullRequest
3 голосов
/ 06 июля 2010

У меня есть собственная система ведения журнала, которая позволяет мне отправлять информацию в файл журнала и на консоль в зависимости от выбранной детализации. Сейчас у меня проблема с выводом в файл, с выводом на консоль, работает нормально.

Вот пример:

     ilra_talk << "Local IP: " << systemIP() << " |  Hostname: " << systemhostname() << endl;
     // the systemIP() and systemhostname() functions have already been defined

Это должно привести к тому, что текущий локальный IP-адрес и имя хоста системы будут напечатаны в файл. Однако это приводит только к тому, что информация выводится на консоль, несмотря на то, что функция перегружена, что приводит к ее печати в обоих случаях.

Я обрисовал в общих чертах код ниже. Любая помощь приветствуется (как всегда).

В настоящее время существует определение для ilra_talk, в результате которого создается новый объект класса:

#define ilra_talk ilra(__FUNCTION__,0)

Определение класса следующее:

class ilra
{
    static int ilralevel_set; // properly initialized in my main .cpp
    static int ilralevel_passed; // properly initialized in my main .cpp
    static bool relay_enabled; // properly initialized in my main .cpp
    static bool log_enabled; // properly initialized in my main .cpp
    static ofstream logfile; // properly initialized in my main .cpp
public:
    // constructor / destructor
    ilra(const std::string &funcName, int toset)
    {
        ilralevel_passed = toset;
    }
    ~ilra(){};

    // enable / disable irla functions
    static void ilra_verbose_level(int toset){
        ilralevel_set = toset;
    }
    static void ilra_log_enabled(bool toset){
        log_enabled = toset;

        if (log_enabled == true){
            // get current time
            time_t rawtime;
            time ( &rawtime );

            // name of log file (based on time of application start)
            stringstream logname_s;
            string logname = "rclient-";
            logname_s << rawtime;
            logname.append(logname_s.str());

            // open a log file
            logfile.open(logname.c_str());
        }
    }

    // output
    template <class T>
    ilra &operator<<(const T &v)
    {
        if(log_enabled == true){ // log_enabled is set to true
            logfile << v; 
            logfile << "Test" << endl;  // test will show up, but intended information will not appear
            }
        if(ilralevel_passed <= ilralevel_set)
            std::cout << v;
        return *this;
    }

    ilra &operator<<(std::ostream&(*f)(std::ostream&))
    {
        if(log_enabled == true) // log_enabled is set to true
            logfile << *f;
        if(ilralevel_passed <= ilralevel_set)
            std::cout << *f;
        return *this;
    }
};  // end of the class

Ответы [ 2 ]

1 голос
/ 07 июля 2010

Я не вижу ничего плохого в коде, хотя лично я сделал бы два изменения:

  1. Поместите logfile.flush () в ilra :: ~ ilra (). Регистрация и буферизация не дружат.

  2. Измените static ofstream logfile на static ofstream *logfile: выделите / удалите его в ilra_log_enabled() и добавьте проверку NULL в операторах <<. Я предпочитаю объекты с явным жизненным циклом. </p>

В целом, поскольку ведение журнала - это снижение производительности, я никогда не использую iostream для него и придерживаюсь макросов, подобных printf (): проверка журналирования выполняется без вызова функции, прямо в макросе. Это имеет важный побочный эффект: если регистрация не нужна, список параметров вообще не оценивается. В вашем случае невозможно избежать вызова функций, например, systemIP() и systemhostname(), поскольку проверка уровня журнала / etc выполняется после того, как они уже были вызваны. С помощью макросов я также могу, например, полностью удалить журналирование на уровне отладки из сборок выпуска (или следствие: в отладочной сборке я могу вести столько журналов, сколько захочу).

0 голосов
/ 07 июля 2010

Похоже, что "Тест", скорее всего, печатается откуда-то еще, и на самом деле log_enabled не установлен в момент, когда вы вставляете данные в поток.Вы пытались безоговорочно вставить данные в поток logfile или распечатать log_enabled каждый раз, когда вызывается operator<<?

Альтернативно, cout имеет тип ostream, а logfile имеет типofstream.Возможно ли, что ваша функция пересылки манипуляторов не выполняет свою работу для ofstream?

...