]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common: enable sending cluster log to journald
author胡玮文 <huww98@outlook.com>
Wed, 3 Mar 2021 07:03:41 +0000 (15:03 +0800)
committer胡玮文 <huww98@outlook.com>
Tue, 9 Mar 2021 12:14:00 +0000 (20:14 +0800)
Use the same infrastructure used for local logs. Also with structured metadata.

Signed-off-by: 胡玮文 <huww98@outlook.com>
src/common/Journald.cc
src/common/Journald.h
src/common/options.cc
src/mon/LogMonitor.cc
src/mon/LogMonitor.h

index 6962f9630e031436ccfd03d18adae17f77e16b20..ba3a84c06c52a2dedb2fcb8b0f0127899d7e276e 100644 (file)
@@ -119,6 +119,39 @@ MESSAGE
   }
 };
 
+class LogEntryEncoder : public EntryEncoderBase {
+ public:
+  void encode(const LogEntry& le)
+  {
+    meta_buf.clear();
+    fmt::format_to(meta_buf,
+      R"(PRIORITY={:d}
+TIMESTAMP={}
+CEPH_NAME={}
+CEPH_RANK={}
+CEPH_SEQ={}
+CEPH_CHANNEL={}
+MESSAGE
+)",
+      clog_type_to_syslog_level(le.prio),
+      le.stamp.to_nsec(),
+      le.name.to_str(),
+      le.rank,
+      le.seq,
+      le.channel);
+
+    uint64_t msg_len = htole64(le.msg.size());
+    meta_buf.resize(meta_buf.size() + sizeof(msg_len));
+    *(reinterpret_cast<uint64_t*>(meta_buf.end()) - 1) = htole64(le.msg.size());
+
+    m_msg_vec[0].iov_base = meta_buf.data();
+    m_msg_vec[0].iov_len = meta_buf.size();
+
+    m_msg_vec[1].iov_base = (void *)le.msg.data();
+    m_msg_vec[1].iov_len = le.msg.size();
+  }
+};
+
 enum class JournaldClient::MemFileMode {
   MEMFD_CREATE,
   OPEN_TMPFILE,
@@ -252,4 +285,19 @@ int JournaldLogger::log_entry(const Entry& e)
   return client.send();
 }
 
+JournaldClusterLogger::JournaldClusterLogger() :
+  m_log_entry_encoder(make_unique<detail::LogEntryEncoder>())
+{
+  client.m_msghdr.msg_iov = m_log_entry_encoder->iovec();
+  client.m_msghdr.msg_iovlen = m_log_entry_encoder->iovec_len();
+}
+
+JournaldClusterLogger::~JournaldClusterLogger() = default;
+
+int JournaldClusterLogger::log_log_entry(const LogEntry &le)
+{
+  m_log_entry_encoder->encode(le);
+  return client.send();
+}
+
 }
index 388d843a03d52382456d081d08b6548406539879..59a9c4421a48156520c71f848ec4164a6a43d24d 100644 (file)
@@ -8,12 +8,15 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
+struct LogEntry;
+
 namespace ceph {
 
 namespace logging {
 
 namespace detail {
 class EntryEncoder;
+class LogEntryEncoder;
 
 class JournaldClient {
  public:
@@ -39,6 +42,8 @@ class SubsystemMap;
  * Logger to send local logs to journald
  * 
  * local logs means @code dout(0) << ... @endcode and similars
+ * 
+ * @see JournaldClusterLogger
  */
 class JournaldLogger {
  public:
@@ -58,6 +63,26 @@ class JournaldLogger {
   const SubsystemMap * m_subs;
 };
 
+/**
+ * Logger to send cluster log recieved by MON to journald
+ * 
+ * @see JournaldLogger
+ */
+class JournaldClusterLogger {
+ public:
+  JournaldClusterLogger();
+  ~JournaldClusterLogger();
+
+  /**
+   * @returns 0 if log entry is successfully sent, -1 otherwise.
+   */
+  int log_log_entry(const LogEntry &le);
+
+ private:
+  detail::JournaldClient client;
+
+  std::unique_ptr<detail::LogEntryEncoder> m_log_entry_encoder;
+};
 
 }
 }
index d86306e9b8cc75d997e2efb4fa3ce7e60d4c61d7..53b9a9bfd742d036077f16b285941d70f58c0253 100644 (file)
@@ -793,6 +793,12 @@ std::vector<Option> get_global_options() {
     .set_description("Graylog port for cluster log messages")
     .add_see_also("mon_cluster_log_to_graylog"),
 
+    Option("mon_cluster_log_to_journald", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+    .set_default("false")
+    .set_flag(Option::FLAG_RUNTIME)
+    .add_service("mon")
+    .set_description("Make monitor send cluster log to journald"),
+
     Option("enable_experimental_unrecoverable_data_corrupting_features", Option::TYPE_STR, Option::LEVEL_ADVANCED)
     .set_flag(Option::FLAG_RUNTIME)
     .set_default("")
index 88327663a5b58313f2dd5f4abc646189afa9df8b..62b805617efbd4025d95f892645184d67dffe1a4 100644 (file)
@@ -25,6 +25,7 @@
 #include "messages/MLog.h"
 #include "messages/MLogAck.h"
 #include "common/Graylog.h"
+#include "common/Journald.h"
 #include "common/errno.h"
 #include "common/strtol.h"
 #include "include/ceph_assert.h"
@@ -163,6 +164,35 @@ ceph::logging::Graylog::Ref LogMonitor::log_channel_info::get_graylog(
   return graylogs[channel];
 }
 
+ceph::logging::JournaldClusterLogger &LogMonitor::log_channel_info::get_journald()
+{
+  dout(25) << __func__ << dendl;
+
+  if (!journald) {
+    journald = std::make_unique<ceph::logging::JournaldClusterLogger>();
+  }
+  return *journald;
+}
+
+void LogMonitor::log_channel_info::clear()
+{
+  log_to_syslog.clear();
+  syslog_level.clear();
+  syslog_facility.clear();
+  log_file.clear();
+  expanded_log_file.clear();
+  log_file_level.clear();
+  log_to_graylog.clear();
+  log_to_graylog_host.clear();
+  log_to_graylog_port.clear();
+  log_to_journald.clear();
+  graylogs.clear();
+  journald.reset();
+}
+
+LogMonitor::log_channel_info::log_channel_info() = default;
+LogMonitor::log_channel_info::~log_channel_info() = default;
+
 
 #undef dout_prefix
 #define dout_prefix _prefix(_dout, mon, get_last_committed())
@@ -274,6 +304,12 @@ void LogMonitor::update_from_paxos(bool *need_bootstrap)
                << " host:" << channels.log_to_graylog_host << dendl;
       }
 
+      if (channels.do_log_to_journald(channel)) {
+        auto &journald = channels.get_journald();
+        journald.log_log_entry(le);
+        dout(7) << "journald: " << channel << dendl;
+      }
+
       if (g_conf()->mon_cluster_log_to_file) {
        string log_file = channels.get_log_file(channel);
        dout(20) << __func__ << " logging for channel '" << channel
@@ -927,6 +963,16 @@ void LogMonitor::update_log_channels()
     return;
   }
 
+  r = get_conf_str_map_helper(
+    g_conf().get_val<string>("mon_cluster_log_to_journald"), oss,
+    &channels.log_to_journald,
+    CLOG_CONFIG_DEFAULT_KEY);
+  if (r < 0) {
+    derr << __func__ << " error parsing 'mon_cluster_log_to_journald'"
+         << dendl;
+    return;
+  }
+
   channels.expand_channel_meta();
 }
 
@@ -941,7 +987,8 @@ void LogMonitor::handle_conf_change(const ConfigProxy& conf,
       changed.count("mon_cluster_log_file_level") ||
       changed.count("mon_cluster_log_to_graylog") ||
       changed.count("mon_cluster_log_to_graylog_host") ||
-      changed.count("mon_cluster_log_to_graylog_port")) {
+      changed.count("mon_cluster_log_to_graylog_port") ||
+      changed.count("mon_cluster_log_to_journald")) {
     update_log_channels();
   }
 }
index 6d6a0b71c68a542f385fb201fd7effff62c796ee..035168848da87cdcf386f9c1e05cf1ed3b1308eb 100644 (file)
@@ -32,6 +32,7 @@ static const std::string LOG_META_CHANNEL = "$channel";
 namespace ceph {
 namespace logging {
   class Graylog;
+  class JournaldClusterLogger;
 }
 }
 
@@ -52,23 +53,17 @@ private:
     std::map<std::string,std::string> log_to_graylog;
     std::map<std::string,std::string> log_to_graylog_host;
     std::map<std::string,std::string> log_to_graylog_port;
+    std::map<std::string,std::string> log_to_journald;
 
     std::map<std::string, std::shared_ptr<ceph::logging::Graylog>> graylogs;
+    std::unique_ptr<ceph::logging::JournaldClusterLogger> journald;
     uuid_d fsid;
     std::string host;
 
-    void clear() {
-      log_to_syslog.clear();
-      syslog_level.clear();
-      syslog_facility.clear();
-      log_file.clear();
-      expanded_log_file.clear();
-      log_file_level.clear();
-      log_to_graylog.clear();
-      log_to_graylog_host.clear();
-      log_to_graylog_port.clear();
-      graylogs.clear();
-    }
+    log_channel_info();
+    ~log_channel_info();
+
+    void clear();
 
     /** expands $channel meta variable on all maps *EXCEPT* log_file
      *
@@ -110,6 +105,13 @@ private:
     }
 
     std::shared_ptr<ceph::logging::Graylog> get_graylog(const std::string &channel);
+
+    bool do_log_to_journald(const std::string &channel) {
+      return (get_str_map_key(log_to_journald, channel,
+                             &CLOG_CONFIG_DEFAULT_KEY) == "true");
+    }
+
+    ceph::logging::JournaldClusterLogger &get_journald();
   } channels;
 
   void update_log_channels();
@@ -179,6 +181,7 @@ private:
       "mon_cluster_log_to_graylog",
       "mon_cluster_log_to_graylog_host",
       "mon_cluster_log_to_graylog_port",
+      "mon_cluster_log_to_journald",
       NULL
     };
     return KEYS;