static int ctail_config_add_match(cu_tail_match_t *tm, const char *plugin_name, const char *plugin_instance, oconfig_item_t *ci) { ctail_config_match_t cm = {0}; int status; if (ci->values_num != 0) { WARNING("tail plugin: Ignoring arguments for the `Match' block."); } status = 0; for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; if (strcasecmp("Regex", option->key) == 0) status = cf_util_get_string(option, &cm.regex); else if (strcasecmp("ExcludeRegex", option->key) == 0) status = cf_util_get_string(option, &cm.excluderegex); else if (strcasecmp("DSType", option->key) == 0) status = ctail_config_add_match_dstype(&cm, option); else if (strcasecmp("Type", option->key) == 0) status = cf_util_get_string(option, &cm.type); else if (strcasecmp("Instance", option->key) == 0) status = cf_util_get_string(option, &cm.type_instance); else { WARNING("tail plugin: Option `%s' not allowed here.", option->key); status = -1; } if (status != 0) break; } /* for (i = 0; i < ci->children_num; i++) */ while (status == 0) { if (cm.regex == NULL) { WARNING("tail plugin: `Regex' missing in `Match' block."); status = -1; break; } if (cm.type == NULL) { WARNING("tail plugin: `Type' missing in `Match' block."); status = -1; break; } if (cm.flags == 0) { WARNING("tail plugin: `DSType' missing in `Match' block."); status = -1; break; } break; } /* while (status == 0) */ if (status == 0) { // TODO(octo): there's nothing "simple" about the latency stuff … status = tail_match_add_match_simple( tm, cm.regex, cm.excluderegex, cm.flags, (plugin_name != NULL) ? plugin_name : "tail", plugin_instance, cm.type, cm.type_instance, cm.latency); if (status != 0) ERROR("tail plugin: tail_match_add_match_simple failed."); } sfree(cm.regex); sfree(cm.excluderegex); sfree(cm.type); sfree(cm.type_instance); latency_config_free(cm.latency); return status; } /* int ctail_config_add_match */
static int latency_submit_match(cu_match_t *match, void *user_data) { cu_tail_match_simple_t *data = (cu_tail_match_simple_t *)user_data; cu_match_value_t *match_value; value_list_t vl = VALUE_LIST_INIT; match_value = (cu_match_value_t *)match_get_user_data(match); if (match_value == NULL) return (-1); sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, data->plugin, sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, data->plugin_instance, sizeof(vl.plugin_instance)); vl.interval = data->interval; vl.time = cdtime(); /* Submit percentiles */ sstrncpy(vl.type, data->type, sizeof(vl.type)); for (size_t i = 0; i < data->latency_config.percentile_num; i++) { if (strlen(data->type_instance) != 0) ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%.0f", data->type_instance, data->latency_config.percentile[i]); else ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%.0f", data->latency_config.percentile[i]); vl.values = &(value_t){ .gauge = (match_value->values_num != 0) ? CDTIME_T_TO_DOUBLE(latency_counter_get_percentile( match_value->latency, data->latency_config.percentile[i])) : NAN, }; vl.values_len = 1; plugin_dispatch_values(&vl); } /* Submit buckets */ sstrncpy(vl.type, "bucket", sizeof(vl.type)); for (size_t i = 0; i < data->latency_config.buckets_num; i++) { latency_bucket_t bucket = data->latency_config.buckets[i]; double lower_bound = CDTIME_T_TO_DOUBLE(bucket.lower_bound); double upper_bound = bucket.upper_bound ? CDTIME_T_TO_DOUBLE(bucket.upper_bound) : INFINITY; if (strlen(data->type_instance) != 0) ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s-%g_%g", data->type, data->type_instance, lower_bound, upper_bound); else ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%g_%g", data->type, lower_bound, upper_bound); vl.values = &(value_t){ .gauge = latency_counter_get_rate(match_value->latency, bucket.lower_bound, bucket.upper_bound, vl.time), }; vl.values_len = 1; plugin_dispatch_values(&vl); } match_value->value.gauge = NAN; match_value->values_num = 0; latency_counter_reset(match_value->latency); return (0); } /* int latency_submit_match */ static int tail_callback(void *data, char *buf, int __attribute__((unused)) buflen) { cu_tail_match_t *obj = (cu_tail_match_t *)data; for (size_t i = 0; i < obj->matches_num; i++) match_apply(obj->matches[i].match, buf); return (0); } /* int tail_callback */ static void tail_match_simple_free(void *data) { cu_tail_match_simple_t *user_data = (cu_tail_match_simple_t *)data; latency_config_free(user_data->latency_config); sfree(user_data); } /* void tail_match_simple_free */ /* * Public functions */ cu_tail_match_t *tail_match_create(const char *filename) { cu_tail_match_t *obj; obj = calloc(1, sizeof(*obj)); if (obj == NULL) return (NULL); obj->tail = cu_tail_create(filename); if (obj->tail == NULL) { sfree(obj); return (NULL); } return (obj); } /* cu_tail_match_t *tail_match_create */