Пример #1
0
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)