1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
9 #include "include/health.h"
10 #include "common/Formatter.h"
12 struct health_check_t {
13 health_status_t severity;
15 std::list<std::string> detail;
17 DENC(health_check_t, v, p) {
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 &&
31 friend bool operator!=(const health_check_t& l,
32 const health_check_t& r) {
36 void dump(Formatter *f) const {
37 f->dump_stream("severity") << severity;
39 f->open_object_section("summary");
40 f->dump_string("message", summary);
43 f->open_array_section("detail");
44 for (auto& p : detail) {
45 f->open_object_section("detail_item");
46 f->dump_string("message", p);
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"};
60 WRITE_CLASS_DENC(health_check_t)
63 struct health_check_map_t {
64 map<std::string,health_check_t> checks;
66 DENC(health_check_map_t, v, p) {
72 void dump(Formatter *f) const {
73 for (auto& p : checks) {
74 f->dump_object(p.first.c_str(), p.second);
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);
82 auto& d = ls.back()->add("FOO", HEALTH_WARN, "foo");
83 d.detail.push_back("a");
84 d.detail.push_back("b");
87 auto& d = ls.back()->add("BAR", HEALTH_ERR, "bar!");
88 d.detail.push_back("c");
89 d.detail.push_back("d");
97 return checks.empty();
99 void swap(health_check_map_t& other) {
100 checks.swap(other.checks);
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;
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;
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()) {
126 checks[p.first] = p.second;
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());
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;
145 f->open_object_section(p.first.c_str());
146 f->dump_stream("severity") << p.second.severity;
148 f->open_object_section("summary");
149 f->dump_string("message", p.second.summary);
153 f->open_array_section("detail");
154 for (auto& d : p.second.detail) {
155 f->open_object_section("detail_item");
156 f->dump_string("message", d);
163 if (!plain->empty()) {
166 *plain += p.second.summary;
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);
181 void dump_detail(Formatter *f, std::string *plain, bool compat) const {
182 for (auto& p : checks) {
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);
193 *plain += p.first + " " + p.second.summary + "\n";
195 for (auto& d : p.second.detail) {
206 friend bool operator==(const health_check_map_t& l,
207 const health_check_map_t& r) {
208 return l.checks == r.checks;
210 friend bool operator!=(const health_check_map_t& l,
211 const health_check_map_t& r) {
215 WRITE_CLASS_DENC(health_check_map_t)