Basically, I have this logger class and prefixer.
class Logger
{
public:
enum LogType
{
LT_DEBUG = 0,
LT_WARNING,
LT_ERROR,
LT_STAT,
LT_TEXT,
LT_INFO,
LT_OTHER,
LT_UNKNOWN
};
__attribute__((format(printf, 7, 8)))
virtual const char* EHLog(LogType, //LogType
bool, //Send to FE
int, //Error code
const char*, //File
int, //Line
const char*, //Format
...) = 0;
virtual void PushPrependString(const char*) = 0;
virtual void PopPrependString() = 0;
virtual ~Logger(){}
};
class Prepender
{
public:
Prepender(Logger& oLogger, const char* zPrependString)
:o_Logger(oLogger)
{
o_Logger.PushPrependString(zPrependString);
}
~Prepender()
{
o_Logger.PopPrependString();
}
private:
Prepender();
Prepender(const Prepender&);
Prepender& operator=(const Prepender&);
Logger& o_Logger;
};
Now, In the functions where any logging is done, I do this:
void SomeObject::SomeMethod()
{
Prepender(*p_Logger, __PRETTY_FUNCTION__);
//Do stuff
}
which works fine.
Is there any way to improve this by doing away with creating a Prepender
object manually where I need logging? (Even macros?) (I do understand that it maybe impossible, I want to know what ideas others have).
EDIT: As I see lot of people getting wrong ideas, I'd ideally like to do this:
void SomeObject::SomeMethod()
{
//Prepender(*p_Logger, __PRETTY_FUNCTION__);
//Do stuff
//And the same results!!!
}
The main motivation开发者_如何学Go for doing this is to make sure that I do not forget to prefix a function when there is logging being done in it. If I did, the function reported will be one level up than the real one.
EDIT2:
Based on the revised Edit in OP, it is not possible to achieve the desired goals of logging in an portable manner at least, IMO.
EDIT1:
- Don't you want to support wide characters?
- Why not using string (wstring) instead of char*?
- Logger should be either a Singleton or a Monostate (should take care of your challenge related to creating it at each function entry)
- Is this requried to be thread safe?
- Why not a pure virtual destructor in Logger?
- The name logger doesn't look right. It should indicate something like LogInterface etc.
- What about exception handling?
I can go on with a few more, until you tell us the specs!!
Well, you could use a macro:
METHOD(void SomeObject::SomeMethod())
// do your stuff...
ENDMETHOD
where:
#define METHOD(method_declaration) method_declaration \
Prepender(*p_Logger, __PRETTY_FUNCTION__);
#define ENDMETHOD }
you could add something to the method's end too, if you like.
精彩评论