]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
dout: add macros for libfmt-style logging
authorCasey Bodley <cbodley@redhat.com>
Mon, 24 Jun 2024 15:23:36 +0000 (11:23 -0400)
committerCasey Bodley <cbodley@redhat.com>
Tue, 25 Jun 2024 18:38:21 +0000 (14:38 -0400)
new dout macros use fmt::print() to write output directly to the
underlying ostream. this enables libfmt's printf-style formatting syntax
for ceph log output, without the string allocation overhead of:

    dout(10) << fmt::format("str={} count={}", str, count) << dendl;

which becomes:

    dout_fmt(10, "str={} count={}", str, count);

Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/common/dout_fmt.h [new file with mode: 0644]
src/test/common/CMakeLists.txt
src/test/common/test_dout_fmt.cc [new file with mode: 0644]

diff --git a/src/common/dout_fmt.h b/src/common/dout_fmt.h
new file mode 100644 (file)
index 0000000..c22fdf3
--- /dev/null
@@ -0,0 +1,56 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright contributors to the Ceph project
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#pragma once
+
+#include <iosfwd>
+#include <iterator>
+#include <fmt/ostream.h>
+#include "dout.h"
+
+/// \file dout_fmt.h
+///
+/// \brief dout macros to format log statements with libfmt
+///
+/// A set of dout macros taking a format string and its corresponding argument
+/// list. Log output is written directly to the underlying std::ostream by
+/// fmt::print() rather than exposing the stream for ostream operator
+/// chaining.
+
+// work around "warning: value computed is not used" with default dout_prefix
+inline void dout_fmt_use_prefix(std::ostream&) {}
+
+#define lsubdout_fmt(cct, sub, v, ...) \
+  dout_impl(cct, ceph_subsys_##sub, v) \
+  dout_fmt_use_prefix(dout_prefix); \
+  fmt::print(*_dout, __VA_ARGS__); \
+  *_dout << dendl
+
+#define ldout_fmt(cct, v, ...) \
+  dout_impl(cct, dout_subsys, v) \
+  dout_fmt_use_prefix(dout_prefix); \
+  fmt::print(*_dout, __VA_ARGS__); \
+  *_dout << dendl
+
+#define dout_fmt(v, ...) \
+  ldout_fmt((dout_context), v, __VA_ARGS__)
+
+#define ldpp_dout_fmt(dpp, v, ...) \
+  if (decltype(auto) pdpp = (dpp); pdpp) { /* workaround -Wnonnull-compare for 'this' */ \
+    dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
+    pdpp->gen_prefix(*_dout); \
+    fmt::print(*_dout, __VA_ARGS__); \
+    *_dout << dendl; \
+  }
index 428ef7b01470f42328555baf9f365a491ae23824..11a7ea0e20c036a7bb41099d552bb872a9dafe1c 100644 (file)
@@ -312,6 +312,10 @@ target_link_libraries(unittest_dns_resolve global)
 add_ceph_unittest(unittest_dns_resolve)
 endif()
 
+add_executable(unittest_dout_fmt test_dout_fmt.cc $<TARGET_OBJECTS:unit-main>)
+target_link_libraries(unittest_dout_fmt global)
+add_ceph_unittest(unittest_dout_fmt)
+
 # We're getting an ICE when trying to compile this test using mingw-gcc and
 # recent Boost versions. Note that mingw-llvm works fine.
 if (NOT WIN32 OR (NOT(CMAKE_CXX_COMPILER_ID STREQUAL GNU)))
diff --git a/src/test/common/test_dout_fmt.cc b/src/test/common/test_dout_fmt.cc
new file mode 100644 (file)
index 0000000..7d6b519
--- /dev/null
@@ -0,0 +1,57 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright contributors to the Ceph project
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include "common/dout_fmt.h"
+#include <gtest/gtest.h>
+
+TEST(DoutFmt, SubDout)
+{
+  // expect level 0 to always be gathered
+  lsubdout_fmt(g_ceph_context, test, 0, "{}: {}", "value", 42);
+  // expect level 99 to be compiled out
+  lsubdout_fmt(g_ceph_context, test, 99, "{}: {}", "value", 42);
+}
+
+#define dout_subsys ceph_subsys_test
+
+TEST(DoutFmt, Dout)
+{
+  ldout_fmt(g_ceph_context, 0, "{}: {}", "value", 42);
+  ldout_fmt(g_ceph_context, 99, "{}: {}", "value", 42);
+}
+
+#define dout_context g_ceph_context
+
+TEST(DoutFmt, DoutContext)
+{
+  dout_fmt(0, "{}: {}", "value", 42);
+  dout_fmt(99, "{}: {}", "value", 42);
+}
+
+#undef dout_prefix
+#define dout_prefix *_dout << "prefix: "
+
+TEST(DoutFmt, DoutPrefix)
+{
+  ldout_fmt(g_ceph_context, 0, "{}: {}", "value", 42);
+  ldout_fmt(g_ceph_context, 99, "{}: {}", "value", 42);
+}
+
+TEST(DoutFmt, DppDout)
+{
+  const DoutPrefix dpp{g_ceph_context, dout_subsys, "prefix: "};
+  ldpp_dout_fmt(&dpp, 0, "{}: {}", "value", 42);
+  ldpp_dout_fmt(&dpp, 99, "{}: {}", "value", 42);
+}