sqlite_health.c 87 KB

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