class ZabbixAnomaly(object): items = {} anom = None datum = None hostid = "" dgetter = None alarm_on = False def __init__(self, hostid): self.hostid = hostid self.load_items() self.dgetter = DataGetter() self.set_anom() self.alarm_on = False def set_anom(self): host = confget("jubatus_server", "host") port = int(confget("jubatus_server", "port")) name = confget("jubatus_server", "name") self.anom = client.Anomaly(host, port, name) def load_items(self): strsql = "select itemid, valuesize from target_items where hostid = \'%s\' and enabled = 1;" % (self.hostid) data = self.exec_selsql(strsql) items = {} for row in data: itemid = str(row[0]) valuesize = row[1] self.items[itemid] = Item(itemid, valuesize) def norm(self, itemid, value): return self.items[str(itemid)].norm_value(value) def learn(self, endclock): self._run_anomaly(endclock, "add") def detect(self, endclock): self._run_anomaly(endclock, "calc") # method="add"|"calc" def _run_anomaly(self, endclock, method="add"): # Prepare data if method == "add": g_data = self.dgetter.g_get_history(endclock) if method == "calc": g_data = self.dgetter.g_copy_history(endclock) datadict = {} for row in g_data: (itemid, clock, value) = row itemid = str(itemid) if datadict.has_key(itemid): self._juba_proc(clock, datadict, method) datadict = {} if not datadict.has_key(self.hostid): (hour, weekday) = self.expand_clock(clock) datadict["hostid"] = self.hostid datadict["weekday"] = weekday*1.0/7 datadict["hour"] = hour*1.0/24 datadict[itemid] = value if len(datadict) > 0: self._juba_proc(clock, datadict, method) if method=="add": cf.log("Saving learned model") self.anom.save("latest") self.dgetter.remove_history(endclock) def _juba_proc(self, clock, datadict, method="add"): #if DEBUG: # print datadict datum = Datum() for k in datadict.keys(): #print "key:%s value:%s" % (str(k), str(datadict[k])) if k == "hostid": datum.add_number(str(k), int(datadict[k])*1.0/ZBX_ITEMID_DIGITS) elif k == "weekday" or k == "hour": datum.add_number(str(k), datadict[k]) elif k != "hostid" and k != "weekday" and k != "hour": datum.add_number(str(k), self.norm(k, datadict[k])) #print datum retry_cnt = JUBA_RETRY_MAX while True: try: if method=="add": print datum ret = self.anom.add(datum) exit() if method=="calc": print datum score = self.anom.calc_score(datum) if score == float('Inf') or score > ML_LIMIT: #print datadict if self.alarm_on == False: self.alarm_on = True cf.log("[%s] score=%f" % (cf.clock2strjst(clock), score)) else: if self.alarm_on == True: self.alarm_on = False cf.log("[%s] score recovered to normal:score=%f" % (cf.clock2strjst(clock), score)) break except (msgpackrpc.error.TransportError, msgpackrpc.error.TimeoutError) as e: retry_count -= 1 if retry_count <= 0: raise self.anom.get_client().close() self.set_anom() print e time.sleep(JUBA_RETRY_INTERVAL) continue def expand_clock(self, clock): d = cf.clock2datetime(clock) hour = d.hour weekday = d.weekday() return (hour, weekday) def exec_selsql(self, strsql): return sf.exec_selsql(MYSQL_JUBATUS, strsql)