sqlite_health.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  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 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 = db_execute(db_meta, command);
  22. if (unlikely(rc))
  23. error_report("HEALTH [%s]: SQLite error during creation of health log table", rrdhost_hostname(host));
  24. else {
  25. snprintfz(command, MAX_HEALTH_SQL_SIZE, "CREATE INDEX IF NOT EXISTS health_log_index_%s ON health_log_%s (unique_id); ", uuid_str, uuid_str);
  26. rc = db_execute(db_meta, command);
  27. if (unlikely(unlikely(rc)))
  28. error_report("HEALTH [%s]: SQLite error during creation of health log table index", rrdhost_hostname(host));
  29. }
  30. return rc;
  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;
  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;
  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;
  471. char command[MAX_HEALTH_SQL_SIZE + 1];
  472. uint32_t max_unique_id = 0;
  473. sqlite3_stmt *res = NULL;
  474. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_LAST_STATUSES(uuid_str));
  475. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  476. if (rc != SQLITE_OK) {
  477. error_report("Failed to prepare statement when trying to check removed statuses");
  478. return;
  479. }
  480. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  481. uint32_t alarm_id, alarm_event_id, unique_id;
  482. RRDCALC_STATUS status;
  483. status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
  484. unique_id = (uint32_t) sqlite3_column_int64(res, 1);
  485. alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
  486. alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
  487. if (unlikely(status != RRDCALC_STATUS_REMOVED)) {
  488. if (unlikely(!max_unique_id))
  489. max_unique_id = sql_get_max_unique_id (uuid_str);
  490. sql_inject_removed_status (uuid_str, alarm_id, alarm_event_id, unique_id, ++max_unique_id);
  491. }
  492. }
  493. rc = sqlite3_finalize(res);
  494. if (unlikely(rc != SQLITE_OK))
  495. error_report("Failed to finalize the statement");
  496. }
  497. /* Health related SQL queries
  498. Load from the health log table
  499. */
  500. #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
  501. void sql_health_alarm_log_load(RRDHOST *host) {
  502. sqlite3_stmt *res = NULL;
  503. int ret;
  504. ssize_t errored = 0, loaded = 0;
  505. char command[MAX_HEALTH_SQL_SIZE + 1];
  506. host->health.health_log_entries_written = 0;
  507. if (unlikely(!db_meta)) {
  508. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  509. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  510. return;
  511. }
  512. char uuid_str[GUID_LEN + 1];
  513. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  514. sql_check_removed_alerts_state(uuid_str);
  515. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_LOAD_HEALTH_LOG(uuid_str, host->health_log.max));
  516. ret = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  517. if (unlikely(ret != SQLITE_OK)) {
  518. error_report("HEALTH [%s]: Failed to prepare sql statement to load health log.", rrdhost_hostname(host));
  519. return;
  520. }
  521. DICTIONARY *all_rrdcalcs = dictionary_create(
  522. DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE);
  523. RRDCALC *rc;
  524. foreach_rrdcalc_in_rrdhost_read(host, rc) {
  525. dictionary_set(all_rrdcalcs, rrdcalc_name(rc), rc, sizeof(*rc));
  526. }
  527. foreach_rrdcalc_in_rrdhost_done(rc);
  528. netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
  529. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  530. ALARM_ENTRY *ae = NULL;
  531. // check that we have valid ids
  532. uint32_t unique_id = (uint32_t) sqlite3_column_int64(res, 1);
  533. if(!unique_id) {
  534. error_report("HEALTH [%s]: Got invalid unique id. Ignoring it.", rrdhost_hostname(host));
  535. errored++;
  536. continue;
  537. }
  538. uint32_t alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
  539. if(!alarm_id) {
  540. error_report("HEALTH [%s]: Got invalid alarm id. Ignoring it.", rrdhost_hostname(host));
  541. errored++;
  542. continue;
  543. }
  544. //need name, chart and family
  545. if (sqlite3_column_type(res, 13) == SQLITE_NULL) {
  546. error_report("HEALTH [%s]: Got null name field. Ignoring it.", rrdhost_hostname(host));
  547. errored++;
  548. continue;
  549. }
  550. if (sqlite3_column_type(res, 14) == SQLITE_NULL) {
  551. error_report("HEALTH [%s]: Got null chart field. Ignoring it.", rrdhost_hostname(host));
  552. errored++;
  553. continue;
  554. }
  555. if (sqlite3_column_type(res, 15) == SQLITE_NULL) {
  556. error_report("HEALTH [%s]: Got null family field. Ignoring it.", rrdhost_hostname(host));
  557. errored++;
  558. continue;
  559. }
  560. // Check if we got last_repeat field
  561. time_t 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. rc = sqlite3_bind_blob(res, ++param, hash_id, sizeof(*hash_id), SQLITE_STATIC);
  687. if (unlikely(rc != SQLITE_OK))
  688. goto bind_fail;
  689. rc = sqlite3_bind_string_or_null(res, cfg->alarm, ++param);
  690. if (unlikely(rc != SQLITE_OK))
  691. goto bind_fail;
  692. rc = sqlite3_bind_string_or_null(res, cfg->template_key, ++param);
  693. if (unlikely(rc != SQLITE_OK))
  694. goto bind_fail;
  695. rc = sqlite3_bind_string_or_null(res, cfg->on, ++param);
  696. if (unlikely(rc != SQLITE_OK))
  697. goto bind_fail;
  698. rc = sqlite3_bind_string_or_null(res, cfg->classification, ++param);
  699. if (unlikely(rc != SQLITE_OK))
  700. goto bind_fail;
  701. rc = sqlite3_bind_string_or_null(res, cfg->component, ++param);
  702. if (unlikely(rc != SQLITE_OK))
  703. goto bind_fail;
  704. rc = sqlite3_bind_string_or_null(res, cfg->type, ++param);
  705. if (unlikely(rc != SQLITE_OK))
  706. goto bind_fail;
  707. rc = sqlite3_bind_string_or_null(res, cfg->os, ++param);
  708. if (unlikely(rc != SQLITE_OK))
  709. goto bind_fail;
  710. rc = sqlite3_bind_string_or_null(res, cfg->host, ++param);
  711. if (unlikely(rc != SQLITE_OK))
  712. goto bind_fail;
  713. rc = sqlite3_bind_string_or_null(res, cfg->lookup, ++param);
  714. if (unlikely(rc != SQLITE_OK))
  715. goto bind_fail;
  716. rc = sqlite3_bind_string_or_null(res, cfg->every, ++param);
  717. if (unlikely(rc != SQLITE_OK))
  718. goto bind_fail;
  719. rc = sqlite3_bind_string_or_null(res, cfg->units, ++param);
  720. if (unlikely(rc != SQLITE_OK))
  721. goto bind_fail;
  722. rc = sqlite3_bind_string_or_null(res, cfg->calc, ++param);
  723. if (unlikely(rc != SQLITE_OK))
  724. goto bind_fail;
  725. rc = sqlite3_bind_string_or_null(res, cfg->families, ++param);
  726. if (unlikely(rc != SQLITE_OK))
  727. goto bind_fail;
  728. rc = sqlite3_bind_string_or_null(res, cfg->plugin, ++param);
  729. if (unlikely(rc != SQLITE_OK))
  730. goto bind_fail;
  731. rc = sqlite3_bind_string_or_null(res, cfg->module, ++param);
  732. if (unlikely(rc != SQLITE_OK))
  733. goto bind_fail;
  734. rc = sqlite3_bind_string_or_null(res, cfg->charts, ++param);
  735. if (unlikely(rc != SQLITE_OK))
  736. goto bind_fail;
  737. rc = sqlite3_bind_string_or_null(res, cfg->green, ++param);
  738. if (unlikely(rc != SQLITE_OK))
  739. goto bind_fail;
  740. rc = sqlite3_bind_string_or_null(res, cfg->red, ++param);
  741. if (unlikely(rc != SQLITE_OK))
  742. goto bind_fail;
  743. rc = sqlite3_bind_string_or_null(res, cfg->warn, ++param);
  744. if (unlikely(rc != SQLITE_OK))
  745. goto bind_fail;
  746. rc = sqlite3_bind_string_or_null(res, cfg->crit, ++param);
  747. if (unlikely(rc != SQLITE_OK))
  748. goto bind_fail;
  749. rc = sqlite3_bind_string_or_null(res, cfg->exec, ++param);
  750. if (unlikely(rc != SQLITE_OK))
  751. goto bind_fail;
  752. rc = sqlite3_bind_string_or_null(res, cfg->to, ++param);
  753. if (unlikely(rc != SQLITE_OK))
  754. goto bind_fail;
  755. rc = sqlite3_bind_string_or_null(res, cfg->info, ++param);
  756. if (unlikely(rc != SQLITE_OK))
  757. goto bind_fail;
  758. rc = sqlite3_bind_string_or_null(res, cfg->delay, ++param);
  759. if (unlikely(rc != SQLITE_OK))
  760. goto bind_fail;
  761. rc = sqlite3_bind_string_or_null(res, cfg->options, ++param);
  762. if (unlikely(rc != SQLITE_OK))
  763. goto bind_fail;
  764. rc = sqlite3_bind_string_or_null(res, cfg->repeat, ++param);
  765. if (unlikely(rc != SQLITE_OK))
  766. goto bind_fail;
  767. rc = sqlite3_bind_string_or_null(res, cfg->host_labels, ++param);
  768. if (unlikely(rc != SQLITE_OK))
  769. goto bind_fail;
  770. if (cfg->p_db_lookup_after) {
  771. rc = sqlite3_bind_string_or_null(res, cfg->p_db_lookup_dimensions, ++param);
  772. if (unlikely(rc != SQLITE_OK))
  773. goto bind_fail;
  774. rc = sqlite3_bind_string_or_null(res, cfg->p_db_lookup_method, ++param);
  775. if (unlikely(rc != SQLITE_OK))
  776. goto bind_fail;
  777. rc = sqlite3_bind_int(res, ++param, (int) cfg->p_db_lookup_options);
  778. if (unlikely(rc != SQLITE_OK))
  779. goto bind_fail;
  780. rc = sqlite3_bind_int(res, ++param, (int) cfg->p_db_lookup_after);
  781. if (unlikely(rc != SQLITE_OK))
  782. goto bind_fail;
  783. rc = sqlite3_bind_int(res, ++param, (int) cfg->p_db_lookup_before);
  784. if (unlikely(rc != SQLITE_OK))
  785. goto bind_fail;
  786. } else {
  787. rc = sqlite3_bind_null(res, ++param);
  788. if (unlikely(rc != SQLITE_OK))
  789. goto bind_fail;
  790. rc = sqlite3_bind_null(res, ++param);
  791. if (unlikely(rc != SQLITE_OK))
  792. goto bind_fail;
  793. rc = sqlite3_bind_null(res, ++param);
  794. if (unlikely(rc != SQLITE_OK))
  795. goto bind_fail;
  796. rc = sqlite3_bind_null(res, ++param);
  797. if (unlikely(rc != SQLITE_OK))
  798. goto bind_fail;
  799. rc = sqlite3_bind_null(res, ++param);
  800. if (unlikely(rc != SQLITE_OK))
  801. goto bind_fail;
  802. }
  803. rc = sqlite3_bind_int(res, ++param, cfg->p_update_every);
  804. if (unlikely(rc != SQLITE_OK))
  805. goto bind_fail;
  806. rc = execute_insert(res);
  807. if (unlikely(rc != SQLITE_DONE))
  808. error_report("Failed to store alert config, rc = %d", rc);
  809. rc = sqlite3_reset(res);
  810. if (unlikely(rc != SQLITE_OK))
  811. error_report("Failed to reset statement in alert hash_id store function, rc = %d", rc);
  812. return 0;
  813. bind_fail:
  814. error_report("Failed to bind parameter %d to store alert hash_id, rc = %d", param, rc);
  815. rc = sqlite3_reset(res);
  816. if (unlikely(rc != SQLITE_OK))
  817. error_report("Failed to reset statement in alert hash_id store function, rc = %d", rc);
  818. return 1;
  819. }
  820. /*
  821. alert hashes are used for cloud communication.
  822. if cloud is disabled or openssl is not available (which will prevent cloud connectivity)
  823. skip hash calculations
  824. */
  825. #if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
  826. #define DIGEST_ALERT_CONFIG_VAL(v) ((v) ? EVP_DigestUpdate(evpctx, (string2str(v)), string_strlen((v))) : EVP_DigestUpdate(evpctx, "", 1))
  827. #endif
  828. int alert_hash_and_store_config(
  829. uuid_t hash_id,
  830. struct alert_config *cfg,
  831. int store_hash)
  832. {
  833. #if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
  834. EVP_MD_CTX *evpctx;
  835. unsigned char hash_value[EVP_MAX_MD_SIZE];
  836. unsigned int hash_len;
  837. evpctx = EVP_MD_CTX_create();
  838. EVP_DigestInit_ex(evpctx, EVP_sha256(), NULL);
  839. DIGEST_ALERT_CONFIG_VAL(cfg->alarm);
  840. DIGEST_ALERT_CONFIG_VAL(cfg->template_key);
  841. DIGEST_ALERT_CONFIG_VAL(cfg->os);
  842. DIGEST_ALERT_CONFIG_VAL(cfg->host);
  843. DIGEST_ALERT_CONFIG_VAL(cfg->on);
  844. DIGEST_ALERT_CONFIG_VAL(cfg->families);
  845. DIGEST_ALERT_CONFIG_VAL(cfg->plugin);
  846. DIGEST_ALERT_CONFIG_VAL(cfg->module);
  847. DIGEST_ALERT_CONFIG_VAL(cfg->charts);
  848. DIGEST_ALERT_CONFIG_VAL(cfg->lookup);
  849. DIGEST_ALERT_CONFIG_VAL(cfg->calc);
  850. DIGEST_ALERT_CONFIG_VAL(cfg->every);
  851. DIGEST_ALERT_CONFIG_VAL(cfg->green);
  852. DIGEST_ALERT_CONFIG_VAL(cfg->red);
  853. DIGEST_ALERT_CONFIG_VAL(cfg->warn);
  854. DIGEST_ALERT_CONFIG_VAL(cfg->crit);
  855. DIGEST_ALERT_CONFIG_VAL(cfg->exec);
  856. DIGEST_ALERT_CONFIG_VAL(cfg->to);
  857. DIGEST_ALERT_CONFIG_VAL(cfg->units);
  858. DIGEST_ALERT_CONFIG_VAL(cfg->info);
  859. DIGEST_ALERT_CONFIG_VAL(cfg->classification);
  860. DIGEST_ALERT_CONFIG_VAL(cfg->component);
  861. DIGEST_ALERT_CONFIG_VAL(cfg->type);
  862. DIGEST_ALERT_CONFIG_VAL(cfg->delay);
  863. DIGEST_ALERT_CONFIG_VAL(cfg->options);
  864. DIGEST_ALERT_CONFIG_VAL(cfg->repeat);
  865. DIGEST_ALERT_CONFIG_VAL(cfg->host_labels);
  866. EVP_DigestFinal_ex(evpctx, hash_value, &hash_len);
  867. EVP_MD_CTX_destroy(evpctx);
  868. fatal_assert(hash_len > sizeof(uuid_t));
  869. char uuid_str[GUID_LEN + 1];
  870. uuid_unparse_lower(*((uuid_t *)&hash_value), uuid_str);
  871. uuid_copy(hash_id, *((uuid_t *)&hash_value));
  872. /* store everything, so it can be recreated when not in memory or just a subset ? */
  873. if (store_hash)
  874. (void)sql_store_alert_config_hash( (uuid_t *)&hash_value, cfg);
  875. #else
  876. UNUSED(hash_id);
  877. UNUSED(cfg);
  878. UNUSED(store_hash);
  879. #endif
  880. return 1;
  881. }