• ceph log机制


    Log 是每个项目必须的,他是跟踪问题的最直接的依据。Ceph 也设计自己的log机制。

    初始化启动log实例,启动log线程。

      _log = new ceph::log::Log(&_conf->subsys);

      _log->start();

    日志的工作函数:

    比较简单,交换队列到临时队列t 中,释放条件变量,开始进入_flush的写操作。

    void Log::flush()

    {

      pthread_mutex_lock(&m_flush_mutex);

      m_flush_mutex_holder = pthread_self();

      pthread_mutex_lock(&m_queue_mutex);

      m_queue_mutex_holder = pthread_self();

      EntryQueue t;

      t.swap(m_new);

      pthread_cond_broadcast(&m_cond_loggers);

      m_queue_mutex_holder = 0;

      pthread_mutex_unlock(&m_queue_mutex);

      _flush(&t, &m_recent, false);

      // trim

      while (m_recent.m_len > m_max_recent) {

        delete m_recent.dequeue();

      }

      m_flush_mutex_holder = 0;

      pthread_mutex_unlock(&m_flush_mutex);

    }

    _flush函数中主要根据subsys 和 其level决定是否写日志,m_subs是负责管理subsys的一个map表。

    这个表是如何生成的呢。

    注意参数:crash 当dump_recent的才会被调用。

    void Log::_flush(EntryQueue *t, EntryQueue *requeue, bool crash)

    {

      Entry *e;

      while ((e = t->dequeue()) != NULL) {

        unsigned sub = e->m_subsys;

        bool should_log = crash || m_subs->get_log_level(sub) >= e->m_prio;

        bool do_fd = m_fd >= 0 && should_log;

        bool do_syslog = m_syslog_crash >= e->m_prio && should_log;

        bool do_stderr = m_stderr_crash >= e->m_prio && should_log;

        bool do_graylog2 = m_graylog_crash >= e->m_prio && should_log;

        e->hint_size();

        if (do_fd || do_syslog || do_stderr) {

          size_t buflen = 0;

          char *buf;

          size_t buf_size = 80 + e->size();

          bool need_dynamic = buf_size >= 0x10000; //avoids >64K buffers

                                                          //allocation at stack

          char buf0[need_dynamic ? 1 : buf_size];

          if (need_dynamic) {

            buf = new char[buf_size];

          } else {

            buf = buf0;

          }

          if (crash)

             buflen += snprintf(buf, buf_size, "%6d> ", -t->m_len);

          buflen += e->m_stamp.sprintf(buf + buflen, buf_size-buflen);

          buflen += snprintf(buf + buflen, buf_size-buflen, " %lx %2d ",

                                (unsigned long)e->m_thread, e->m_prio);

          buflen += e->snprintf(buf + buflen, buf_size - buflen - 1);

          if (buflen > buf_size - 1) { //paranoid check, buf was declared

                                            //to hold everything

            buflen = buf_size - 1;

            buf[buflen] = 0;

          }

          if (do_syslog) {

            syslog(LOG_USER|LOG_INFO, "%s", buf);

          }

          if (do_stderr) {

            cerr << buf << std::endl;

          }

          if (do_fd) {

            buf[buflen] = ' ';

            int r = safe_write(m_fd, buf, buflen+1);

             if (r != m_fd_last_error) {

               if (r < 0)

                 cerr << "problem writing to " << m_log_file

                        << ": " << cpp_strerror(r)

                        << std::endl;

               m_fd_last_error = r;

             }

          }

          if (need_dynamic)

            delete[] buf;

        }

        if (do_graylog2 && m_graylog) {

          m_graylog->log_entry(e);

        }

        requeue->enqueue(e);

      }

    }

    SubsystemMap

    负责管理所有的subsys。

    _log = new ceph::log::Log(&_conf->subsys);

    通过参数将其传入到Log.cc中。

    _conf->subsys的初始化工作,如何做的呢?

    首先定义了3个宏

    定义宏SUBSYS(name, log, gather) 是执行subsys.add(ceph_subsys_##name, STRINGIFY(name), log, gather);

    定义宏DEFAULT_SUBSYS(log, gather) 是执行subsys.add(ceph_subsys_, "none", log, gather);

    定义宏#define OPTION(a, b, c) 为空

    将config_opts.h展开,依次执行subsys.add即可完成,

    void md_config_t::init_subsys()

    {

    #define SUBSYS(name, log, gather)

    subsys.add(ceph_subsys_##name, STRINGIFY(name), log, gather);

    #define DEFAULT_SUBSYS(log, gather)

    subsys.add(ceph_subsys_, "none", log, gather);

    #define OPTION(a, b, c)

    #include "common/config_opts.h"

    #undef OPTION

    #undef SUBSYS

    #undef DEFAULT_SUBSYS

    }

    ceph_subsys_##name 的值从哪儿来的呢?同样使用了宏的机制。和上一个宏一样,展开后在enum变量中。

    enum config_subsys_id {

      ceph_subsys_,   // default

    #define OPTION(a,b,c)

    #define SUBSYS(name, log, gather)

      ceph_subsys_##name,

    #define DEFAULT_SUBSYS(log, gather)

    #include "common/config_opts.h"

    #undef SUBSYS

    #undef OPTION

    #undef DEFAULT_SUBSYS

      ceph_subsys_max

    };

    如何调用ldout 写日志呢?

    #define ldout(cct, v)  dout_impl(cct, dout_subsys, v) dout_prefix

    Dout_impl 生成了log_entry 写入到日志文件, dout_prefix 标准输出

  • 相关阅读:
    Android之Handler实现延迟执行
    static{}语句块
    (转)git常见错误
    smarty使用
    git简易操作
    angular路由——ui.route
    angular服务二
    angular服务一
    angualr 实现tab选项卡功能
    EF 集合版 状态版的 增加、删除、修改 的实践
  • 原文地址:https://www.cnblogs.com/damizhou/p/6272550.html
Copyright © 2020-2023  润新知