]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/health_check.h
4e74637f9e53d99622e8516cad9ff54653490ed9
[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 "include/utime.h"
11 #include "common/Formatter.h"
12
13 struct health_check_t {
14 health_status_t severity;
15 std::string summary;
16 std::list<std::string> detail;
17 int64_t count = 0;
18
19 DENC(health_check_t, v, p) {
20 DENC_START(2, 1, p);
21 denc(v.severity, p);
22 denc(v.summary, p);
23 denc(v.detail, p);
24 if (struct_v >= 2) {
25 denc(v.count, p);
26 }
27 DENC_FINISH(p);
28 }
29
30 friend bool operator==(const health_check_t& l,
31 const health_check_t& r) {
32 return l.severity == r.severity &&
33 l.summary == r.summary &&
34 l.detail == r.detail &&
35 l.count == r.count;
36 }
37 friend bool operator!=(const health_check_t& l,
38 const health_check_t& r) {
39 return !(l == r);
40 }
41
42 void dump(ceph::Formatter *f, bool want_detail=true) const {
43 f->dump_stream("severity") << severity;
44
45 f->open_object_section("summary");
46 f->dump_string("message", summary);
47 f->dump_int("count", count);
48 f->close_section();
49
50 if (want_detail) {
51 f->open_array_section("detail");
52 for (auto& p : detail) {
53 f->open_object_section("detail_item");
54 f->dump_string("message", p);
55 f->close_section();
56 }
57 f->close_section();
58 }
59 }
60
61 static void generate_test_instances(std::list<health_check_t*>& ls) {
62 ls.push_back(new health_check_t);
63 ls.push_back(new health_check_t);
64 ls.back()->severity = HEALTH_ERR;
65 ls.back()->summary = "summarization";
66 ls.back()->detail = {"one", "two", "three"};
67 ls.back()->count = 42;
68 }
69 };
70 WRITE_CLASS_DENC(health_check_t)
71
72
73 struct health_mute_t {
74 std::string code;
75 utime_t ttl;
76 bool sticky = false;
77 std::string summary;
78 int64_t count;
79
80 DENC(health_mute_t, v, p) {
81 DENC_START(1, 1, p);
82 denc(v.code, p);
83 denc(v.ttl, p);
84 denc(v.sticky, p);
85 denc(v.summary, p);
86 denc(v.count, p);
87 DENC_FINISH(p);
88 }
89
90 void dump(ceph::Formatter *f) const {
91 f->dump_string("code", code);
92 if (ttl != utime_t()) {
93 f->dump_stream("ttl") << ttl;
94 }
95 f->dump_bool("sticky", sticky);
96 f->dump_string("summary", summary);
97 f->dump_int("count", count);
98 }
99
100 static void generate_test_instances(std::list<health_mute_t*>& ls) {
101 ls.push_back(new health_mute_t);
102 ls.push_back(new health_mute_t);
103 ls.back()->code = "OSD_DOWN";
104 ls.back()->ttl = utime_t(1, 2);
105 ls.back()->sticky = true;
106 ls.back()->summary = "foo bar";
107 ls.back()->count = 2;
108 }
109 };
110 WRITE_CLASS_DENC(health_mute_t)
111
112 struct health_check_map_t {
113 std::map<std::string,health_check_t> checks;
114
115 DENC(health_check_map_t, v, p) {
116 DENC_START(1, 1, p);
117 denc(v.checks, p);
118 DENC_FINISH(p);
119 }
120
121 void dump(ceph::Formatter *f) const {
122 for (auto& [code, check] : checks) {
123 f->dump_object(code, check);
124 }
125 }
126
127 static void generate_test_instances(std::list<health_check_map_t*>& ls) {
128 ls.push_back(new health_check_map_t);
129 ls.push_back(new health_check_map_t);
130 {
131 auto& d = ls.back()->add("FOO", HEALTH_WARN, "foo", 2);
132 d.detail.push_back("a");
133 d.detail.push_back("b");
134 }
135 {
136 auto& d = ls.back()->add("BAR", HEALTH_ERR, "bar!", 3);
137 d.detail.push_back("c");
138 d.detail.push_back("d");
139 d.detail.push_back("e");
140 }
141 }
142
143 void clear() {
144 checks.clear();
145 }
146 bool empty() const {
147 return checks.empty();
148 }
149 void swap(health_check_map_t& other) {
150 checks.swap(other.checks);
151 }
152
153 health_check_t& add(const std::string& code,
154 health_status_t severity,
155 const std::string& summary,
156 int64_t count) {
157 ceph_assert(checks.count(code) == 0);
158 health_check_t& r = checks[code];
159 r.severity = severity;
160 r.summary = summary;
161 r.count = count;
162 return r;
163 }
164 health_check_t& get_or_add(const std::string& code,
165 health_status_t severity,
166 const std::string& summary,
167 int64_t count) {
168 health_check_t& r = checks[code];
169 r.severity = severity;
170 r.summary = summary;
171 r.count += count;
172 return r;
173 }
174
175 void merge(const health_check_map_t& o) {
176 for (auto& [code, check] : o.checks) {
177 auto [it, new_check] = checks.try_emplace(code, check);
178 if (!new_check) {
179 // merge details, and hope the summary matches!
180 it->second.detail.insert(
181 it->second.detail.end(),
182 check.detail.begin(),
183 check.detail.end());
184 it->second.count += check.count;
185 }
186 }
187 }
188
189 friend bool operator==(const health_check_map_t& l,
190 const health_check_map_t& r) {
191 return l.checks == r.checks;
192 }
193 friend bool operator!=(const health_check_map_t& l,
194 const health_check_map_t& r) {
195 return !(l == r);
196 }
197 };
198 WRITE_CLASS_DENC(health_check_map_t)