]>
Commit | Line | Data |
---|---|---|
224ce89b WB |
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; | |
d2e6a577 FG |
38 | |
39 | f->open_object_section("summary"); | |
40 | f->dump_string("message", summary); | |
41 | f->close_section(); | |
42 | ||
224ce89b WB |
43 | f->open_array_section("detail"); |
44 | for (auto& p : detail) { | |
d2e6a577 FG |
45 | f->open_object_section("detail_item"); |
46 | f->dump_string("message", p); | |
47 | f->close_section(); | |
224ce89b WB |
48 | } |
49 | f->close_section(); | |
50 | } | |
51 | ||
52 | static void generate_test_instances(list<health_check_t*>& ls) { | |
53 | ls.push_back(new health_check_t); | |
54 | ls.push_back(new health_check_t); | |
55 | ls.back()->severity = HEALTH_ERR; | |
56 | ls.back()->summary = "summarization"; | |
57 | ls.back()->detail = {"one", "two", "three"}; | |
58 | } | |
59 | }; | |
60 | WRITE_CLASS_DENC(health_check_t) | |
61 | ||
62 | ||
63 | struct health_check_map_t { | |
64 | map<std::string,health_check_t> checks; | |
65 | ||
66 | DENC(health_check_map_t, v, p) { | |
67 | DENC_START(1, 1, p); | |
68 | denc(v.checks, p); | |
69 | DENC_FINISH(p); | |
70 | } | |
71 | ||
72 | void dump(Formatter *f) const { | |
73 | for (auto& p : checks) { | |
74 | f->dump_object(p.first.c_str(), p.second); | |
75 | } | |
76 | } | |
77 | ||
78 | static void generate_test_instances(list<health_check_map_t*>& ls) { | |
79 | ls.push_back(new health_check_map_t); | |
80 | ls.push_back(new health_check_map_t); | |
81 | { | |
82 | auto& d = ls.back()->add("FOO", HEALTH_WARN, "foo"); | |
83 | d.detail.push_back("a"); | |
84 | d.detail.push_back("b"); | |
85 | } | |
86 | { | |
87 | auto& d = ls.back()->add("BAR", HEALTH_ERR, "bar!"); | |
88 | d.detail.push_back("c"); | |
89 | d.detail.push_back("d"); | |
90 | } | |
91 | } | |
92 | ||
93 | void clear() { | |
94 | checks.clear(); | |
95 | } | |
c07f9fc5 FG |
96 | bool empty() const { |
97 | return checks.empty(); | |
98 | } | |
224ce89b WB |
99 | void swap(health_check_map_t& other) { |
100 | checks.swap(other.checks); | |
101 | } | |
102 | ||
103 | health_check_t& add(const std::string& code, | |
104 | health_status_t severity, | |
105 | const std::string& summary) { | |
106 | assert(checks.count(code) == 0); | |
107 | health_check_t& r = checks[code]; | |
108 | r.severity = severity; | |
109 | r.summary = summary; | |
110 | return r; | |
111 | } | |
112 | health_check_t& get_or_add(const std::string& code, | |
113 | health_status_t severity, | |
114 | const std::string& summary) { | |
115 | health_check_t& r = checks[code]; | |
116 | r.severity = severity; | |
117 | r.summary = summary; | |
118 | return r; | |
119 | } | |
120 | ||
121 | void merge(const health_check_map_t& o) { | |
122 | for (auto& p : o.checks) { | |
123 | auto q = checks.find(p.first); | |
124 | if (q == checks.end()) { | |
125 | // new check | |
126 | checks[p.first] = p.second; | |
127 | } else { | |
128 | // merge details, and hope the summary matches! | |
129 | q->second.detail.insert( | |
130 | q->second.detail.end(), | |
131 | p.second.detail.begin(), | |
132 | p.second.detail.end()); | |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | health_status_t dump_summary(Formatter *f, std::string *plain, | |
138 | const char *sep, bool detail) const { | |
139 | health_status_t r = HEALTH_OK; | |
140 | for (auto& p : checks) { | |
141 | if (r > p.second.severity) { | |
142 | r = p.second.severity; | |
143 | } | |
144 | if (f) { | |
145 | f->open_object_section(p.first.c_str()); | |
146 | f->dump_stream("severity") << p.second.severity; | |
d2e6a577 FG |
147 | |
148 | f->open_object_section("summary"); | |
149 | f->dump_string("message", p.second.summary); | |
150 | f->close_section(); | |
151 | ||
224ce89b WB |
152 | if (detail) { |
153 | f->open_array_section("detail"); | |
154 | for (auto& d : p.second.detail) { | |
d2e6a577 FG |
155 | f->open_object_section("detail_item"); |
156 | f->dump_string("message", d); | |
157 | f->close_section(); | |
224ce89b WB |
158 | } |
159 | f->close_section(); | |
160 | } | |
161 | f->close_section(); | |
162 | } else { | |
163 | if (!plain->empty()) { | |
164 | *plain += sep; | |
165 | } | |
166 | *plain += p.second.summary; | |
167 | } | |
168 | } | |
169 | return r; | |
170 | } | |
171 | ||
172 | void dump_summary_compat(Formatter *f) const { | |
173 | for (auto& p : checks) { | |
174 | f->open_object_section("item"); | |
175 | f->dump_stream("severity") << p.second.severity; | |
176 | f->dump_string("summary", p.second.summary); | |
177 | f->close_section(); | |
178 | } | |
179 | } | |
180 | ||
181 | void dump_detail(Formatter *f, std::string *plain, bool compat) const { | |
182 | for (auto& p : checks) { | |
183 | if (f) { | |
184 | if (compat) { | |
185 | // this is sloppy, but the best we can do: just dump all of the | |
186 | // individual checks' details together | |
187 | for (auto& d : p.second.detail) { | |
188 | f->dump_string("item", d); | |
189 | } | |
190 | } | |
191 | } else { | |
192 | if (!compat) { | |
193 | *plain += p.first + " " + p.second.summary + "\n"; | |
194 | } | |
195 | for (auto& d : p.second.detail) { | |
196 | if (!compat) { | |
197 | *plain += " "; | |
198 | } | |
199 | *plain += d; | |
200 | *plain += "\n"; | |
201 | } | |
202 | } | |
203 | } | |
204 | } | |
205 | ||
206 | friend bool operator==(const health_check_map_t& l, | |
207 | const health_check_map_t& r) { | |
208 | return l.checks == r.checks; | |
209 | } | |
210 | friend bool operator!=(const health_check_map_t& l, | |
211 | const health_check_map_t& r) { | |
212 | return !(l == r); | |
213 | } | |
214 | }; | |
215 | WRITE_CLASS_DENC(health_check_map_t) |