report-generator: refactor 55/182755/8
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Wed, 27 Jun 2018 14:33:02 +0000 (16:33 +0200)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Mon, 2 Jul 2018 11:24:35 +0000 (13:24 +0200)
Move the statistic calculation logic out-of report-generator.

Change-Id: I4993271bc9e0dbb0dd665f48f6fe66933e7b8bc3

src/CMakeLists.txt
src/report-generator.c
src/stats.c [new file with mode: 0644]
src/stats.h [new file with mode: 0644]

index 6b258d0..37806ba 100644 (file)
@@ -25,6 +25,7 @@ SET(SRCS
        config-deserializer.c
        appinfo-provider.c
        report-json-serializer.c
+       stats.c
 )
 ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
 
index 3b24dbf..a763e91 100644 (file)
 #include <unistd.h>
 
 #include "report-generator.h"
-#include "procfs.h"
 #include "log.h"
 #include "err-check.h"
 #include "appinfo-provider.h"
+#include "stats.h"
 
 struct report_generator_system {
-       /** previous read from procfs */
-       struct procfs_system_cpu_usage_info previous;
-};
-
-struct process_ticks_snapshot
-{
-       unsigned long long system_ticks;
-       unsigned long long process_ticks;
+       /** system cpu usage statistics */
+       struct stats_system previous;
 };
 
 struct report_generator_process
 {
        /** process pid */
        int pid;
-       /** previous process stats */
-       struct process_ticks_snapshot previous;
+       /** process cpu usage statistics */
+       struct stats_process previous;
 };
 
 struct report_generator_app
@@ -51,7 +45,6 @@ struct report_generator_app
        report_generator_process_t *process_gen;
 };
 
-static int _report_generator_read_process_ticks(int pid, struct process_ticks_snapshot *ticks);
 int _app_report_generator_setup_process_generator(report_generator_app_t *generator);
 
 static struct timespec clock_get_monotonic()
@@ -75,8 +68,8 @@ report_generator_system_t *report_generator_new_system_report_generator()
        if (!ret)
                return NULL;
 
-       if (procfs_read_system_cpu_usage(&ret->previous) != 0) {
-               ERR("procfs_read_system_cpu_usage failed");
+       if (stats_update_system_stats(&ret->previous) != 0) {
+               ERR("stats_update_system_stats failed");
                free(ret);
                return NULL;
        }
@@ -100,8 +93,8 @@ report_generator_process_t *report_generator_new_process_report_generator(int pi
        if (!ret)
                return NULL;
 
-       if (_report_generator_read_process_ticks(pid, &ret->previous) != 0) {
-               ERR("_report_generator_read_process_ticks failed.");
+       if (stats_update_process_stats(pid, &ret->previous) != 0) {
+               ERR("stats_update_process_stats failed.");
                free(ret);
                return NULL;
        };
@@ -142,34 +135,6 @@ void report_generator_free_app_generator(report_generator_app_t *generator)
        free(generator);
 }
 
-static void _calculate_system_cpu_usage(
-               struct procfs_system_cpu_usage_info *previous,
-               struct procfs_system_cpu_usage_info *current,
-               float *usage)
-{
-       struct procfs_system_cpu_usage_info diff_ticks = { 0,};
-
-       diff_ticks.user = current->user > previous->user ? current->user - previous->user : 0;
-       diff_ticks.system = current->system > previous->system ? current->system - previous->system : 0;
-       diff_ticks.nice = current->nice > previous->nice ? current->nice - previous->nice : 0;
-       diff_ticks.idle = current->idle > previous->idle ? current->idle - previous->idle : 0;
-       diff_ticks.iowait = current->iowait > previous->iowait ? current->iowait - previous->iowait : 0;
-       diff_ticks.irq = current->irq > previous->irq ? current->irq - previous->irq : 0;
-       diff_ticks.softirq = current->softirq > previous->softirq ? current->softirq - previous->softirq : 0;
-
-       unsigned long long total = diff_ticks.user + diff_ticks.system + diff_ticks.nice +
-               diff_ticks.idle + diff_ticks.iowait + diff_ticks.irq + diff_ticks.softirq;
-
-       unsigned long long busy = diff_ticks.user + diff_ticks.system + diff_ticks.nice +
-               diff_ticks.irq + diff_ticks.softirq;
-
-       if (total == 0) {
-               *usage = 0;
-       } else {
-               *usage = (float)busy / total;
-       }
-}
-
 int report_generator_generate_system_cpu_usage_report(
                report_generator_system_t *generator,
                int interval,
@@ -179,24 +144,28 @@ int report_generator_generate_system_cpu_usage_report(
        ON_TRUE_RETURN_VAL(interval < 0, -1);
        ON_NULL_RETURN_VAL(report, -1);
 
-       struct procfs_system_cpu_usage_info current = {0,};
        float usage;
        bool block = interval > 0;
+       struct stats_system current;
 
        if (block) {
-               if (procfs_read_system_cpu_usage(&generator->previous) != 0) {
-                       ERR("procfs_read_system_cpu_usage failed.");
+               if (stats_update_system_stats(&generator->previous) != 0) {
+                       ERR("stats_update_system_stats failed.");
                        return -1;
                }
                sleep(interval);
        }
 
-       if (procfs_read_system_cpu_usage(&current) != 0) {
-               ERR("procfs_read_system_cpu_usage failed.");
+       if (stats_update_system_stats(&current) != 0) {
+               ERR("stats_update_system_stats failed.");
                return -1;
        }
 
-       _calculate_system_cpu_usage(&generator->previous, &current, &usage);
+       if (stats_get_system_cpu_usage_average(&generator->previous, &current, &usage))
+       {
+               ERR("stats_get_system_cpu_usage_average failed");
+               return -1;
+       }
 
        report->usage = usage;
        report->time = clock_get_monotonic().tv_sec;
@@ -212,61 +181,15 @@ int report_generator_generate_system_memory_usage_report(
        ON_NULL_RETURN_VAL(generator, -1);
        ON_NULL_RETURN_VAL(report, -1);
 
-       struct procfs_system_memory_usage_info mem_usage;
+       float usage;
 
-       if (procfs_read_system_memory_usage(&mem_usage) != 0) {
-               ERR("procfs_read_system_memory_usage failed.");
+       if (stats_get_system_memory_usage(&usage) != 0) {
+               ERR("stats_get_system_memory_usage failed.");
                return -1;
        }
 
        report->time = clock_get_monotonic().tv_sec;
-       report->usage = (float)mem_usage.used / mem_usage.total;
-
-       return 0;
-}
-
-/**
- * Calculates system average cpu usage between previous and current
- * snapshots.
- */
-static void _calculate_process_cpu_usage(struct process_ticks_snapshot *previous,
-               struct process_ticks_snapshot *current, int ncpus, float *usage)
-{
-       struct process_ticks_snapshot diff;
-
-       diff.process_ticks = current->process_ticks > previous->process_ticks ? current->process_ticks - previous->process_ticks: 0;
-       diff.system_ticks = current->system_ticks > previous->system_ticks ? current->system_ticks - previous->system_ticks : 0;
-
-       if (diff.system_ticks == 0)
-               *usage = 0;
-       else
-               *usage = (float)diff.process_ticks / diff.system_ticks * ncpus;
-}
-
-static unsigned long long
-_system_total_time(const struct procfs_system_cpu_usage_info *info)
-{
-       return info->user + info->system + info->nice + info->idle;
-}
-
-static int
-_report_generator_read_process_ticks(int pid, struct process_ticks_snapshot *ticks)
-{
-       struct procfs_system_cpu_usage_info system_ticks;
-       struct procfs_process_cpu_usage_info process_ticks;
-
-       if (procfs_read_process_cpu_usage(pid, &process_ticks) != 0) {
-               ERR("procfs_read_process_cpu_usage failed.");
-               return -1;
-       }
-
-       if (procfs_read_system_cpu_usage(&system_ticks) != 0) {
-               ERR("procfs_read_system_cpu_usage failed.");
-               return -1;
-       }
-
-       ticks->process_ticks = process_ticks.stime + process_ticks.utime;
-       ticks->system_ticks = _system_total_time(&system_ticks);
+       report->usage = usage;
 
        return 0;
 }
@@ -280,31 +203,28 @@ int report_generator_generate_process_cpu_usage_report(
        ON_TRUE_RETURN_VAL(interval < 0, -1);
        ON_NULL_RETURN_VAL(report, -1);
 
-       struct process_ticks_snapshot current;
+       struct stats_process current = {0,};
        bool block = interval > 0;
        float usage;
-       int ncpus;
 
        if (block) {
-               if (_report_generator_read_process_ticks(generator->pid, &generator->previous) != 0) {
-                       ERR("Unable to update process cpu ticks.");
+               if (stats_update_process_stats(generator->pid, &generator->previous) != 0) {
+                       ERR("stats_update_process_stats failed.");
                        return -1;
                }
                sleep(interval);
        }
 
-       if (_report_generator_read_process_ticks(generator->pid, &current) != 0) {
-               ERR("Unable to update process cpu ticks.");
+       if (stats_update_process_stats(generator->pid, &current) != 0) {
+               ERR("stats_update_process_stats failed.");
                return -1;
        }
 
-       if (procfs_read_cpu_count(&ncpus) != 0) {
-               ERR("procfs_read_cpu_count failed.");
+       if (stats_get_process_cpu_usage_average(&generator->previous, &current, &usage) ) {
+               ERR("stats_update_process_stats failed.");
                return -1;
        }
 
-       _calculate_process_cpu_usage(&generator->previous, &current, ncpus, &usage);
-
        report->time = clock_get_monotonic().tv_sec;
        report->pid = generator->pid;
        report->usage = usage;
@@ -321,21 +241,15 @@ int report_generator_generate_process_memory_usage_report(
        ON_NULL_RETURN_VAL(generator, -1);
        ON_NULL_RETURN_VAL(report, -1);
 
-       struct procfs_process_memory_usage_info mem_info;
-       struct procfs_system_memory_usage_info sys_info;
-
-       if (procfs_read_process_memory_usage(generator->pid, &mem_info) != 0) {
-               ERR("procfs_read_process_memory_usage failed.");
-               return -1;
-       }
+       float usage;
 
-       if (procfs_read_system_memory_usage(&sys_info) != 0) {
-               ERR("procfs_read_system_memory_usage failed.");
+       if (stats_get_process_memory_usage(generator->pid, &usage) != 0) {
+               ERR("stats_get_process_memory_usage failed.");
                return -1;
        }
 
        report->time = clock_get_monotonic().tv_sec;
-       report->usage = sys_info.total > 0 ? (float)mem_info.rss / sys_info.total : 0;
+       report->usage = usage;
 
        return 0;
 }
@@ -409,17 +323,17 @@ int report_generator_generate_load_average_report(struct system_load_average_rep
 {
        ON_NULL_RETURN_VAL(report, -1);
 
-       struct procfs_load_average_info info = {0,};
+       float a1, a5, a15;
 
-       if (procfs_read_system_load_average(&info) != 0) {
-               ERR("procfs_read_system_load_average failed.");
+       if (stats_get_load_averages(&a1, &a5, &a15) != 0) {
+               ERR("stats_get_load_averages failed.");
                return -1;
        }
 
        report->time = clock_get_monotonic().tv_sec;
-       report->one_min_avg = info.one_min_avg;
-       report->five_min_avg = info.five_min_avg;
-       report->fifteen_min_avg = info.fifteen_min_avg;
+       report->one_min_avg = a1;
+       report->five_min_avg = a5;
+       report->fifteen_min_avg = a15;
 
        return 0;
 }
diff --git a/src/stats.c b/src/stats.c
new file mode 100644 (file)
index 0000000..275e860
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stats.h"
+#include "procfs.h"
+#include "err-check.h"
+
+static int ncpus;
+
+int stats_get_system_cpu_usage_average(struct stats_system *previous, struct stats_system *current, float *usage)
+{
+       struct stats_system diff;
+
+       diff.busy_ticks = current->busy_ticks > previous->busy_ticks ? current->busy_ticks - previous->busy_ticks : 0;
+
+       diff.total_ticks = current->total_ticks > previous->total_ticks ? current->total_ticks - previous->total_ticks : 0;
+
+       if (diff.total_ticks == 0) {
+               *usage = 0;
+       } else {
+               *usage = (float)diff.busy_ticks / diff.total_ticks;
+       }
+
+       return 0;
+}
+
+int stats_update_system_stats(struct stats_system *sys)
+{
+       ON_NULL_RETURN_VAL(sys, -1);
+
+       struct procfs_system_cpu_usage_info info;
+
+       if (procfs_read_system_cpu_usage(&info) != 0) {
+               return -1;
+       }
+
+       sys->busy_ticks = info.user + info.system + info.nice + info.irq + info.softirq;
+       sys->total_ticks = info.user + info.system + info.nice + info.irq + info.softirq + info.idle + info.iowait;
+
+       return 0;
+}
+
+int stats_get_system_memory_usage(float *usage)
+{
+       ON_NULL_RETURN_VAL(usage, -1);
+
+       struct procfs_system_memory_usage_info info;
+
+       if (procfs_read_system_memory_usage(&info) != 0) {
+               ERR("procfs_read_system_memory_usage failed.");
+               return -1;
+       }
+
+       *usage = (float)info.used / info.total;
+
+       return 0;
+}
+
+int stats_update_process_stats(int pid, struct stats_process *stats)
+{
+       ON_TRUE_RETURN_VAL(pid < 0, -1);
+       ON_NULL_RETURN_VAL(stats, -1);
+
+       struct procfs_process_cpu_usage_info proc_info;
+       struct procfs_system_cpu_usage_info sys_info;
+
+       if (procfs_read_process_cpu_usage(pid, &proc_info) != 0) {
+               ERR("procfs_read_process_cpu_usage failed.");
+               return -1;
+       }
+
+       if (procfs_read_system_cpu_usage(&sys_info) != 0) {
+               ERR("procfs_read_system_cpu_usage failed.");
+               return -1;
+       }
+
+       stats->process_ticks = proc_info.stime + proc_info.utime;
+       stats->system_ticks = sys_info.user + sys_info.system + sys_info.nice + sys_info.idle;
+
+
+       return 0;
+}
+
+int stats_get_process_cpu_usage_average(struct stats_process *previous, struct stats_process *current, float *usage)
+{
+       struct stats_process diff;
+
+       diff.process_ticks = current->process_ticks > previous->process_ticks ? current->process_ticks - previous->process_ticks: 0;
+       diff.system_ticks = current->system_ticks > previous->system_ticks ? current->system_ticks - previous->system_ticks : 0;
+
+       if (diff.system_ticks == 0)
+               *usage = 0;
+       else
+               *usage = (float)diff.process_ticks / diff.system_ticks * ncpus;
+
+       return 0;
+}
+
+int stats_get_process_memory_usage(int pid, float *usage)
+{
+       ON_TRUE_RETURN_VAL(pid < 0, -1);
+       ON_NULL_RETURN_VAL(usage, -1);
+
+       struct procfs_process_memory_usage_info mem_info;
+       struct procfs_system_memory_usage_info sys_info;
+
+       if (procfs_read_process_memory_usage(pid, &mem_info) != 0) {
+               ERR("procfs_read_process_memory_usage failed.");
+               return -1;
+       }
+
+       if (procfs_read_system_memory_usage(&sys_info) != 0) {
+               ERR("procfs_read_system_memory_usage failed.");
+               return -1;
+       }
+
+       *usage = sys_info.total > 0 ? (float)mem_info.rss / sys_info.total : 0;
+
+       return 0;
+}
+
+int stats_get_load_averages(float *a1, float *a5, float *a15)
+{
+       struct procfs_load_average_info info;
+
+       if (procfs_read_system_load_average(&info) != 0) {
+               ERR("procfs_read_system_load_average failed.");
+               return -1;
+       }
+
+       if (a1) *a1 = info.one_min_avg;
+       if (a5) *a5 = info.five_min_avg;
+       if (a15) *a15 = info.fifteen_min_avg;
+
+       return 0;
+}
+
+int stats_init()
+{
+       if (procfs_read_cpu_count(&ncpus) != 0) {
+               ERR("procfs_read_cpu_count failed.");
+               return -1;
+       }
+       return 0;
+}
diff --git a/src/stats.h b/src/stats.h
new file mode 100644 (file)
index 0000000..0382cf8
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _STATS_H_
+#define _STATS_H_
+
+/**
+ * @brief System's statistics snapshot
+ */
+struct stats_system
+{
+       unsigned long long busy_ticks;
+       unsigned long long total_ticks;
+};
+
+/**
+ * @brief Process's statistics snapshot
+ */
+struct stats_process
+{
+       unsigned long long system_ticks;
+       unsigned long long process_ticks;
+};
+
+/**
+ * @brief Initializes stats module.
+ *
+ * @return: 0 on success, other value on error.
+ *
+ * @note function should be called before any other function call from this
+ * module.
+ */
+int stats_init();
+
+/**
+ * @brief Calculates average cpu usage between two stats snapshots.
+ *
+ * @param[in] previous the stats snapshots taken before current
+ * @param[in] current the stats snapshots taken after previous
+ * @param[out] usage the cpu usage as percent.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_get_system_cpu_usage_average(struct stats_system *previous, struct stats_system *current, float *usage);
+
+/**
+ * @brief Takes system statistics snapshot.
+ *
+ * @param[out] stats System's statistics snapshot.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_update_system_stats(struct stats_system *stats);
+
+/**
+ * @brief Calculates system memory usage.
+ *
+ * @param[out] usage the memory usage as percent.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_get_system_memory_usage(float *usage);
+
+/**
+ * @brief Takes process statistics snapshot.
+ *
+ * @param[in] pid the process id.
+ * @param[out] stats process statistcs.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_update_process_stats(int pid, struct stats_process *stats);
+
+/**
+ * @brief Calculates average process cpu usage between two stats snapshots.
+ *
+ * @param[in] previous the stats snapshots taken before current
+ * @param[in] current the stats snapshots taken after previous
+ * @param[out] usage the cpu usage as percent. It may be greater then 100% in
+ * case of multithreaded applications.
+ *
+ * @note in case when process has 2 threads which runs tight loop, the function
+ * will report 200% usage.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_get_process_cpu_usage_average(struct stats_process *previous, struct stats_process *current, float *usage);
+
+/**
+ * @brief Calculates process memory usage.
+ *
+ * @param[in] pid the process id.
+ * @param[out] usage process memory usage.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_get_process_memory_usage(int pid, float *usage);
+
+/**
+ * @brief Gets system load averages stats.
+ *
+ * @param[out] a1 one minute average.
+ * @param[out] a5 five minute average.
+ * @param[out] a15 fifteen minute average.
+ *
+ * @return: 0 on success, other value on error
+ */
+int stats_get_load_averages(float *a1, float *a5, float *a15);
+
+#endif
+
+