]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/dout.h
import ceph quincy 17.2.4
[ceph.git] / ceph / src / common / dout.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
7 * Copyright (C) 2010 Dreamhost
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
16#ifndef CEPH_DOUT_H
17#define CEPH_DOUT_H
18
c07f9fc5
FG
19#include <type_traits>
20
11fdf7f2 21#include "include/ceph_assert.h"
9f95a23c
TL
22#include "include/common_fwd.h"
23#if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
11fdf7f2
TL
24#include <seastar/util/log.hh>
25#include "crimson/common/log.h"
26#include "crimson/common/config_proxy.h"
27#else
7c673cae 28#include "global/global_context.h"
11fdf7f2 29#include "common/ceph_context.h"
7c673cae
FG
30#include "common/config.h"
31#include "common/likely.h"
32#include "common/Clock.h"
33#include "log/Log.h"
11fdf7f2 34#endif
7c673cae
FG
35
36extern void dout_emergency(const char * const str);
37extern void dout_emergency(const std::string &str);
38
39// intentionally conflict with endl
40class _bad_endl_use_dendl_t { public: _bad_endl_use_dendl_t(int) {} };
41static const _bad_endl_use_dendl_t endl = 0;
42inline std::ostream& operator<<(std::ostream& out, _bad_endl_use_dendl_t) {
11fdf7f2 43 ceph_abort_msg("you are using the wrong endl.. use std::endl or dendl");
7c673cae
FG
44 return out;
45}
46
47class DoutPrefixProvider {
48public:
11fdf7f2 49 virtual std::ostream& gen_prefix(std::ostream& out) const = 0;
7c673cae
FG
50 virtual CephContext *get_cct() const = 0;
51 virtual unsigned get_subsys() const = 0;
52 virtual ~DoutPrefixProvider() {}
53};
54
11fdf7f2
TL
55// a prefix provider with empty prefix
56class NoDoutPrefix : public DoutPrefixProvider {
57 CephContext *const cct;
58 const unsigned subsys;
59 public:
60 NoDoutPrefix(CephContext *cct, unsigned subsys) : cct(cct), subsys(subsys) {}
61
62 std::ostream& gen_prefix(std::ostream& out) const override { return out; }
63 CephContext *get_cct() const override { return cct; }
64 unsigned get_subsys() const override { return subsys; }
65};
66
67// a prefix provider with static (const char*) prefix
68class DoutPrefix : public NoDoutPrefix {
69 const char *const prefix;
70 public:
71 DoutPrefix(CephContext *cct, unsigned subsys, const char *prefix)
72 : NoDoutPrefix(cct, subsys), prefix(prefix) {}
73
74 std::ostream& gen_prefix(std::ostream& out) const override {
75 return out << prefix;
76 }
77};
78
79// a prefix provider that composes itself on top of another
80class DoutPrefixPipe : public DoutPrefixProvider {
81 const DoutPrefixProvider& dpp;
82 public:
83 DoutPrefixPipe(const DoutPrefixProvider& dpp) : dpp(dpp) {}
84
85 std::ostream& gen_prefix(std::ostream& out) const override final {
86 dpp.gen_prefix(out);
87 add_prefix(out);
88 return out;
89 }
90 CephContext *get_cct() const override { return dpp.get_cct(); }
91 unsigned get_subsys() const override { return dpp.get_subsys(); }
92
93 virtual void add_prefix(std::ostream& out) const = 0;
94};
95
96// helpers
97namespace ceph::dout {
98
99template<typename T>
100struct dynamic_marker_t {
101 T value;
2a845540
TL
102 // constexpr ctor isn't needed as it's an aggregate type
103 constexpr operator T() const { return value; }
11fdf7f2
TL
104};
105
106template<typename T>
2a845540 107constexpr dynamic_marker_t<T> need_dynamic(T&& t) {
11fdf7f2
TL
108 return dynamic_marker_t<T>{ std::forward<T>(t) };
109}
110
111template<typename T>
112struct is_dynamic : public std::false_type {};
113
114template<typename T>
115struct is_dynamic<dynamic_marker_t<T>> : public std::true_type {};
116
117} // ceph::dout
118
7c673cae
FG
119// generic macros
120#define dout_prefix *_dout
121
9f95a23c 122#if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
11fdf7f2
TL
123#define dout_impl(cct, sub, v) \
124 do { \
9f95a23c
TL
125 if (crimson::common::local_conf()->subsys.should_gather(sub, v)) { \
126 seastar::logger& _logger = crimson::get_logger(sub); \
11fdf7f2
TL
127 const auto _lv = v; \
128 std::ostringstream _out; \
129 std::ostream* _dout = &_out;
130#define dendl_impl \
131 ""; \
9f95a23c 132 _logger.log(crimson::to_log_level(_lv), \
f67539c2 133 "{}", _out.str().c_str()); \
11fdf7f2 134 } \
9f95a23c
TL
135 } while (0)
136#elif defined(WITH_SEASTAR) && defined(WITH_ALIEN)
137#define dout_impl(cct, sub, v) \
138 do { \
139 if (0) { \
140 ceph::logging::MutableEntry _dout_e(v, sub); \
141 std::ostream* _dout = &_dout_e.get_ostream();
142
143#define dendl_impl std::flush; \
144 } \
11fdf7f2
TL
145 } while (0)
146#else
7c673cae
FG
147#define dout_impl(cct, sub, v) \
148 do { \
11fdf7f2
TL
149 const bool should_gather = [&](const auto cctX) { \
150 if constexpr (ceph::dout::is_dynamic<decltype(sub)>::value || \
151 ceph::dout::is_dynamic<decltype(v)>::value) { \
152 return cctX->_conf->subsys.should_gather(sub, v); \
153 } else { \
154 /* The parentheses are **essential** because commas in angle \
155 * brackets are NOT ignored on macro expansion! A language's \
156 * limitation, sorry. */ \
157 return (cctX->_conf->subsys.template should_gather<sub, v>()); \
7c673cae 158 } \
11fdf7f2
TL
159 }(cct); \
160 \
161 if (should_gather) { \
162 ceph::logging::MutableEntry _dout_e(v, sub); \
c07f9fc5
FG
163 static_assert(std::is_convertible<decltype(&*cct), \
164 CephContext* >::value, \
165 "provided cct must be compatible with CephContext*"); \
166 auto _dout_cct = cct; \
11fdf7f2
TL
167 std::ostream* _dout = &_dout_e.get_ostream();
168
169#define dendl_impl std::flush; \
170 _dout_cct->_log->submit_entry(std::move(_dout_e)); \
171 } \
172 } while (0)
173#endif // WITH_SEASTAR
7c673cae
FG
174
175#define lsubdout(cct, sub, v) dout_impl(cct, ceph_subsys_##sub, v) dout_prefix
176#define ldout(cct, v) dout_impl(cct, dout_subsys, v) dout_prefix
177#define lderr(cct) dout_impl(cct, ceph_subsys_, -1) dout_prefix
178
b3b6e05e
TL
179#define ldpp_subdout(dpp, sub, v) \
180 if (decltype(auto) pdpp = (dpp); pdpp) /* workaround -Wnonnull-compare for 'this' */ \
181 dout_impl(pdpp->get_cct(), ceph_subsys_##sub, v) \
182 pdpp->gen_prefix(*_dout)
183
11fdf7f2
TL
184#define ldpp_dout(dpp, v) \
185 if (decltype(auto) pdpp = (dpp); pdpp) /* workaround -Wnonnull-compare for 'this' */ \
186 dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
187 pdpp->gen_prefix(*_dout)
7c673cae
FG
188
189#define lgeneric_subdout(cct, sub, v) dout_impl(cct, ceph_subsys_##sub, v) *_dout
190#define lgeneric_dout(cct, v) dout_impl(cct, ceph_subsys_, v) *_dout
191#define lgeneric_derr(cct) dout_impl(cct, ceph_subsys_, -1) *_dout
192
193#define ldlog_p1(cct, sub, lvl) \
194 (cct->_conf->subsys.should_gather((sub), (lvl)))
195
7c673cae
FG
196#define dendl dendl_impl
197
198#endif