#include #ifdef UWSGI_ROUTING struct uwsgi_router_metric_conf { // the name of the metric char *name; size_t name_len; // the value for the metric char *value; size_t value_len; int (*func)(char *, char *, int64_t); }; // metricinc/metricdec/metricmul/metricdiv/metricset static int uwsgi_routing_func_metricmath(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){ struct uwsgi_router_metric_conf *urmc = (struct uwsgi_router_metric_conf *) ur->data2; char **subject = (char **) (((char *)(wsgi_req))+ur->subject); uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->name, urmc->name_len); if (!ub) return UWSGI_ROUTE_BREAK; struct uwsgi_buffer *ub_val = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->value, urmc->value_len); if (!ub_val) { uwsgi_buffer_destroy(ub); return UWSGI_ROUTE_BREAK; } int64_t num = strtol(ub_val->buf, NULL, 10); uwsgi_buffer_destroy(ub_val); if (urmc->func(ub->buf, NULL, num)) { uwsgi_buffer_destroy(ub); return UWSGI_ROUTE_BREAK; } uwsgi_buffer_destroy(ub); return UWSGI_ROUTE_NEXT; } static struct uwsgi_router_metric_conf *uwsgi_router_metricmath(struct uwsgi_route *ur, char *args) { ur->func = uwsgi_routing_func_metricmath; ur->data = args; ur->data_len = strlen(args); struct uwsgi_router_metric_conf *urmc = uwsgi_calloc(sizeof(struct uwsgi_router_metric_conf)); char *comma = strchr(args, ','); if (comma) { urmc->value = comma+1; urmc->value_len = strlen(urmc->value); *comma = 0; } else { urmc->value = "1"; urmc->value_len = 1; } urmc->name = args; urmc->name_len = strlen(args); if (comma) *comma = ','; ur->data2 = urmc; return urmc; } static int uwsgi_router_metricinc(struct uwsgi_route *ur, char *args) { struct uwsgi_router_metric_conf *urmc = uwsgi_router_metricmath(ur, args); if (!urmc) return -1; urmc->func = uwsgi_metric_inc; return 0; } static int uwsgi_router_metricdec(struct uwsgi_route *ur, char *args) { struct uwsgi_router_metric_conf *urmc = uwsgi_router_metricmath(ur, args); if (!urmc) return -1; urmc->func = uwsgi_metric_dec; return 0; } static int uwsgi_router_metricmul(struct uwsgi_route *ur, char *args) { struct uwsgi_router_metric_conf *urmc = uwsgi_router_metricmath(ur, args); if (!urmc) return -1; urmc->func = uwsgi_metric_mul; return 0; } static int uwsgi_router_metricdiv(struct uwsgi_route *ur, char *args) { struct uwsgi_router_metric_conf *urmc = uwsgi_router_metricmath(ur, args); if (!urmc) return -1; urmc->func = uwsgi_metric_div; return 0; } static int uwsgi_router_metricset(struct uwsgi_route *ur, char *args) { struct uwsgi_router_metric_conf *urmc = uwsgi_router_metricmath(ur, args); if (!urmc) return -1; urmc->func = uwsgi_metric_set; return 0; } static char *uwsgi_route_var_metric(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) { int64_t metric = uwsgi_metric_getn(key, keylen, NULL, 0); char *ret = uwsgi_64bit2str(metric); *vallen = strlen(ret); return ret; } static void router_metrics_register() { uwsgi_register_router("metricinc", uwsgi_router_metricinc); uwsgi_register_router("metricdec", uwsgi_router_metricdec); uwsgi_register_router("metricmul", uwsgi_router_metricmul); uwsgi_register_router("metricdiv", uwsgi_router_metricdiv); uwsgi_register_router("metricset", uwsgi_router_metricset); struct uwsgi_route_var *urv = uwsgi_register_route_var("metric", uwsgi_route_var_metric); urv->need_free = 1; } struct uwsgi_plugin router_metrics_plugin = { .name = "router_metrics", .on_load = router_metrics_register, }; #else struct uwsgi_plugin router_metrics_plugin = { .name = "router_metrics", }; #endif