utils.py 2.3 KB

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