You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
11 KiB

4 years ago
  1. from types import SimpleNamespace
  2. import attr
  3. from multidict import CIMultiDict
  4. from yarl import URL
  5. from .client_reqrep import ClientResponse
  6. from .signals import Signal
  7. __all__ = (
  8. 'TraceConfig', 'TraceRequestStartParams', 'TraceRequestEndParams',
  9. 'TraceRequestExceptionParams', 'TraceConnectionQueuedStartParams',
  10. 'TraceConnectionQueuedEndParams', 'TraceConnectionCreateStartParams',
  11. 'TraceConnectionCreateEndParams', 'TraceConnectionReuseconnParams',
  12. 'TraceDnsResolveHostStartParams', 'TraceDnsResolveHostEndParams',
  13. 'TraceDnsCacheHitParams', 'TraceDnsCacheMissParams',
  14. 'TraceRequestRedirectParams',
  15. 'TraceRequestChunkSentParams', 'TraceResponseChunkReceivedParams',
  16. )
  17. class TraceConfig:
  18. """First-class used to trace requests launched via ClientSession
  19. objects."""
  20. def __init__(self, trace_config_ctx_factory=SimpleNamespace):
  21. self._on_request_start = Signal(self)
  22. self._on_request_chunk_sent = Signal(self)
  23. self._on_response_chunk_received = Signal(self)
  24. self._on_request_end = Signal(self)
  25. self._on_request_exception = Signal(self)
  26. self._on_request_redirect = Signal(self)
  27. self._on_connection_queued_start = Signal(self)
  28. self._on_connection_queued_end = Signal(self)
  29. self._on_connection_create_start = Signal(self)
  30. self._on_connection_create_end = Signal(self)
  31. self._on_connection_reuseconn = Signal(self)
  32. self._on_dns_resolvehost_start = Signal(self)
  33. self._on_dns_resolvehost_end = Signal(self)
  34. self._on_dns_cache_hit = Signal(self)
  35. self._on_dns_cache_miss = Signal(self)
  36. self._trace_config_ctx_factory = trace_config_ctx_factory
  37. def trace_config_ctx(self, trace_request_ctx=None):
  38. """ Return a new trace_config_ctx instance """
  39. return self._trace_config_ctx_factory(
  40. trace_request_ctx=trace_request_ctx)
  41. def freeze(self):
  42. self._on_request_start.freeze()
  43. self._on_request_chunk_sent.freeze()
  44. self._on_response_chunk_received.freeze()
  45. self._on_request_end.freeze()
  46. self._on_request_exception.freeze()
  47. self._on_request_redirect.freeze()
  48. self._on_connection_queued_start.freeze()
  49. self._on_connection_queued_end.freeze()
  50. self._on_connection_create_start.freeze()
  51. self._on_connection_create_end.freeze()
  52. self._on_connection_reuseconn.freeze()
  53. self._on_dns_resolvehost_start.freeze()
  54. self._on_dns_resolvehost_end.freeze()
  55. self._on_dns_cache_hit.freeze()
  56. self._on_dns_cache_miss.freeze()
  57. @property
  58. def on_request_start(self):
  59. return self._on_request_start
  60. @property
  61. def on_request_chunk_sent(self):
  62. return self._on_request_chunk_sent
  63. @property
  64. def on_response_chunk_received(self):
  65. return self._on_response_chunk_received
  66. @property
  67. def on_request_end(self):
  68. return self._on_request_end
  69. @property
  70. def on_request_exception(self):
  71. return self._on_request_exception
  72. @property
  73. def on_request_redirect(self):
  74. return self._on_request_redirect
  75. @property
  76. def on_connection_queued_start(self):
  77. return self._on_connection_queued_start
  78. @property
  79. def on_connection_queued_end(self):
  80. return self._on_connection_queued_end
  81. @property
  82. def on_connection_create_start(self):
  83. return self._on_connection_create_start
  84. @property
  85. def on_connection_create_end(self):
  86. return self._on_connection_create_end
  87. @property
  88. def on_connection_reuseconn(self):
  89. return self._on_connection_reuseconn
  90. @property
  91. def on_dns_resolvehost_start(self):
  92. return self._on_dns_resolvehost_start
  93. @property
  94. def on_dns_resolvehost_end(self):
  95. return self._on_dns_resolvehost_end
  96. @property
  97. def on_dns_cache_hit(self):
  98. return self._on_dns_cache_hit
  99. @property
  100. def on_dns_cache_miss(self):
  101. return self._on_dns_cache_miss
  102. @attr.s(frozen=True, slots=True)
  103. class TraceRequestStartParams:
  104. """ Parameters sent by the `on_request_start` signal"""
  105. method = attr.ib(type=str)
  106. url = attr.ib(type=URL)
  107. headers = attr.ib(type=CIMultiDict)
  108. @attr.s(frozen=True, slots=True)
  109. class TraceRequestChunkSentParams:
  110. """ Parameters sent by the `on_request_chunk_sent` signal"""
  111. chunk = attr.ib(type=bytes)
  112. @attr.s(frozen=True, slots=True)
  113. class TraceResponseChunkReceivedParams:
  114. """ Parameters sent by the `on_response_chunk_received` signal"""
  115. chunk = attr.ib(type=bytes)
  116. @attr.s(frozen=True, slots=True)
  117. class TraceRequestEndParams:
  118. """ Parameters sent by the `on_request_end` signal"""
  119. method = attr.ib(type=str)
  120. url = attr.ib(type=URL)
  121. headers = attr.ib(type=CIMultiDict)
  122. response = attr.ib(type=ClientResponse)
  123. @attr.s(frozen=True, slots=True)
  124. class TraceRequestExceptionParams:
  125. """ Parameters sent by the `on_request_exception` signal"""
  126. method = attr.ib(type=str)
  127. url = attr.ib(type=URL)
  128. headers = attr.ib(type=CIMultiDict)
  129. exception = attr.ib(type=Exception)
  130. @attr.s(frozen=True, slots=True)
  131. class TraceRequestRedirectParams:
  132. """ Parameters sent by the `on_request_redirect` signal"""
  133. method = attr.ib(type=str)
  134. url = attr.ib(type=URL)
  135. headers = attr.ib(type=CIMultiDict)
  136. response = attr.ib(type=ClientResponse)
  137. @attr.s(frozen=True, slots=True)
  138. class TraceConnectionQueuedStartParams:
  139. """ Parameters sent by the `on_connection_queued_start` signal"""
  140. @attr.s(frozen=True, slots=True)
  141. class TraceConnectionQueuedEndParams:
  142. """ Parameters sent by the `on_connection_queued_end` signal"""
  143. @attr.s(frozen=True, slots=True)
  144. class TraceConnectionCreateStartParams:
  145. """ Parameters sent by the `on_connection_create_start` signal"""
  146. @attr.s(frozen=True, slots=True)
  147. class TraceConnectionCreateEndParams:
  148. """ Parameters sent by the `on_connection_create_end` signal"""
  149. @attr.s(frozen=True, slots=True)
  150. class TraceConnectionReuseconnParams:
  151. """ Parameters sent by the `on_connection_reuseconn` signal"""
  152. @attr.s(frozen=True, slots=True)
  153. class TraceDnsResolveHostStartParams:
  154. """ Parameters sent by the `on_dns_resolvehost_start` signal"""
  155. host = attr.ib(type=str)
  156. @attr.s(frozen=True, slots=True)
  157. class TraceDnsResolveHostEndParams:
  158. """ Parameters sent by the `on_dns_resolvehost_end` signal"""
  159. host = attr.ib(type=str)
  160. @attr.s(frozen=True, slots=True)
  161. class TraceDnsCacheHitParams:
  162. """ Parameters sent by the `on_dns_cache_hit` signal"""
  163. host = attr.ib(type=str)
  164. @attr.s(frozen=True, slots=True)
  165. class TraceDnsCacheMissParams:
  166. """ Parameters sent by the `on_dns_cache_miss` signal"""
  167. host = attr.ib(type=str)
  168. class Trace:
  169. """ Internal class used to keep together the main dependencies used
  170. at the moment of send a signal."""
  171. def __init__(self, session, trace_config, trace_config_ctx):
  172. self._trace_config = trace_config
  173. self._trace_config_ctx = trace_config_ctx
  174. self._session = session
  175. async def send_request_start(self, method, url, headers):
  176. return await self._trace_config.on_request_start.send(
  177. self._session,
  178. self._trace_config_ctx,
  179. TraceRequestStartParams(method, url, headers)
  180. )
  181. async def send_request_chunk_sent(self, chunk):
  182. return await self._trace_config.on_request_chunk_sent.send(
  183. self._session,
  184. self._trace_config_ctx,
  185. TraceRequestChunkSentParams(chunk)
  186. )
  187. async def send_response_chunk_received(self, chunk):
  188. return await self._trace_config.on_response_chunk_received.send(
  189. self._session,
  190. self._trace_config_ctx,
  191. TraceResponseChunkReceivedParams(chunk)
  192. )
  193. async def send_request_end(self, method, url, headers, response):
  194. return await self._trace_config.on_request_end.send(
  195. self._session,
  196. self._trace_config_ctx,
  197. TraceRequestEndParams(method, url, headers, response)
  198. )
  199. async def send_request_exception(self, method, url, headers, exception):
  200. return await self._trace_config.on_request_exception.send(
  201. self._session,
  202. self._trace_config_ctx,
  203. TraceRequestExceptionParams(method, url, headers, exception)
  204. )
  205. async def send_request_redirect(self, method, url, headers, response):
  206. return await self._trace_config._on_request_redirect.send(
  207. self._session,
  208. self._trace_config_ctx,
  209. TraceRequestRedirectParams(method, url, headers, response)
  210. )
  211. async def send_connection_queued_start(self):
  212. return await self._trace_config.on_connection_queued_start.send(
  213. self._session,
  214. self._trace_config_ctx,
  215. TraceConnectionQueuedStartParams()
  216. )
  217. async def send_connection_queued_end(self):
  218. return await self._trace_config.on_connection_queued_end.send(
  219. self._session,
  220. self._trace_config_ctx,
  221. TraceConnectionQueuedEndParams()
  222. )
  223. async def send_connection_create_start(self):
  224. return await self._trace_config.on_connection_create_start.send(
  225. self._session,
  226. self._trace_config_ctx,
  227. TraceConnectionCreateStartParams()
  228. )
  229. async def send_connection_create_end(self):
  230. return await self._trace_config.on_connection_create_end.send(
  231. self._session,
  232. self._trace_config_ctx,
  233. TraceConnectionCreateEndParams()
  234. )
  235. async def send_connection_reuseconn(self):
  236. return await self._trace_config.on_connection_reuseconn.send(
  237. self._session,
  238. self._trace_config_ctx,
  239. TraceConnectionReuseconnParams()
  240. )
  241. async def send_dns_resolvehost_start(self, host):
  242. return await self._trace_config.on_dns_resolvehost_start.send(
  243. self._session,
  244. self._trace_config_ctx,
  245. TraceDnsResolveHostStartParams(host)
  246. )
  247. async def send_dns_resolvehost_end(self, host):
  248. return await self._trace_config.on_dns_resolvehost_end.send(
  249. self._session,
  250. self._trace_config_ctx,
  251. TraceDnsResolveHostEndParams(host)
  252. )
  253. async def send_dns_cache_hit(self, host):
  254. return await self._trace_config.on_dns_cache_hit.send(
  255. self._session,
  256. self._trace_config_ctx,
  257. TraceDnsCacheHitParams(host)
  258. )
  259. async def send_dns_cache_miss(self, host):
  260. return await self._trace_config.on_dns_cache_miss.send(
  261. self._session,
  262. self._trace_config_ctx,
  263. TraceDnsCacheMissParams(host)
  264. )