diff options
Diffstat (limited to 'libnetdata/worker_utilization/worker_utilization.c')
-rw-r--r-- | libnetdata/worker_utilization/worker_utilization.c | 149 |
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); |