sqlite_health.c 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "sqlite_health.h"
  3. #include "sqlite_functions.h"
  4. #include "sqlite_db_migration.h"
  5. #define MAX_HEALTH_SQL_SIZE 2048
  6. #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))
  7. /* Health related SQL queries
  8. Updates an entry in the table
  9. */
  10. #define SQL_UPDATE_HEALTH_LOG "UPDATE health_log_detail set updated_by_id = ?, flags = ?, exec_run_timestamp = ?, exec_code = ? where unique_id = ? AND alarm_id = ? and transition_id = ?;"
  11. void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) {
  12. sqlite3_stmt *res = NULL;
  13. int rc;
  14. if (unlikely(!db_meta)) {
  15. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  16. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  17. return;
  18. }
  19. rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG, -1, &res, 0);
  20. if (unlikely(rc != SQLITE_OK)) {
  21. error_report("HEALTH [%s]: Failed to prepare statement for SQL_UPDATE_HEALTH_LOG", rrdhost_hostname(host));
  22. return;
  23. }
  24. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) ae->updated_by_id);
  25. if (unlikely(rc != SQLITE_OK)) {
  26. error_report("Failed to bind updated_by_id parameter for SQL_UPDATE_HEALTH_LOG");
  27. goto failed;
  28. }
  29. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->flags);
  30. if (unlikely(rc != SQLITE_OK)) {
  31. error_report("Failed to bind flags parameter for SQL_UPDATE_HEALTH_LOG");
  32. goto failed;
  33. }
  34. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->exec_run_timestamp);
  35. if (unlikely(rc != SQLITE_OK)) {
  36. error_report("Failed to bind exec_run_timestamp parameter for SQL_UPDATE_HEALTH_LOG");
  37. goto failed;
  38. }
  39. rc = sqlite3_bind_int(res, 4, ae->exec_code);
  40. if (unlikely(rc != SQLITE_OK)) {
  41. error_report("Failed to bind exec_code parameter for SQL_UPDATE_HEALTH_LOG");
  42. goto failed;
  43. }
  44. rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) ae->unique_id);
  45. if (unlikely(rc != SQLITE_OK)) {
  46. error_report("Failed to bind unique_id parameter for SQL_UPDATE_HEALTH_LOG");
  47. goto failed;
  48. }
  49. rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->alarm_id);
  50. if (unlikely(rc != SQLITE_OK)) {
  51. error_report("Failed to bind unique_id parameter for SQL_UPDATE_HEALTH_LOG");
  52. goto failed;
  53. }
  54. rc = sqlite3_bind_blob(res, 7, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
  55. if (unlikely(rc != SQLITE_OK)) {
  56. error_report("Failed to bind host_id for SQL_UPDATE_HEALTH_LOG.");
  57. goto failed;
  58. }
  59. rc = execute_insert(res);
  60. if (unlikely(rc != SQLITE_DONE)) {
  61. error_report("HEALTH [%s]: Failed to update health log, rc = %d", rrdhost_hostname(host), rc);
  62. }
  63. failed:
  64. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  65. error_report("HEALTH [%s]: Failed to finalize the prepared statement for updating health log.", rrdhost_hostname(host));
  66. }
  67. /* Health related SQL queries
  68. Inserts an entry in the table
  69. */
  70. #define SQL_INSERT_HEALTH_LOG "INSERT INTO health_log (host_id, alarm_id, " \
  71. "config_hash_id, name, chart, family, exec, recipient, units, chart_context, last_transition_id) " \
  72. "VALUES (?,?,?,?,?,?,?,?,?,?,?) " \
  73. "ON CONFLICT (host_id, alarm_id) DO UPDATE SET last_transition_id = excluded.last_transition_id RETURNING health_log_id; "
  74. #define SQL_INSERT_HEALTH_LOG_DETAIL "INSERT INTO health_log_detail (health_log_id, unique_id, alarm_id, alarm_event_id, " \
  75. "updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, " \
  76. "info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, global_id) " \
  77. "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,@global_id); "
  78. void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
  79. sqlite3_stmt *res = NULL;
  80. int rc;
  81. uint64_t health_log_id = 0;
  82. if (unlikely(!db_meta)) {
  83. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  84. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  85. return;
  86. }
  87. rc = sqlite3_prepare_v2(db_meta, SQL_INSERT_HEALTH_LOG, -1, &res, 0);
  88. if (unlikely(rc != SQLITE_OK)) {
  89. error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host));
  90. return;
  91. }
  92. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  93. if (unlikely(rc != SQLITE_OK)) {
  94. error_report("Failed to bind host_id for SQL_INSERT_HEALTH_LOG.");
  95. goto failed;
  96. }
  97. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->alarm_id);
  98. if (unlikely(rc != SQLITE_OK)) {
  99. error_report("Failed to bind alarm_id parameter for SQL_INSERT_HEALTH_LOG");
  100. goto failed;
  101. }
  102. rc = sqlite3_bind_blob(res, 3, &ae->config_hash_id, sizeof(ae->config_hash_id), SQLITE_STATIC);
  103. if (unlikely(rc != SQLITE_OK)) {
  104. error_report("Failed to bind config_hash_id parameter for SQL_INSERT_HEALTH_LOG");
  105. goto failed;
  106. }
  107. rc = sqlite3_bind_string_or_null(res, ae->name, 4);
  108. if (unlikely(rc != SQLITE_OK)) {
  109. error_report("Failed to bind name parameter for SQL_INSERT_HEALTH_LOG");
  110. goto failed;
  111. }
  112. rc = sqlite3_bind_string_or_null(res, ae->chart, 5);
  113. if (unlikely(rc != SQLITE_OK)) {
  114. error_report("Failed to bind chart parameter for SQL_INSERT_HEALTH_LOG");
  115. goto failed;
  116. }
  117. rc = sqlite3_bind_string_or_null(res, ae->family, 6);
  118. if (unlikely(rc != SQLITE_OK)) {
  119. error_report("Failed to bind family parameter for SQL_INSERT_HEALTH_LOG");
  120. goto failed;
  121. }
  122. rc = sqlite3_bind_string_or_null(res, ae->exec, 7);
  123. if (unlikely(rc != SQLITE_OK)) {
  124. error_report("Failed to bind exec parameter for SQL_INSERT_HEALTH_LOG");
  125. goto failed;
  126. }
  127. rc = sqlite3_bind_string_or_null(res, ae->recipient, 8);
  128. if (unlikely(rc != SQLITE_OK)) {
  129. error_report("Failed to bind recipient parameter for SQL_INSERT_HEALTH_LOG");
  130. goto failed;
  131. }
  132. rc = sqlite3_bind_string_or_null(res, ae->units, 9);
  133. if (unlikely(rc != SQLITE_OK)) {
  134. error_report("Failed to bind host_id parameter to store node instance information");
  135. goto failed;
  136. }
  137. rc = sqlite3_bind_string_or_null(res, ae->chart_context, 10);
  138. if (unlikely(rc != SQLITE_OK)) {
  139. error_report("Failed to bind chart_context parameter for SQL_INSERT_HEALTH_LOG");
  140. goto failed;
  141. }
  142. rc = sqlite3_bind_blob(res, 11, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
  143. if (unlikely(rc != SQLITE_OK)) {
  144. error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG");
  145. goto failed;
  146. }
  147. rc = sqlite3_step_monitored(res);
  148. if (likely(rc == SQLITE_ROW))
  149. health_log_id = (size_t) sqlite3_column_int64(res, 0);
  150. else {
  151. error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG, rc = %d", rrdhost_hostname(host), rc);
  152. goto failed;
  153. }
  154. rc = sqlite3_finalize(res);
  155. if (unlikely(rc != SQLITE_OK))
  156. error_report("HEALTH [%s]: Failed to finalize the prepared statement for inserting to health log.", rrdhost_hostname(host));
  157. rc = sqlite3_prepare_v2(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, -1, &res, 0);
  158. if (unlikely(rc != SQLITE_OK)) {
  159. error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG_DETAIL", rrdhost_hostname(host));
  160. return;
  161. }
  162. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) health_log_id);
  163. if (unlikely(rc != SQLITE_OK)) {
  164. error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  165. goto failed;
  166. }
  167. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->unique_id);
  168. if (unlikely(rc != SQLITE_OK)) {
  169. error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  170. goto failed;
  171. }
  172. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->alarm_id);
  173. if (unlikely(rc != SQLITE_OK)) {
  174. error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  175. goto failed;
  176. }
  177. rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) ae->alarm_event_id);
  178. if (unlikely(rc != SQLITE_OK)) {
  179. error_report("Failed to bind alarm_event_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  180. goto failed;
  181. }
  182. rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) ae->updated_by_id);
  183. if (unlikely(rc != SQLITE_OK)) {
  184. error_report("Failed to bind updated_by_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  185. goto failed;
  186. }
  187. rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->updates_id);
  188. if (unlikely(rc != SQLITE_OK)) {
  189. error_report("Failed to bind updates_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  190. goto failed;
  191. }
  192. rc = sqlite3_bind_int64(res, 7, (sqlite3_int64) ae->when);
  193. if (unlikely(rc != SQLITE_OK)) {
  194. error_report("Failed to bind when parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  195. goto failed;
  196. }
  197. rc = sqlite3_bind_int64(res, 8, (sqlite3_int64) ae->duration);
  198. if (unlikely(rc != SQLITE_OK)) {
  199. error_report("Failed to bind duration parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  200. goto failed;
  201. }
  202. rc = sqlite3_bind_int64(res, 9, (sqlite3_int64) ae->non_clear_duration);
  203. if (unlikely(rc != SQLITE_OK)) {
  204. error_report("Failed to bind non_clear_duration parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  205. goto failed;
  206. }
  207. rc = sqlite3_bind_int64(res, 10, (sqlite3_int64) ae->flags);
  208. if (unlikely(rc != SQLITE_OK)) {
  209. error_report("Failed to bind flags parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  210. goto failed;
  211. }
  212. rc = sqlite3_bind_int64(res, 11, (sqlite3_int64) ae->exec_run_timestamp);
  213. if (unlikely(rc != SQLITE_OK)) {
  214. error_report("Failed to bind exec_run_timestamp parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  215. goto failed;
  216. }
  217. rc = sqlite3_bind_int64(res, 12, (sqlite3_int64) ae->delay_up_to_timestamp);
  218. if (unlikely(rc != SQLITE_OK)) {
  219. error_report("Failed to bind delay_up_to_timestamp parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  220. goto failed;
  221. }
  222. rc = sqlite3_bind_string_or_null(res, ae->info, 13);
  223. if (unlikely(rc != SQLITE_OK)) {
  224. error_report("Failed to bind info parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  225. goto failed;
  226. }
  227. rc = sqlite3_bind_int(res, 14, ae->exec_code);
  228. if (unlikely(rc != SQLITE_OK)) {
  229. error_report("Failed to bind exec_code parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  230. goto failed;
  231. }
  232. rc = sqlite3_bind_int(res, 15, ae->new_status);
  233. if (unlikely(rc != SQLITE_OK)) {
  234. error_report("Failed to bind new_status parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  235. goto failed;
  236. }
  237. rc = sqlite3_bind_int(res, 16, ae->old_status);
  238. if (unlikely(rc != SQLITE_OK)) {
  239. error_report("Failed to bind old_status parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  240. goto failed;
  241. }
  242. rc = sqlite3_bind_int(res, 17, ae->delay);
  243. if (unlikely(rc != SQLITE_OK)) {
  244. error_report("Failed to bind delay parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  245. goto failed;
  246. }
  247. rc = sqlite3_bind_double(res, 18, ae->new_value);
  248. if (unlikely(rc != SQLITE_OK)) {
  249. error_report("Failed to bind new_value parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  250. goto failed;
  251. }
  252. rc = sqlite3_bind_double(res, 19, ae->old_value);
  253. if (unlikely(rc != SQLITE_OK)) {
  254. error_report("Failed to bind old_value parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  255. goto failed;
  256. }
  257. rc = sqlite3_bind_int64(res, 20, (sqlite3_int64) ae->last_repeat);
  258. if (unlikely(rc != SQLITE_OK)) {
  259. error_report("Failed to bind last_repeat parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  260. goto failed;
  261. }
  262. rc = sqlite3_bind_blob(res, 21, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
  263. if (unlikely(rc != SQLITE_OK)) {
  264. error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  265. goto failed;
  266. }
  267. rc = sqlite3_bind_int64(res, 22, (sqlite3_int64) ae->global_id);
  268. if (unlikely(rc != SQLITE_OK)) {
  269. error_report("Failed to bind global_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
  270. goto failed;
  271. }
  272. rc = execute_insert(res);
  273. if (unlikely(rc != SQLITE_DONE)) {
  274. error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG_DETAIL, rc = %d", rrdhost_hostname(host), rc);
  275. goto failed;
  276. }
  277. ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
  278. host->health.health_log_entries_written++;
  279. failed:
  280. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  281. error_report("HEALTH [%s]: Failed to finalize the prepared statement for inserting to health log.", rrdhost_hostname(host));
  282. }
  283. void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae)
  284. {
  285. if (ae->flags & HEALTH_ENTRY_FLAG_SAVED)
  286. sql_health_alarm_log_update(host, ae);
  287. else {
  288. sql_health_alarm_log_insert(host, ae);
  289. #ifdef ENABLE_ACLK
  290. if (netdata_cloud_enabled) {
  291. sql_queue_alarm_to_aclk(host, ae, 0);
  292. }
  293. #endif
  294. }
  295. }
  296. /* Health related SQL queries
  297. Get a count of rows from health log table
  298. */
  299. #define SQL_COUNT_HEALTH_LOG_DETAIL "SELECT count(1) FROM health_log_detail hld, health_log hl where hl.host_id = @host_id and hl.health_log_id = hld.health_log_id;"
  300. void sql_health_alarm_log_count(RRDHOST *host) {
  301. sqlite3_stmt *res = NULL;
  302. int rc;
  303. if (unlikely(!db_meta)) {
  304. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  305. error_report("Database has not been initialized");
  306. return;
  307. }
  308. rc = sqlite3_prepare_v2(db_meta, SQL_COUNT_HEALTH_LOG_DETAIL, -1, &res, 0);
  309. if (unlikely(rc != SQLITE_OK)) {
  310. error_report("Failed to prepare statement to count health log entries from db");
  311. return;
  312. }
  313. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  314. if (unlikely(rc != SQLITE_OK)) {
  315. error_report("Failed to bind host_id for SQL_COUNT_HEALTH_LOG.");
  316. sqlite3_finalize(res);
  317. return;
  318. }
  319. rc = sqlite3_step_monitored(res);
  320. if (likely(rc == SQLITE_ROW))
  321. host->health.health_log_entries_written = (size_t) sqlite3_column_int64(res, 0);
  322. rc = sqlite3_finalize(res);
  323. if (unlikely(rc != SQLITE_OK))
  324. error_report("Failed to finalize the prepared statement to count health log entries from db");
  325. netdata_log_info("HEALTH [%s]: Table health_log_detail contains %lu entries.", rrdhost_hostname(host), (unsigned long int) host->health.health_log_entries_written);
  326. }
  327. /* Health related SQL queries
  328. Cleans up the health_log_detail table on a non-claimed host
  329. */
  330. #define SQL_CLEANUP_HEALTH_LOG_DETAIL_NOT_CLAIMED "DELETE FROM health_log_detail WHERE health_log_id IN (SELECT health_log_id FROM health_log WHERE host_id = ?1) AND when_key + ?2 < unixepoch() AND updated_by_id <> 0 AND transition_id NOT IN (SELECT last_transition_id FROM health_log hl WHERE hl.host_id = ?3);"
  331. void sql_health_alarm_log_cleanup_not_claimed(RRDHOST *host) {
  332. sqlite3_stmt *res = NULL;
  333. int rc;
  334. char command[MAX_HEALTH_SQL_SIZE + 1];
  335. if (unlikely(!db_meta)) {
  336. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  337. error_report("Database has not been initialized");
  338. return;
  339. }
  340. char uuid_str[UUID_STR_LEN];
  341. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  342. rc = sqlite3_prepare_v2(db_meta, SQL_CLEANUP_HEALTH_LOG_DETAIL_NOT_CLAIMED, -1, &res, 0);
  343. if (unlikely(rc != SQLITE_OK)) {
  344. error_report("Failed to prepare statement to cleanup health log detail table (un-claimed)");
  345. return;
  346. }
  347. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  348. if (unlikely(rc != SQLITE_OK)) {
  349. error_report("Failed to bind host_id for SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED.");
  350. sqlite3_finalize(res);
  351. return;
  352. }
  353. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64)host->health_log.health_log_history);
  354. if (unlikely(rc != SQLITE_OK)) {
  355. error_report("Failed to bind health log history for SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED.");
  356. sqlite3_finalize(res);
  357. return;
  358. }
  359. rc = sqlite3_bind_blob(res, 3, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  360. if (unlikely(rc != SQLITE_OK)) {
  361. error_report("Failed to bind host_id for SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED.");
  362. sqlite3_finalize(res);
  363. return;
  364. }
  365. rc = sqlite3_step_monitored(res);
  366. if (unlikely(rc != SQLITE_DONE))
  367. error_report("Failed to cleanup health log detail table, rc = %d", rc);
  368. rc = sqlite3_finalize(res);
  369. if (unlikely(rc != SQLITE_OK))
  370. error_report("Failed to finalize the prepared statement to cleanup health log detail table (un-claimed)");
  371. sql_health_alarm_log_count(host);
  372. snprintfz(command, MAX_HEALTH_SQL_SIZE, "aclk_alert_%s", uuid_str);
  373. if (unlikely(table_exists_in_database(command))) {
  374. sql_aclk_alert_clean_dead_entries(host);
  375. }
  376. }
  377. /* Health related SQL queries
  378. Cleans up the health_log_detail table on a claimed host
  379. */
  380. #define SQL_CLEANUP_HEALTH_LOG_DETAIL_CLAIMED(guid) "DELETE from health_log_detail WHERE unique_id NOT IN (SELECT filtered_alert_unique_id FROM aclk_alert_%s) AND unique_id IN (SELECT hld.unique_id FROM health_log hl, health_log_detail hld WHERE hl.host_id = ?1 AND hl.health_log_id = hld.health_log_id) AND health_log_id IN (SELECT health_log_id FROM health_log WHERE host_id = ?2) AND when_key + ?3 < unixepoch() AND updated_by_id <> 0 AND transition_id NOT IN (SELECT last_transition_id FROM health_log hl WHERE hl.host_id = ?4);", guid
  381. void sql_health_alarm_log_cleanup_claimed(RRDHOST *host) {
  382. sqlite3_stmt *res = NULL;
  383. int rc;
  384. char command[MAX_HEALTH_SQL_SIZE + 1];
  385. if (unlikely(!db_meta)) {
  386. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  387. error_report("Database has not been initialized");
  388. return;
  389. }
  390. char uuid_str[UUID_STR_LEN];
  391. uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
  392. snprintfz(command, MAX_HEALTH_SQL_SIZE, "aclk_alert_%s", uuid_str);
  393. if (!table_exists_in_database(command)) {
  394. sql_health_alarm_log_cleanup_not_claimed(host);
  395. return;
  396. }
  397. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CLEANUP_HEALTH_LOG_DETAIL_CLAIMED(uuid_str));
  398. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  399. if (unlikely(rc != SQLITE_OK)) {
  400. error_report("Failed to prepare statement to cleanup health log detail table (claimed)");
  401. return;
  402. }
  403. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  404. if (unlikely(rc != SQLITE_OK)) {
  405. error_report("Failed to bind first host_id for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
  406. sqlite3_finalize(res);
  407. return;
  408. }
  409. rc = sqlite3_bind_blob(res, 2, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  410. if (unlikely(rc != SQLITE_OK)) {
  411. error_report("Failed to bind second host_id for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
  412. sqlite3_finalize(res);
  413. return;
  414. }
  415. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64)host->health_log.health_log_history);
  416. if (unlikely(rc != SQLITE_OK)) {
  417. error_report("Failed to bind health log history for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
  418. sqlite3_finalize(res);
  419. return;
  420. }
  421. rc = sqlite3_bind_blob(res, 4, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  422. if (unlikely(rc != SQLITE_OK)) {
  423. error_report("Failed to bind second host_id for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
  424. sqlite3_finalize(res);
  425. return;
  426. }
  427. rc = sqlite3_step_monitored(res);
  428. if (unlikely(rc != SQLITE_DONE))
  429. error_report("Failed to cleanup health log detail table, rc = %d", rc);
  430. rc = sqlite3_finalize(res);
  431. if (unlikely(rc != SQLITE_OK))
  432. error_report("Failed to finalize the prepared statement to cleanup health log detail table (claimed)");
  433. sql_health_alarm_log_count(host);
  434. sql_aclk_alert_clean_dead_entries(host);
  435. }
  436. /* Health related SQL queries
  437. Cleans up the health_log table.
  438. */
  439. void sql_health_alarm_log_cleanup(RRDHOST *host) {
  440. if (!claimed()) {
  441. sql_health_alarm_log_cleanup_not_claimed(host);
  442. } else
  443. sql_health_alarm_log_cleanup_claimed(host);
  444. }
  445. #define SQL_INJECT_REMOVED "insert into health_log_detail (health_log_id, unique_id, alarm_id, alarm_event_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, global_id) select health_log_id, ?1, ?2, ?3, 0, ?4, unixepoch(), 0, 0, flags, exec_run_timestamp, unixepoch(), info, exec_code, -2, new_status, delay, NULL, new_value, 0, ?5, now_usec(0) from health_log_detail where unique_id = ?6 and transition_id = ?7;"
  446. #define SQL_INJECT_REMOVED_UPDATE_DETAIL "update health_log_detail set flags = flags | ?1, updated_by_id = ?2 where unique_id = ?3 and transition_id = ?4;"
  447. #define SQL_INJECT_REMOVED_UPDATE_LOG "update health_log set last_transition_id = ?1 where alarm_id = ?2 and last_transition_id = ?3 and host_id = ?4;"
  448. void sql_inject_removed_status(RRDHOST *host, uint32_t alarm_id, uint32_t alarm_event_id, uint32_t unique_id, uint32_t max_unique_id, uuid_t *prev_transition_id)
  449. {
  450. int rc;
  451. if (!alarm_id || !alarm_event_id || !unique_id || !max_unique_id)
  452. return;
  453. sqlite3_stmt *res = NULL;
  454. rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED, -1, &res, 0);
  455. if (rc != SQLITE_OK) {
  456. error_report("Failed to prepare statement when trying to inject removed event");
  457. return;
  458. }
  459. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) max_unique_id);
  460. if (unlikely(rc != SQLITE_OK)) {
  461. error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED");
  462. goto failed;
  463. }
  464. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
  465. if (unlikely(rc != SQLITE_OK)) {
  466. error_report("Failed to bind alarm_id parameter for SQL_INJECT_REMOVED");
  467. goto failed;
  468. }
  469. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) alarm_event_id + 1);
  470. if (unlikely(rc != SQLITE_OK)) {
  471. error_report("Failed to bind alarm_event_id parameter for SQL_INJECT_REMOVED");
  472. goto failed;
  473. }
  474. rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) unique_id);
  475. if (unlikely(rc != SQLITE_OK)) {
  476. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED");
  477. goto failed;
  478. }
  479. uuid_t transition_id;
  480. uuid_generate_random(transition_id);
  481. rc = sqlite3_bind_blob(res, 5, &transition_id, sizeof(transition_id), SQLITE_STATIC);
  482. if (unlikely(rc != SQLITE_OK)) {
  483. error_report("Failed to bind config_hash_id parameter for SQL_INJECT_REMOVED");
  484. goto failed;
  485. }
  486. rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) unique_id);
  487. if (unlikely(rc != SQLITE_OK)) {
  488. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED");
  489. goto failed;
  490. }
  491. rc = sqlite3_bind_blob(res, 7, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC);
  492. if (unlikely(rc != SQLITE_OK)) {
  493. error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED.");
  494. goto failed;
  495. }
  496. rc = execute_insert(res);
  497. if (unlikely(rc != SQLITE_DONE)) {
  498. error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED, rc = %d", rc);
  499. goto failed;
  500. }
  501. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  502. error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
  503. //update the old entry in health_log_detail
  504. rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_DETAIL, -1, &res, 0);
  505. if (rc != SQLITE_OK) {
  506. error_report("Failed to prepare statement when trying to update health_log_detail during inject removed event");
  507. return;
  508. }
  509. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) HEALTH_ENTRY_FLAG_UPDATED);
  510. if (unlikely(rc != SQLITE_OK)) {
  511. error_report("Failed to bind flags parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
  512. goto failed;
  513. }
  514. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) max_unique_id);
  515. if (unlikely(rc != SQLITE_OK)) {
  516. error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
  517. goto failed;
  518. }
  519. rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) unique_id);
  520. if (unlikely(rc != SQLITE_OK)) {
  521. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
  522. goto failed;
  523. }
  524. rc = sqlite3_bind_blob(res, 4, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC);
  525. if (unlikely(rc != SQLITE_OK)) {
  526. error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
  527. goto failed;
  528. }
  529. rc = execute_insert(res);
  530. if (unlikely(rc != SQLITE_DONE)) {
  531. error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc);
  532. goto failed;
  533. }
  534. //update the health_log_table
  535. rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_LOG, -1, &res, 0);
  536. if (rc != SQLITE_OK) {
  537. error_report("Failed to prepare statement when trying to update health_log during inject removed event");
  538. return;
  539. }
  540. rc = sqlite3_bind_blob(res, 1, &transition_id, sizeof(transition_id), SQLITE_STATIC);
  541. if (unlikely(rc != SQLITE_OK)) {
  542. error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_LOG");
  543. goto failed;
  544. }
  545. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
  546. if (unlikely(rc != SQLITE_OK)) {
  547. error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
  548. goto failed;
  549. }
  550. rc = sqlite3_bind_blob(res, 3, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC);
  551. if (unlikely(rc != SQLITE_OK)) {
  552. error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_LOG");
  553. goto failed;
  554. }
  555. rc = sqlite3_bind_blob(res, 4, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  556. if (unlikely(rc != SQLITE_OK)) {
  557. error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
  558. goto failed;
  559. }
  560. rc = execute_insert(res);
  561. if (unlikely(rc != SQLITE_DONE)) {
  562. error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc);
  563. goto failed;
  564. }
  565. failed:
  566. if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
  567. error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
  568. }
  569. #define SQL_SELECT_MAX_UNIQUE_ID "SELECT MAX(hld.unique_id) from health_log_detail hld, health_log hl where hl.host_id = @host_id; and hl.health_log_id = hld.health_log_id"
  570. uint32_t sql_get_max_unique_id (RRDHOST *host)
  571. {
  572. int rc;
  573. uint32_t max_unique_id = 0;
  574. sqlite3_stmt *res = NULL;
  575. rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_MAX_UNIQUE_ID, -1, &res, 0);
  576. if (rc != SQLITE_OK) {
  577. error_report("Failed to prepare statement when trying to get max unique id");
  578. return 0;
  579. }
  580. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  581. if (unlikely(rc != SQLITE_OK)) {
  582. error_report("Failed to bind host_id parameter for SQL_SELECT_MAX_UNIQUE_ID.");
  583. sqlite3_finalize(res);
  584. return 0;
  585. }
  586. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  587. max_unique_id = (uint32_t) sqlite3_column_int64(res, 0);
  588. }
  589. rc = sqlite3_finalize(res);
  590. if (unlikely(rc != SQLITE_OK))
  591. error_report("Failed to finalize the statement");
  592. return max_unique_id;
  593. }
  594. #define SQL_SELECT_LAST_STATUSES "SELECT hld.new_status, hld.unique_id, hld.alarm_id, hld.alarm_event_id, hld.transition_id from health_log hl, health_log_detail hld where hl.host_id = @host_id and hl.last_transition_id = hld.transition_id;"
  595. void sql_check_removed_alerts_state(RRDHOST *host)
  596. {
  597. int rc;
  598. uint32_t max_unique_id = 0;
  599. sqlite3_stmt *res = NULL;
  600. uuid_t transition_id;
  601. rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_LAST_STATUSES, -1, &res, 0);
  602. if (rc != SQLITE_OK) {
  603. error_report("Failed to prepare statement when trying to check removed statuses");
  604. return;
  605. }
  606. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  607. if (unlikely(rc != SQLITE_OK)) {
  608. error_report("Failed to bind host_id parameter for SQL_SELECT_LAST_STATUSES.");
  609. sqlite3_finalize(res);
  610. return;
  611. }
  612. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  613. uint32_t alarm_id, alarm_event_id, unique_id;
  614. RRDCALC_STATUS status;
  615. status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
  616. unique_id = (uint32_t) sqlite3_column_int64(res, 1);
  617. alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
  618. alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
  619. uuid_copy(transition_id, *((uuid_t *) sqlite3_column_blob(res, 4)));
  620. if (unlikely(status != RRDCALC_STATUS_REMOVED)) {
  621. if (unlikely(!max_unique_id))
  622. max_unique_id = sql_get_max_unique_id (host);
  623. sql_inject_removed_status (host, alarm_id, alarm_event_id, unique_id, ++max_unique_id, &transition_id);
  624. }
  625. }
  626. rc = sqlite3_finalize(res);
  627. if (unlikely(rc != SQLITE_OK))
  628. error_report("Failed to finalize the statement");
  629. }
  630. /* Health related SQL queries
  631. Load from the health log table
  632. */
  633. #define SQL_LOAD_HEALTH_LOG "SELECT hld.unique_id, hld.alarm_id, hld.alarm_event_id, hl.config_hash_id, hld.updated_by_id, " \
  634. "hld.updates_id, hld.when_key, hld.duration, hld.non_clear_duration, hld.flags, hld.exec_run_timestamp, " \
  635. "hld.delay_up_to_timestamp, hl.name, hl.chart, hl.family, hl.exec, hl.recipient, ah.source, hl.units, " \
  636. "hld.info, hld.exec_code, hld.new_status, hld.old_status, hld.delay, hld.new_value, hld.old_value, " \
  637. "hld.last_repeat, ah.class, ah.component, ah.type, hl.chart_context, hld.transition_id, hld.global_id " \
  638. "FROM health_log hl, alert_hash ah, health_log_detail hld " \
  639. "WHERE hl.config_hash_id = ah.hash_id and hl.host_id = @host_id and hl.last_transition_id = hld.transition_id;"
  640. void sql_health_alarm_log_load(RRDHOST *host) {
  641. sqlite3_stmt *res = NULL;
  642. int ret;
  643. ssize_t errored = 0, loaded = 0;
  644. host->health.health_log_entries_written = 0;
  645. if (unlikely(!db_meta)) {
  646. if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
  647. error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
  648. return;
  649. }
  650. sql_check_removed_alerts_state(host);
  651. ret = sqlite3_prepare_v2(db_meta, SQL_LOAD_HEALTH_LOG, -1, &res, 0);
  652. if (unlikely(ret != SQLITE_OK)) {
  653. error_report("HEALTH [%s]: Failed to prepare sql statement to load health log.", rrdhost_hostname(host));
  654. return;
  655. }
  656. ret = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  657. if (unlikely(ret != SQLITE_OK)) {
  658. error_report("Failed to bind host_id parameter for SQL_LOAD_HEALTH_LOG.");
  659. sqlite3_finalize(res);
  660. return;
  661. }
  662. DICTIONARY *all_rrdcalcs = dictionary_create(
  663. DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE);
  664. RRDCALC *rc;
  665. foreach_rrdcalc_in_rrdhost_read(host, rc) {
  666. dictionary_set(all_rrdcalcs, rrdcalc_name(rc), rc, sizeof(*rc));
  667. }
  668. foreach_rrdcalc_in_rrdhost_done(rc);
  669. rw_spinlock_read_lock(&host->health_log.spinlock);
  670. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  671. ALARM_ENTRY *ae = NULL;
  672. // check that we have valid ids
  673. uint32_t unique_id = (uint32_t) sqlite3_column_int64(res, 0);
  674. if(!unique_id) {
  675. error_report("HEALTH [%s]: Got invalid unique id. Ignoring it.", rrdhost_hostname(host));
  676. errored++;
  677. continue;
  678. }
  679. uint32_t alarm_id = (uint32_t) sqlite3_column_int64(res, 1);
  680. if(!alarm_id) {
  681. error_report("HEALTH [%s]: Got invalid alarm id. Ignoring it.", rrdhost_hostname(host));
  682. errored++;
  683. continue;
  684. }
  685. //need name, chart and family
  686. if (sqlite3_column_type(res, 12) == SQLITE_NULL) {
  687. error_report("HEALTH [%s]: Got null name field. Ignoring it.", rrdhost_hostname(host));
  688. errored++;
  689. continue;
  690. }
  691. if (sqlite3_column_type(res, 13) == SQLITE_NULL) {
  692. error_report("HEALTH [%s]: Got null chart field. Ignoring it.", rrdhost_hostname(host));
  693. errored++;
  694. continue;
  695. }
  696. if (sqlite3_column_type(res, 14) == SQLITE_NULL) {
  697. error_report("HEALTH [%s]: Got null family field. Ignoring it.", rrdhost_hostname(host));
  698. errored++;
  699. continue;
  700. }
  701. // Check if we got last_repeat field
  702. time_t last_repeat = (time_t)sqlite3_column_int64(res, 26);
  703. rc = dictionary_get(all_rrdcalcs, (char *) sqlite3_column_text(res, 13));
  704. if(unlikely(rc)) {
  705. if (rrdcalc_isrepeating(rc)) {
  706. rc->last_repeat = last_repeat;
  707. // We iterate through repeating alarm entries only to
  708. // find the latest last_repeat timestamp. Otherwise,
  709. // there is no need to keep them in memory.
  710. continue;
  711. }
  712. }
  713. ae = callocz(1, sizeof(ALARM_ENTRY));
  714. ae->unique_id = unique_id;
  715. ae->alarm_id = alarm_id;
  716. if (sqlite3_column_type(res, 3) != SQLITE_NULL)
  717. uuid_copy(ae->config_hash_id, *((uuid_t *) sqlite3_column_blob(res, 3)));
  718. ae->alarm_event_id = (uint32_t) sqlite3_column_int64(res, 2);
  719. ae->updated_by_id = (uint32_t) sqlite3_column_int64(res, 4);
  720. ae->updates_id = (uint32_t) sqlite3_column_int64(res, 5);
  721. ae->when = (time_t) sqlite3_column_int64(res, 6);
  722. ae->duration = (time_t) sqlite3_column_int64(res, 7);
  723. ae->non_clear_duration = (time_t) sqlite3_column_int64(res, 8);
  724. ae->flags = (uint32_t) sqlite3_column_int64(res, 9);
  725. ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
  726. ae->exec_run_timestamp = (time_t) sqlite3_column_int64(res, 10);
  727. ae->delay_up_to_timestamp = (time_t) sqlite3_column_int64(res, 11);
  728. ae->name = string_strdupz((char *) sqlite3_column_text(res, 12));
  729. ae->chart = string_strdupz((char *) sqlite3_column_text(res, 13));
  730. ae->family = string_strdupz((char *) sqlite3_column_text(res, 14));
  731. if (sqlite3_column_type(res, 15) != SQLITE_NULL)
  732. ae->exec = string_strdupz((char *) sqlite3_column_text(res, 15));
  733. else
  734. ae->exec = NULL;
  735. if (sqlite3_column_type(res, 16) != SQLITE_NULL)
  736. ae->recipient = string_strdupz((char *) sqlite3_column_text(res, 16));
  737. else
  738. ae->recipient = NULL;
  739. if (sqlite3_column_type(res, 17) != SQLITE_NULL)
  740. ae->source = string_strdupz((char *) sqlite3_column_text(res, 17));
  741. else
  742. ae->source = NULL;
  743. if (sqlite3_column_type(res, 18) != SQLITE_NULL)
  744. ae->units = string_strdupz((char *) sqlite3_column_text(res, 18));
  745. else
  746. ae->units = NULL;
  747. if (sqlite3_column_type(res, 19) != SQLITE_NULL)
  748. ae->info = string_strdupz((char *) sqlite3_column_text(res, 19));
  749. else
  750. ae->info = NULL;
  751. ae->exec_code = (int) sqlite3_column_int(res, 20);
  752. ae->new_status = (RRDCALC_STATUS) sqlite3_column_int(res, 21);
  753. ae->old_status = (RRDCALC_STATUS)sqlite3_column_int(res, 22);
  754. ae->delay = (int) sqlite3_column_int(res, 23);
  755. ae->new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 24);
  756. ae->old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 25);
  757. ae->last_repeat = last_repeat;
  758. if (sqlite3_column_type(res, 27) != SQLITE_NULL)
  759. ae->classification = string_strdupz((char *) sqlite3_column_text(res, 27));
  760. else
  761. ae->classification = NULL;
  762. if (sqlite3_column_type(res, 28) != SQLITE_NULL)
  763. ae->component = string_strdupz((char *) sqlite3_column_text(res, 28));
  764. else
  765. ae->component = NULL;
  766. if (sqlite3_column_type(res, 29) != SQLITE_NULL)
  767. ae->type = string_strdupz((char *) sqlite3_column_text(res, 29));
  768. else
  769. ae->type = NULL;
  770. if (sqlite3_column_type(res, 30) != SQLITE_NULL)
  771. ae->chart_context = string_strdupz((char *) sqlite3_column_text(res, 30));
  772. else
  773. ae->chart_context = NULL;
  774. if (sqlite3_column_type(res, 31) != SQLITE_NULL)
  775. uuid_copy(ae->transition_id, *((uuid_t *)sqlite3_column_blob(res, 31)));
  776. if (sqlite3_column_type(res, 32) != SQLITE_NULL)
  777. ae->global_id = sqlite3_column_int64(res, 32);
  778. char value_string[100 + 1];
  779. string_freez(ae->old_value_string);
  780. string_freez(ae->new_value_string);
  781. ae->old_value_string = string_strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae_units(ae), -1));
  782. ae->new_value_string = string_strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae_units(ae), -1));
  783. ae->next = host->health_log.alarms;
  784. host->health_log.alarms = ae;
  785. if(unlikely(ae->unique_id > host->health_max_unique_id))
  786. host->health_max_unique_id = ae->unique_id;
  787. if(unlikely(ae->alarm_id >= host->health_max_alarm_id))
  788. host->health_max_alarm_id = ae->alarm_id;
  789. loaded++;
  790. }
  791. rw_spinlock_read_unlock(&host->health_log.spinlock);
  792. dictionary_destroy(all_rrdcalcs);
  793. all_rrdcalcs = NULL;
  794. if(!host->health_max_unique_id) host->health_max_unique_id = (uint32_t)now_realtime_sec();
  795. if(!host->health_max_alarm_id) host->health_max_alarm_id = (uint32_t)now_realtime_sec();
  796. host->health_log.next_log_id = host->health_max_unique_id + 1;
  797. if (unlikely(!host->health_log.next_alarm_id || host->health_log.next_alarm_id <= host->health_max_alarm_id))
  798. host->health_log.next_alarm_id = host->health_max_alarm_id + 1;
  799. netdata_log_health("[%s]: Table health_log, loaded %zd alarm entries, errors in %zd entries.", rrdhost_hostname(host), loaded, errored);
  800. ret = sqlite3_finalize(res);
  801. if (unlikely(ret != SQLITE_OK))
  802. error_report("Failed to finalize the health log read statement");
  803. sql_health_alarm_log_count(host);
  804. }
  805. /*
  806. * Store an alert config hash in the database
  807. */
  808. #define SQL_STORE_ALERT_CONFIG_HASH "insert or replace into alert_hash (hash_id, date_updated, alarm, template, " \
  809. "on_key, class, component, type, os, hosts, lookup, every, units, calc, families, plugin, module, " \
  810. "charts, green, red, warn, crit, exec, to_key, info, delay, options, repeat, host_labels, " \
  811. "p_db_lookup_dimensions, p_db_lookup_method, p_db_lookup_options, p_db_lookup_after, " \
  812. "p_db_lookup_before, p_update_every, source, chart_labels) values (?1,unixepoch(),?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12," \
  813. "?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33,?34,?35,?36);"
  814. int sql_store_alert_config_hash(uuid_t *hash_id, struct alert_config *cfg)
  815. {
  816. static __thread sqlite3_stmt *res = NULL;
  817. int rc, param = 0;
  818. if (unlikely(!db_meta)) {
  819. if (default_rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE)
  820. return 0;
  821. error_report("Database has not been initialized");
  822. return 1;
  823. }
  824. if (unlikely(!res)) {
  825. rc = prepare_statement(db_meta, SQL_STORE_ALERT_CONFIG_HASH, &res);
  826. if (unlikely(rc != SQLITE_OK)) {
  827. error_report("Failed to prepare statement to store alert configuration, rc = %d", rc);
  828. return 1;
  829. }
  830. }
  831. rc = sqlite3_bind_blob(res, ++param, hash_id, sizeof(*hash_id), SQLITE_STATIC);
  832. if (unlikely(rc != SQLITE_OK))
  833. goto bind_fail;
  834. rc = sqlite3_bind_string_or_null(res, cfg->alarm, ++param);
  835. if (unlikely(rc != SQLITE_OK))
  836. goto bind_fail;
  837. rc = sqlite3_bind_string_or_null(res, cfg->template_key, ++param);
  838. if (unlikely(rc != SQLITE_OK))
  839. goto bind_fail;
  840. rc = sqlite3_bind_string_or_null(res, cfg->on, ++param);
  841. if (unlikely(rc != SQLITE_OK))
  842. goto bind_fail;
  843. rc = sqlite3_bind_string_or_null(res, cfg->classification, ++param);
  844. if (unlikely(rc != SQLITE_OK))
  845. goto bind_fail;
  846. rc = sqlite3_bind_string_or_null(res, cfg->component, ++param);
  847. if (unlikely(rc != SQLITE_OK))
  848. goto bind_fail;
  849. rc = sqlite3_bind_string_or_null(res, cfg->type, ++param);
  850. if (unlikely(rc != SQLITE_OK))
  851. goto bind_fail;
  852. rc = sqlite3_bind_string_or_null(res, cfg->os, ++param);
  853. if (unlikely(rc != SQLITE_OK))
  854. goto bind_fail;
  855. rc = sqlite3_bind_string_or_null(res, cfg->host, ++param);
  856. if (unlikely(rc != SQLITE_OK))
  857. goto bind_fail;
  858. rc = sqlite3_bind_string_or_null(res, cfg->lookup, ++param);
  859. if (unlikely(rc != SQLITE_OK))
  860. goto bind_fail;
  861. rc = sqlite3_bind_string_or_null(res, cfg->every, ++param);
  862. if (unlikely(rc != SQLITE_OK))
  863. goto bind_fail;
  864. rc = sqlite3_bind_string_or_null(res, cfg->units, ++param);
  865. if (unlikely(rc != SQLITE_OK))
  866. goto bind_fail;
  867. rc = sqlite3_bind_string_or_null(res, cfg->calc, ++param);
  868. if (unlikely(rc != SQLITE_OK))
  869. goto bind_fail;
  870. rc = sqlite3_bind_string_or_null(res, cfg->families, ++param);
  871. if (unlikely(rc != SQLITE_OK))
  872. goto bind_fail;
  873. rc = sqlite3_bind_string_or_null(res, cfg->plugin, ++param);
  874. if (unlikely(rc != SQLITE_OK))
  875. goto bind_fail;
  876. rc = sqlite3_bind_string_or_null(res, cfg->module, ++param);
  877. if (unlikely(rc != SQLITE_OK))
  878. goto bind_fail;
  879. rc = sqlite3_bind_string_or_null(res, cfg->charts, ++param);
  880. if (unlikely(rc != SQLITE_OK))
  881. goto bind_fail;
  882. rc = sqlite3_bind_string_or_null(res, cfg->green, ++param);
  883. if (unlikely(rc != SQLITE_OK))
  884. goto bind_fail;
  885. rc = sqlite3_bind_string_or_null(res, cfg->red, ++param);
  886. if (unlikely(rc != SQLITE_OK))
  887. goto bind_fail;
  888. rc = sqlite3_bind_string_or_null(res, cfg->warn, ++param);
  889. if (unlikely(rc != SQLITE_OK))
  890. goto bind_fail;
  891. rc = sqlite3_bind_string_or_null(res, cfg->crit, ++param);
  892. if (unlikely(rc != SQLITE_OK))
  893. goto bind_fail;
  894. rc = sqlite3_bind_string_or_null(res, cfg->exec, ++param);
  895. if (unlikely(rc != SQLITE_OK))
  896. goto bind_fail;
  897. rc = sqlite3_bind_string_or_null(res, cfg->to, ++param);
  898. if (unlikely(rc != SQLITE_OK))
  899. goto bind_fail;
  900. rc = sqlite3_bind_string_or_null(res, cfg->info, ++param);
  901. if (unlikely(rc != SQLITE_OK))
  902. goto bind_fail;
  903. rc = sqlite3_bind_string_or_null(res, cfg->delay, ++param);
  904. if (unlikely(rc != SQLITE_OK))
  905. goto bind_fail;
  906. rc = sqlite3_bind_string_or_null(res, cfg->options, ++param);
  907. if (unlikely(rc != SQLITE_OK))
  908. goto bind_fail;
  909. rc = sqlite3_bind_string_or_null(res, cfg->repeat, ++param);
  910. if (unlikely(rc != SQLITE_OK))
  911. goto bind_fail;
  912. rc = sqlite3_bind_string_or_null(res, cfg->host_labels, ++param);
  913. if (unlikely(rc != SQLITE_OK))
  914. goto bind_fail;
  915. if (cfg->p_db_lookup_after) {
  916. rc = sqlite3_bind_string_or_null(res, cfg->p_db_lookup_dimensions, ++param);
  917. if (unlikely(rc != SQLITE_OK))
  918. goto bind_fail;
  919. rc = sqlite3_bind_string_or_null(res, cfg->p_db_lookup_method, ++param);
  920. if (unlikely(rc != SQLITE_OK))
  921. goto bind_fail;
  922. rc = sqlite3_bind_int(res, ++param, (int) cfg->p_db_lookup_options);
  923. if (unlikely(rc != SQLITE_OK))
  924. goto bind_fail;
  925. rc = sqlite3_bind_int(res, ++param, (int) cfg->p_db_lookup_after);
  926. if (unlikely(rc != SQLITE_OK))
  927. goto bind_fail;
  928. rc = sqlite3_bind_int(res, ++param, (int) cfg->p_db_lookup_before);
  929. if (unlikely(rc != SQLITE_OK))
  930. goto bind_fail;
  931. } else {
  932. rc = sqlite3_bind_null(res, ++param);
  933. if (unlikely(rc != SQLITE_OK))
  934. goto bind_fail;
  935. rc = sqlite3_bind_null(res, ++param);
  936. if (unlikely(rc != SQLITE_OK))
  937. goto bind_fail;
  938. rc = sqlite3_bind_null(res, ++param);
  939. if (unlikely(rc != SQLITE_OK))
  940. goto bind_fail;
  941. rc = sqlite3_bind_null(res, ++param);
  942. if (unlikely(rc != SQLITE_OK))
  943. goto bind_fail;
  944. rc = sqlite3_bind_null(res, ++param);
  945. if (unlikely(rc != SQLITE_OK))
  946. goto bind_fail;
  947. }
  948. rc = sqlite3_bind_int(res, ++param, cfg->p_update_every);
  949. if (unlikely(rc != SQLITE_OK))
  950. goto bind_fail;
  951. rc = sqlite3_bind_string_or_null(res, cfg->source, ++param);
  952. if (unlikely(rc != SQLITE_OK))
  953. goto bind_fail;
  954. rc = sqlite3_bind_string_or_null(res, cfg->chart_labels, ++param);
  955. if (unlikely(rc != SQLITE_OK))
  956. goto bind_fail;
  957. rc = execute_insert(res);
  958. if (unlikely(rc != SQLITE_DONE))
  959. error_report("Failed to store alert config, rc = %d", rc);
  960. rc = sqlite3_reset(res);
  961. if (unlikely(rc != SQLITE_OK))
  962. error_report("Failed to reset statement in alert hash_id store function, rc = %d", rc);
  963. return 0;
  964. bind_fail:
  965. error_report("Failed to bind parameter %d to store alert hash_id, rc = %d", param, rc);
  966. rc = sqlite3_reset(res);
  967. if (unlikely(rc != SQLITE_OK))
  968. error_report("Failed to reset statement in alert hash_id store function, rc = %d", rc);
  969. return 1;
  970. }
  971. /*
  972. alert hashes are used for cloud communication.
  973. if cloud is disabled or openssl is not available (which will prevent cloud connectivity)
  974. skip hash calculations
  975. */
  976. #if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
  977. #define DIGEST_ALERT_CONFIG_VAL(v) ((v) ? EVP_DigestUpdate(evpctx, (string2str(v)), string_strlen((v))) : EVP_DigestUpdate(evpctx, "", 1))
  978. #endif
  979. int alert_hash_and_store_config(
  980. uuid_t hash_id,
  981. struct alert_config *cfg,
  982. int store_hash)
  983. {
  984. #if !defined DISABLE_CLOUD && defined ENABLE_HTTPS
  985. EVP_MD_CTX *evpctx;
  986. unsigned char hash_value[EVP_MAX_MD_SIZE];
  987. unsigned int hash_len;
  988. evpctx = EVP_MD_CTX_create();
  989. EVP_DigestInit_ex(evpctx, EVP_sha256(), NULL);
  990. DIGEST_ALERT_CONFIG_VAL(cfg->alarm);
  991. DIGEST_ALERT_CONFIG_VAL(cfg->template_key);
  992. DIGEST_ALERT_CONFIG_VAL(cfg->os);
  993. DIGEST_ALERT_CONFIG_VAL(cfg->host);
  994. DIGEST_ALERT_CONFIG_VAL(cfg->on);
  995. DIGEST_ALERT_CONFIG_VAL(cfg->families);
  996. DIGEST_ALERT_CONFIG_VAL(cfg->plugin);
  997. DIGEST_ALERT_CONFIG_VAL(cfg->module);
  998. DIGEST_ALERT_CONFIG_VAL(cfg->charts);
  999. DIGEST_ALERT_CONFIG_VAL(cfg->lookup);
  1000. DIGEST_ALERT_CONFIG_VAL(cfg->calc);
  1001. DIGEST_ALERT_CONFIG_VAL(cfg->every);
  1002. DIGEST_ALERT_CONFIG_VAL(cfg->green);
  1003. DIGEST_ALERT_CONFIG_VAL(cfg->red);
  1004. DIGEST_ALERT_CONFIG_VAL(cfg->warn);
  1005. DIGEST_ALERT_CONFIG_VAL(cfg->crit);
  1006. DIGEST_ALERT_CONFIG_VAL(cfg->exec);
  1007. DIGEST_ALERT_CONFIG_VAL(cfg->to);
  1008. DIGEST_ALERT_CONFIG_VAL(cfg->units);
  1009. DIGEST_ALERT_CONFIG_VAL(cfg->info);
  1010. DIGEST_ALERT_CONFIG_VAL(cfg->classification);
  1011. DIGEST_ALERT_CONFIG_VAL(cfg->component);
  1012. DIGEST_ALERT_CONFIG_VAL(cfg->type);
  1013. DIGEST_ALERT_CONFIG_VAL(cfg->delay);
  1014. DIGEST_ALERT_CONFIG_VAL(cfg->options);
  1015. DIGEST_ALERT_CONFIG_VAL(cfg->repeat);
  1016. DIGEST_ALERT_CONFIG_VAL(cfg->host_labels);
  1017. DIGEST_ALERT_CONFIG_VAL(cfg->chart_labels);
  1018. EVP_DigestFinal_ex(evpctx, hash_value, &hash_len);
  1019. EVP_MD_CTX_destroy(evpctx);
  1020. fatal_assert(hash_len > sizeof(uuid_t));
  1021. char uuid_str[UUID_STR_LEN];
  1022. uuid_unparse_lower(*((uuid_t *)&hash_value), uuid_str);
  1023. uuid_copy(hash_id, *((uuid_t *)&hash_value));
  1024. /* store everything, so it can be recreated when not in memory or just a subset ? */
  1025. if (store_hash)
  1026. (void)sql_store_alert_config_hash( (uuid_t *)&hash_value, cfg);
  1027. #else
  1028. UNUSED(hash_id);
  1029. UNUSED(cfg);
  1030. UNUSED(store_hash);
  1031. #endif
  1032. return 1;
  1033. }
  1034. #define SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT "SELECT hld.new_status FROM health_log hl, health_log_detail hld WHERE hl.alarm_id = %u AND hld.unique_id != %u AND hld.flags & %u AND hl.host_id = @host_id and hl.health_log_id = hld.health_log_id ORDER BY hld.unique_id DESC LIMIT 1;"
  1035. int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_STATUS *last_executed_status)
  1036. {
  1037. int rc = 0, ret = -1;
  1038. char command[MAX_HEALTH_SQL_SIZE + 1];
  1039. sqlite3_stmt *res = NULL;
  1040. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT, ae->alarm_id, ae->unique_id, (uint32_t) HEALTH_ENTRY_FLAG_EXEC_RUN);
  1041. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  1042. if (rc != SQLITE_OK) {
  1043. error_report("Failed to prepare statement when trying to get last executed status");
  1044. return ret;
  1045. }
  1046. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  1047. if (unlikely(rc != SQLITE_OK)) {
  1048. error_report("Failed to bind host_id parameter for SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT.");
  1049. sqlite3_finalize(res);
  1050. return ret;
  1051. }
  1052. ret = 0;
  1053. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  1054. *last_executed_status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
  1055. ret = 1;
  1056. }
  1057. rc = sqlite3_finalize(res);
  1058. if (unlikely(rc != SQLITE_OK))
  1059. error_report("Failed to finalize the statement.");
  1060. return ret;
  1061. }
  1062. #define SQL_SELECT_HEALTH_LOG "SELECT hld.unique_id, hld.alarm_id, hld.alarm_event_id, hl.config_hash_id, hld.updated_by_id, hld.updates_id, hld.when_key, hld.duration, hld.non_clear_duration, hld.flags, hld.exec_run_timestamp, hld.delay_up_to_timestamp, hl.name, hl.chart, hl.family, hl.exec, hl.recipient, ah.source, hl.units, hld.info, hld.exec_code, hld.new_status, hld.old_status, hld.delay, hld.new_value, hld.old_value, hld.last_repeat, ah.class, ah.component, ah.type, hl.chart_context, hld.transition_id FROM health_log hl, alert_hash ah, health_log_detail hld WHERE hl.config_hash_id = ah.hash_id and hl.health_log_id = hld.health_log_id and hl.host_id = @host_id "
  1063. void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *chart) {
  1064. buffer_strcat(wb, "[");
  1065. unsigned int max = host->health_log.max;
  1066. unsigned int count = 0;
  1067. sqlite3_stmt *res = NULL;
  1068. int rc;
  1069. BUFFER *command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
  1070. buffer_sprintf(command, SQL_SELECT_HEALTH_LOG);
  1071. if (chart) {
  1072. char chart_sql[MAX_HEALTH_SQL_SIZE + 1];
  1073. snprintfz(chart_sql, MAX_HEALTH_SQL_SIZE, "AND hl.chart = '%s' ", chart);
  1074. buffer_strcat(command, chart_sql);
  1075. }
  1076. if (after) {
  1077. char after_sql[MAX_HEALTH_SQL_SIZE + 1];
  1078. snprintfz(after_sql, MAX_HEALTH_SQL_SIZE, "AND hld.unique_id > %u ", after);
  1079. buffer_strcat(command, after_sql);
  1080. }
  1081. {
  1082. char limit_sql[MAX_HEALTH_SQL_SIZE + 1];
  1083. snprintfz(limit_sql, MAX_HEALTH_SQL_SIZE, "ORDER BY hld.unique_id DESC LIMIT %u ", max);
  1084. buffer_strcat(command, limit_sql);
  1085. }
  1086. rc = sqlite3_prepare_v2(db_meta, buffer_tostring(command), -1, &res, 0);
  1087. if (unlikely(rc != SQLITE_OK)) {
  1088. error_report("Failed to prepare statement SQL_SELECT_HEALTH_LOG");
  1089. buffer_free(command);
  1090. return;
  1091. }
  1092. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  1093. if (unlikely(rc != SQLITE_OK)) {
  1094. error_report("Failed to bind host_id for SQL_SELECT_HEALTH_LOG.");
  1095. sqlite3_finalize(res);
  1096. buffer_free(command);
  1097. return;
  1098. }
  1099. while (sqlite3_step(res) == SQLITE_ROW) {
  1100. char old_value_string[100 + 1];
  1101. char new_value_string[100 + 1];
  1102. char config_hash_id[UUID_STR_LEN];
  1103. uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 3)), config_hash_id);
  1104. char transition_id[UUID_STR_LEN] = {0};
  1105. if (sqlite3_column_type(res, 31) != SQLITE_NULL)
  1106. uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 31)), transition_id);
  1107. char *edit_command = sqlite3_column_bytes(res, 17) > 0 ? health_edit_command_from_source((char *)sqlite3_column_text(res, 17)) : strdupz("UNKNOWN=0=UNKNOWN");
  1108. if (count)
  1109. buffer_sprintf(wb, ",");
  1110. count++;
  1111. buffer_sprintf(
  1112. wb,
  1113. "\n\t{\n"
  1114. "\t\t\"hostname\": \"%s\",\n"
  1115. "\t\t\"utc_offset\": %d,\n"
  1116. "\t\t\"timezone\": \"%s\",\n"
  1117. "\t\t\"unique_id\": %u,\n"
  1118. "\t\t\"alarm_id\": %u,\n"
  1119. "\t\t\"alarm_event_id\": %u,\n"
  1120. "\t\t\"config_hash_id\": \"%s\",\n"
  1121. "\t\t\"transition_id\": \"%s\",\n"
  1122. "\t\t\"name\": \"%s\",\n"
  1123. "\t\t\"chart\": \"%s\",\n"
  1124. "\t\t\"context\": \"%s\",\n"
  1125. "\t\t\"family\": \"%s\",\n"
  1126. "\t\t\"class\": \"%s\",\n"
  1127. "\t\t\"component\": \"%s\",\n"
  1128. "\t\t\"type\": \"%s\",\n"
  1129. "\t\t\"processed\": %s,\n"
  1130. "\t\t\"updated\": %s,\n"
  1131. "\t\t\"exec_run\": %lu,\n"
  1132. "\t\t\"exec_failed\": %s,\n"
  1133. "\t\t\"exec\": \"%s\",\n"
  1134. "\t\t\"recipient\": \"%s\",\n"
  1135. "\t\t\"exec_code\": %d,\n"
  1136. "\t\t\"source\": \"%s\",\n"
  1137. "\t\t\"command\": \"%s\",\n"
  1138. "\t\t\"units\": \"%s\",\n"
  1139. "\t\t\"when\": %lu,\n"
  1140. "\t\t\"duration\": %lu,\n"
  1141. "\t\t\"non_clear_duration\": %lu,\n"
  1142. "\t\t\"status\": \"%s\",\n"
  1143. "\t\t\"old_status\": \"%s\",\n"
  1144. "\t\t\"delay\": %d,\n"
  1145. "\t\t\"delay_up_to_timestamp\": %lu,\n"
  1146. "\t\t\"updated_by_id\": %u,\n"
  1147. "\t\t\"updates_id\": %u,\n"
  1148. "\t\t\"value_string\": \"%s\",\n"
  1149. "\t\t\"old_value_string\": \"%s\",\n"
  1150. "\t\t\"last_repeat\": \"%lu\",\n"
  1151. "\t\t\"silenced\": \"%s\",\n",
  1152. rrdhost_hostname(host),
  1153. host->utc_offset,
  1154. rrdhost_abbrev_timezone(host),
  1155. (unsigned int) sqlite3_column_int64(res, 0),
  1156. (unsigned int) sqlite3_column_int64(res, 1),
  1157. (unsigned int) sqlite3_column_int64(res, 2),
  1158. config_hash_id,
  1159. transition_id,
  1160. sqlite3_column_text(res, 12),
  1161. sqlite3_column_text(res, 13),
  1162. sqlite3_column_text(res, 30),
  1163. sqlite3_column_text(res, 14),
  1164. sqlite3_column_text(res, 27) ? (const char *) sqlite3_column_text(res, 27) : (char *) "Unknown",
  1165. sqlite3_column_text(res, 28) ? (const char *) sqlite3_column_text(res, 28) : (char *) "Unknown",
  1166. sqlite3_column_text(res, 29) ? (const char *) sqlite3_column_text(res, 29) : (char *) "Unknown",
  1167. (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false",
  1168. (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false",
  1169. (long unsigned int)sqlite3_column_int64(res, 10),
  1170. (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false",
  1171. sqlite3_column_text(res, 15) ? (const char *) sqlite3_column_text(res, 15) : string2str(host->health.health_default_exec),
  1172. sqlite3_column_text(res, 16) ? (const char *) sqlite3_column_text(res, 16) : string2str(host->health.health_default_recipient),
  1173. sqlite3_column_int(res, 20),
  1174. sqlite3_column_text(res, 17) ? (const char *) sqlite3_column_text(res, 17) : (char *) "Unknown",
  1175. edit_command,
  1176. sqlite3_column_text(res, 18),
  1177. (long unsigned int)sqlite3_column_int64(res, 6),
  1178. (long unsigned int)sqlite3_column_int64(res, 7),
  1179. (long unsigned int)sqlite3_column_int64(res, 8),
  1180. rrdcalc_status2string(sqlite3_column_int(res, 21)),
  1181. rrdcalc_status2string(sqlite3_column_int(res, 22)),
  1182. sqlite3_column_int(res, 23),
  1183. (long unsigned int)sqlite3_column_int64(res, 11),
  1184. (unsigned int)sqlite3_column_int64(res, 4),
  1185. (unsigned int)sqlite3_column_int64(res, 5),
  1186. sqlite3_column_type(res, 24) == SQLITE_NULL ? "-" : format_value_and_unit(new_value_string, 100, sqlite3_column_double(res, 24), (char *) sqlite3_column_text(res, 18), -1),
  1187. sqlite3_column_type(res, 25) == SQLITE_NULL ? "-" : format_value_and_unit(old_value_string, 100, sqlite3_column_double(res, 25), (char *) sqlite3_column_text(res, 18), -1),
  1188. (long unsigned int)sqlite3_column_int64(res, 26),
  1189. (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_SILENCED)?"true":"false");
  1190. health_string2json(wb, "\t\t", "info", (char *) sqlite3_column_text(res, 19), ",\n");
  1191. if(unlikely(sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
  1192. buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n");
  1193. }
  1194. buffer_strcat(wb, "\t\t\"value\":");
  1195. if (sqlite3_column_type(res, 24) == SQLITE_NULL)
  1196. buffer_strcat(wb, "null");
  1197. else
  1198. buffer_print_netdata_double(wb, sqlite3_column_double(res, 24));
  1199. buffer_strcat(wb, ",\n");
  1200. buffer_strcat(wb, "\t\t\"old_value\":");
  1201. if (sqlite3_column_type(res, 25) == SQLITE_NULL)
  1202. buffer_strcat(wb, "null");
  1203. else
  1204. buffer_print_netdata_double(wb, sqlite3_column_double(res, 25));
  1205. buffer_strcat(wb, "\n");
  1206. buffer_strcat(wb, "\t}");
  1207. freez(edit_command);
  1208. }
  1209. buffer_strcat(wb, "\n]");
  1210. rc = sqlite3_finalize(res);
  1211. if (unlikely(rc != SQLITE_OK))
  1212. error_report("Failed to finalize statement for SQL_SELECT_HEALTH_LOG");
  1213. buffer_free(command);
  1214. }
  1215. #define SQL_COPY_HEALTH_LOG(table) "INSERT OR IGNORE INTO health_log (host_id, alarm_id, config_hash_id, name, chart, family, exec, recipient, units, chart_context) SELECT ?1, alarm_id, config_hash_id, name, chart, family, exec, recipient, units, chart_context from %s;", table
  1216. #define SQL_COPY_HEALTH_LOG_DETAIL(table) "INSERT INTO health_log_detail (unique_id, alarm_id, alarm_event_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, global_id, host_id) SELECT unique_id, alarm_id, alarm_event_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, now_usec(1), ?1 from %s;", table
  1217. #define SQL_UPDATE_HEALTH_LOG_DETAIL_TRANSITION_ID "update health_log_detail set transition_id = uuid_random() where transition_id is null;"
  1218. #define SQL_UPDATE_HEALTH_LOG_DETAIL_HEALTH_LOG_ID "update health_log_detail set health_log_id = (select health_log_id from health_log where host_id = ?1 and alarm_id = health_log_detail.alarm_id) where health_log_id is null and host_id = ?2;"
  1219. #define SQL_UPDATE_HEALTH_LOG_LAST_TRANSITION_ID "update health_log set last_transition_id = (select transition_id from health_log_detail where health_log_id = health_log.health_log_id and alarm_id = health_log.alarm_id group by (alarm_id) having max(alarm_event_id)) where host_id = ?1;"
  1220. int health_migrate_old_health_log_table(char *table) {
  1221. if (!table)
  1222. return 0;
  1223. //table should contain guid. We need to
  1224. //keep it in the new table along with it's data
  1225. //health_log_XXXXXXXX_XXXX_XXXX_XXXX_XXXXXXXXXXXX
  1226. if (strnlen(table, 46) != 46) {
  1227. return 0;
  1228. }
  1229. char *uuid_from_table = strdupz(table + 11);
  1230. uuid_t uuid;
  1231. if (uuid_parse_fix(uuid_from_table, uuid)) {
  1232. freez(uuid_from_table);
  1233. return 0;
  1234. }
  1235. int rc;
  1236. char command[MAX_HEALTH_SQL_SIZE + 1];
  1237. sqlite3_stmt *res = NULL;
  1238. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COPY_HEALTH_LOG(table));
  1239. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  1240. if (unlikely(rc != SQLITE_OK)) {
  1241. error_report("Failed to prepare statement to copy health log, rc = %d", rc);
  1242. freez(uuid_from_table);
  1243. return 0;
  1244. }
  1245. rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
  1246. if (unlikely(rc != SQLITE_OK)) {
  1247. rc = sqlite3_finalize(res);
  1248. if (unlikely(rc != SQLITE_OK))
  1249. error_report("Failed to reset statement to copy health log table, rc = %d", rc);
  1250. freez(uuid_from_table);
  1251. return 0;
  1252. }
  1253. rc = execute_insert(res);
  1254. if (unlikely(rc != SQLITE_DONE)) {
  1255. error_report("Failed to execute SQL_COPY_HEALTH_LOG, rc = %d", rc);
  1256. rc = sqlite3_finalize(res);
  1257. if (unlikely(rc != SQLITE_OK))
  1258. error_report("Failed to reset statement to copy health log table, rc = %d", rc);
  1259. freez(uuid_from_table);
  1260. }
  1261. //detail
  1262. snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COPY_HEALTH_LOG_DETAIL(table));
  1263. rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
  1264. if (unlikely(rc != SQLITE_OK)) {
  1265. error_report("Failed to prepare statement to copy health log detail, rc = %d", rc);
  1266. return 0;
  1267. }
  1268. rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
  1269. if (unlikely(rc != SQLITE_OK)) {
  1270. rc = sqlite3_finalize(res);
  1271. if (unlikely(rc != SQLITE_OK))
  1272. error_report("Failed to reset statement to copy health log detail, rc = %d", rc);
  1273. return 0;
  1274. }
  1275. rc = execute_insert(res);
  1276. if (unlikely(rc != SQLITE_DONE)) {
  1277. error_report("Failed to execute SQL_COPY_HEALTH_LOG_DETAIL, rc = %d", rc);
  1278. rc = sqlite3_finalize(res);
  1279. if (unlikely(rc != SQLITE_OK))
  1280. error_report("Failed to reset statement to copy health log detail table, rc = %d", rc);
  1281. return 0;
  1282. }
  1283. //update transition ids
  1284. rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG_DETAIL_TRANSITION_ID, -1, &res, 0);
  1285. if (unlikely(rc != SQLITE_OK)) {
  1286. error_report("Failed to prepare statement to update health log detail with transition ids, rc = %d", rc);
  1287. return 0;
  1288. }
  1289. rc = execute_insert(res);
  1290. if (unlikely(rc != SQLITE_DONE)) {
  1291. error_report("Failed to execute SQL_UPDATE_HEALTH_LOG_DETAIL_TRANSITION_ID, rc = %d", rc);
  1292. rc = sqlite3_finalize(res);
  1293. if (unlikely(rc != SQLITE_OK))
  1294. error_report("Failed to reset statement to update health log detail table with transition ids, rc = %d", rc);
  1295. return 0;
  1296. }
  1297. //update health_log_id
  1298. rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG_DETAIL_HEALTH_LOG_ID, -1, &res, 0);
  1299. if (unlikely(rc != SQLITE_OK)) {
  1300. error_report("Failed to prepare statement to update health log detail with health log ids, rc = %d", rc);
  1301. return 0;
  1302. }
  1303. rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
  1304. if (unlikely(rc != SQLITE_OK)) {
  1305. rc = sqlite3_finalize(res);
  1306. if (unlikely(rc != SQLITE_OK))
  1307. error_report("Failed to reset statement to update health log detail with health log ids, rc = %d", rc);
  1308. return 0;
  1309. }
  1310. rc = sqlite3_bind_blob(res, 2, &uuid, sizeof(uuid), SQLITE_STATIC);
  1311. if (unlikely(rc != SQLITE_OK)) {
  1312. rc = sqlite3_finalize(res);
  1313. if (unlikely(rc != SQLITE_OK))
  1314. error_report("Failed to reset statement to update health log detail with health log ids, rc = %d", rc);
  1315. return 0;
  1316. }
  1317. rc = execute_insert(res);
  1318. if (unlikely(rc != SQLITE_DONE)) {
  1319. error_report("Failed to execute SQL_UPDATE_HEALTH_LOG_DETAIL_HEALTH_LOG_ID, rc = %d", rc);
  1320. rc = sqlite3_finalize(res);
  1321. if (unlikely(rc != SQLITE_OK))
  1322. error_report("Failed to reset statement to update health log detail table with health log ids, rc = %d", rc);
  1323. }
  1324. //update last transition id
  1325. rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG_LAST_TRANSITION_ID, -1, &res, 0);
  1326. if (unlikely(rc != SQLITE_OK)) {
  1327. error_report("Failed to prepare statement to update health log with last transition id, rc = %d", rc);
  1328. return 0;
  1329. }
  1330. rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
  1331. if (unlikely(rc != SQLITE_OK)) {
  1332. rc = sqlite3_finalize(res);
  1333. if (unlikely(rc != SQLITE_OK))
  1334. error_report("Failed to reset statement to update health log with last transition id, rc = %d", rc);
  1335. return 0;
  1336. }
  1337. rc = execute_insert(res);
  1338. if (unlikely(rc != SQLITE_DONE)) {
  1339. error_report("Failed to execute SQL_UPDATE_HEALTH_LOG_LAST_TRANSITION_ID, rc = %d", rc);
  1340. rc = sqlite3_finalize(res);
  1341. if (unlikely(rc != SQLITE_OK))
  1342. error_report("Failed to reset statement to update health log table with last transition id, rc = %d", rc);
  1343. }
  1344. return 1;
  1345. }
  1346. #define SQL_GET_ALARM_ID "select alarm_id, health_log_id from health_log where host_id = @host_id and chart = @chart and name = @name and config_hash_id = @config_hash_id"
  1347. #define SQL_GET_EVENT_ID "select max(alarm_event_id) + 1 from health_log_detail where health_log_id = @health_log_id and alarm_id = @alarm_id"
  1348. uint32_t sql_get_alarm_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id)
  1349. {
  1350. int rc = 0;
  1351. sqlite3_stmt *res = NULL;
  1352. uint32_t alarm_id = 0;
  1353. uint64_t health_log_id = 0;
  1354. rc = sqlite3_prepare_v2(db_meta, SQL_GET_ALARM_ID, -1, &res, 0);
  1355. if (rc != SQLITE_OK) {
  1356. error_report("Failed to prepare statement when trying to get an alarm id");
  1357. return alarm_id;
  1358. }
  1359. rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
  1360. if (unlikely(rc != SQLITE_OK)) {
  1361. error_report("Failed to bind host_id parameter for SQL_GET_ALARM_ID.");
  1362. sqlite3_finalize(res);
  1363. return alarm_id;
  1364. }
  1365. rc = sqlite3_bind_string_or_null(res, chart, 2);
  1366. if (unlikely(rc != SQLITE_OK)) {
  1367. error_report("Failed to bind char parameter for SQL_GET_ALARM_ID.");
  1368. sqlite3_finalize(res);
  1369. return alarm_id;
  1370. }
  1371. rc = sqlite3_bind_string_or_null(res, name, 3);
  1372. if (unlikely(rc != SQLITE_OK)) {
  1373. error_report("Failed to bind name parameter for SQL_GET_ALARM_ID.");
  1374. sqlite3_finalize(res);
  1375. return alarm_id;
  1376. }
  1377. rc = sqlite3_bind_blob(res, 4, config_hash_id, sizeof(*config_hash_id), SQLITE_STATIC);
  1378. if (unlikely(rc != SQLITE_OK)) {
  1379. error_report("Failed to bind config_hash_id parameter for SQL_GET_ALARM_ID.");
  1380. sqlite3_finalize(res);
  1381. return alarm_id;
  1382. }
  1383. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  1384. alarm_id = (uint32_t) sqlite3_column_int64(res, 0);
  1385. health_log_id = (uint64_t) sqlite3_column_int64(res, 1);
  1386. }
  1387. rc = sqlite3_finalize(res);
  1388. if (unlikely(rc != SQLITE_OK))
  1389. error_report("Failed to finalize the statement while getting an alarm id.");
  1390. if (alarm_id) {
  1391. rc = sqlite3_prepare_v2(db_meta, SQL_GET_EVENT_ID, -1, &res, 0);
  1392. if (rc != SQLITE_OK) {
  1393. error_report("Failed to prepare statement when trying to get an event id");
  1394. return alarm_id;
  1395. }
  1396. rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) health_log_id);
  1397. if (unlikely(rc != SQLITE_OK)) {
  1398. error_report("Failed to bind host_id parameter for SQL_GET_EVENT_ID.");
  1399. sqlite3_finalize(res);
  1400. return alarm_id;
  1401. }
  1402. rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
  1403. if (unlikely(rc != SQLITE_OK)) {
  1404. error_report("Failed to bind char parameter for SQL_GET_EVENT_ID.");
  1405. sqlite3_finalize(res);
  1406. return alarm_id;
  1407. }
  1408. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  1409. *next_event_id = (uint32_t) sqlite3_column_int64(res, 0);
  1410. }
  1411. rc = sqlite3_finalize(res);
  1412. if (unlikely(rc != SQLITE_OK))
  1413. error_report("Failed to finalize the statement while getting an alarm id.");
  1414. }
  1415. return alarm_id;
  1416. }
  1417. #define SQL_GET_ALARM_ID_FROM_TRANSITION_ID "SELECT hld.alarm_id, hl.host_id, hl.chart_context FROM " \
  1418. "health_log_detail hld, health_log hl WHERE hld.transition_id = @transition_id " \
  1419. "and hld.health_log_id = hl.health_log_id"
  1420. bool sql_find_alert_transition(const char *transition, void (*cb)(const char *machine_guid, const char *context, time_t alert_id, void *data), void *data)
  1421. {
  1422. static __thread sqlite3_stmt *res = NULL;
  1423. char machine_guid[UUID_STR_LEN];
  1424. int rc;
  1425. uuid_t transition_uuid;
  1426. if (uuid_parse(transition, transition_uuid))
  1427. return false;
  1428. if (unlikely(!res)) {
  1429. rc = prepare_statement(db_meta, SQL_GET_ALARM_ID_FROM_TRANSITION_ID, &res);
  1430. if (unlikely(rc != SQLITE_OK)) {
  1431. error_report("Failed to prepare statement when trying to get transition id");
  1432. return false;
  1433. }
  1434. }
  1435. bool ok = false;
  1436. rc = sqlite3_bind_blob(res, 1, &transition_uuid, sizeof(transition_uuid), SQLITE_STATIC);
  1437. if (unlikely(rc != SQLITE_OK)) {
  1438. error_report("Failed to bind transition");
  1439. goto fail;
  1440. }
  1441. while (sqlite3_step_monitored(res) == SQLITE_ROW) {
  1442. ok = true;
  1443. uuid_unparse_lower(*(uuid_t *) sqlite3_column_blob(res, 1), machine_guid);
  1444. cb(machine_guid, (const char *) sqlite3_column_text(res, 2), sqlite3_column_int(res, 0), data);
  1445. }
  1446. fail:
  1447. rc = sqlite3_reset(res);
  1448. if (unlikely(rc != SQLITE_OK))
  1449. error_report("Failed to reset the statement when trying to find transition");
  1450. return ok;
  1451. }
  1452. #define SQL_BUILD_ALERT_TRANSITION "CREATE TEMP TABLE IF NOT EXISTS v_%p (host_id blob)"
  1453. #define SQL_POPULATE_TEMP_ALERT_TRANSITION_TABLE "INSERT INTO v_%p (host_id) VALUES (@host_id)"
  1454. #define SQL_SEARCH_ALERT_TRANSITION_SELECT "SELECT " \
  1455. "h.host_id, h.alarm_id, h.config_hash_id, h.name, h.chart, h.family, h.recipient, h.units, h.exec, " \
  1456. "h.chart_context, d.when_key, d.duration, d.non_clear_duration, d.flags, d.delay_up_to_timestamp, " \
  1457. "d.info, d.exec_code, d.new_status, d.old_status, d.delay, d.new_value, d.old_value, d.last_repeat, " \
  1458. "d.transition_id, d.global_id, ah.class, ah.type, ah.component, d.exec_run_timestamp"
  1459. #define SQL_SEARCH_ALERT_TRANSITION_COMMON_WHERE \
  1460. "h.config_hash_id = ah.hash_id AND h.health_log_id = d.health_log_id"
  1461. #define SQL_SEARCH_ALERT_TRANSITION SQL_SEARCH_ALERT_TRANSITION_SELECT " FROM health_log h, health_log_detail d, v_%p t, alert_hash ah " \
  1462. " WHERE h.host_id = t.host_id AND " SQL_SEARCH_ALERT_TRANSITION_COMMON_WHERE " AND ( d.new_status > 2 OR d.old_status > 2 ) AND d.global_id BETWEEN @after AND @before "
  1463. #define SQL_SEARCH_ALERT_TRANSITION_DIRECT SQL_SEARCH_ALERT_TRANSITION_SELECT " FROM health_log h, health_log_detail d, alert_hash ah " \
  1464. " WHERE " SQL_SEARCH_ALERT_TRANSITION_COMMON_WHERE " AND transition_id = @transition "
  1465. void sql_alert_transitions(
  1466. DICTIONARY *nodes,
  1467. time_t after,
  1468. time_t before,
  1469. const char *context,
  1470. const char *alert_name,
  1471. const char *transition,
  1472. void (*cb)(struct sql_alert_transition_data *, void *),
  1473. void *data,
  1474. bool debug __maybe_unused)
  1475. {
  1476. uuid_t transition_uuid;
  1477. char sql[512];
  1478. int rc;
  1479. sqlite3_stmt *res = NULL;
  1480. BUFFER *command = NULL;
  1481. if (unlikely(!nodes))
  1482. return;
  1483. if (transition) {
  1484. if (uuid_parse(transition, transition_uuid)) {
  1485. error_report("Invalid transition given %s", transition);
  1486. return;
  1487. }
  1488. rc = sqlite3_prepare_v2(db_meta, SQL_SEARCH_ALERT_TRANSITION_DIRECT, -1, &res, 0);
  1489. rc = sqlite3_bind_blob(res, 1, &transition_uuid, sizeof(transition_uuid), SQLITE_STATIC);
  1490. if (unlikely(rc != SQLITE_OK)) {
  1491. error_report("Failed to bind transition_id parameter");
  1492. goto fail;
  1493. }
  1494. goto run_query;
  1495. }
  1496. snprintfz(sql, 511, SQL_BUILD_ALERT_TRANSITION, nodes);
  1497. rc = db_execute(db_meta, sql);
  1498. if (rc)
  1499. return;
  1500. snprintfz(sql, 511, SQL_POPULATE_TEMP_ALERT_TRANSITION_TABLE, nodes);
  1501. // Prepare statement to add things
  1502. rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
  1503. if (unlikely(rc != SQLITE_OK)) {
  1504. error_report("Failed to prepare statement to INSERT into v_%p", nodes);
  1505. goto fail_only_drop;
  1506. }
  1507. void *t;
  1508. dfe_start_read(nodes, t) {
  1509. uuid_t host_uuid;
  1510. uuid_parse( t_dfe.name, host_uuid);
  1511. rc = sqlite3_bind_blob(res, 1, &host_uuid, sizeof(host_uuid), SQLITE_STATIC);
  1512. if (unlikely(rc != SQLITE_OK))
  1513. error_report("Failed to bind host_id parameter.");
  1514. rc = sqlite3_step_monitored(res);
  1515. if (rc != SQLITE_DONE)
  1516. error_report("Error while populating temp table");
  1517. rc = sqlite3_reset(res);
  1518. if (rc != SQLITE_OK)
  1519. error_report("Error while resetting parameters");
  1520. }
  1521. dfe_done(t);
  1522. rc = sqlite3_finalize(res);
  1523. if (unlikely(rc != SQLITE_OK)) {
  1524. // log error but continue
  1525. error_report("Failed to finalize statement for sql_alert_transitions temp table population");
  1526. }
  1527. command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
  1528. buffer_sprintf(command, SQL_SEARCH_ALERT_TRANSITION, nodes);
  1529. if (context)
  1530. buffer_sprintf(command, " AND h.chart_context = @context");
  1531. if (alert_name)
  1532. buffer_sprintf(command, " AND h.name = @alert_name");
  1533. buffer_strcat(command, " ORDER BY d.global_id DESC");
  1534. rc = sqlite3_prepare_v2(db_meta, buffer_tostring(command), -1, &res, 0);
  1535. if (unlikely(rc != SQLITE_OK)) {
  1536. error_report("Failed to prepare statement sql_alert_transitions");
  1537. goto fail_only_drop;
  1538. }
  1539. int param = 1;
  1540. rc = sqlite3_bind_int64(res, param++, (sqlite3_int64)(after * USEC_PER_SEC));
  1541. if (unlikely(rc != SQLITE_OK)) {
  1542. error_report("Failed to bind after parameter");
  1543. goto fail;
  1544. }
  1545. rc = sqlite3_bind_int64(res, param++, (sqlite3_int64)(before * USEC_PER_SEC));
  1546. if (unlikely(rc != SQLITE_OK)) {
  1547. error_report("Failed to bind before parameter");
  1548. goto fail;
  1549. }
  1550. if (context) {
  1551. rc = sqlite3_bind_text(res, param++, context, -1, SQLITE_STATIC);
  1552. if (unlikely(rc != SQLITE_OK)) {
  1553. error_report("Failed to bind context parameter");
  1554. goto fail;
  1555. }
  1556. }
  1557. if (alert_name) {
  1558. rc = sqlite3_bind_text(res, param++, alert_name, -1, SQLITE_STATIC);
  1559. if (unlikely(rc != SQLITE_OK)) {
  1560. error_report("Failed to bind alert_name parameter");
  1561. goto fail;
  1562. }
  1563. }
  1564. run_query:;
  1565. struct sql_alert_transition_data atd = {0 };
  1566. while (sqlite3_step(res) == SQLITE_ROW) {
  1567. atd.host_id = (uuid_t *) sqlite3_column_blob(res, 0);
  1568. atd.alarm_id = sqlite3_column_int64(res, 1);
  1569. atd.config_hash_id = (uuid_t *)sqlite3_column_blob(res, 2);
  1570. atd.alert_name = (const char *) sqlite3_column_text(res, 3);
  1571. atd.chart = (const char *) sqlite3_column_text(res, 4);
  1572. atd.chart_name = (const char *) sqlite3_column_text(res, 4); // FIXME don't copy the id, find the name
  1573. atd.family = (const char *) sqlite3_column_text(res, 5);
  1574. atd.recipient = (const char *) sqlite3_column_text(res, 6);
  1575. atd.units = (const char *) sqlite3_column_text(res, 7);
  1576. atd.exec = (const char *) sqlite3_column_text(res, 8);
  1577. atd.chart_context = (const char *) sqlite3_column_text(res, 9);
  1578. atd.when_key = sqlite3_column_int64(res, 10);
  1579. atd.duration = sqlite3_column_int64(res, 11);
  1580. atd.non_clear_duration = sqlite3_column_int64(res, 12);
  1581. atd.flags = sqlite3_column_int64(res, 13);
  1582. atd.delay_up_to_timestamp = sqlite3_column_int64(res, 14);
  1583. atd.info = (const char *) sqlite3_column_text(res, 15);
  1584. atd.exec_code = sqlite3_column_int(res, 16);
  1585. atd.new_status = sqlite3_column_int(res, 17);
  1586. atd.old_status = sqlite3_column_int(res, 18);
  1587. atd.delay = (int) sqlite3_column_int(res, 19);
  1588. atd.new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 20);
  1589. atd.old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 21);
  1590. atd.last_repeat = sqlite3_column_int64(res, 22);
  1591. atd.transition_id = (uuid_t *) sqlite3_column_blob(res, 23);
  1592. atd.global_id = sqlite3_column_int64(res, 24);
  1593. atd.classification = (const char *) sqlite3_column_text(res, 25);
  1594. atd.type = (const char *) sqlite3_column_text(res, 26);
  1595. atd.component = (const char *) sqlite3_column_text(res, 27);
  1596. atd.exec_run_timestamp = sqlite3_column_int64(res, 28);
  1597. cb(&atd, data);
  1598. }
  1599. fail:
  1600. rc = sqlite3_finalize(res);
  1601. if (unlikely(rc != SQLITE_OK))
  1602. error_report("Failed to finalize statement for sql_alert_transitions");
  1603. fail_only_drop:
  1604. if (likely(!transition)) {
  1605. (void)snprintfz(sql, 511, "DROP TABLE IF EXISTS v_%p", nodes);
  1606. (void)db_execute(db_meta, sql);
  1607. buffer_free(command);
  1608. }
  1609. }
  1610. #define SQL_BUILD_CONFIG_TARGET_LIST "CREATE TEMP TABLE IF NOT EXISTS c_%p (hash_id blob)"
  1611. #define SQL_POPULATE_TEMP_CONFIG_TARGET_TABLE "INSERT INTO c_%p (hash_id) VALUES (@hash_id)"
  1612. #define SQL_SEARCH_CONFIG_LIST "SELECT ah.hash_id, alarm, template, on_key, class, component, type, os, hosts, lookup, every, " \
  1613. " units, calc, families, plugin, module, charts, green, red, warn, crit, " \
  1614. " exec, to_key, info, delay, options, repeat, host_labels, p_db_lookup_dimensions, p_db_lookup_method, " \
  1615. " p_db_lookup_options, p_db_lookup_after, p_db_lookup_before, p_update_every, source, chart_labels " \
  1616. " FROM alert_hash ah, c_%p t where ah.hash_id = t.hash_id"
  1617. int sql_get_alert_configuration(
  1618. DICTIONARY *configs,
  1619. void (*cb)(struct sql_alert_config_data *, void *),
  1620. void *data,
  1621. bool debug __maybe_unused)
  1622. {
  1623. int added = -1;
  1624. char sql[512];
  1625. int rc;
  1626. sqlite3_stmt *res = NULL;
  1627. BUFFER *command = NULL;
  1628. if (unlikely(!configs))
  1629. return added;
  1630. snprintfz(sql, 511, SQL_BUILD_CONFIG_TARGET_LIST, configs);
  1631. rc = db_execute(db_meta, sql);
  1632. if (rc)
  1633. return added;
  1634. snprintfz(sql, 511, SQL_POPULATE_TEMP_CONFIG_TARGET_TABLE, configs);
  1635. // Prepare statement to add things
  1636. rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
  1637. if (unlikely(rc != SQLITE_OK)) {
  1638. error_report("Failed to prepare statement to INSERT into c_%p", configs);
  1639. goto fail_only_drop;
  1640. }
  1641. void *t;
  1642. dfe_start_read(configs, t) {
  1643. uuid_t hash_id;
  1644. uuid_parse( t_dfe.name, hash_id);
  1645. rc = sqlite3_bind_blob(res, 1, &hash_id, sizeof(hash_id), SQLITE_STATIC);
  1646. if (unlikely(rc != SQLITE_OK))
  1647. error_report("Failed to bind host_id parameter.");
  1648. rc = sqlite3_step_monitored(res);
  1649. if (rc != SQLITE_DONE)
  1650. error_report("Error while populating temp table");
  1651. rc = sqlite3_reset(res);
  1652. if (rc != SQLITE_OK)
  1653. error_report("Error while resetting parameters");
  1654. }
  1655. dfe_done(t);
  1656. rc = sqlite3_finalize(res);
  1657. if (unlikely(rc != SQLITE_OK)) {
  1658. // log error but continue
  1659. error_report("Failed to finalize statement for sql_get_alert_configuration temp table population");
  1660. }
  1661. command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
  1662. buffer_sprintf(command, SQL_SEARCH_CONFIG_LIST, configs);
  1663. rc = sqlite3_prepare_v2(db_meta, buffer_tostring(command), -1, &res, 0);
  1664. if (unlikely(rc != SQLITE_OK)) {
  1665. error_report("Failed to prepare statement sql_get_alert_configuration");
  1666. goto fail_only_drop;
  1667. }
  1668. struct sql_alert_config_data acd = {0 };
  1669. added = 0;
  1670. int param;
  1671. while (sqlite3_step(res) == SQLITE_ROW) {
  1672. param = 0;
  1673. acd.config_hash_id = (uuid_t *) sqlite3_column_blob(res, param++);
  1674. acd.name = (const char *) sqlite3_column_text(res, param++);
  1675. acd.selectors.on_template = (const char *) sqlite3_column_text(res, param++);
  1676. acd.selectors.on_key = (const char *) sqlite3_column_text(res, param++);
  1677. acd.classification = (const char *) sqlite3_column_text(res, param++);
  1678. acd.component = (const char *) sqlite3_column_text(res, param++);
  1679. acd.type = (const char *) sqlite3_column_text(res, param++);
  1680. acd.selectors.os = (const char *) sqlite3_column_text(res, param++);
  1681. acd.selectors.hosts = (const char *) sqlite3_column_text(res, param++);
  1682. acd.value.db.lookup = (const char *) sqlite3_column_text(res, param++);
  1683. acd.value.every = (const char *) sqlite3_column_text(res, param++);
  1684. acd.value.units = (const char *) sqlite3_column_text(res, param++);
  1685. acd.value.calc = (const char *) sqlite3_column_text(res, param++);
  1686. acd.selectors.families = (const char *) sqlite3_column_text(res, param++);
  1687. acd.selectors.plugin = (const char *) sqlite3_column_text(res, param++);
  1688. acd.selectors.module = (const char *) sqlite3_column_text(res, param++);
  1689. acd.selectors.charts = (const char *) sqlite3_column_text(res, param++);
  1690. acd.status.green = (const char *) sqlite3_column_text(res, param++);
  1691. acd.status.red = (const char *) sqlite3_column_text(res, param++);
  1692. acd.status.warn = (const char *) sqlite3_column_text(res, param++);
  1693. acd.status.crit = (const char *) sqlite3_column_text(res, param++);
  1694. acd.notification.exec = (const char *) sqlite3_column_text(res, param++);
  1695. acd.notification.to_key = (const char *) sqlite3_column_text(res, param++);
  1696. acd.info = (const char *) sqlite3_column_text(res, param++);
  1697. acd.notification.delay = (const char *) sqlite3_column_text(res, param++);
  1698. acd.notification.options = (const char *) sqlite3_column_text(res, param++);
  1699. acd.notification.repeat = (const char *) sqlite3_column_text(res, param++);
  1700. acd.selectors.host_labels = (const char *) sqlite3_column_text(res, param++);
  1701. acd.value.db.dimensions = (const char *) sqlite3_column_text(res, param++);
  1702. acd.value.db.method = (const char *) sqlite3_column_text(res, param++);
  1703. acd.value.db.options = (uint32_t) sqlite3_column_int(res, param++);
  1704. acd.value.db.after = (int32_t) sqlite3_column_int(res, param++);
  1705. acd.value.db.before = (int32_t) sqlite3_column_int(res, param++);
  1706. acd.value.update_every = (int32_t) sqlite3_column_int(res, param++);
  1707. acd.source = (const char *) sqlite3_column_text(res, param++);
  1708. acd.selectors.chart_labels = (const char *) sqlite3_column_text(res, param++);
  1709. cb(&acd, data);
  1710. added++;
  1711. }
  1712. rc = sqlite3_finalize(res);
  1713. if (unlikely(rc != SQLITE_OK))
  1714. error_report("Failed to finalize statement for sql_get_alert_configuration");
  1715. fail_only_drop:
  1716. (void)snprintfz(sql, 511, "DROP TABLE IF EXISTS c_%p", configs);
  1717. (void)db_execute(db_meta, sql);
  1718. buffer_free(command);
  1719. return added;
  1720. }