def __index_modules(reload=False):
    """Add all modules in module_list."""
    global __modules_data

    if __modules_data and not reload:
        return

    dir_list = sorted(os.listdir(MODULES_PATH))
    nb = 0

    __modules_data.clear()
    for module_name in dir_list:

        if is_disabled(module_name):
            continue

        if '__pycache__' in module_name:
            continue

        __modules_data[module_name] = {
            'disabled': False,
            'instance': None,
            'thread': None
        }
        Log.debug('index "%s" module' % module_name)
        nb += 1

    Log.info('%d modules indexed' % nb)
Esempio n. 2
0
class UpdateToken:
    def __init__(self, config_vk):
        self.log = Log("UpdateToken")

        self.config = config_vk
        self.client_id = self.config.client_id
        self.finished = Event()

    async def __call__(self) -> str:
        async with RedirectServer() as server:
            redirect_address = server.redirect_address

            url = "https://oauth.vk.com/authorize" \
                  f"?client_id={self.client_id}" \
                  "&display=page" \
                  f"&redirect_uri={redirect_address}" \
                  "&scope=friends,wall,offline,groups" \
                  "&response_type=token" \
                  "&v=5.103"

            webbrowser.open_new(url)

            data = await server()

            self.config.token = data['access_token']
            self.config.user_id = data['user_id']

            self.config.update()
            self.log.info("Token updated")

        self.finished.set()
Esempio n. 3
0
        async def x(index):
            log = Log(f"{from_}=>{to_}#{index}")

            retries = retries_

            while True:
                found = False

                async for item in db.choose(M, {FIELD_NAME: from_}, {FIELD_NAME: to_}, limit_=limit):
                    log.info(item=item)
                    processed[(from_, to_)] += 1
                    await asyncio.sleep(sleep_time)
                    found = True

                if found:
                    break

                if retries == 0:
                    return

                retries -= 1

                log.warning(retry=retries_ - retries)

                await asyncio.sleep(sleep_time * sleep_coef)
            log.important("STOP")
def stop_all():
    """Stop all modules."""
    nb = 0

    for module_name in __modules_data.copy():
        if __modules_data[module_name]['instance'] and stop(module_name):
            nb += 1

    Log.info('%d modules stopped' % nb)
def load_config(module_name):
    """Load module config."""
    if is_disabled(module_name):
        return False

    if call(module_name, 'load_config', c_optional_call=True):
        Log.info('start "%s" module' % module_name)
        return True

    return False
def stop(module_name):
    """Stop module."""
    __active_modules_name.remove(module_name)
    Log.info('stop "%s" module' % module_name)

    __modules_data[module_name]['instance'].stopped()
    __modules_data[module_name]['instance'].is_running = False
    __modules_data.pop(module_name)

    return True
Esempio n. 7
0
def stop():
    """Stop daemon."""
    global __is_running

    if not __is_running:
        return

    Log.info('stop deamon')
    __is_running = False
    ModuleManager.stop_all()
    sys.exit(0)
Esempio n. 8
0
class RedirectServer:
    def __init__(self):
        self.log = Log("RedirectServer")

        self.app: web.Application = None
        self.runner: web.AppRunner = None
        self.site: web.TCPSite = None
        self.template: str = None

        self.data = None
        self.data_received = Event()

        self.address = "localhost"
        self.port = randint(8081, 9000)

    @property
    def redirect_address(self):
        return f"{self.address}:{self.port}/redirect"

    async def warm_up(self):
        async with aiofiles.open("vk_utils/redirect_page.html", mode='rt') as f:
            self.template = await f.read()

        self.app = web.Application()
        self.app.add_routes([
            web.get('/redirect', self._handler_get),
            web.post('/redirect', self._handler_post)
        ])

        self.runner = web.AppRunner(self.app)
        await self.runner.setup()
        self.site = web.TCPSite(self.runner, self.address, self.port)
        self.log.info("Start redirect server")
        await self.site.start()

    async def _handler_get(self, request: BaseRequest):
        return web.Response(body=self.template, content_type="text/html")

    async def _handler_post(self, request: BaseRequest):
        path = (await request.json())['answer']
        self.data = dict(item.split('=') for item in path.split("&"))
        self.data_received.set()
        return web.json_response({'status': 'ok'})

    async def __call__(self):
        await self.data_received.wait()
        self.log.info("Data received!")
        return self.data

    async def __aenter__(self):
        await self.warm_up()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        self.log.info("Stopping WebServer")
        await self.site.stop()
        await self.runner.cleanup()
        await self.app.cleanup()
        self.log.info("WebServer stopped")
Esempio n. 9
0
def LoadConfig(file_name: str = None) -> "Config":
    log = Log("LoadConfig")

    file_name = file_name or "private.yaml"

    log.info("Load config", source=file_name)

    with open(file_name, "rt") as f:
        data = yaml.safe_load(f)

    def do_update():
        log.info("Update config file", source=file_name)
        with open(file_name, "wt") as f:
            yaml.safe_dump(data, f)

    return Config(data, do_update, "", source=file_name)
def start(module_name):
    """Start module."""
    if is_disabled(module_name):
        return False

    if module_name not in __modules_data or __modules_data[module_name]['instance'] is None:
        return False

    __modules_data[module_name]['instance'].started()
    __modules_data[module_name]['instance'].is_running = True
    __modules_data[module_name]['thread'] = threading.Thread(
        None,
        __modules_data[module_name]['instance'].run,
        'module: %s' % module_name
    )
    __modules_data[module_name]['thread'].setDaemon(True)
    __modules_data[module_name]['thread'].start()

    __active_modules_name.append(module_name)

    Log.info('start "%s" module' % module_name)
    return True
 def add_info(self, text, *args, **kwargs):
     """Add a message to logger"""
     text = '%s %s: %s' % (self.name_prefix, self.name, text)
     Log.info(text, *args, **kwargs)
def load_config_all():
    """Load all modules config."""
    started = [load_config(module_name) for module_name in __modules_data]
    Log.info('%d modules config loaded' % sum(started))
Esempio n. 13
0
class Monitoring:
    """Класс веб-сервера"""
    API_PATH = "/api"

    def __init__(self, addr, port):
        self.addr = addr
        self.port = port
        self.log = Log(f"Monitoring")
        self._pages: Dict[str, BasePage] = {}

        self.main_page = MainPage("_main", "Info")
        self.add_page(self.main_page)

        self.app: web.Application = None

        self._middleware = []

    def __getitem__(self, item: str) -> BasePage:
        """Возвращает страницу"""
        return self._pages[item]

    def __getattr__(self, item):
        try:
            return super().__getattr__(item)
        except AttributeError:
            return self._pages[item]

    def add_page(self, page: BasePage):
        assert page.id not in self._pages
        self._pages[page.id] = page

    def add_middleware(self, func):
        self._middleware.append(func)

    async def warm_up(self):
        self.log.info("Running", addr=self.addr, port=self.port)
        self.log.important("You can access to monitoring by",
                           addr=f"http://{self.addr}:{self.port}/")

        self.app = web.Application(middlewares=[self.error_middleware])

        self.app.add_routes([
            web.get(f"/", self._get_index),
            web.get(f"{self.API_PATH}/ping", self._get_ping),
            web.get(f"{self.API_PATH}/pages", self._get_pages),
            web.get(f"{self.API_PATH}/page/{{id}}", self._get_page),
        ])

        self.runner = web.AppRunner(self.app)
        await self.runner.setup()
        site = web.TCPSite(self.runner, self.addr, self.port)

        await site.start()
        self.log.info("Server started")
        self.main_page.start_time = time()

    async def shutdown(self):
        self.log.info("Server shutdown")
        await self.runner.shutdown()
        self.log.info("Server cleanup")
        await self.runner.cleanup()
        self.log.info("Server gracefully stopped")

    async def _get_index(self, request):
        async with aiofiles.open("core/monitor/app.html", mode='rt') as f:
            template = await f.read()

        return web.Response(body=template, content_type="text/html")

    async def _get_ping(self, request):
        return web.json_response({'status': 'ok', 'time': time()})

    async def _get_pages(self, request):
        answer_ = []

        for page in self._pages.values():
            answer_.append(page.page_info())

        return web.json_response(answer_)

    async def _get_page(self, request):
        page_id = request.match_info['id']

        # TODO: NotFoundPage
        page = self._pages[page_id]

        return web.json_response(page.to_dict())

    @web.middleware
    async def error_middleware(self, request: Request, handler):
        try:
            for md in self._middleware:
                md(request, handler)

            self.main_page.queries += 1

            response = await handler(request)

            if response.status == 200:
                return response

            message = response.message
        except web.HTTPException as ex:
            self.log.exception(request=request, handler=handler)

            if ex.status != 404:
                raise
            message = ex.reason
        except Exception as e:
            self.log.exception(request=request, handler=handler)
            message = str(e)

        return web.json_response({'status': 'error', 'message': message})
Esempio n. 14
0
class TimeSeries:
    def __init__(self, name: str, ts: InpT, vs: Optional[InpT] = None):
        self.name = name
        self.log = Log(f"TimeSeries:{name}")
        if vs is None:
            self.ts, self.vs = np.unique(ts, return_counts=True)
        else:
            self.ts, self.vs = ts, vs

        assert isinstance(self.ts, np.ndarray)
        assert isinstance(self.vs, np.ndarray)

        assert len(self.ts) == len(self.vs)

    @staticmethod
    def _normalize(t):
        if t is None:
            return t

        if isinstance(t,
                      (int, float, np.int64, np.uint, np.integer, np.float)):
            return t

        if isinstance(t, datetime.datetime):
            return t.timestamp()

        if isinstance(t, datetime.timedelta):
            return t.total_seconds()

        raise TypeError(type(t))

    def __getitem__(self, item: slice) -> "TimeSeries":
        start = self._normalize(item.start or self.ts.min())
        stop = self._normalize(item.stop or self.ts.max())
        step = self._normalize(item.step)

        if item.start or item.stop:
            filter_ = (start <= self.ts) & (self.ts <= stop)
            t, v = self.ts[filter_], self.vs[filter_]
        else:
            t, v = self.ts, self.vs

        if not step:
            return TimeSeries(f"{self.name}[sliced]", t, v)

        count = int((stop - start) / step) or 1

        xi = np.linspace(start, stop, num=count, dtype=int)
        new_v = np.zeros((len(xi) + 1, ), dtype=int)

        indexes = ((t - start) // step).round().astype(int)

        np.add.at(new_v, indexes, v)
        new_v[-2] += new_v[-1]

        return TimeSeries(f"{self.name}[sliced#]", xi, new_v[:-1])

    def min(self):
        index = self.vs.argmin()
        return self.ts[index], self.vs[index]

    def max(self):
        index = self.vs.argmax()
        return self.ts[index], self.vs[index]

    def sum(self):
        return self.vs.sum()

    def cumsum(self):
        return TimeSeries(f"∫({self.name})", self.ts, self.vs.cumsum())

    def __truediv__(self, other: float):
        return TimeSeries(f"{self.name} / {other}", self.ts, self.vs / other)

    def dist(self, ts: "TimeSeries"):
        assert np.array_equal(
            self.ts, ts.ts
        ), "Need identical grid for dist calculation. Use `.dist_grid`"
        dist = np.sum((self.vs - ts.vs)**2)**0.5
        return dist

    def dist_grid(self, ts: "TimeSeries"):
        """Сравнивает, предварительно приведя к одной решетке"""
        tss = np.unique(np.append(self.ts, ts.ts))
        tss.sort()

        start = tss.min()
        stop = tss.max()
        step = np.percentile(np.diff(tss), 50)
        self.log.info("Grid:", start, stop, step)

        self_g = self[start:stop:step]
        ts_g = ts[start:stop:step]

        self_g.dist(ts_g)

    def p(self, percentile: float) -> float:
        """Перцентиль от значений"""
        assert 0 < percentile < 100
        return np.percentile(self.vs, percentile)

    def peaks(self, percentile=95):
        """ Возвращает локальные максимумы выше перцентиля """
        indices, _ = find_peaks(self.vs, height=self.p(percentile))
        for ts, vs in zip(self.ts[indices], self.vs[indices]):
            yield int(ts), float(vs)

    @staticmethod
    def fmt_date(time_stamp: int):
        return datetime.datetime.utcfromtimestamp(time_stamp).strftime(
            '%Y-%m-%dT%H:%M:%SZ')

    def __len__(self):
        return len(self.ts)

    def __eq__(self, other: "TimeSeries"):
        return np.array_equal(self.ts, other.ts) and np.array_equal(
            self.vs, other.vs)

    def __repr__(self):
        from_ = self.ts.min()
        to_ = self.ts.max()

        return f"<TimeSeries of `{self.name}` " \
               f"[{self.fmt_date(from_)} - {self.fmt_date(to_)}] " \
               f"{len(self.ts)} items, " \
               f"∑={self.vs.sum():.2f}" \
               f">"
def restart(module_name):
    """Restart module."""
    Log.info('restart "%s" module' % module_name)
    stop(module_name)
    start(module_name)
Esempio n. 16
0
 def __server_ready(self, server, bind):
     Log.info('Start MoLa network : %s:%d' % bind)
Esempio n. 17
0
 def __server_peer_connect(self, sock, host, port):
     Log.info('Peer connect : %s' % host)
def start_all():
    """Start all modules."""
    started = [start(module_name) for module_name in __modules_data]
    Log.info('%d modules started' % sum(started))
Esempio n. 19
0
 def __server_peer_disconnect(self, sock):
     Log.info('Peer disconect : %s' % str(sock))
Esempio n. 20
0
class BaseWork:
    start_time = time()

    MUTE_EXCEPTION = True

    PARALLEL = 10
    INPUT_RETRIES = 0
    WAIT_COEF = 1

    need_stop = False

    work_ids: Dict[str, int] = {}

    def __init__(self):
        work_name = self.__class__.__name__
        self.log = Log(work_name)

        self.log.debug("Register work")
        self.work_ids.setdefault(work_name, -1)
        self.work_ids[work_name] += 1
        work_id = f"{work_name}_{self.work_ids[work_name]}"
        self.log.debug("Work registered", work_id=work_id)

        self.stat = Stats(work_id, work_name)

        self.log.debug("Run task manager")
        self.task_manager = TasksManager(self.PARALLEL)
        self.tasks: List[TaskInfo] = []

        self.state = "Base class initialized"

    @property
    def state(self):
        return self.stat.state

    @state.setter
    def state(self, value):
        self.stat.state = value
        self.log.debug(self.state)

    async def warm_up(self):
        pass

    async def input(self):
        yield
        raise NotImplementedError()

    async def process(self, item):
        yield
        raise NotImplementedError()

    async def update(self, result):
        raise NotImplementedError()

    async def shutdown(self):
        pass

    async def __call__(self):
        self.state = "🔥 Warming up"
        await self.warm_up()
        self.stat._start_time = time()

        try:
            await self.main_cycle()
        except Exception:
            self.log.exception("MAIN CYCLE")
            if not self.MUTE_EXCEPTION:
                raise

        self.stat.finished_time = time()

        self.state = "🛑 Shutdown"
        await self.shutdown()

        self.state = "🏁 Finished"

    async def main_cycle(self):
        self.state = "⌛️ Ready to start"
        await asyncio.gather(self._input_cycle(), self._result_cycle())

    async def _result_cycle(self):
        while True:
            try:
                result = await asyncio.wait_for(self.task_manager.take(), 1)
            except asyncio.TimeoutError:
                continue

            if isinstance(result, TasksManager.Finish):
                break

            await self.update(result)

            self.stat.updated_items += 1

    async def _input_cycle(self):
        self.stat.retries = 0

        while not self.need_stop:
            self.state = "🔎 Wait for new item"

            async for item in self.input():
                self.stat.input_items += 1
                await self.task_manager.put(self._run_task(TaskInfo(item)))
                self.stat.retries = None

            if self.INPUT_RETRIES == 0:
                # Need to run only one time
                self.need_stop = True
                continue

            if self.stat.retries is None:
                # Item found
                self.stat.retries = 0
                await asyncio.sleep(0)
                continue

            if self.stat.retries >= self.INPUT_RETRIES:
                self.log.warning("Too many retries, i'm done",
                                 retries=self.stat.retries)
                self.need_stop = True
                continue

            # Retry logic
            self.stat.retries += 1
            self.state = f"🔎 Wait items, repeat №{self.stat.retries}"
            await asyncio.sleep(self.stat.retries * self.WAIT_COEF)

        await self.task_manager.stop()

    async def _run_task(self, info: TaskInfo):
        self.tasks.append(info)

        info.update("🎬 Task started")

        info.update(f"🛠 Processing")

        async for result in self.process(info.item):
            self.stat.returned_items += 1
            info.update(f"🛠 {repr(result)}")
            yield result
            info.update(f"🛠 Processing")

        self.stat.processed_items += 1
        info.update("✅ Finish processing")

        if info.processed_callback:
            info.update("🤙 Run callback")

            self.log.info("Run processed callback",
                          processed_callback=info.processed_callback)
            await info.processed_callback

        self.stat.finished_items += 1

        info.update("🏁 Task finished")

        self.tasks.remove(info)

    async def take_error(self):
        return await self.task_manager.take_error()
Esempio n. 21
0
 def __client_peer_disconnect(self, connection_name, hostname, port,
                              client_channel, client_obj):
     Log.info('Disconnected to %s (%s:%d)' % (
         connection_name, hostname, port
     ))
def init_all():
    """Init all modules."""
    __index_modules()
    initialized = [init(module_name) for module_name in __modules_data.copy()]

    Log.info('%d modules initialized' % sum(initialized))