1 #define NETDATA_HEALTH_INTERNALS
4 static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) {
6 buffer_sprintf(wb, "%s\"%s\":\"%s\"%s", prefix, label, value, suffix);
8 buffer_sprintf(wb, "%s\"%s\":null%s", prefix, label, suffix);
11 static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host) {
14 "\t\t\"hostname\": \"%s\",\n"
15 "\t\t\"unique_id\": %u,\n"
16 "\t\t\"alarm_id\": %u,\n"
17 "\t\t\"alarm_event_id\": %u,\n"
18 "\t\t\"name\": \"%s\",\n"
19 "\t\t\"chart\": \"%s\",\n"
20 "\t\t\"family\": \"%s\",\n"
21 "\t\t\"processed\": %s,\n"
22 "\t\t\"updated\": %s,\n"
23 "\t\t\"exec_run\": %lu,\n"
24 "\t\t\"exec_failed\": %s,\n"
25 "\t\t\"exec\": \"%s\",\n"
26 "\t\t\"recipient\": \"%s\",\n"
27 "\t\t\"exec_code\": %d,\n"
28 "\t\t\"source\": \"%s\",\n"
29 "\t\t\"units\": \"%s\",\n"
30 "\t\t\"info\": \"%s\",\n"
31 "\t\t\"when\": %lu,\n"
32 "\t\t\"duration\": %lu,\n"
33 "\t\t\"non_clear_duration\": %lu,\n"
34 "\t\t\"status\": \"%s\",\n"
35 "\t\t\"old_status\": \"%s\",\n"
36 "\t\t\"delay\": %d,\n"
37 "\t\t\"delay_up_to_timestamp\": %lu,\n"
38 "\t\t\"updated_by_id\": %u,\n"
39 "\t\t\"updates_id\": %u,\n"
40 "\t\t\"value_string\": \"%s\",\n"
41 "\t\t\"old_value_string\": \"%s\",\n"
49 , (ae->flags & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false"
50 , (ae->flags & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false"
51 , (unsigned long)ae->exec_run_timestamp
52 , (ae->flags & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false"
53 , ae->exec?ae->exec:host->health_default_exec
54 , ae->recipient?ae->recipient:host->health_default_recipient
57 , ae->units?ae->units:""
58 , ae->info?ae->info:""
59 , (unsigned long)ae->when
60 , (unsigned long)ae->duration
61 , (unsigned long)ae->non_clear_duration
62 , rrdcalc_status2string(ae->new_status)
63 , rrdcalc_status2string(ae->old_status)
65 , (unsigned long)ae->delay_up_to_timestamp
68 , ae->new_value_string
69 , ae->old_value_string
72 if(unlikely(ae->flags & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
73 buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n");
76 buffer_strcat(wb, "\t\t\"value\":");
77 buffer_rrd_value(wb, ae->new_value);
78 buffer_strcat(wb, ",\n");
80 buffer_strcat(wb, "\t\t\"old_value\":");
81 buffer_rrd_value(wb, ae->old_value);
82 buffer_strcat(wb, "\n");
84 buffer_strcat(wb, "\t}");
87 void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after) {
88 pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
90 buffer_strcat(wb, "[");
92 unsigned int max = host->health_log.max;
93 unsigned int count = 0;
95 for(ae = host->health_log.alarms; ae && count < max ; count++, ae = ae->next) {
96 if(ae->unique_id > after) {
97 if(likely(count)) buffer_strcat(wb, ",");
98 health_alarm_entry2json_nolock(wb, ae, host);
102 buffer_strcat(wb, "\n]\n");
104 pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock);
107 static inline void health_rrdcalc2json_nolock(RRDHOST *host, BUFFER *wb, RRDCALC *rc) {
108 char value_string[100 + 1];
109 format_value_and_unit(value_string, 100, rc->value, rc->units, -1);
113 "\t\t\t\"id\": %lu,\n"
114 "\t\t\t\"name\": \"%s\",\n"
115 "\t\t\t\"chart\": \"%s\",\n"
116 "\t\t\t\"family\": \"%s\",\n"
117 "\t\t\t\"active\": %s,\n"
118 "\t\t\t\"exec\": \"%s\",\n"
119 "\t\t\t\"recipient\": \"%s\",\n"
120 "\t\t\t\"source\": \"%s\",\n"
121 "\t\t\t\"units\": \"%s\",\n"
122 "\t\t\t\"info\": \"%s\",\n"
123 "\t\t\t\"status\": \"%s\",\n"
124 "\t\t\t\"last_status_change\": %lu,\n"
125 "\t\t\t\"last_updated\": %lu,\n"
126 "\t\t\t\"next_update\": %lu,\n"
127 "\t\t\t\"update_every\": %d,\n"
128 "\t\t\t\"delay_up_duration\": %d,\n"
129 "\t\t\t\"delay_down_duration\": %d,\n"
130 "\t\t\t\"delay_max_duration\": %d,\n"
131 "\t\t\t\"delay_multiplier\": %f,\n"
132 "\t\t\t\"delay\": %d,\n"
133 "\t\t\t\"delay_up_to_timestamp\": %lu,\n"
134 "\t\t\t\"value_string\": \"%s\",\n"
135 , rc->chart, rc->name
136 , (unsigned long)rc->id
139 , (rc->rrdset && rc->rrdset->family)?rc->rrdset->family:""
140 , (rc->rrdset)?"true":"false"
141 , rc->exec?rc->exec:host->health_default_exec
142 , rc->recipient?rc->recipient:host->health_default_recipient
144 , rc->units?rc->units:""
145 , rc->info?rc->info:""
146 , rrdcalc_status2string(rc->status)
147 , (unsigned long)rc->last_status_change
148 , (unsigned long)rc->last_updated
149 , (unsigned long)rc->next_update
151 , rc->delay_up_duration
152 , rc->delay_down_duration
153 , rc->delay_max_duration
154 , rc->delay_multiplier
156 , (unsigned long)rc->delay_up_to_timestamp
160 if(unlikely(rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION)) {
161 buffer_strcat(wb, "\t\t\t\"no_clear_notification\": true,\n");
164 if(RRDCALC_HAS_DB_LOOKUP(rc)) {
165 if(rc->dimensions && *rc->dimensions)
166 health_string2json(wb, "\t\t\t", "lookup_dimensions", rc->dimensions, ",\n");
169 "\t\t\t\"db_after\": %lu,\n"
170 "\t\t\t\"db_before\": %lu,\n"
171 "\t\t\t\"lookup_method\": \"%s\",\n"
172 "\t\t\t\"lookup_after\": %d,\n"
173 "\t\t\t\"lookup_before\": %d,\n"
174 "\t\t\t\"lookup_options\": \"",
175 (unsigned long) rc->db_after,
176 (unsigned long) rc->db_before,
177 group_method2string(rc->group),
181 buffer_data_options2string(wb, rc->options);
182 buffer_strcat(wb, "\",\n");
185 if(rc->calculation) {
186 health_string2json(wb, "\t\t\t", "calc", rc->calculation->source, ",\n");
187 health_string2json(wb, "\t\t\t", "calc_parsed", rc->calculation->parsed_as, ",\n");
191 health_string2json(wb, "\t\t\t", "warn", rc->warning->source, ",\n");
192 health_string2json(wb, "\t\t\t", "warn_parsed", rc->warning->parsed_as, ",\n");
196 health_string2json(wb, "\t\t\t", "crit", rc->critical->source, ",\n");
197 health_string2json(wb, "\t\t\t", "crit_parsed", rc->critical->parsed_as, ",\n");
200 buffer_strcat(wb, "\t\t\t\"green\":");
201 buffer_rrd_value(wb, rc->green);
202 buffer_strcat(wb, ",\n");
204 buffer_strcat(wb, "\t\t\t\"red\":");
205 buffer_rrd_value(wb, rc->red);
206 buffer_strcat(wb, ",\n");
208 buffer_strcat(wb, "\t\t\t\"value\":");
209 buffer_rrd_value(wb, rc->value);
210 buffer_strcat(wb, "\n");
212 buffer_strcat(wb, "\t\t}");
215 //void health_rrdcalctemplate2json_nolock(BUFFER *wb, RRDCALCTEMPLATE *rt) {
219 void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) {
222 rrdhost_rdlock(host);
223 buffer_sprintf(wb, "{\n\t\"hostname\": \"%s\","
224 "\n\t\"latest_alarm_log_unique_id\": %u,"
225 "\n\t\"status\": %s,"
227 "\n\t\"alarms\": {\n",
229 (host->health_log.next_log_id > 0)?(host->health_log.next_log_id - 1):0,
230 host->health_enabled?"true":"false",
231 (unsigned long)now_realtime_sec());
234 for(i = 0, rc = host->alarms; rc ; rc = rc->next) {
235 if(unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
238 if(likely(!all && !(rc->status == RRDCALC_STATUS_WARNING || rc->status == RRDCALC_STATUS_CRITICAL)))
241 if(likely(i)) buffer_strcat(wb, ",\n");
242 health_rrdcalc2json_nolock(host, wb, rc);
246 // buffer_strcat(wb, "\n\t},\n\t\"templates\": {");
247 // RRDCALCTEMPLATE *rt;
248 // for(rt = host->templates; rt ; rt = rt->next)
249 // health_rrdcalctemplate2json_nolock(wb, rt);
251 buffer_strcat(wb, "\n\t}\n}\n");
252 rrdhost_unlock(host);