sqlite_health.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "sqlite_health.h"
  3. #include "sqlite_functions.h"
  4. #define MAX_HEALTH_SQL_SIZE 2048
  5. #define sqlite3_bind_string_or_null(res,key,param) ((key) ? sqlite3_bind_text(res, param, string2str(key), -1, SQLITE_STATIC) : sqlite3_bind_null(res, param))
  6. /* Health related SQL queries
  7. Creates a health log table in sqlite, one per host guid
  8. */
  9. #define SQL_CREATE_HEALTH_LOG_TABLE(guid) "CREATE TABLE IF NOT EXISTS health_log_%s(hostname text, unique_id int, alarm_id int, alarm_event_id int, config_hash_id blob, updated_by_id int, updates_id int, when_key int, duration int, non_clear_duration int, flags int, exec_run_timestamp int, delay_up_to_timestamp int, name text, chart text, family text, exec text, recipient text, source text, units text, info text, exec_code int, new_status real, old_status real, delay int, new_value double, old_value double, last_repeat int, class text, component text, type text, chart_context text);", guid
  10. int sql_create_health_log_table(RRDHOST *host) {
  11. int rc;
  12. char *err_msg = NULL, command[MAX_HEALTH_SQL_SIZE + 1];
  13. if (unlikely(!db_meta)) {
  14. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  15. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  16. return 1;
  17. }
  18. char uuid_str[GUID_LEN + 1];
  19. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  20. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CREATE_HEALTH_LOG_TABLE(uuid_str));
  21. rc = sqlite3_exec_monitored(db_meta, command, 0, 0, &err_msg);
  22. if (rc != SQLITE_OK) {
  23. error_report("HEALTH [%s]: SQLite error during creation of health log table, rc = %d (%s)", rrdhost_hostname(host), rc, err_msg);
  24. sqlite3_free(err_msg);
  25. return 1;
  26. }
  27. snprintfz(command, MAX_HEALTH_SQL_SIZE, "CREATE INDEX IF NOT EXISTS "
  28. "health_log_index_%s ON health_log_%s (unique_id); ", uuid_str, uuid_str);
  29. db_execute(command);
  30. return 0;
  31. }
  32. /* Health related SQL queries
  33. Updates an entry in the table
  34. */
  35. #define SQL_UPDATE_HEALTH_LOG(guid) "UPDATE health_log_%s set updated_by_id = ?, flags = ?, exec_run_timestamp = ?, exec_code = ? where unique_id = ?;", guid
  36. void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) {
  37. sqlite3_stmt *res = NULL;
  38. int rc;
  39. char command[MAX_HEALTH_SQL_SIZE + 1];
  40. if (unlikely(!db_meta)) {
  41. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  42. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  43. return;
  44. }
  45. char uuid_str[GUID_LEN + 1];
  46. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  47. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_UPDATE_HEALTH_LOG(uuid_str));
  48. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  49. if (unlikely(rc != SQLITE_OK)) {
  50. sql_create_health_log_table(host);
  51. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  52. if (unlikely(rc != SQLITE_OK)) {
  53. error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host));
  54. return;
  55. }
  56. }
  57. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) ae->updated_by_id);
  58. if (unlikely(rc != SQLITE_OK)) {
  59. error_report("Failed to bind updated_by_id parameter for SQL_UPDATE_HEALTH_LOG");
  60. goto failed;
  61. }
  62. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->flags);
  63. if (unlikely(rc != SQLITE_OK)) {
  64. error_report("Failed to bind flags parameter for SQL_UPDATE_HEALTH_LOG");
  65. goto failed;
  66. }
  67. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->exec_run_timestamp);
  68. if (unlikely(rc != SQLITE_OK)) {
  69. error_report("Failed to bind exec_run_timestamp parameter for SQL_UPDATE_HEALTH_LOG");
  70. goto failed;
  71. }
  72. rc = sqlite3_bind_int(res, 4, ae->exec_code);
  73. if (unlikely(rc != SQLITE_OK)) {
  74. error_report("Failed to bind exec_code parameter for SQL_UPDATE_HEALTH_LOG");
  75. goto failed;
  76. }
  77. rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) ae->unique_id);
  78. if (unlikely(rc != SQLITE_OK)) {
  79. error_report("Failed to bind unique_id parameter for SQL_UPDATE_HEALTH_LOG");
  80. goto failed;
  81. }
  82. rc = execute_insert(res);
  83. if (unlikely(rc != SQLITE_DONE)) {
  84. error_report("HEALTH [%s]: Failed to update health log, rc = %d", rrdhost_hostname(host), rc);
  85. }
  86. failed:
  87. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  88. error_report("HEALTH [%s]: Failed to finalize the prepared statement for updating health log.", rrdhost_hostname(host));
  89. }
  90. /* Health related SQL queries
  91. Inserts an entry in the table
  92. */
  93. #define SQL_INSERT_HEALTH_LOG(guid) "INSERT INTO health_log_%s(hostname, unique_id, alarm_id, alarm_event_id, " \
  94. "config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, " \
  95. "exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, " \
  96. "units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, " \
  97. "class, component, type, chart_context) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);", guid
  98. void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
  99. sqlite3_stmt *res = NULL;
  100. int rc;
  101. char command[MAX_HEALTH_SQL_SIZE + 1];
  102. if (unlikely(!db_meta)) {
  103. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  104. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  105. return;
  106. }
  107. char uuid_str[GUID_LEN + 1];
  108. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  109. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_INSERT_HEALTH_LOG(uuid_str));
  110. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  111. if (unlikely(rc != SQLITE_OK)) {
  112. sql_create_health_log_table(host);
  113. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  114. if (unlikely(rc != SQLITE_OK)) {
  115. error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host));
  116. return;
  117. }
  118. }
  119. rc = sqlite3_bind_text(res, 1, rrdhost_hostname(host), -1, SQLITE_STATIC);
  120. if (unlikely(rc != SQLITE_OK)) {
  121. error_report("Failed to bind hostname parameter for SQL_INSERT_HEALTH_LOG");
  122. goto failed;
  123. }
  124. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->unique_id);
  125. if (unlikely(rc != SQLITE_OK)) {
  126. error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG");
  127. goto failed;
  128. }
  129. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->alarm_id);
  130. if (unlikely(rc != SQLITE_OK)) {
  131. error_report("Failed to bind alarm_id parameter for SQL_INSERT_HEALTH_LOG");
  132. goto failed;
  133. }
  134. rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) ae->alarm_event_id);
  135. if (unlikely(rc != SQLITE_OK)) {
  136. error_report("Failed to bind alarm_event_id parameter for SQL_INSERT_HEALTH_LOG");
  137. goto failed;
  138. }
  139. rc = sqlite3_bind_blob(res, 5, &ae->config_hash_id, sizeof(ae->config_hash_id), SQLITE_STATIC);
  140. if (unlikely(rc != SQLITE_OK)) {
  141. error_report("Failed to bind config_hash_id parameter for SQL_INSERT_HEALTH_LOG");
  142. goto failed;
  143. }
  144. rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->updated_by_id);
  145. if (unlikely(rc != SQLITE_OK)) {
  146. error_report("Failed to bind updated_by_id parameter for SQL_INSERT_HEALTH_LOG");
  147. goto failed;
  148. }
  149. rc = sqlite3_bind_int64(res, 7, (sqlite3_int64) ae->updates_id);
  150. if (unlikely(rc != SQLITE_OK)) {
  151. error_report("Failed to bind updates_id parameter for SQL_INSERT_HEALTH_LOG");
  152. goto failed;
  153. }
  154. rc = sqlite3_bind_int64(res, 8, (sqlite3_int64) ae->when);
  155. if (unlikely(rc != SQLITE_OK)) {
  156. error_report("Failed to bind when parameter for SQL_INSERT_HEALTH_LOG");
  157. goto failed;
  158. }
  159. rc = sqlite3_bind_int64(res, 9, (sqlite3_int64) ae->duration);
  160. if (unlikely(rc != SQLITE_OK)) {
  161. error_report("Failed to bind duration parameter for SQL_INSERT_HEALTH_LOG");
  162. goto failed;
  163. }
  164. rc = sqlite3_bind_int64(res, 10, (sqlite3_int64) ae->non_clear_duration);
  165. if (unlikely(rc != SQLITE_OK)) {
  166. error_report("Failed to bind non_clear_duration parameter for SQL_INSERT_HEALTH_LOG");
  167. goto failed;
  168. }
  169. rc = sqlite3_bind_int64(res, 11, (sqlite3_int64) ae->flags);
  170. if (unlikely(rc != SQLITE_OK)) {
  171. error_report("Failed to bind flags parameter for SQL_INSERT_HEALTH_LOG");
  172. goto failed;
  173. }
  174. rc = sqlite3_bind_int64(res, 12, (sqlite3_int64) ae->exec_run_timestamp);
  175. if (unlikely(rc != SQLITE_OK)) {
  176. error_report("Failed to bind exec_run_timestamp parameter for SQL_INSERT_HEALTH_LOG");
  177. goto failed;
  178. }
  179. rc = sqlite3_bind_int64(res, 13, (sqlite3_int64) ae->delay_up_to_timestamp);
  180. if (unlikely(rc != SQLITE_OK)) {
  181. error_report("Failed to bind delay_up_to_timestamp parameter for SQL_INSERT_HEALTH_LOG");
  182. goto failed;
  183. }
  184. rc = sqlite3_bind_string_or_null(res, ae->name, 14);
  185. if (unlikely(rc != SQLITE_OK)) {
  186. error_report("Failed to bind name parameter for SQL_INSERT_HEALTH_LOG");
  187. goto failed;
  188. }
  189. rc = sqlite3_bind_string_or_null(res, ae->chart, 15);
  190. if (unlikely(rc != SQLITE_OK)) {
  191. error_report("Failed to bind chart parameter for SQL_INSERT_HEALTH_LOG");
  192. goto failed;
  193. }
  194. rc = sqlite3_bind_string_or_null(res, ae->family, 16);
  195. if (unlikely(rc != SQLITE_OK)) {
  196. error_report("Failed to bind family parameter for SQL_INSERT_HEALTH_LOG");
  197. goto failed;
  198. }
  199. rc = sqlite3_bind_string_or_null(res, ae->exec, 17);
  200. if (unlikely(rc != SQLITE_OK)) {
  201. error_report("Failed to bind exec parameter for SQL_INSERT_HEALTH_LOG");
  202. goto failed;
  203. }
  204. rc = sqlite3_bind_string_or_null(res, ae->recipient, 18);
  205. if (unlikely(rc != SQLITE_OK)) {
  206. error_report("Failed to bind recipient parameter for SQL_INSERT_HEALTH_LOG");
  207. goto failed;
  208. }
  209. rc = sqlite3_bind_string_or_null(res, ae->source, 19);
  210. if (unlikely(rc != SQLITE_OK)) {
  211. error_report("Failed to bind source parameter for SQL_INSERT_HEALTH_LOG");
  212. goto failed;
  213. }
  214. rc = sqlite3_bind_string_or_null(res, ae->units, 20);
  215. if (unlikely(rc != SQLITE_OK)) {
  216. error_report("Failed to bind host_id parameter to store node instance information");
  217. goto failed;
  218. }
  219. rc = sqlite3_bind_string_or_null(res, ae->info, 21);
  220. if (unlikely(rc != SQLITE_OK)) {
  221. error_report("Failed to bind info parameter for SQL_INSERT_HEALTH_LOG");
  222. goto failed;
  223. }
  224. rc = sqlite3_bind_int(res, 22, ae->exec_code);
  225. if (unlikely(rc != SQLITE_OK)) {
  226. error_report("Failed to bind exec_code parameter for SQL_INSERT_HEALTH_LOG");
  227. goto failed;
  228. }
  229. rc = sqlite3_bind_int(res, 23, ae->new_status);
  230. if (unlikely(rc != SQLITE_OK)) {
  231. error_report("Failed to bind new_status parameter for SQL_INSERT_HEALTH_LOG");
  232. goto failed;
  233. }
  234. rc = sqlite3_bind_int(res, 24, ae->old_status);
  235. if (unlikely(rc != SQLITE_OK)) {
  236. error_report("Failed to bind old_status parameter for SQL_INSERT_HEALTH_LOG");
  237. goto failed;
  238. }
  239. rc = sqlite3_bind_int(res, 25, ae->delay);
  240. if (unlikely(rc != SQLITE_OK)) {
  241. error_report("Failed to bind delay parameter for SQL_INSERT_HEALTH_LOG");
  242. goto failed;
  243. }
  244. rc = sqlite3_bind_double(res, 26, ae->new_value);
  245. if (unlikely(rc != SQLITE_OK)) {
  246. error_report("Failed to bind new_value parameter for SQL_INSERT_HEALTH_LOG");
  247. goto failed;
  248. }
  249. rc = sqlite3_bind_double(res, 27, ae->old_value);
  250. if (unlikely(rc != SQLITE_OK)) {
  251. error_report("Failed to bind old_value parameter for SQL_INSERT_HEALTH_LOG");
  252. goto failed;
  253. }
  254. rc = sqlite3_bind_int64(res, 28, (sqlite3_int64) ae->last_repeat);
  255. if (unlikely(rc != SQLITE_OK)) {
  256. error_report("Failed to bind last_repeat parameter for SQL_INSERT_HEALTH_LOG");
  257. goto failed;
  258. }
  259. rc = sqlite3_bind_string_or_null(res, ae->classification, 29);
  260. if (unlikely(rc != SQLITE_OK)) {
  261. error_report("Failed to bind classification parameter for SQL_INSERT_HEALTH_LOG");
  262. goto failed;
  263. }
  264. rc = sqlite3_bind_string_or_null(res, ae->component, 30);
  265. if (unlikely(rc != SQLITE_OK)) {
  266. error_report("Failed to bind component parameter for SQL_INSERT_HEALTH_LOG");
  267. goto failed;
  268. }
  269. rc = sqlite3_bind_string_or_null(res, ae->type, 31);
  270. if (unlikely(rc != SQLITE_OK)) {
  271. error_report("Failed to bind type parameter for SQL_INSERT_HEALTH_LOG");
  272. goto failed;
  273. }
  274. rc = sqlite3_bind_string_or_null(res, ae->chart_context, 32);
  275. if (unlikely(rc != SQLITE_OK)) {
  276. error_report("Failed to bind chart_context parameter for SQL_INSERT_HEALTH_LOG");
  277. goto failed;
  278. }
  279. rc = execute_insert(res);
  280. if (unlikely(rc != SQLITE_DONE)) {
  281. error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG, rc = %d", rrdhost_hostname(host), rc);
  282. goto failed;
  283. }
  284. ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
  285. host->health.health_log_entries_written++;
  286. failed:
  287. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  288. error_report("HEALTH [%s]: Failed to finalize the prepared statement for inserting to health log.", rrdhost_hostname(host));
  289. }
  290. void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae)
  291. {
  292. if (ae->flags & HEALTH_ENTRY_FLAG_SAVED)
  293. sql_health_alarm_log_update(host, ae);
  294. else
  295. sql_health_alarm_log_insert(host, ae);
  296. }
  297. /* Health related SQL queries
  298. Cleans up the health_log table.
  299. */
  300. #define SQL_CLEANUP_HEALTH_LOG(guid,guid2,limit) "DELETE from health_log_%s where unique_id in (SELECT unique_id from health_log_%s order by unique_id asc LIMIT %lu);", guid, guid2, limit
  301. void sql_health_alarm_log_cleanup(RRDHOST *host) {
  302. sqlite3_stmt *res = NULL;
  303. static size_t rotate_every = 0;
  304. int rc;
  305. char command[MAX_HEALTH_SQL_SIZE + 1];
  306. if(unlikely(rotate_every == 0)) {
  307. rotate_every = (size_t)config_get_number(CONFIG_SECTION_HEALTH, "rotate log every lines", 2000);
  308. if(rotate_every < 100) rotate_every = 100;
  309. }
  310. if(likely(host->health.health_log_entries_written < rotate_every)) {
  311. return;
  312. }
  313. if (unlikely(!db_meta)) {
  314. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  315. error_report("Database has not been initialized");
  316. return;
  317. }
  318. char uuid_str[GUID_LEN + 1];
  319. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  320. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CLEANUP_HEALTH_LOG(uuid_str, uuid_str, (unsigned long int) (host->health.health_log_entries_written - rotate_every)));
  321. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  322. if (unlikely(rc != SQLITE_OK)) {
  323. error_report("Failed to prepare statement to cleanup health log table");
  324. return;
  325. }
  326. rc = sqlite3_step_monitored(res);
  327. if (unlikely(rc != SQLITE_DONE))
  328. error_report("Failed to cleanup health log table, rc = %d", rc);
  329. rc = sqlite3_finalize(res);
  330. if (unlikely(rc != SQLITE_OK))
  331. error_report("Failed to finalize the prepared statement to cleanup health log table");
  332. host->health.health_log_entries_written = rotate_every;
  333. sql_aclk_alert_clean_dead_entries(host);
  334. }
  335. /* Health related SQL queries
  336. Get a count of rows from health log table
  337. */
  338. #define SQL_COUNT_HEALTH_LOG(guid) "SELECT count(1) FROM health_log_%s;", guid
  339. void sql_health_alarm_log_count(RRDHOST *host) {
  340. sqlite3_stmt *res = NULL;
  341. int rc;
  342. char command[MAX_HEALTH_SQL_SIZE + 1];
  343. if (unlikely(!db_meta)) {
  344. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  345. error_report("Database has not been initialized");
  346. return;
  347. }
  348. char uuid_str[GUID_LEN + 1];
  349. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  350. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COUNT_HEALTH_LOG(uuid_str));
  351. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  352. if (unlikely(rc != SQLITE_OK)) {
  353. error_report("Failed to prepare statement to count health log entries from db");
  354. return;
  355. }
  356. rc = sqlite3_step_monitored(res);
  357. if (likely(rc == SQLITE_ROW))
  358. host->health.health_log_entries_written = (size_t) sqlite3_column_int64(res, 0);
  359. rc = sqlite3_finalize(res);
  360. if (unlikely(rc != SQLITE_OK))
  361. error_report("Failed to finalize the prepared statement to count health log entries from db");
  362. info("HEALTH [%s]: Table health_log_%s, contains %lu entries.", rrdhost_hostname(host), uuid_str, (unsigned long int) host->health.health_log_entries_written);
  363. }
  364. #define SQL_INJECT_REMOVED(guid, guid2) "insert into health_log_%s (hostname, unique_id, alarm_id, alarm_event_id, config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, " \
  365. "delay_up_to_timestamp, name, chart, family, exec, recipient, source, units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, class, component, type, chart_context) " \
  366. "select hostname, ?1, ?2, ?3, config_hash_id, 0, ?4, unixepoch(), 0, 0, flags, exec_run_timestamp, " \
  367. "unixepoch(), name, chart, family, exec, recipient, source, units, info, exec_code, -2, new_status, delay, NULL, new_value, 0, class, component, type, chart_context " \
  368. "from health_log_%s where unique_id = ?5", guid, guid2
  369. #define SQL_INJECT_REMOVED_UPDATE(guid) "update health_log_%s set flags = flags | ?1, updated_by_id = ?2 where unique_id = ?3; ", guid
  370. void sql_inject_removed_status(char *uuid_str, uint32_t alarm_id, uint32_t alarm_event_id, uint32_t unique_id, uint32_t max_unique_id)
  371. {
  372. int rc = 0;
  373. char command[MAX_HEALTH_SQL_SIZE + 1];
  374. if (!alarm_id || !alarm_event_id || !unique_id || !max_unique_id)
  375. return;
  376. sqlite3_stmt *res = NULL;
  377. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_INJECT_REMOVED(uuid_str, uuid_str));
  378. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  379. if (rc != SQLITE_OK) {
  380. error_report("Failed to prepare statement when trying to inject removed event");
  381. return;
  382. }
  383. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) max_unique_id);
  384. if (unlikely(rc != SQLITE_OK)) {
  385. error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED");
  386. goto failed;
  387. }
  388. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
  389. if (unlikely(rc != SQLITE_OK)) {
  390. error_report("Failed to bind alarm_id parameter for SQL_INJECT_REMOVED");
  391. goto failed;
  392. }
  393. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) alarm_event_id + 1);
  394. if (unlikely(rc != SQLITE_OK)) {
  395. error_report("Failed to bind alarm_event_id parameter for SQL_INJECT_REMOVED");
  396. goto failed;
  397. }
  398. rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) unique_id);
  399. if (unlikely(rc != SQLITE_OK)) {
  400. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED");
  401. goto failed;
  402. }
  403. rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) unique_id);
  404. if (unlikely(rc != SQLITE_OK)) {
  405. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED");
  406. goto failed;
  407. }
  408. rc = execute_insert(res);
  409. if (unlikely(rc != SQLITE_DONE)) {
  410. error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED, rc = %d", rc);
  411. goto failed;
  412. }
  413. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  414. error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
  415. //update the old entry
  416. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_INJECT_REMOVED_UPDATE(uuid_str));
  417. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  418. if (rc != SQLITE_OK) {
  419. error_report("Failed to prepare statement when trying to update during inject removed event");
  420. return;
  421. }
  422. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) HEALTH_ENTRY_FLAG_UPDATED);
  423. if (unlikely(rc != SQLITE_OK)) {
  424. error_report("Failed to bind flags parameter for SQL_INJECT_REMOVED (update)");
  425. goto failed;
  426. }
  427. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) max_unique_id);
  428. if (unlikely(rc != SQLITE_OK)) {
  429. error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED (update)");
  430. goto failed;
  431. }
  432. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) unique_id);
  433. if (unlikely(rc != SQLITE_OK)) {
  434. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED (update)");
  435. goto failed;
  436. }
  437. rc = execute_insert(res);
  438. if (unlikely(rc != SQLITE_DONE)) {
  439. error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE, rc = %d", rc);
  440. goto failed;
  441. }
  442. failed:
  443. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  444. error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
  445. }
  446. #define SQL_SELECT_MAX_UNIQUE_ID(guid) "SELECT MAX(unique_id) from health_log_%s", guid
  447. uint32_t sql_get_max_unique_id (char *uuid_str)
  448. {
  449. int rc = 0;
  450. char command[MAX_HEALTH_SQL_SIZE + 1];
  451. uint32_t max_unique_id = 0;
  452. sqlite3_stmt *res = NULL;
  453. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_MAX_UNIQUE_ID(uuid_str));
  454. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  455. if (rc != SQLITE_OK) {
  456. error_report("Failed to prepare statement when trying to get max unique id");
  457. return 0;
  458. }
  459. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  460. max_unique_id = (uint32_t) sqlite3_column_int64(res, 0);
  461. }
  462. rc = sqlite3_finalize(res);
  463. if (unlikely(rc != SQLITE_OK))
  464. error_report("Failed to finalize the statement");
  465. return max_unique_id;
  466. }
  467. #define SQL_SELECT_LAST_STATUSES(guid) "SELECT new_status, unique_id, alarm_id, alarm_event_id from health_log_%s group by alarm_id having max(alarm_event_id)", guid
  468. void sql_check_removed_alerts_state(char *uuid_str)
  469. {
  470. int rc = 0;
  471. char command[MAX_HEALTH_SQL_SIZE + 1];
  472. RRDCALC_STATUS status;
  473. uint32_t alarm_id = 0, alarm_event_id = 0, unique_id = 0, max_unique_id = 0;
  474. sqlite3_stmt *res = NULL;
  475. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_LAST_STATUSES(uuid_str));
  476. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  477. if (rc != SQLITE_OK) {
  478. error_report("Failed to prepare statement when trying to check removed statuses");
  479. return;
  480. }
  481. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  482. status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
  483. unique_id = (uint32_t) sqlite3_column_int64(res, 1);
  484. alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
  485. alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
  486. if (unlikely(status != RRDCALC_STATUS_REMOVED)) {
  487. if (unlikely(!max_unique_id))
  488. max_unique_id = sql_get_max_unique_id (uuid_str);
  489. sql_inject_removed_status (uuid_str, alarm_id, alarm_event_id, unique_id, ++max_unique_id);
  490. }
  491. }
  492. rc = sqlite3_finalize(res);
  493. if (unlikely(rc != SQLITE_OK))
  494. error_report("Failed to finalize the statement");
  495. }
  496. /* Health related SQL queries
  497. Load from the health log table
  498. */
  499. #define SQL_LOAD_HEALTH_LOG(guid,limit) "SELECT hostname, unique_id, alarm_id, alarm_event_id, config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, class, component, type, chart_context FROM (SELECT hostname, unique_id, alarm_id, alarm_event_id, config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, class, component, type, chart_context FROM health_log_%s order by unique_id desc limit %u) order by unique_id asc;", guid, limit
  500. void sql_health_alarm_log_load(RRDHOST *host) {
  501. sqlite3_stmt *res = NULL;
  502. int ret;
  503. ssize_t errored = 0, loaded = 0;
  504. char command[MAX_HEALTH_SQL_SIZE + 1];
  505. host->health.health_log_entries_written = 0;
  506. if (unlikely(!db_meta)) {
  507. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  508. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  509. return;
  510. }
  511. char uuid_str[GUID_LEN + 1];
  512. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  513. sql_check_removed_alerts_state(uuid_str);
  514. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_LOAD_HEALTH_LOG(uuid_str, host->health_log.max));
  515. ret = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  516. if (unlikely(ret != SQLITE_OK)) {
  517. error_report("HEALTH [%s]: Failed to prepare sql statement to load health log.", rrdhost_hostname(host));
  518. return;
  519. }
  520. DICTIONARY *all_rrdcalcs = dictionary_create(
  521. DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE);
  522. RRDCALC *rc;
  523. foreach_rrdcalc_in_rrdhost_read(host, rc) {
  524. dictionary_set(all_rrdcalcs, rrdcalc_name(rc), rc, sizeof(*rc));
  525. }
  526. foreach_rrdcalc_in_rrdhost_done(rc);
  527. netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
  528. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  529. ALARM_ENTRY *ae = NULL;
  530. // check that we have valid ids
  531. uint32_t unique_id = (uint32_t) sqlite3_column_int64(res, 1);
  532. if(!unique_id) {
  533. error_report("HEALTH [%s]: Got invalid unique id. Ignoring it.", rrdhost_hostname(host));
  534. errored++;
  535. continue;
  536. }
  537. uint32_t alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
  538. if(!alarm_id) {
  539. error_report("HEALTH [%s]: Got invalid alarm id. Ignoring it.", rrdhost_hostname(host));
  540. errored++;
  541. continue;
  542. }
  543. //need name, chart and family
  544. if (sqlite3_column_type(res, 13) == SQLITE_NULL) {
  545. error_report("HEALTH [%s]: Got null name field. Ignoring it.", rrdhost_hostname(host));
  546. errored++;
  547. continue;
  548. }
  549. if (sqlite3_column_type(res, 14) == SQLITE_NULL) {
  550. error_report("HEALTH [%s]: Got null chart field. Ignoring it.", rrdhost_hostname(host));
  551. errored++;
  552. continue;
  553. }
  554. if (sqlite3_column_type(res, 15) == SQLITE_NULL) {
  555. error_report("HEALTH [%s]: Got null family field. Ignoring it.", rrdhost_hostname(host));
  556. errored++;
  557. continue;
  558. }
  559. // Check if we got last_repeat field
  560. time_t last_repeat = 0;
  561. last_repeat = (time_t)sqlite3_column_int64(res, 27);
  562. rc = dictionary_get(all_rrdcalcs, (char *) sqlite3_column_text(res, 14));
  563. if(unlikely(rc)) {
  564. if (rrdcalc_isrepeating(rc)) {
  565. rc->last_repeat = last_repeat;
  566. // We iterate through repeating alarm entries only to
  567. // find the latest last_repeat timestamp. Otherwise,
  568. // there is no need to keep them in memory.
  569. continue;
  570. }
  571. }
  572. ae = callocz(1, sizeof(ALARM_ENTRY));
  573. ae->unique_id = unique_id;
  574. ae->alarm_id = alarm_id;
  575. if (sqlite3_column_type(res, 4) != SQLITE_NULL)
  576. uuid_copy(ae->config_hash_id, *((uuid_t *) sqlite3_column_blob(res, 4)));
  577. ae->alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
  578. ae->updated_by_id = (uint32_t) sqlite3_column_int64(res, 5);
  579. ae->updates_id = (uint32_t) sqlite3_column_int64(res, 6);
  580. ae->when = (time_t) sqlite3_column_int64(res, 7);
  581. ae->duration = (time_t) sqlite3_column_int64(res, 8);
  582. ae->non_clear_duration = (time_t) sqlite3_column_int64(res, 9);
  583. ae->flags = (uint32_t) sqlite3_column_int64(res, 10);
  584. ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
  585. ae->exec_run_timestamp = (time_t) sqlite3_column_int64(res, 11);
  586. ae->delay_up_to_timestamp = (time_t) sqlite3_column_int64(res, 12);
  587. ae->name = string_strdupz((char *) sqlite3_column_text(res, 13));
  588. ae->chart = string_strdupz((char *) sqlite3_column_text(res, 14));
  589. ae->family = string_strdupz((char *) sqlite3_column_text(res, 15));
  590. if (sqlite3_column_type(res, 16) != SQLITE_NULL)
  591. ae->exec = string_strdupz((char *) sqlite3_column_text(res, 16));
  592. else
  593. ae->exec = NULL;
  594. if (sqlite3_column_type(res, 17) != SQLITE_NULL)
  595. ae->recipient = string_strdupz((char *) sqlite3_column_text(res, 17));
  596. else
  597. ae->recipient = NULL;
  598. if (sqlite3_column_type(res, 18) != SQLITE_NULL)
  599. ae->source = string_strdupz((char *) sqlite3_column_text(res, 18));
  600. else
  601. ae->source = NULL;
  602. if (sqlite3_column_type(res, 19) != SQLITE_NULL)
  603. ae->units = string_strdupz((char *) sqlite3_column_text(res, 19));
  604. else
  605. ae->units = NULL;
  606. if (sqlite3_column_type(res, 20) != SQLITE_NULL)
  607. ae->info = string_strdupz((char *) sqlite3_column_text(res, 20));
  608. else
  609. ae->info = NULL;
  610. ae->exec_code = (int) sqlite3_column_int(res, 21);
  611. ae->new_status = (RRDCALC_STATUS) sqlite3_column_int(res, 22);
  612. ae->old_status = (RRDCALC_STATUS)sqlite3_column_int(res, 23);
  613. ae->delay = (int) sqlite3_column_int(res, 24);
  614. ae->new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 25);
  615. ae->old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 26);
  616. ae->last_repeat = last_repeat;
  617. if (sqlite3_column_type(res, 28) != SQLITE_NULL)
  618. ae->classification = string_strdupz((char *) sqlite3_column_text(res, 28));
  619. else
  620. ae->classification = NULL;
  621. if (sqlite3_column_type(res, 29) != SQLITE_NULL)
  622. ae->component = string_strdupz((char *) sqlite3_column_text(res, 29));
  623. else
  624. ae->component = NULL;
  625. if (sqlite3_column_type(res, 30) != SQLITE_NULL)
  626. ae->type = string_strdupz((char *) sqlite3_column_text(res, 30));
  627. else
  628. ae->type = NULL;
  629. if (sqlite3_column_type(res, 31) != SQLITE_NULL)
  630. ae->chart_context = string_strdupz((char *) sqlite3_column_text(res, 31));
  631. else
  632. ae->chart_context = NULL;
  633. char value_string[100 + 1];
  634. string_freez(ae->old_value_string);
  635. string_freez(ae->new_value_string);
  636. ae->old_value_string = string_strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae_units(ae), -1));
  637. ae->new_value_string = string_strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae_units(ae), -1));
  638. ae->next = host->health_log.alarms;
  639. host->health_log.alarms = ae;
  640. if(unlikely(ae->unique_id > host->health_max_unique_id))
  641. host->health_max_unique_id = ae->unique_id;
  642. if(unlikely(ae->alarm_id >= host->health_max_alarm_id))
  643. host->health_max_alarm_id = ae->alarm_id;
  644. loaded++;
  645. }
  646. netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
  647. dictionary_destroy(all_rrdcalcs);
  648. all_rrdcalcs = NULL;
  649. if(!host->health_max_unique_id) host->health_max_unique_id = (uint32_t)now_realtime_sec();
  650. if(!host->health_max_alarm_id) host->health_max_alarm_id = (uint32_t)now_realtime_sec();
  651. host->health_log.next_log_id = host->health_max_unique_id + 1;
  652. if (unlikely(!host->health_log.next_alarm_id || host->health_log.next_alarm_id <= host->health_max_alarm_id))
  653. host->health_log.next_alarm_id = host->health_max_alarm_id + 1;
  654. log_health("[%s]: Table health_log_%s, loaded %zd alarm entries, errors in %zd entries.", rrdhost_hostname(host), uuid_str, loaded, errored);
  655. ret = sqlite3_finalize(res);
  656. if (unlikely(ret != SQLITE_OK))
  657. error_report("Failed to finalize the health log read statement");
  658. sql_health_alarm_log_count(host);
  659. }
  660. /*
  661. * Store an alert config hash in the database
  662. */
  663. #define SQL_STORE_ALERT_CONFIG_HASH "insert or replace into alert_hash (hash_id, date_updated, alarm, template, " \
  664. "on_key, class, component, type, os, hosts, lookup, every, units, calc, families, plugin, module, " \
  665. "charts, green, red, warn, crit, exec, to_key, info, delay, options, repeat, host_labels, " \
  666. "p_db_lookup_dimensions, p_db_lookup_method, p_db_lookup_options, p_db_lookup_after, " \
  667. "p_db_lookup_before, p_update_every) values (?1,unixepoch(),?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12," \
  668. "?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33,?34);"
  669. int sql_store_alert_config_hash(uuid_t *hash_id, struct alert_config *cfg)
  670. {
  671. static __thread sqlite3_stmt *res = NULL;
  672. int rc, param = 0;
  673. if (unlikely(!db_meta)) {
  674. if (default_rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE)
  675. return 0;
  676. error_report("Database has not been initialized");
  677. return 1;
  678. }
  679. if (unlikely(!res)) {
  680. rc = prepare_statement(db_meta, SQL_STORE_ALERT_CONFIG_HASH, &res);
  681. if (unlikely(rc != SQLITE_OK)) {
  682. error_report("Failed to prepare statement to store alert configuration, rc = %d", rc);
  683. return 1;
  684. }
  685. }
  686. param++;
  687. rc = sqlite3_bind_blob(res, param, hash_id, sizeof(*hash_id), SQLITE_STATIC);
  688. if (unlikely(rc != SQLITE_OK))
  689. goto bind_fail;
  690. param++;
  691. rc = sqlite3_bind_string_or_null(res, cfg->alarm, param);
  692. if (unlikely(rc != SQLITE_OK))
  693. goto bind_fail;
  694. param++;
  695. rc = sqlite3_bind_string_or_null(res, cfg->template_key, param);
  696. if (unlikely(rc != SQLITE_OK))
  697. goto bind_fail;
  698. param++;
  699. rc = sqlite3_bind_string_or_null(res, cfg->on, param);
  700. if (unlikely(rc != SQLITE_OK))
  701. goto bind_fail;
  702. param++;
  703. rc = sqlite3_bind_string_or_null(res, cfg->classification, param);
  704. if (unlikely(rc != SQLITE_OK))
  705. goto bind_fail;
  706. param++;
  707. rc = sqlite3_bind_string_or_null(res, cfg->component, param);
  708. if (unlikely(rc != SQLITE_OK))
  709. goto bind_fail;
  710. param++;
  711. rc = sqlite3_bind_string_or_null(res, cfg->type, param);
  712. if (unlikely(rc != SQLITE_OK))
  713. goto bind_fail;
  714. param++;
  715. rc = sqlite3_bind_string_or_null(res, cfg->os, param);
  716. if (unlikely(rc != SQLITE_OK))
  717. goto bind_fail;
  718. param++;
  719. rc = sqlite3_bind_string_or_null(res, cfg->host, param);
  720. if (unlikely(rc != SQLITE_OK))
  721. goto bind_fail;
  722. param++;
  723. rc = sqlite3_bind_string_or_null(res, cfg->lookup, param);
  724. if (unlikely(rc != SQLITE_OK))
  725. goto bind_fail;
  726. param++;
  727. rc = sqlite3_bind_string_or_null(res, cfg->every, param);
  728. if (unlikely(rc != SQLITE_OK))
  729. goto bind_fail;
  730. param++;
  731. rc = sqlite3_bind_string_or_null(res, cfg->units, param);
  732. if (unlikely(rc != SQLITE_OK))
  733. goto bind_fail;
  734. param++;
  735. rc = sqlite3_bind_string_or_null(res, cfg->calc, param);
  736. if (unlikely(rc != SQLITE_OK))
  737. goto bind_fail;
  738. param++;
  739. rc = sqlite3_bind_string_or_null(res, cfg->families, param);
  740. if (unlikely(rc != SQLITE_OK))
  741. goto bind_fail;
  742. param++;
  743. rc = sqlite3_bind_string_or_null(res, cfg->plugin, param);
  744. if (unlikely(rc != SQLITE_OK))
  745. goto bind_fail;
  746. param++;
  747. rc = sqlite3_bind_string_or_null(res, cfg->module, param);
  748. if (unlikely(rc != SQLITE_OK))
  749. goto bind_fail;
  750. param++;
  751. rc = sqlite3_bind_string_or_null(res, cfg->charts, param);
  752. if (unlikely(rc != SQLITE_OK))
  753. goto bind_fail;
  754. param++;
  755. rc = sqlite3_bind_string_or_null(res, cfg->green, param);
  756. if (unlikely(rc != SQLITE_OK))
  757. goto bind_fail;
  758. param++;
  759. rc = sqlite3_bind_string_or_null(res, cfg->red, param);
  760. if (unlikely(rc != SQLITE_OK))
  761. goto bind_fail;
  762. param++;
  763. rc = sqlite3_bind_string_or_null(res, cfg->warn, param);
  764. if (unlikely(rc != SQLITE_OK))
  765. goto bind_fail;
  766. param++;
  767. rc = sqlite3_bind_string_or_null(res, cfg->crit, param);
  768. if (unlikely(rc != SQLITE_OK))
  769. goto bind_fail;
  770. param++;
  771. rc = sqlite3_bind_string_or_null(res, cfg->exec, param);
  772. if (unlikely(rc != SQLITE_OK))
  773. goto bind_fail;
  774. param++;
  775. rc = sqlite3_bind_string_or_null(res, cfg->to, param);
  776. if (unlikely(rc != SQLITE_OK))
  777. goto bind_fail;
  778. param++;
  779. rc = sqlite3_bind_string_or_null(res, cfg->info, param);
  780. if (unlikely(rc != SQLITE_OK))
  781. goto bind_fail;
  782. param++;
  783. rc = sqlite3_bind_string_or_null(res, cfg->delay, param);
  784. if (unlikely(rc != SQLITE_OK))
  785. goto bind_fail;
  786. param++;
  787. rc = sqlite3_bind_string_or_null(res, cfg->options, param);
  788. if (unlikely(rc != SQLITE_OK))
  789. goto bind_fail;
  790. param++;
  791. rc = sqlite3_bind_string_or_null(res, cfg->repeat, param);
  792. if (unlikely(rc != SQLITE_OK))
  793. goto bind_fail;
  794. param++;
  795. rc = sqlite3_bind_string_or_null(res, cfg->host_labels, param);
  796. if (unlikely(rc != SQLITE_OK))
  797. goto bind_fail;
  798. if (cfg->p_db_lookup_after) {
  799. param++;
  800. rc = sqlite3_bind_string_or_null(res, cfg->p_db_lookup_dimensions, param);
  801. if (unlikely(rc != SQLITE_OK))
  802. goto bind_fail;
  803. param++;
  804. rc = sqlite3_bind_string_or_null(res, cfg->p_db_lookup_method, param);
  805. if (unlikely(rc != SQLITE_OK))
  806. goto bind_fail;
  807. param++;
  808. rc = sqlite3_bind_int(res, 31, cfg->p_db_lookup_options);
  809. if (unlikely(rc != SQLITE_OK))
  810. goto bind_fail;
  811. param++;
  812. rc = sqlite3_bind_int(res, 32, cfg->p_db_lookup_after);
  813. if (unlikely(rc != SQLITE_OK))
  814. goto bind_fail;
  815. param++;
  816. rc = sqlite3_bind_int(res, 33, cfg->p_db_lookup_before);
  817. if (unlikely(rc != SQLITE_OK))
  818. goto bind_fail;
  819. } else {
  820. param++;
  821. rc = sqlite3_bind_null(res, 29);
  822. if (unlikely(rc != SQLITE_OK))
  823. goto bind_fail;
  824. param++;
  825. rc = sqlite3_bind_null(res, 30);
  826. if (unlikely(rc != SQLITE_OK))
  827. goto bind_fail;
  828. param++;
  829. rc = sqlite3_bind_null(res, 31);
  830. if (unlikely(rc != SQLITE_OK))
  831. goto bind_fail;
  832. param++;
  833. rc = sqlite3_bind_null(res, 32);
  834. if (unlikely(rc != SQLITE_OK))
  835. goto bind_fail;
  836. param++;
  837. rc = sqlite3_bind_null(res, 33);
  838. if (unlikely(rc != SQLITE_OK))
  839. goto bind_fail;
  840. }
  841. param++;
  842. rc = sqlite3_bind_int(res, 34, cfg->p_update_every);
  843. if (unlikely(rc != SQLITE_OK))
  844. goto bind_fail;
  845. rc = execute_insert(res);
  846. if (unlikely(rc != SQLITE_DONE))
  847. error_report("Failed to store alert config, rc = %d", rc);
  848. rc = sqlite3_reset(res);
  849. if (unlikely(rc != SQLITE_OK))
  850. error_report("Failed to reset statement in alert hash_id store function, rc = %d", rc);
  851. return 0;
  852. bind_fail:
  853. error_report("Failed to bind parameter %d to store alert hash_id, rc = %d", param, rc);
  854. rc = sqlite3_reset(res);
  855. if (unlikely(rc != SQLITE_OK))
  856. error_report("Failed to reset statement in alert hash_id store function, rc = %d", rc);
  857. return 1;
  858. }
  859. /*
  860. alert hashes are used for cloud communication.
  861. if cloud is disabled or openssl is not available (which will prevent cloud connectivity)
  862. skip hash calculations
  863. */
  864. #if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
  865. #define DIGEST_ALERT_CONFIG_VAL(v) ((v) ? EVP_DigestUpdate(evpctx, (string2str(v)), string_strlen((v))) : EVP_DigestUpdate(evpctx, "", 1))
  866. #endif
  867. int alert_hash_and_store_config(
  868. uuid_t hash_id,
  869. struct alert_config *cfg,
  870. int store_hash)
  871. {
  872. #if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
  873. EVP_MD_CTX *evpctx;
  874. unsigned char hash_value[EVP_MAX_MD_SIZE];
  875. unsigned int hash_len;
  876. evpctx = EVP_MD_CTX_create();
  877. EVP_DigestInit_ex(evpctx, EVP_sha256(), NULL);
  878. DIGEST_ALERT_CONFIG_VAL(cfg->alarm);
  879. DIGEST_ALERT_CONFIG_VAL(cfg->template_key);
  880. DIGEST_ALERT_CONFIG_VAL(cfg->os);
  881. DIGEST_ALERT_CONFIG_VAL(cfg->host);
  882. DIGEST_ALERT_CONFIG_VAL(cfg->on);
  883. DIGEST_ALERT_CONFIG_VAL(cfg->families);
  884. DIGEST_ALERT_CONFIG_VAL(cfg->plugin);
  885. DIGEST_ALERT_CONFIG_VAL(cfg->module);
  886. DIGEST_ALERT_CONFIG_VAL(cfg->charts);
  887. DIGEST_ALERT_CONFIG_VAL(cfg->lookup);
  888. DIGEST_ALERT_CONFIG_VAL(cfg->calc);
  889. DIGEST_ALERT_CONFIG_VAL(cfg->every);
  890. DIGEST_ALERT_CONFIG_VAL(cfg->green);
  891. DIGEST_ALERT_CONFIG_VAL(cfg->red);
  892. DIGEST_ALERT_CONFIG_VAL(cfg->warn);
  893. DIGEST_ALERT_CONFIG_VAL(cfg->crit);
  894. DIGEST_ALERT_CONFIG_VAL(cfg->exec);
  895. DIGEST_ALERT_CONFIG_VAL(cfg->to);
  896. DIGEST_ALERT_CONFIG_VAL(cfg->units);
  897. DIGEST_ALERT_CONFIG_VAL(cfg->info);
  898. DIGEST_ALERT_CONFIG_VAL(cfg->classification);
  899. DIGEST_ALERT_CONFIG_VAL(cfg->component);
  900. DIGEST_ALERT_CONFIG_VAL(cfg->type);
  901. DIGEST_ALERT_CONFIG_VAL(cfg->delay);
  902. DIGEST_ALERT_CONFIG_VAL(cfg->options);
  903. DIGEST_ALERT_CONFIG_VAL(cfg->repeat);
  904. DIGEST_ALERT_CONFIG_VAL(cfg->host_labels);
  905. EVP_DigestFinal_ex(evpctx, hash_value, &hash_len);
  906. EVP_MD_CTX_destroy(evpctx);
  907. fatal_assert(hash_len > sizeof(uuid_t));
  908. char uuid_str[GUID_LEN + 1];
  909. uuid_unparse_lower(*((uuid_t *)&hash_value), uuid_str);
  910. uuid_copy(hash_id, *((uuid_t *)&hash_value));
  911. /* store everything, so it can be recreated when not in memory or just a subset ? */
  912. if (store_hash)
  913. (void)sql_store_alert_config_hash( (uuid_t *)&hash_value, cfg);
  914. #else
  915. UNUSED(hash_id);
  916. UNUSED(cfg);
  917. UNUSED(store_hash);
  918. #endif
  919. return 1;
  920. }