]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/health_check.h
51f0e1095d8e5179d4481f94c81f4844d189935a
[ceph.git] / ceph / src / mon / health_check.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include <string>
7 #include <map>
8
9 #include "include/health.h"
10 #include "common/Formatter.h"
11
12 struct health_check_t {
13 health_status_t severity;
14 std::string summary;
15 std::list<std::string> detail;
16
17 DENC(health_check_t, v, p) {
18 DENC_START(1, 1, p);
19 denc(v.severity, p);
20 denc(v.summary, p);
21 denc(v.detail, p);
22 DENC_FINISH(p);
23 }
24
25 friend bool operator==(const health_check_t& l,
26 const health_check_t& r) {
27 return l.severity == r.severity &&
28 l.summary == r.summary &&
29 l.detail == r.detail;
30 }
31 friend bool operator!=(const health_check_t& l,
32 const health_check_t& r) {
33 return !(l == r);
34 }
35
36 void dump(Formatter *f) const {
37 f->dump_stream("severity") << severity;
38 f->dump_string("summary", summary);
39 f->open_array_section("detail");
40 for (auto& p : detail) {
41 f->dump_string("item", p);
42 }
43 f->close_section();
44 }
45
46 static void generate_test_instances(list<health_check_t*>& ls) {
47 ls.push_back(new health_check_t);
48 ls.push_back(new health_check_t);
49 ls.back()->severity = HEALTH_ERR;
50 ls.back()->summary = "summarization";
51 ls.back()->detail = {"one", "two", "three"};
52 }
53 };
54 WRITE_CLASS_DENC(health_check_t)
55
56
57 struct health_check_map_t {
58 map<std::string,health_check_t> checks;
59
60 DENC(health_check_map_t, v, p) {
61 DENC_START(1, 1, p);
62 denc(v.checks, p);
63 DENC_FINISH(p);
64 }
65
66 void dump(Formatter *f) const {
67 for (auto& p : checks) {
68 f->dump_object(p.first.c_str(), p.second);
69 }
70 }
71
72 static void generate_test_instances(list<health_check_map_t*>& ls) {
73 ls.push_back(new health_check_map_t);
74 ls.push_back(new health_check_map_t);
75 {
76 auto& d = ls.back()->add("FOO", HEALTH_WARN, "foo");
77 d.detail.push_back("a");
78 d.detail.push_back("b");
79 }
80 {
81 auto& d = ls.back()->add("BAR", HEALTH_ERR, "bar!");
82 d.detail.push_back("c");
83 d.detail.push_back("d");
84 }
85 }
86
87 void clear() {
88 checks.clear();
89 }
90 bool empty() const {
91 return checks.empty();
92 }
93 void swap(health_check_map_t& other) {
94 checks.swap(other.checks);
95 }
96
97 health_check_t& add(const std::string& code,
98 health_status_t severity,
99 const std::string& summary) {
100 assert(checks.count(code) == 0);
101 health_check_t& r = checks[code];
102 r.severity = severity;
103 r.summary = summary;
104 return r;
105 }
106 health_check_t& get_or_add(const std::string& code,
107 health_status_t severity,
108 const std::string& summary) {
109 health_check_t& r = checks[code];
110 r.severity = severity;
111 r.summary = summary;
112 return r;
113 }
114
115 void merge(const health_check_map_t& o) {
116 for (auto& p : o.checks) {
117 auto q = checks.find(p.first);
118 if (q == checks.end()) {
119 // new check
120 checks[p.first] = p.second;
121 } else {
122 // merge details, and hope the summary matches!
123 q->second.detail.insert(
124 q->second.detail.end(),
125 p.second.detail.begin(),
126 p.second.detail.end());
127 }
128 }
129 }
130
131 health_status_t dump_summary(Formatter *f, std::string *plain,
132 const char *sep, bool detail) const {
133 health_status_t r = HEALTH_OK;
134 for (auto& p : checks) {
135 if (r > p.second.severity) {
136 r = p.second.severity;
137 }
138 if (f) {
139 f->open_object_section(p.first.c_str());
140 f->dump_stream("severity") << p.second.severity;
141 f->dump_string("message", p.second.summary);
142 if (detail) {
143 f->open_array_section("detail");
144 for (auto& d : p.second.detail) {
145 f->dump_string("item", d);
146 }
147 f->close_section();
148 }
149 f->close_section();
150 } else {
151 if (!plain->empty()) {
152 *plain += sep;
153 }
154 *plain += p.second.summary;
155 }
156 }
157 return r;
158 }
159
160 void dump_summary_compat(Formatter *f) const {
161 for (auto& p : checks) {
162 f->open_object_section("item");
163 f->dump_stream("severity") << p.second.severity;
164 f->dump_string("summary", p.second.summary);
165 f->close_section();
166 }
167 }
168
169 void dump_detail(Formatter *f, std::string *plain, bool compat) const {
170 for (auto& p : checks) {
171 if (f) {
172 if (compat) {
173 // this is sloppy, but the best we can do: just dump all of the
174 // individual checks' details together
175 for (auto& d : p.second.detail) {
176 f->dump_string("item", d);
177 }
178 }
179 } else {
180 if (!compat) {
181 *plain += p.first + " " + p.second.summary + "\n";
182 }
183 for (auto& d : p.second.detail) {
184 if (!compat) {
185 *plain += " ";
186 }
187 *plain += d;
188 *plain += "\n";
189 }
190 }
191 }
192 }
193
194 friend bool operator==(const health_check_map_t& l,
195 const health_check_map_t& r) {
196 return l.checks == r.checks;
197 }
198 friend bool operator!=(const health_check_map_t& l,
199 const health_check_map_t& r) {
200 return !(l == r);
201 }
202 };
203 WRITE_CLASS_DENC(health_check_map_t)