utils.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import asyncio
  2. import time
  3. from datetime import timedelta
  4. from ssl import SSLError
  5. import aiohttp
  6. from aiohttp.client_exceptions import ClientConnectorError
  7. from .constants import MonitorCheckReason, MonitorType
  8. DEFAULT_TIMEOUT = 30
  9. DEFAULT_PING_TIMEOUT = 30
  10. DEFAULT_AIOHTTP_TIMEOUT = aiohttp.ClientTimeout(total=DEFAULT_TIMEOUT)
  11. PING_AIOHTTP_TIMEOUT = aiohttp.ClientTimeout(total=DEFAULT_PING_TIMEOUT)
  12. async def process_response(monitor, response):
  13. if response.status == monitor["expected_status"]:
  14. if monitor["expected_body"]:
  15. if monitor["expected_body"] in await response.text():
  16. monitor["is_up"] = True
  17. else:
  18. monitor["reason"] = MonitorCheckReason.BODY
  19. else:
  20. monitor["is_up"] = True
  21. else:
  22. monitor["reason"] = MonitorCheckReason.STATUS
  23. async def fetch(session, monitor):
  24. url = monitor["url"]
  25. monitor["is_up"] = False
  26. start = time.monotonic()
  27. try:
  28. if monitor["monitor_type"] == MonitorType.PING:
  29. async with session.head(url, timeout=PING_AIOHTTP_TIMEOUT):
  30. monitor["is_up"] = True
  31. elif monitor["monitor_type"] == MonitorType.GET:
  32. async with session.get(url, timeout=DEFAULT_AIOHTTP_TIMEOUT) as response:
  33. await process_response(monitor, response)
  34. elif monitor["monitor_type"] == MonitorType.POST:
  35. async with session.post(url, timeout=DEFAULT_AIOHTTP_TIMEOUT) as response:
  36. await process_response(monitor, response)
  37. monitor["response_time"] = timedelta(seconds=time.monotonic() - start)
  38. except SSLError:
  39. monitor["reason"] = MonitorCheckReason.SSL
  40. except asyncio.TimeoutError:
  41. monitor["reason"] = MonitorCheckReason.TIMEOUT
  42. except ClientConnectorError:
  43. monitor["reason"] = MonitorCheckReason.NETWORK
  44. except OSError:
  45. monitor["reason"] = MonitorCheckReason.UNKNOWN
  46. return monitor
  47. async def fetch_all(monitors, loop):
  48. async with aiohttp.ClientSession(loop=loop) as session:
  49. results = await asyncio.gather(
  50. *[fetch(session, monitor) for monitor in monitors], return_exceptions=True
  51. )
  52. return results