Example #1
0
class CarbonSender(Service):
    host = "127.0.0.1"          # type: str
    port = 2003                 # type: int
    send_interval = 5           # type: int
    protocol = "udp"            # type: str
    namespace = ("",)           # type: t.Iterable[str]
    storage = TotalStorage
    _handle = None              # type: PeriodicCallback

    async def start(self) -> None:
        namespace = ".".join(
            strip_carbon_ns(item) for item in self.namespace
        )

        client = PROTOCOLS[self.protocol](
            self.host,
            self.port,
            namespace=namespace,
            storage=self.storage(),
        )

        set_client(client)

        self._handle = PeriodicCallback(client.send)
        self._handle.start(self.send_interval, loop=self.loop)
        log.info(
            "Periodic carbon metrics sender started. Send to %s://%s:%d with "
            "interval %rs", self.protocol, self.host, self.port,
            self.send_interval,
        )

    async def stop(self, exc: Exception = None) -> None:
        self._handle.stop()
Example #2
0
    async def start(self) -> None:
        addr = self._get_socket_addr()
        if addr is None:
            log.debug(
                "NOTIFY_SOCKET not exported. Skipping service %r",
                self,
            )
            return None

        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
        self.socket.connect(addr)
        self.socket.setblocking(False)

        await self._send("STATUS=starting")

        if self.watchdog_interval is None:
            return

        if self.watchdog_interval != WATCHDOG_INTERVAL:
            watchdog_usec = int(self.watchdog_interval * 1000000)
            await self._send(f"WATCHDOG_USEC={watchdog_usec}")

        self.start_event.set()
        self._watchdog_timer = PeriodicCallback(
            self._send,
            "WATCHDOG=1",
        )
        # Send notifications twice as often
        self._watchdog_timer.start(self.watchdog_interval / 2)

        # Removing signals from entrypoint factory because the currently
        # running entrypoint instance has been cloned the signals.
        entrypoint.POST_START.disconnect(self._post_start)
        entrypoint.PRE_STOP.disconnect(self._pre_stop)
Example #3
0
class RespawningProcessService(ProcessService, ABC):
    process_poll_timeout: int = 5

    _supervisor: PeriodicCallback

    async def __supervise(self) -> None:
        if not hasattr(self, "process"):
            return

        if await self.loop.run_in_executor(None, self.process.is_alive):
            return

        log.info(
            "Process in service %r exited with code %r, respawning.",
            self,
            self.process.exitcode,
        )
        await super().start()

    async def start(self) -> None:
        await super().start()
        self._supervisor = PeriodicCallback(self.__supervise)
        self._supervisor.start(self.process_poll_timeout, )

    async def stop(self, exception: Exception = None) -> Any:
        await self._supervisor.stop()
        await super().stop(exception)
Example #4
0
class CarbonSender(Service):
    host = '127.0.0.1'  # type: str
    port = 2003  # type: int
    send_interval = 5  # type: int
    protocol = 'udp'  # type: str
    namespace = ''  # type: List[str]
    storage = TotalStorage
    _handle = None  # type: PeriodicCallback

    async def start(self):
        namespace = ".".join(strip_carbon_ns(item) for item in self.namespace)

        client = PROTOCOLS[self.protocol](
            self.host,
            self.port,
            namespace=namespace,
            storage=self.storage(),
        )

        set_client(client)

        self._handle = PeriodicCallback(client.send)
        self._handle.start(self.send_interval, loop=self.loop)
        log.info(
            'Periodic carbon metrics sender started. Send to %s://%s:%d with '
            'interval %rs', self.protocol, self.host, self.port,
            self.send_interval)

    async def stop(self, *_):
        self._handle.stop()
Example #5
0
async def test_shield(event_loop):
    counter = 0

    async def task():
        nonlocal counter
        counter += 1
        await asyncio.sleep(2)

    periodic = PeriodicCallback(task)
    periodic.start(0.1, event_loop, shield=True)

    await asyncio.sleep(0)

    with pytest.raises(asyncio.CancelledError):
        await periodic.stop()

    assert counter == 1

    # No shield
    counter = 0
    periodic = PeriodicCallback(task)
    periodic.start(0.1, event_loop, shield=False)

    await asyncio.sleep(0)

    with pytest.raises(asyncio.CancelledError):
        await periodic.stop()

    assert counter == 0
Example #6
0
    async def start(self):
        namespace = ".".join(strip_carbon_ns(item) for item in self.namespace)

        client = PROTOCOLS[self.protocol](self.host,
                                          self.port,
                                          namespace=namespace,
                                          storage=self.storage(),
                                          loop=self.loop)

        set_client(client)

        self._handle = PeriodicCallback(client.send)
        self._handle.start(self.send_interval, loop=self.loop)
        log.info(
            'Periodic carbon metrics sender started. Send to %s://%s:%d with '
            'interval %rs', self.protocol, self.host, self.port,
            self.send_interval)
Example #7
0
File: log.py Project: Pehat/aiomisc
def wrap_logging_handler(handler: logging.Handler,
                         loop: asyncio.AbstractEventLoop = None,
                         buffer_size: int = 1024,
                         flush_interval: float = 0.1):
    loop = loop or asyncio.get_event_loop()

    buffered_handler = AsyncMemoryHandler(buffer_size, target=handler)

    periodic = PeriodicCallback(buffered_handler.flush_async)
    loop.call_soon_threadsafe(periodic.start, flush_interval, loop)

    return buffered_handler
Example #8
0
async def test_long_func(event_loop):
    counter = 0

    async def task():
        nonlocal counter
        counter += 1
        await asyncio.sleep(0.5)

    periodic = PeriodicCallback(task)
    periodic.start(0.1, event_loop)

    await asyncio.sleep(1, loop=event_loop)
    periodic.stop()

    assert 1 < counter < 3
Example #9
0
async def test_periodic(event_loop):
    counter = 0

    def task():
        nonlocal counter
        counter += 1

    periodic = PeriodicCallback(task)
    periodic.start(0.1, event_loop)

    await asyncio.sleep(0.5, loop=event_loop)
    periodic.stop()

    assert 4 < counter < 7

    await asyncio.sleep(0.5, loop=event_loop)

    assert 4 < counter < 7
Example #10
0
class SDWatchdogService(Service):
    socket: socket.socket
    watchdog_interval: Optional[TimeoutType]
    _watchdog_timer: PeriodicCallback

    async def _send(self, payload: str) -> None:
        try:
            await self.loop.sock_sendall(
                self.socket,
                payload.encode(),
            )
        except (ConnectionError, OSError) as e:
            log.warning("SystemD notify socket communication problem: %r", e)

    async def _post_start(self, services: Tuple[Service, ...],
                          **__: Any) -> None:
        if not hasattr(self, "socket"):
            return

        await self._send(f"STATUS=Started {len(services)} services")
        await self._send("READY=1")

    async def _pre_stop(self, *_: Any, **__: Any) -> None:
        if not hasattr(self, "socket"):
            return
        await self._send("STOPPING=1")

    def __init__(self,
                 *,
                 watchdog_interval: Optional[TimeoutType] = WATCHDOG_INTERVAL,
                 **kwargs: Any):
        self.watchdog_interval = watchdog_interval
        entrypoint.POST_START.connect(self._post_start)
        entrypoint.PRE_STOP.connect(self._pre_stop)
        super().__init__(**kwargs)

    @staticmethod
    def _get_socket_addr() -> Optional[str]:
        addr = os.getenv("NOTIFY_SOCKET")
        if addr is None:
            return None

        if addr[0] == "@":
            addr = "\0" + addr[1:]

        return addr

    async def start(self) -> None:
        addr = self._get_socket_addr()
        if addr is None:
            log.debug(
                "NOTIFY_SOCKET not exported. Skipping service %r",
                self,
            )
            return None

        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
        self.socket.connect(addr)
        self.socket.setblocking(False)

        await self._send("STATUS=starting")

        if self.watchdog_interval is None:
            return

        if self.watchdog_interval != WATCHDOG_INTERVAL:
            watchdog_usec = int(self.watchdog_interval * 1000000)
            await self._send(f"WATCHDOG_USEC={watchdog_usec}")

        self.start_event.set()
        self._watchdog_timer = PeriodicCallback(
            self._send,
            "WATCHDOG=1",
        )
        # Send notifications twice as often
        self._watchdog_timer.start(self.watchdog_interval / 2)

        # Removing signals from entrypoint factory because the currently
        # running entrypoint instance has been cloned the signals.
        entrypoint.POST_START.disconnect(self._post_start)
        entrypoint.PRE_STOP.disconnect(self._pre_stop)

    async def stop(self, exception: Exception = None) -> Any:
        await self._watchdog_timer.stop()
Example #11
0
 async def start(self) -> None:
     await super().start()
     self._supervisor = PeriodicCallback(self.__supervise)
     self._supervisor.start(self.process_poll_timeout, )