]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/dout.h
import 15.2.0 Octopus source
[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;
102 operator T() const { return value; }
103};
104
105template<typename T>
106dynamic_marker_t<T> need_dynamic(T&& t) {
107 return dynamic_marker_t<T>{ std::forward<T>(t) };
108}
109
110template<typename T>
111struct is_dynamic : public std::false_type {};
112
113template<typename T>
114struct is_dynamic<dynamic_marker_t<T>> : public std::true_type {};
115
116} // ceph::dout
117
7c673cae
FG
118// generic macros
119#define dout_prefix *_dout
120
9f95a23c 121#if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
11fdf7f2
TL
122#define dout_impl(cct, sub, v) \
123 do { \
9f95a23c
TL
124 if (crimson::common::local_conf()->subsys.should_gather(sub, v)) { \
125 seastar::logger& _logger = crimson::get_logger(sub); \
11fdf7f2
TL
126 const auto _lv = v; \
127 std::ostringstream _out; \
128 std::ostream* _dout = &_out;
129#define dendl_impl \
130 ""; \
9f95a23c
TL
131 _logger.log(crimson::to_log_level(_lv), \
132 _out.str().c_str()); \
11fdf7f2 133 } \
9f95a23c
TL
134 } while (0)
135#elif defined(WITH_SEASTAR) && defined(WITH_ALIEN)
136#define dout_impl(cct, sub, v) \
137 do { \
138 if (0) { \
139 ceph::logging::MutableEntry _dout_e(v, sub); \
140 std::ostream* _dout = &_dout_e.get_ostream();
141
142#define dendl_impl std::flush; \
143 } \
11fdf7f2
TL
144 } while (0)
145#else
7c673cae
FG
146#define dout_impl(cct, sub, v) \
147 do { \
11fdf7f2
TL
148 const bool should_gather = [&](const auto cctX) { \
149 if constexpr (ceph::dout::is_dynamic<decltype(sub)>::value || \
150 ceph::dout::is_dynamic<decltype(v)>::value) { \
151 return cctX->_conf->subsys.should_gather(sub, v); \
152 } else { \
153 /* The parentheses are **essential** because commas in angle \
154 * brackets are NOT ignored on macro expansion! A language's \
155 * limitation, sorry. */ \
156 return (cctX->_conf->subsys.template should_gather<sub, v>()); \
7c673cae 157 } \
11fdf7f2
TL
158 }(cct); \
159 \
160 if (should_gather) { \
161 ceph::logging::MutableEntry _dout_e(v, sub); \
c07f9fc5
FG
162 static_assert(std::is_convertible<decltype(&*cct), \
163 CephContext* >::value, \
164 "provided cct must be compatible with CephContext*"); \
165 auto _dout_cct = cct; \
11fdf7f2
TL
166 std::ostream* _dout = &_dout_e.get_ostream();
167
168#define dendl_impl std::flush; \
169 _dout_cct->_log->submit_entry(std::move(_dout_e)); \
170 } \
171 } while (0)
172#endif // WITH_SEASTAR
7c673cae
FG
173
174#define lsubdout(cct, sub, v) dout_impl(cct, ceph_subsys_##sub, v) dout_prefix
175#define ldout(cct, v) dout_impl(cct, dout_subsys, v) dout_prefix
176#define lderr(cct) dout_impl(cct, ceph_subsys_, -1) dout_prefix
177
11fdf7f2
TL
178#define ldpp_dout(dpp, v) \
179 if (decltype(auto) pdpp = (dpp); pdpp) /* workaround -Wnonnull-compare for 'this' */ \
180 dout_impl(pdpp->get_cct(), ceph::dout::need_dynamic(pdpp->get_subsys()), v) \
181 pdpp->gen_prefix(*_dout)
7c673cae
FG
182
183#define lgeneric_subdout(cct, sub, v) dout_impl(cct, ceph_subsys_##sub, v) *_dout
184#define lgeneric_dout(cct, v) dout_impl(cct, ceph_subsys_, v) *_dout
185#define lgeneric_derr(cct) dout_impl(cct, ceph_subsys_, -1) *_dout
186
187#define ldlog_p1(cct, sub, lvl) \
188 (cct->_conf->subsys.should_gather((sub), (lvl)))
189
7c673cae
FG
190#define dendl dendl_impl
191
192#endif