From: Michael Tremer Date: Thu, 26 May 2022 11:55:13 +0000 (+0000) Subject: builders: Refactor stats X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a4c6436011304d809a8ba1e17dc5cfb141eb532;p=pbs.git builders: Refactor stats We will now have multiple tables to track the history of any system stats which have also been extended to send more data. Signed-off-by: Michael Tremer --- diff --git a/src/buildservice/builders.py b/src/buildservice/builders.py index ce277d60..ff0b0a6c 100644 --- a/src/buildservice/builders.py +++ b/src/buildservice/builders.py @@ -185,38 +185,103 @@ class Builder(base.DataObject): """ return self.online_until >= datetime.datetime.utcnow() - @property - def keepalive(self): - """ - Returns time of last keepalive message from this host. - """ - return self.data.time_keepalive - - def update_keepalive(self, loadavg1=None, loadavg5=None, loadavg15=None, - mem_total=None, mem_free=None, swap_total=None, swap_free=None, - space_free=None): - """ - Update the keepalive timestamp of this machine. - """ - self.db.execute("UPDATE builders SET time_keepalive = NOW(), \ - loadavg1 = %s, loadavg5 = %s, loadavg15 = %s, space_free = %s, \ - mem_total = %s, mem_free = %s, swap_total = %s, swap_free = %s \ - WHERE id = %s", loadavg1, loadavg5, loadavg15, space_free, - mem_total, mem_free, swap_total, swap_free, self.id) - def set_online_until(self, online_until): self._set_attribute("online_until", online_until) online_until = property(lambda s: s.data.online_until, set_online_until) - def update_info(self, cpu_model=None, cpu_count=None, cpu_arch=None, cpu_bogomips=None, - pakfire_version=None, host_key=None, os_name=None): - # Update all the rest. - self.db.execute("UPDATE builders SET time_updated = NOW(), \ - pakfire_version = %s, cpu_model = %s, cpu_count = %s, cpu_arch = %s, \ - cpu_bogomips = %s, host_key_id = %s, os_name = %s WHERE id = %s", - pakfire_version, cpu_model, cpu_count, cpu_arch, cpu_bogomips, - host_key, os_name, self.id) + def update_info(self, cpu_model=None, cpu_count=None, cpu_arch=None, + pakfire_version=None, os_name=None): + self.db.execute(""" + UPDATE + builders + SET + updated_at = CURRENT_TIMESTAMP, + cpu_model = %s, + cpu_count = %s, + cpu_arch = %s, + pakfire_version = %s, + os_name = %s + WHERE + id = %s""", + cpu_model, + cpu_count, + cpu_arch, + pakfire_version, + os_name, + self.id, + ) + + def log_stats(self, cpu_user, cpu_nice, cpu_system, cpu_idle, cpu_iowait, + cpu_irq, cpu_softirq, cpu_steal, cpu_guest, cpu_guest_nice, + loadavg1, loadavg5, loadavg15, mem_total, mem_available, mem_used, + mem_free, mem_active, mem_inactive, mem_buffers, mem_cached, mem_shared, + swap_total, swap_used, swap_free): + """ + Logs some stats about this builder + """ + self.db.execute(""" + INSERT INTO + builder_stats + ( + builder_id, + cpu_user, + cpu_nice, + cpu_system, + cpu_idle, + cpu_iowait, + cpu_irq, + cpu_softirq, + cpu_steal, + cpu_guest, + cpu_guest_nice, + loadavg1, + loadavg5, + loadavg15, + mem_total, + mem_available, + mem_used, + mem_free, + mem_active, + mem_inactive, + mem_buffers, + mem_cached, + mem_shared, + swap_total, + swap_used, + swap_free + ) + VALUES ( + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s + )""", + self.id, + cpu_user, + cpu_nice, + cpu_system, + cpu_idle, + cpu_iowait, + cpu_irq, + cpu_softirq, + cpu_steal, + cpu_guest, + cpu_guest_nice, + loadavg1, + loadavg5, + loadavg15, + mem_total, + mem_available, + mem_used, + mem_free, + mem_active, + mem_inactive, + mem_buffers, + mem_cached, + mem_shared, + swap_total, + swap_used, + swap_free, + ) def set_enabled(self, enabled): self._set_attribute("enabled", enabled) @@ -275,38 +340,6 @@ class Builder(base.DataObject): def passphrase(self): return self.data.passphrase - @property - def performance_index(self): - """ - Returns a number that determines how "fast" the builder is - """ - # XXX needs to be something better - index = self.cpu_bogomips - - # We devide the performance index by the number of already running - # builds to avoid that the fastest builder always gets all the jobs - index /= len(self.active_jobs) + 1 - - return index - - # Load average - - @property - def loadavg(self): - return ", ".join(["%.2f" % l for l in (self.loadavg1, self.loadavg5, self.loadavg15)]) - - @property - def loadavg1(self): - return self.data.loadavg1 or 0.0 - - @property - def loadavg5(self): - return self.data.loadavg5 or 0.0 - - @property - def loadavg15(self): - return self.data.loadavg15 or 0.0 - @property def pakfire_version(self): return self.data.pakfire_version or "" @@ -327,54 +360,6 @@ class Builder(base.DataObject): def cpu_arch(self): return self.data.cpu_arch - @property - def cpu_bogomips(self): - return self.data.cpu_bogomips or 0.0 - - @property - def mem_percentage(self): - if not self.mem_total: - return None - - return self.mem_used * 100 / self.mem_total - - @property - def mem_total(self): - return self.data.mem_total - - @property - def mem_used(self): - if self.mem_total and self.mem_free: - return self.mem_total - self.mem_free - - @property - def mem_free(self): - return self.data.mem_free - - @property - def swap_percentage(self): - if not self.swap_total: - return None - - return self.swap_used * 100 / self.swap_total - - @property - def swap_total(self): - return self.data.swap_total - - @property - def swap_used(self): - if self.swap_total and self.swap_free: - return self.swap_total - self.swap_free - - @property - def swap_free(self): - return self.data.swap_free - - @property - def space_free(self): - return self.data.space_free - @property def host_key_id(self): return self.data.host_key_id diff --git a/src/database.sql b/src/database.sql index ca2b44c2..1125bf0f 100644 --- a/src/database.sql +++ b/src/database.sql @@ -82,6 +82,43 @@ ALTER TABLE public.arches_id_seq OWNER TO pakfire; ALTER SEQUENCE public.arches_id_seq OWNED BY public.arches.id; +-- +-- Name: builder_stats; Type: TABLE; Schema: public; Owner: pakfire +-- + +CREATE TABLE public.builder_stats ( + builder_id integer NOT NULL, + created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + cpu_user double precision NOT NULL, + cpu_nice double precision NOT NULL, + cpu_system double precision NOT NULL, + cpu_idle double precision NOT NULL, + cpu_iowait double precision NOT NULL, + cpu_irq double precision NOT NULL, + cpu_softirq double precision NOT NULL, + cpu_steal double precision NOT NULL, + cpu_guest double precision NOT NULL, + cpu_guest_nice double precision NOT NULL, + loadavg1 double precision NOT NULL, + loadavg5 double precision NOT NULL, + loadavg15 double precision NOT NULL, + mem_total bigint NOT NULL, + mem_available bigint NOT NULL, + mem_used bigint NOT NULL, + mem_free bigint NOT NULL, + mem_active bigint NOT NULL, + mem_inactive bigint NOT NULL, + mem_buffers bigint NOT NULL, + mem_cached bigint NOT NULL, + mem_shared bigint NOT NULL, + swap_total bigint NOT NULL, + swap_used bigint NOT NULL, + swap_free bigint NOT NULL +); + + +ALTER TABLE public.builder_stats OWNER TO pakfire; + -- -- Name: builders; Type: TABLE; Schema: public; Owner: pakfire -- @@ -100,23 +137,12 @@ CREATE TABLE public.builders ( os_name text, cpu_model text, cpu_count integer DEFAULT 1 NOT NULL, - cpu_arch text, - cpu_bogomips double precision, - memory bigint DEFAULT 0 NOT NULL, - free_space bigint DEFAULT 0 NOT NULL, host_key_id text, time_created timestamp without time zone DEFAULT now() NOT NULL, - time_updated timestamp without time zone, + updated_at timestamp without time zone, time_keepalive timestamp without time zone, - loadavg1 double precision, - loadavg5 double precision, - loadavg15 double precision, - mem_total bigint, - mem_free bigint, - swap_total bigint, - swap_free bigint, - space_free bigint, - online_until timestamp without time zone + online_until timestamp without time zone, + cpu_arch text ); @@ -2412,6 +2438,14 @@ ALTER TABLE ONLY public.arches_compat ADD CONSTRAINT arches_compat_build_arch FOREIGN KEY (build_arch) REFERENCES public.arches(name); +-- +-- Name: builder_stats builder_stats_builder_id; Type: FK CONSTRAINT; Schema: public; Owner: pakfire +-- + +ALTER TABLE ONLY public.builder_stats + ADD CONSTRAINT builder_stats_builder_id FOREIGN KEY (builder_id) REFERENCES public.builders(id); + + -- -- Name: builders_history builders_history_builder_id; Type: FK CONSTRAINT; Schema: public; Owner: pakfire -- diff --git a/src/hub/__init__.py b/src/hub/__init__.py index 675b6a15..53ff81e5 100644 --- a/src/hub/__init__.py +++ b/src/hub/__init__.py @@ -23,12 +23,13 @@ class Application(tornado.web.Application): # Builders (r"/builders/info", handlers.BuildersInfoHandler), + (r"/builders/stats", handlers.BuildersStatsHandler), + (r"/builders/jobs/get", handlers.BuildersGetNextJobHandler), (r"/builders/jobs/queue", handlers.BuildersJobsQueueHandler), (r"/builders/jobs/(.*)/addfile/(.*)", handlers.BuildersJobsAddFileHandler), (r"/builders/jobs/(.*)/buildroot", handlers.BuildersJobsBuildrootHandler), (r"/builders/jobs/(.*)/state/(.*)", handlers.BuildersJobsStateHandler), - (r"/builders/keepalive", handlers.BuildersKeepaliveHandler), # Jobs (r"/jobs/active", handlers.JobsGetActiveHandler), diff --git a/src/hub/handlers.py b/src/hub/handlers.py index 954f98de..1d1b69b2 100644 --- a/src/hub/handlers.py +++ b/src/hub/handlers.py @@ -437,44 +437,72 @@ class BuildersInfoHandler(BuildersBaseHandler): def post(self): args = { # CPU info - "cpu_model" : self.get_argument("cpu_model", None), - "cpu_count" : self.get_argument("cpu_count", None), - "cpu_arch" : self.get_argument("cpu_arch", None), - "cpu_bogomips" : self.get_argument("cpu_bogomips", None), + "cpu_model" : self.get_argument("cpu_model", None), + "cpu_count" : self.get_argument("cpu_count", None), + "cpu_arch" : self.get_argument("cpu_arch", None), # Pakfire "pakfire_version" : self.get_argument("pakfire_version", None), - "host_key" : self.get_argument("host_key", None), # OS - "os_name" : self.get_argument("os_name", None), + "os_name" : self.get_argument("os_name", None), } - self.builder.update_info(**args) + + with self.db.transaction(): + self.builder.update_info(**args) + + # Send something back + self.finish({ + "status" : "OK", + }) -class BuildersKeepaliveHandler(BuildersBaseHandler): +class BuildersStatsHandler(BuildersBaseHandler): @tornado.web.authenticated def post(self): args = { + # CPU + "cpu_user" : self.get_argument_float("cpu_user"), + "cpu_nice" : self.get_argument_float("cpu_nice"), + "cpu_system" : self.get_argument_float("cpu_system"), + "cpu_idle" : self.get_argument_float("cpu_idle"), + "cpu_iowait" : self.get_argument_float("cpu_iowait"), + "cpu_irq" : self.get_argument_float("cpu_irq"), + "cpu_softirq" : self.get_argument_float("cpu_softirq"), + "cpu_steal" : self.get_argument_float("cpu_steal"), + "cpu_guest" : self.get_argument_float("cpu_guest"), + "cpu_guest_nice" : self.get_argument_float("cpu_guest_nice"), + # Load average - "loadavg1" : self.get_argument_float("loadavg1", None), - "loadavg5" : self.get_argument_float("loadavg5", None), - "loadavg15" : self.get_argument_float("loadavg15", None), + "loadavg1" : self.get_argument_float("loadavg1"), + "loadavg5" : self.get_argument_float("loadavg5"), + "loadavg15" : self.get_argument_float("loadavg15"), # Memory - "mem_total" : self.get_argument_int("mem_total", None), - "mem_free" : self.get_argument_int("mem_free", None), + "mem_total" : self.get_argument_int("mem_total"), + "mem_available" : self.get_argument_int("mem_available"), + "mem_used" : self.get_argument_int("mem_used"), + "mem_free" : self.get_argument_int("mem_free"), + "mem_active" : self.get_argument_int("mem_active"), + "mem_inactive" : self.get_argument_int("mem_inactive"), + "mem_buffers" : self.get_argument_int("mem_buffers"), + "mem_cached" : self.get_argument_int("mem_cached"), + "mem_shared" : self.get_argument_int("mem_shared"), + + # Swap + "swap_total" : self.get_argument_int("swap_total"), + "swap_used" : self.get_argument_int("swap_used"), + "swap_free" : self.get_argument_int("swap_free"), - # swap - "swap_total" : self.get_argument_int("swap_total", None), - "swap_free" : self.get_argument_int("swap_free", None), - - # Disk space - "space_free" : self.get_argument_int("space_free", None), } - self.builder.update_keepalive(**args) - self.finish("OK") + with self.db.transaction(): + self.builder.log_stats(**args) + + # Send something back + self.finish({ + "status" : "OK", + }) class BuildersGetNextJobHandler(BuildersBaseHandler):