import matplotlib as mt import matplotlib.pyplot as plt class Graph: def __init__(self, key): self.key = key self.data = None # internal data structure modified and used by self.process and self.draw # increment dictionary entry by val, initially setting to default if it does not exist def inc(self, rel: dict, key, val=1, default=0): self.validate(rel, key, default) rel[key] += val # check if key exists in rel. if not init it def validate(self, rel: dict, key, default=0): if key not in rel: rel[key] = default # called for every line in the log file. returns any error messages def process(self, ip, time, request, size, location, log): raise NotImplementedError() # create and save graph from self.data def draw(self, path): raise NotImplementedError() _COLORS = {} # given a set of labels, assign/get a consistent color scheme # used to ensure that every label has a consistent color that is persisted across graphs def getColors(self, names, category='country'): if category not in Graph._COLORS: # as func to get infinite cycle Graph._COLORS[category] = {'_cycle': iter(mt.cycler(plt.rcParams['axes.prop_cycle'])())} out = [] c = Graph._COLORS[category] for n in names: if n not in c: c[n] = next(c['_cycle'])['color'] out.append(c[n]) return out # called at end of program to recycle any memory, if needed def close(self): pass