From e59d55447b1ebd259b4761e12ef8a3232200a8f4 Mon Sep 17 00:00:00 2001 From: Julien Desfossez Date: Mon, 7 Apr 2014 15:35:19 -0400 Subject: [PATCH] beginning activity tracker Signed-off-by: Julien Desfossez --- activity.py | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100755 activity.py diff --git a/activity.py b/activity.py new file mode 100755 index 0000000..c5d5e43 --- /dev/null +++ b/activity.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +import sys +import argparse +import shutil +import time +import os +import sqlite3 +from babeltrace import * +from LTTngAnalyzes.common import * + +DB_NAME = "proc.db" + +class Analyzes(): + def __init__(self, traces): + self.traces = traces + self.processes = {} + self.cpus = {} + + def connect_db(self): + self.conn = sqlite3.connect(DB_NAME) + self.cur = self.conn.cursor() + + def init_db(self): + self.connect_db() + self.cur.execute("DROP TABLE IF EXISTS processes") + self.cur.execute("CREATE TABLE processes (name TEXT)") + self.cur.execute("DROP TABLE IF EXISTS syscalls") + self.cur.execute("CREATE TABLE syscalls (proc_name TEXT, syscall_name TEXT)") + + self.cur.execute("DROP TABLE IF EXISTS staging_processes") + self.cur.execute("CREATE TABLE staging_processes (name TEXT)") + self.cur.execute("DROP TABLE IF EXISTS staging_syscalls") + self.cur.execute("CREATE TABLE staging_syscalls (proc_name TEST, syscall_name TEXT)") + + def check_process(self, proc): + self.cur.execute("SELECT * FROM processes WHERE name=:name", + {"name": proc}) + p = self.cur.fetchall() + if p: + return + self.cur.execute("SELECT * FROM staging_processes WHERE name=:name", + {"name": proc}) + p = self.cur.fetchall() + if not p: + self.cur.execute("INSERT INTO staging_processes VALUES (:proc)", + {"proc": proc}) + + def check_syscall(self, proc, syscall): + self.cur.execute("SELECT * FROM syscalls WHERE proc_name=:proc_name " \ + "AND syscall_name=:syscall_name", + {"proc_name": proc, "syscall_name": syscall}) + p = self.cur.fetchall() + if p: + return + self.cur.execute("SELECT * FROM staging_syscalls WHERE proc_name=:proc_name " \ + "AND syscall_name=:syscall_name", + {"proc_name": proc, "syscall_name": syscall}) + p = self.cur.fetchall() + if not p: + self.cur.execute("INSERT INTO staging_syscalls VALUES(?,?)", + (proc, syscall)) + + def add_proc(self, p): + self.cur.execute("INSERT INTO processes VALUES (:proc)", + {"proc": p}) + self.cur.execute("DELETE FROM staging_processes WHERE name=:proc", + {"proc": p}) + + def add_syscall(self, p, s): + self.cur.execute("INSERT INTO syscalls VALUES (:proc, :syscall)", + {"proc": p, "syscall": s}) + self.cur.execute("DELETE FROM staging_syscalls WHERE proc_name=:proc " \ + "AND syscall_name=:syscall", {"proc": p, "syscall": s}) + + def review_processes(self): + self.cur.execute("SELECT * FROM staging_processes") + proc = self.cur.fetchall() + if not proc: + return + add_all = 0 + for p in proc: + if add_all: + print("Adding %s" % p[0]) + self.add_proc(p[0]) + continue + + print("Found new process running : %s, add it to the DB (Y/n/a/q) ?" % + (p)) + a = sys.stdin.readline().strip() + if a in ["y", "Y", ""]: + self.add_proc(p[0]) + elif a == "a": + add_all = 1 + self.add_proc(p[0]) + elif a == "q": + return + else: + continue + + def review_syscalls(self): + self.cur.execute("SELECT * FROM staging_syscalls") + sysc = self.cur.fetchall() + if not sysc: + return + add_all = 0 + for p in sysc: + if add_all: + print("Adding %s to %s" % (p[1], p[0])) + self.add_syscall(p[0], p[1]) + continue + + print("Found new syscall %s for proc %s, add it to the DB (Y/n/a/q) ?" % + (p[1], p[0])) + a = sys.stdin.readline().strip() + if a in ["y", "Y", ""]: + self.add_syscall(p[0], p[1]) + elif a == "a": + add_all = 1 + self.add_syscall(p[0], p[1]) + elif a == "q": + return + else: + continue + + def lttng_statedump_process_state(self, event): + name = event["name"] + if not name in self.processes.keys(): + self.processes[name] = Process() + self.check_process(name) + + def sched_switch(self, event): + next_comm = event["next_comm"] + cpu_id = event["cpu_id"] + if not cpu_id in self.cpus.keys(): + self.cpus[cpu_id] = CPU() + self.cpus[cpu_id].current_comm = next_comm + if not next_comm in self.processes.keys(): + self.processes[next_comm] = Process() + self.check_process(next_comm) + + def syscall_entry(self, event): + cpu_id = event["cpu_id"] + if not cpu_id in self.cpus.keys(): + return + p = self.processes[self.cpus[cpu_id].current_comm] + p.syscalls[event.name] = Syscall() + self.check_syscall(self.cpus[cpu_id].current_comm, event.name) + + def run(self, args): + for event in self.traces.events: + if event.name == "sched_switch": + self.sched_switch(event) + elif event.name == "lttng_statedump_process_state": + self.lttng_statedump_process_state(event) + elif event.name[0:4] == "sys_": + self.syscall_entry(event) + self.conn.commit() + self.review_processes() + self.review_syscalls() + self.conn.commit() + + def report(self): + for p in self.processes.keys(): + print(p) + for s in self.processes[p].syscalls.keys(): + print(" %s" % s) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Activity tracker') + parser.add_argument('path', metavar="", help='Trace path') + parser.add_argument('--reset', action="store_true", + help='Destroy and init the database') + args = parser.parse_args() + + traces = TraceCollection() + handle = traces.add_trace(args.path, "ctf") + if handle is None: + sys.exit(1) + + c = Analyzes(traces) + if not os.path.isfile(DB_NAME): + print("Creating the database for the first time") + c.init_db() + elif args.reset: + print("Resetting the database") + c.init_db() + else: + c.connect_db() + + c.run(args) + #c.report() + + traces.remove_trace(handle) -- 2.34.1