diff --git a/core/metrics.c b/core/metrics.c index 9db52234..cfe43ec2 100644 --- a/core/metrics.c +++ b/core/metrics.c @@ -223,6 +223,9 @@ struct uwsgi_metric *uwsgi_register_metric_do(char *name, char *oid, uint8_t val found: metric->oid = oid; + if (metric->oid) { + metric->oid_len = strlen(oid); + } metric->type = value_type; metric->collect_way = collect_way; metric->ptr = ptr; @@ -413,7 +416,7 @@ void uwsgi_metrics_start_collector() { uwsgi_log("metrics collector thread started\n"); } -struct uwsgi_metric *uwsgi_metric_find_by_name(char *name) { +static struct uwsgi_metric *uwsgi_metric_find_by_name(char *name) { struct uwsgi_metric *um = uwsgi.metrics; while(um) { if (!strcmp(um->name, name)) { @@ -425,6 +428,18 @@ struct uwsgi_metric *uwsgi_metric_find_by_name(char *name) { return NULL; } +static struct uwsgi_metric *uwsgi_metric_find_by_namen(char *name, size_t len) { + struct uwsgi_metric *um = uwsgi.metrics; + while(um) { + if (!uwsgi_strncmp(um->name, um->name_len, name, len)) { + return um; + } + um = um->next; + } + + return NULL; +} + struct uwsgi_metric_child *uwsgi_metric_add_child(struct uwsgi_metric *parent, struct uwsgi_metric *child) { struct uwsgi_metric_child *umc = parent->children, *old_umc = NULL; while(umc) { @@ -443,7 +458,7 @@ struct uwsgi_metric_child *uwsgi_metric_add_child(struct uwsgi_metric *parent, s return umc; } -struct uwsgi_metric *uwsgi_metric_find_by_oid(char *oid) { +static struct uwsgi_metric *uwsgi_metric_find_by_oid(char *oid) { struct uwsgi_metric *um = uwsgi.metrics; while(um) { if (um->oid && !strcmp(um->oid, oid)) { @@ -455,6 +470,18 @@ struct uwsgi_metric *uwsgi_metric_find_by_oid(char *oid) { return NULL; } +static struct uwsgi_metric *uwsgi_metric_find_by_oidn(char *oid, size_t len) { + struct uwsgi_metric *um = uwsgi.metrics; + while(um) { + if (um->oid && !uwsgi_strncmp(um->oid, um->oid_len, oid, len)) { + return um; + } + um = um->next; + } + + return NULL; +} + /* api functions @@ -537,6 +564,27 @@ int64_t uwsgi_metric_get(char *name, char *oid) { return ret; } +int64_t uwsgi_metric_getn(char *name, size_t nlen, char *oid, size_t olen) { + if (!uwsgi.has_metrics) return 0; + int64_t ret = 0; + struct uwsgi_metric *um = NULL; + if (name) { + um = uwsgi_metric_find_by_namen(name, nlen); + } + else if (oid) { + um = uwsgi_metric_find_by_oidn(oid, olen); + } + if (!um) return 0; + + // now (in rlocked context) we get the value from + // the map + uwsgi_rlock(uwsgi.metrics_lock); + ret = um->initial_value+*um->value; + // unlock + uwsgi_rwunlock(uwsgi.metrics_lock); + return ret; +} + #define uwsgi_metric_name(f, n) if (snprintf(buf, 4096, f, n) <= 1) { uwsgi_log("unable to register metric name %s\n", f); exit(1);} #define uwsgi_metric_name2(f, n, n2) if (snprintf(buf, 4096, f, n, n2) <= 1) { uwsgi_log("unable to register metric name %s\n", f); exit(1);} diff --git a/core/routing.c b/core/routing.c index dc8a7160..e053ff69 100644 --- a/core/routing.c +++ b/core/routing.c @@ -1583,6 +1583,13 @@ static char *uwsgi_route_var_mime(struct wsgi_request *wsgi_req, char *key, uint return ret; } +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 char *uwsgi_route_var_httptime(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) { // 30+1 char *ht = uwsgi_calloc(31); @@ -1752,6 +1759,8 @@ void uwsgi_register_embedded_routers() { #endif urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64); urv->need_free = 1; + urv = uwsgi_register_route_var("metric", uwsgi_route_var_metric); + urv->need_free = 1; urv = uwsgi_register_route_var("hex", uwsgi_route_var_hex); urv->need_free = 1; diff --git a/uwsgi.h b/uwsgi.h index 08b6b5c0..5b6bf2f9 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -4422,6 +4422,7 @@ struct uwsgi_metric { char *oid; size_t name_len; + size_t oid_len; // pre-computed snmp representation char *asn; @@ -4482,6 +4483,7 @@ int uwsgi_metric_dec(char *, char *, int64_t); int uwsgi_metric_mul(char *, char *, int64_t); int uwsgi_metric_div(char *, char *, int64_t); int64_t uwsgi_metric_get(char *, char *); +int64_t uwsgi_metric_getn(char *, size_t, char *, size_t); #ifdef __cplusplus }