0

I tried to make a custom logger class, with which i then can log information and controll a log-level. But sadly I don't seem to get the setOut, setWarning and setError methods working.

To test things I made a pretty easy logging class, which inherits from std::ostream (because the above mentioned methods expect a std::ostream argument) and overrides the << operator:

#include <ostream>
#include <iostream>

class Logger: public std::ostream
{
    template<typename T>
    friend Logger& operator<<(Logger& logger, const T& t)
    {
        std::cout << "[Log]: " << t;
        return logger;
    }
};

Then I set the test-logging class with:

// a lot of setup, which can be summed up with the following three lines:
IloEnv env;
IloModel model(env);
IloCplex cp(model);

logger::Logger log;
cp.setOut(log);

When I run the code no output is done at all. When removing the cp.setOut(log) code and replacing it with env.setOut(log); the normal information are printed, but without the addional [Log]: :

Version identifier: 20.1.0.0 | 2020-11-10 | 9bedb6d68
Tried aggregator 1 time.
No LP presolve or aggregator reductions.
Presolve time = 0.00 sec. (0.56 ticks)
Initializing dual steep norms . . .

Iteration log . . .
Iteration:     1   Dual objective     =             0.000000
Iteration:    62   Dual objective     =             0.740539

What am I doing wrong and why isn't my code logged, as I would expect?


Edit:

I just noticed, that when setting the cplex out stream to std::cout (cp.setOut(std::cout)) everything workes flawlessly.

Moritz
  • 378
  • 5
  • 14

1 Answers1

0

It seems that I didn't implemented the derived ostream class correctly.

According to this Stack Overflow Answer, when implementing std::ostream you also have to implement the std::streambuf class and implement the (can be private) int overflow(int c) override method. You don't need to provide a << operator, it will work out of the box.

My Logging class now looks like so:

class Logger: private std::streambuf, public std::ostream
{
    std::string buffer;

public:
    Logger(): std::ostream(this) {}

private:
    int overflow(int c) override
    {
        // add the character c to the buffer, unless it is a newline character.
        // if it is a newline character, then print/ log the buffer and afterwards clear it
        if (c == '\n') {
            std::cout << buffer << std::endl; // log the buffer
            buffer.clear();                   // set the buffer to be an empty string
        }
        else {
            buffer += static_cast<char>(c);
        }

        return 0;
    }
};
Moritz
  • 378
  • 5
  • 14