sqlite_health.c 89 KB

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