summaryrefslogtreecommitdiffstats
path: root/database/rrdcalctemplate.c
blob: 9789f4beab8c7b3b6289dc6385023bbf03e7d12e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic
// SPDX-License-Identifier: GPL-3.0-or-later

#define NETDATA_HEALTH_INTERNALS
#include "rrd.h"

// ----------------------------------------------------------------------------

static int rrdcalctemplate_is_there_label_restriction(RRDCALCTEMPLATE *rt,  RRDHOST *host) {
    if(!rt->labels)
        return 0;

    errno = 0;
    struct label *move = host->labels.head;
    char cmp[CONFIG_FILE_LINE_MAX+1];

    int ret;
    if(move) {
        rrdhost_check_rdlock(host);
        netdata_rwlock_rdlock(&host->labels.labels_rwlock);
        while(move) {
            snprintfz(cmp, CONFIG_FILE_LINE_MAX, "%s=%s", move->key, move->value);
            if (simple_pattern_matches(rt->splabels, move->key) ||
                simple_pattern_matches(rt->splabels, cmp)) {
                break;
            }
            move = move->next;
        }
        netdata_rwlock_unlock(&host->labels.labels_rwlock);

        if(!move) {
            error("Health template '%s' cannot be applied, because the host %s does not have the label(s) '%s'",
                   rt->name,
                   host->hostname,
                   rt->labels
            );
            ret = 1;
        } else {
            ret = 0;
        }
    } else {
        ret =0;
    }

    return ret;
}

static inline int rrdcalctemplate_test_additional_restriction(RRDCALCTEMPLATE *rt, RRDSET *st) {
    if (rt->charts_pattern && !simple_pattern_matches(rt->charts_pattern, st->name))
        return 0;

    if (rt->family_pattern && !simple_pattern_matches(rt->family_pattern, st->family))
        return 0;

    if (rt->module_pattern && !simple_pattern_matches(rt->module_pattern, st->module_name))
        return 0;

    if (rt->plugin_pattern && !simple_pattern_matches(rt->plugin_pattern, st->plugin_name))
        return 0;

    return 1;
}

// RRDCALCTEMPLATE management
/**
 * RRDCALC TEMPLATE LINK MATCHING
 *
 * @param rt is the template used to create the chart.
 * @param st is the chart where the alarm will be attached.
 */
void rrdcalctemplate_link_matching_test(RRDCALCTEMPLATE *rt, RRDSET *st, RRDHOST *host) {
    if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) &&
        rrdcalctemplate_test_additional_restriction(rt, st) ) {
        if (!rrdcalctemplate_is_there_label_restriction(rt, host)) {
            RRDCALC *rc = rrdcalc_create_from_template(host, rt, st->id);
            if (unlikely(!rc))
                info("Health tried to create alarm from template '%s' on chart '%s' of host '%s', but it failed",
                     rt->name, st->id, host->hostname);
#ifdef NETDATA_INTERNAL_CHECKS
            else if (rc->rrdset != st &&
                     !rc->foreachdim) //When we have a template with foreadhdim, the child will be added to the index late
                error("Health alarm '%s.%s' should be linked to chart '%s', but it is not",
                      rc->chart ? rc->chart : "NOCHART", rc->name, st->id);
#endif
        }
    }
}

void rrdcalctemplate_link_matching(RRDSET *st) {
    RRDHOST *host = st->rrdhost;
    RRDCALCTEMPLATE *rt;

    for(rt = host->templates; rt ; rt = rt->next) {
        rrdcalctemplate_link_matching_test(rt, st, host);
    }

    for(rt = host->alarms_template_with_foreach; rt ; rt = rt->next) {
        rrdcalctemplate_link_matching_test(rt, st, host);
    }
}

inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) {
    if(unlikely(!rt)) return;

    expression_free(rt->calculation);
    expression_free(rt->warning);
    expression_free(rt->critical);

    freez(rt->family_match);
    simple_pattern_free(rt->family_pattern);

    freez(rt->plugin_match);
    simple_pattern_free(rt->plugin_pattern);

    freez(rt->module_match);
    simple_pattern_free(rt->module_pattern);

    freez(rt->charts_match);
    simple_pattern_free(rt->charts_pattern);

    freez(rt->name);
    freez(rt->exec);
    freez(rt->recipient);
    freez(rt->classification);
    freez(rt->component);
    freez(rt->type);
    freez(rt->context);
    freez(rt->source);
    freez(rt->units);
    freez(rt->info);
    freez(rt->dimensions);
    freez(rt->foreachdim);
    freez(rt->labels);
    simple_pattern_free(rt->spdim);
    simple_pattern_free(rt->splabels);
    freez(rt);
}

inline void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt) {
    if(unlikely(!rt)) return;

    debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname);

    if(host->templates == rt) {
        host->templates = rt->next;
    }
    else {
        RRDCALCTEMPLATE *t;
        for (t = host->templates; t && t->next != rt; t = t->next ) ;
        if(t) {
            t->next = rt->next;
            rt->next = NULL;
        }
        else
            error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname);
    }

    rrdcalctemplate_free(rt);
}
span> (tc_bus_get_info(&tc_bus)) goto out_err; INIT_LIST_HEAD(&tc_bus.devices); dev_set_name(&tc_bus.dev, "tc"); if (device_register(&tc_bus.dev)) goto out_err_device; if (tc_bus.info.slot_size) { unsigned int tc_clock = tc_get_speed(&tc_bus) / 100000; pr_info("tc: TURBOchannel rev. %d at %d.%d MHz " "(with%s parity)\n", tc_bus.info.revision, tc_clock / 10, tc_clock % 10, tc_bus.info.parity ? "" : "out"); tc_bus.resource[0].start = tc_bus.slot_base; tc_bus.resource[0].end = tc_bus.slot_base + (tc_bus.info.slot_size << 20) * tc_bus.num_tcslots - 1; tc_bus.resource[0].name = tc_bus.name; tc_bus.resource[0].flags = IORESOURCE_MEM; if (request_resource(&iomem_resource, &tc_bus.resource[0]) < 0) { pr_err("tc: Cannot reserve resource\n"); goto out_err_device; } if (tc_bus.ext_slot_size) { tc_bus.resource[1].start = tc_bus.ext_slot_base; tc_bus.resource[1].end = tc_bus.ext_slot_base + tc_bus.ext_slot_size * tc_bus.num_tcslots - 1; tc_bus.resource[1].name = tc_bus.name; tc_bus.resource[1].flags = IORESOURCE_MEM; if (request_resource(&iomem_resource, &tc_bus.resource[1]) < 0) { pr_err("tc: Cannot reserve resource\n"); goto out_err_resource; } } tc_bus_add_devices(&tc_bus); } return 0; out_err_resource: release_resource(&tc_bus.resource[0]); out_err_device: put_device(&tc_bus.dev); out_err: return 0; } subsys_initcall(tc_init);