rrdcalctemplate.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #define NETDATA_HEALTH_INTERNALS
  3. #include "rrd.h"
  4. // ----------------------------------------------------------------------------
  5. static int rrdcalctemplate_is_there_label_restriction(RRDCALCTEMPLATE *rt, RRDHOST *host) {
  6. if(!rt->labels)
  7. return 0;
  8. errno = 0;
  9. struct label *move = host->labels.head;
  10. char cmp[CONFIG_FILE_LINE_MAX+1];
  11. int ret;
  12. if(move) {
  13. rrdhost_check_rdlock(host);
  14. netdata_rwlock_rdlock(&host->labels.labels_rwlock);
  15. while(move) {
  16. snprintfz(cmp, CONFIG_FILE_LINE_MAX, "%s=%s", move->key, move->value);
  17. if (simple_pattern_matches(rt->splabels, move->key) ||
  18. simple_pattern_matches(rt->splabels, cmp)) {
  19. break;
  20. }
  21. move = move->next;
  22. }
  23. netdata_rwlock_unlock(&host->labels.labels_rwlock);
  24. if(!move) {
  25. error("Health template '%s' cannot be applied, because the host %s does not have the label(s) '%s'",
  26. rt->name,
  27. host->hostname,
  28. rt->labels
  29. );
  30. ret = 1;
  31. } else {
  32. ret = 0;
  33. }
  34. } else {
  35. ret =0;
  36. }
  37. return ret;
  38. }
  39. static inline int rrdcalctemplate_test_additional_restriction(RRDCALCTEMPLATE *rt, RRDSET *st) {
  40. if (rt->charts_pattern && !simple_pattern_matches(rt->charts_pattern, st->name))
  41. return 0;
  42. if (rt->family_pattern && !simple_pattern_matches(rt->family_pattern, st->family))
  43. return 0;
  44. if (rt->module_pattern && !simple_pattern_matches(rt->module_pattern, st->module_name))
  45. return 0;
  46. if (rt->plugin_pattern && !simple_pattern_matches(rt->plugin_pattern, st->plugin_name))
  47. return 0;
  48. return 1;
  49. }
  50. // RRDCALCTEMPLATE management
  51. /**
  52. * RRDCALC TEMPLATE LINK MATCHING
  53. *
  54. * @param rt is the template used to create the chart.
  55. * @param st is the chart where the alarm will be attached.
  56. */
  57. void rrdcalctemplate_link_matching_test(RRDCALCTEMPLATE *rt, RRDSET *st, RRDHOST *host) {
  58. if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) &&
  59. rrdcalctemplate_test_additional_restriction(rt, st) ) {
  60. if (!rrdcalctemplate_is_there_label_restriction(rt, host)) {
  61. RRDCALC *rc = rrdcalc_create_from_template(host, rt, st->id);
  62. if (unlikely(!rc))
  63. info("Health tried to create alarm from template '%s' on chart '%s' of host '%s', but it failed",
  64. rt->name, st->id, host->hostname);
  65. #ifdef NETDATA_INTERNAL_CHECKS
  66. else if (rc->rrdset != st &&
  67. !rc->foreachdim) //When we have a template with foreadhdim, the child will be added to the index late
  68. error("Health alarm '%s.%s' should be linked to chart '%s', but it is not",
  69. rc->chart ? rc->chart : "NOCHART", rc->name, st->id);
  70. #endif
  71. }
  72. }
  73. }
  74. void rrdcalctemplate_link_matching(RRDSET *st) {
  75. RRDHOST *host = st->rrdhost;
  76. RRDCALCTEMPLATE *rt;
  77. for(rt = host->templates; rt ; rt = rt->next) {
  78. rrdcalctemplate_link_matching_test(rt, st, host);
  79. }
  80. for(rt = host->alarms_template_with_foreach; rt ; rt = rt->next) {
  81. rrdcalctemplate_link_matching_test(rt, st, host);
  82. }
  83. }
  84. inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) {
  85. if(unlikely(!rt)) return;
  86. expression_free(rt->calculation);
  87. expression_free(rt->warning);
  88. expression_free(rt->critical);
  89. freez(rt->family_match);
  90. simple_pattern_free(rt->family_pattern);
  91. freez(rt->plugin_match);
  92. simple_pattern_free(rt->plugin_pattern);
  93. freez(rt->module_match);
  94. simple_pattern_free(rt->module_pattern);
  95. freez(rt->charts_match);
  96. simple_pattern_free(rt->charts_pattern);
  97. freez(rt->name);
  98. freez(rt->exec);
  99. freez(rt->recipient);
  100. freez(rt->classification);
  101. freez(rt->component);
  102. freez(rt->type);
  103. freez(rt->context);
  104. freez(rt->source);
  105. freez(rt->units);
  106. freez(rt->info);
  107. freez(rt->dimensions);
  108. freez(rt->foreachdim);
  109. freez(rt->labels);
  110. simple_pattern_free(rt->spdim);
  111. simple_pattern_free(rt->splabels);
  112. freez(rt);
  113. }
  114. inline void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
  115. if(unlikely(!rt)) return;
  116. debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname);
  117. if(host->templates == rt) {
  118. host->templates = rt->next;
  119. }
  120. else {
  121. RRDCALCTEMPLATE *t;
  122. for (t = host->templates; t && t->next != rt; t = t->next ) ;
  123. if(t) {
  124. t->next = rt->next;
  125. rt->next = NULL;
  126. }
  127. else
  128. error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname);
  129. }
  130. rrdcalctemplate_free(rt);
  131. }