sqlite_health.c 90 KB

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