【问题标题】:How to improve this logging scheme (A little more)如何改进此日志记录方案(更多)
【发布时间】:2010-11-18 07:14:39
【问题描述】:

基本上,我有这个记录器类和前缀。

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;
};

现在,在完成任何日志记录的函数中,我这样做:

void SomeObject::SomeMethod()
{
   Prepender(*p_Logger, __PRETTY_FUNCTION__);

   //Do stuff
}

效果很好。

有没有办法通过在需要记录的地方手动创建Prepender 对象来改善这一点? (甚至宏?)(我明白这可能是不可能的,我想知道其他人有什么想法)。

编辑:因为我看到很多人有错误的想法,我最好这样做:

void SomeObject::SomeMethod()
{
   //Prepender(*p_Logger, __PRETTY_FUNCTION__);

   //Do stuff
   //And the same results!!!
}

这样做的主要动机是确保在其中完成日志记录时我不会忘记为函数添加前缀。如果我这样做了,报告的功能将比真实的高一级。

【问题讨论】:

  • 您不能说明您想要达到的目标吗?您希望客户端代码如何显示?
  • @Simone:"有什么办法可以通过在需要记录的地方手动创建Prepender 对象来改善这一点?" ?
  • 我改变了主意:可以做到:)

标签: c++


【解决方案1】:

EDIT2:

根据 OP 中修改后的 Edit,至少 IMO 无法实现以可移植方式登录的预期目标。

编辑1:

  1. 您不想支持宽字符吗?
  2. 为什么不使用字符串 (wstring) 而不是 char*?
  3. Lo​​gger 应该是 Singleton 或 Monostate(应该处理与在每个函数入口处创建它相关的挑战)
  4. 这是否要求线程安全?
  5. 为什么不在 Logger 中使用纯虚拟析构函数?
  6. 名称记录器看起来不正确。它应该表示类似 LogInterface 等。
  7. 异常处理呢?

在你告诉我们规格之前,我可以继续做一些!

【讨论】:

  • 嘿,我只是在谈论摆脱手动创建Prepender :D。当然你可以改进它。这是菜鸟编码的!
  • 哦。我被帖子的标题迷住了(也)
  • @nakiya:你可以查看stackoverflow.com/questions/949556/…。抱歉,您将不得不等待其他专家获得更多想法
  • 在查看了您提供的链接并稍加思考后,我现在几乎可以确定我所问的是不可能的。除此之外,你的第 5 点呢? :)。纯虚拟析构函数?我认为你必须提供一个析构函数体,无论它是否是虚拟的(甚至是纯虚拟的)。
【解决方案2】:

嗯,你可以使用宏:

METHOD(void SomeObject::SomeMethod())
   // do your stuff...
ENDMETHOD

where:

#define METHOD(method_declaration) method_declaration \
   Prepender(*p_Logger, __PRETTY_FUNCTION__); 

#define ENDMETHOD }

如果你愿意,你也可以在方法的末尾添加一些东西。

【讨论】:

  • 是的,但这并不能解决基本问题。如果我忘记将函数包含在宏中,我最终可能仍会为错误消息记录错误的函数签名。理想情况下,我希望在某处进行一次性初始化,并且可以轻松地认为前缀将被覆盖。在我和你的方法中,我必须手动确保 - 甚至无法产生编译器或运行时错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 2018-07-29
  • 1970-01-01
  • 2018-06-21
相关资源
最近更新 更多