summaryrefslogtreecommitdiffstats
path: root/libnetdata/worker_utilization/worker_utilization.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/worker_utilization/worker_utilization.c')
-rw-r--r--libnetdata/worker_utilization/worker_utilization.c149
1 files changed, 116 insertions, 33 deletions
diff --git a/libnetdata/worker_utilization/worker_utilization.c b/libnetdata/worker_utilization/worker_utilization.c
index bd3ad60e09..7df050f386 100644
--- a/libnetdata/worker_utilization/worker_utilization.c
+++ b/libnetdata/worker_utilization/worker_utilization.c
@@ -4,15 +4,20 @@
#define WORKER_BUSY 'B'
struct worker_job_type {
- char name[WORKER_UTILIZATION_MAX_JOB_NAME_LENGTH + 1];
+ STRING *name;
+ STRING *units;
// statistics controlled variables
size_t statistics_last_jobs_started;
usec_t statistics_last_busy_time;
+ NETDATA_DOUBLE statistics_last_custom_value;
// worker controlled variables
volatile size_t worker_jobs_started;
volatile usec_t worker_busy_time;
+
+ WORKER_METRIC_TYPE type;
+ NETDATA_DOUBLE custom_value;
};
struct worker {
@@ -36,6 +41,7 @@ struct worker {
struct worker_job_type per_job_type[WORKER_UTILIZATION_MAX_JOB_TYPES];
struct worker *next;
+ struct worker *prev;
};
static netdata_mutex_t base_lock = NETDATA_MUTEX_INITIALIZER;
@@ -57,40 +63,44 @@ void worker_register(const char *workname) {
worker->last_action = WORKER_IDLE;
netdata_mutex_lock(&base_lock);
- worker->next = base;
- base = worker;
+ DOUBLE_LINKED_LIST_PREPEND_UNSAFE(base, worker, prev, next);
netdata_mutex_unlock(&base_lock);
}
-void worker_register_job_name(size_t job_id, const char *name) {
+void worker_register_job_custom_metric(size_t job_id, const char *name, const char *units, WORKER_METRIC_TYPE type) {
if(unlikely(!worker)) return;
if(unlikely(job_id >= WORKER_UTILIZATION_MAX_JOB_TYPES)) {
error("WORKER_UTILIZATION: job_id %zu is too big. Max is %zu", job_id, (size_t)(WORKER_UTILIZATION_MAX_JOB_TYPES - 1));
return;
}
- if (*worker->per_job_type[job_id].name) {
- error("WORKER_UTILIZATION: duplicate job registration: worker '%s' job id %zu is '%s', ignoring '%s'", worker->workname, job_id, worker->per_job_type[job_id].name, name);
+ if(worker->per_job_type[job_id].name) {
+ if(strcmp(string2str(worker->per_job_type[job_id].name), name) != 0 || worker->per_job_type[job_id].type != type || strcmp(string2str(worker->per_job_type[job_id].units), units) != 0)
+ error("WORKER_UTILIZATION: duplicate job registration: worker '%s' job id %zu is '%s', ignoring the later '%s'", worker->workname, job_id, string2str(worker->per_job_type[job_id].name), name);
return;
}
- strncpy(worker->per_job_type[job_id].name, name, WORKER_UTILIZATION_MAX_JOB_NAME_LENGTH);
+ worker->per_job_type[job_id].name = string_strdupz(name);
+ worker->per_job_type[job_id].units = string_strdupz(units);
+ worker->per_job_type[job_id].type = type;
+}
+
+void worker_register_job_name(size_t job_id, const char *name) {
+ worker_register_job_custom_metric(job_id, name, "", WORKER_METRIC_IDLE_BUSY);
}
void worker_unregister(void) {
if(unlikely(!worker)) return;
netdata_mutex_lock(&base_lock);
- if(base == worker)
- base = worker->next;
- else {
- struct worker *p;
- for(p = base; p && p->next && p->next != worker ;p = p->next);
- if(p && p->next == worker)
- p->next = worker->next;
- }
+ DOUBLE_LINKED_LIST_REMOVE_UNSAFE(base, worker, prev, next);
netdata_mutex_unlock(&base_lock);
+ for(int i = 0; i < WORKER_UTILIZATION_MAX_JOB_TYPES ;i++) {
+ string_freez(worker->per_job_type[i].name);
+ string_freez(worker->per_job_type[i].units);
+ }
+
freez((void *)worker->tag);
freez((void *)worker->workname);
freez(worker);
@@ -112,16 +122,14 @@ static inline void worker_is_idle_with_time(usec_t now) {
}
void worker_is_idle(void) {
- if(unlikely(!worker)) return;
- if(unlikely(worker->last_action != WORKER_BUSY)) return;
+ if(unlikely(!worker || worker->last_action != WORKER_BUSY)) return;
worker_is_idle_with_time(now_realtime_usec());
}
void worker_is_busy(size_t job_id) {
- if(unlikely(!worker)) return;
- if(unlikely(job_id >= WORKER_UTILIZATION_MAX_JOB_TYPES))
- job_id = 0;
+ if(unlikely(!worker || job_id >= WORKER_UTILIZATION_MAX_JOB_TYPES))
+ return;
usec_t now = now_realtime_usec();
@@ -138,35 +146,97 @@ void worker_is_busy(size_t job_id) {
worker->last_action = WORKER_BUSY;
}
+void worker_set_metric(size_t job_id, NETDATA_DOUBLE value) {
+ if(unlikely(!worker)) return;
+ if(unlikely(job_id >= WORKER_UTILIZATION_MAX_JOB_TYPES))
+ return;
+
+ if(worker->per_job_type[job_id].type == WORKER_METRIC_INCREMENTAL)
+ worker->per_job_type[job_id].custom_value += value;
+ else
+ worker->per_job_type[job_id].custom_value = value;
+}
// statistics interface
-void workers_foreach(const char *workname, void (*callback)(void *data, pid_t pid, const char *thread_tag, size_t utilization_usec, size_t duration_usec, size_t jobs_started, size_t is_running, const char **job_types_names, size_t *job_types_jobs_started, usec_t *job_types_busy_time), void *data) {
+void workers_foreach(const char *workname, void (*callback)(
+ void *data
+ , pid_t pid
+ , const char *thread_tag
+ , size_t utilization_usec
+ , size_t duration_usec
+ , size_t jobs_started, size_t is_running
+ , STRING **job_types_names
+ , STRING **job_types_units
+ , WORKER_METRIC_TYPE *job_metric_types
+ , size_t *job_types_jobs_started
+ , usec_t *job_types_busy_time
+ , NETDATA_DOUBLE *job_custom_values
+ )
+ , void *data) {
netdata_mutex_lock(&base_lock);
uint32_t hash = simple_hash(workname);
usec_t busy_time, delta;
size_t i, jobs_started, jobs_running;
struct worker *p;
- for(p = base; p ; p = p->next) {
- if(hash != p->workname_hash || strcmp(workname, p->workname)) continue;
+ DOUBLE_LINKED_LIST_FOREACH_FORWARD(base, p, prev, next) {
+ if(hash != p->workname_hash || strcmp(workname, p->workname) != 0) continue;
usec_t now = now_realtime_usec();
// find per job type statistics
- const char *per_job_type_name[WORKER_UTILIZATION_MAX_JOB_TYPES];
+ STRING *per_job_type_name[WORKER_UTILIZATION_MAX_JOB_TYPES];
+ STRING *per_job_type_units[WORKER_UTILIZATION_MAX_JOB_TYPES];
+ WORKER_METRIC_TYPE per_job_metric_type[WORKER_UTILIZATION_MAX_JOB_TYPES];
size_t per_job_type_jobs_started[WORKER_UTILIZATION_MAX_JOB_TYPES];
usec_t per_job_type_busy_time[WORKER_UTILIZATION_MAX_JOB_TYPES];
+ NETDATA_DOUBLE per_job_custom_values[WORKER_UTILIZATION_MAX_JOB_TYPES];
+
for(i = 0; i < WORKER_UTILIZATION_MAX_JOB_TYPES ;i++) {
per_job_type_name[i] = p->per_job_type[i].name;
-
- size_t tmp_jobs_started = p->per_job_type[i].worker_jobs_started;
- per_job_type_jobs_started[i] = tmp_jobs_started - p->per_job_type[i].statistics_last_jobs_started;
- p->per_job_type[i].statistics_last_jobs_started = tmp_jobs_started;
-
- usec_t tmp_busy_time = p->per_job_type[i].worker_busy_time;
- per_job_type_busy_time[i] = tmp_busy_time - p->per_job_type[i].statistics_last_busy_time;
- p->per_job_type[i].statistics_last_busy_time = tmp_busy_time;
+ per_job_type_units[i] = p->per_job_type[i].units;
+ per_job_metric_type[i] = p->per_job_type[i].type;
+
+ switch(p->per_job_type[i].type) {
+ default:
+ case WORKER_METRIC_EMPTY:
+ per_job_type_jobs_started[i] = 0;
+ per_job_type_busy_time[i] = 0;
+ per_job_custom_values[i] = NAN;
+ break;
+
+ case WORKER_METRIC_IDLE_BUSY: {
+ size_t tmp_jobs_started = p->per_job_type[i].worker_jobs_started;
+ per_job_type_jobs_started[i] = tmp_jobs_started - p->per_job_type[i].statistics_last_jobs_started;
+ p->per_job_type[i].statistics_last_jobs_started = tmp_jobs_started;
+
+ usec_t tmp_busy_time = p->per_job_type[i].worker_busy_time;
+ per_job_type_busy_time[i] = tmp_busy_time - p->per_job_type[i].statistics_last_busy_time;
+ p->per_job_type[i].statistics_last_busy_time = tmp_busy_time;
+
+ per_job_custom_values[i] = NAN;
+ break;
+ }
+
+ case WORKER_METRIC_ABSOLUTE:
+ per_job_type_jobs_started[i] = 0;
+ per_job_type_busy_time[i] = 0;
+
+ per_job_custom_values[i] = p->per_job_type[i].custom_value;
+ break;
+
+ case WORKER_METRIC_INCREMENTAL: {
+ per_job_type_jobs_started[i] = 0;
+ per_job_type_busy_time[i] = 0;
+
+ NETDATA_DOUBLE tmp_custom_value = p->per_job_type[i].custom_value;
+ per_job_custom_values[i] = tmp_custom_value - p->per_job_type[i].statistics_last_custom_value;
+ p->per_job_type[i].statistics_last_custom_value = tmp_custom_value;
+
+ break;
+ }
+ }
}
// get a copy of the worker variables
@@ -203,7 +273,20 @@ void workers_foreach(const char *workname, void (*callback)(void *data, pid_t pi
jobs_running = 1;
}
- callback(data, p->pid, p->tag, busy_time, delta, jobs_started, jobs_running, per_job_type_name, per_job_type_jobs_started, per_job_type_busy_time);
+ callback(data
+ , p->pid
+ , p->tag
+ , busy_time
+ , delta
+ , jobs_started
+ , jobs_running
+ , per_job_type_name
+ , per_job_type_units
+ , per_job_metric_type
+ , per_job_type_jobs_started
+ , per_job_type_busy_time
+ , per_job_custom_values
+ );
}
netdata_mutex_unlock(&base_lock);