-
Notifications
You must be signed in to change notification settings - Fork 468
Events for web frameworks #2667
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
30a86f2
7872d7f
364e56d
77ab54d
e13bbbc
b78f855
7d0259e
fc12d21
4e43175
63545c7
91a199e
e9dc83e
5bd6cdf
f1653dd
1248e27
9348a26
4569a49
769988f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| from typing import Callable | ||
| from typing import Mapping | ||
| from typing import Optional | ||
| from typing import Type | ||
| from typing import Union | ||
|
|
||
| import attr | ||
|
|
||
| from ddtrace import Span | ||
| from ddtrace import _hooks | ||
| from ddtrace import config | ||
| from ddtrace.internal import compat | ||
|
|
||
|
|
||
| _HOOKS = _hooks.Hooks() | ||
|
|
||
|
|
||
| @attr.s(frozen=True) | ||
| class IntegrationEvent(object): | ||
| """ | ||
| An IntegrationEvent is emitted by an integration (e.g. the flask framework integration) | ||
| and is linked to a span. | ||
| """ | ||
| span = attr.ib(type=Span) | ||
| integration = attr.ib(type=str) | ||
|
|
||
| def emit(self): | ||
| # type: () -> None | ||
| """Alias for emitting this event.""" | ||
| emit(self) | ||
|
|
||
| @classmethod | ||
| def register(cls, func=None): | ||
| # type: (Optional[Callable]) -> Optional[Callable] | ||
| """Alias for registering a listener for this event type.""" | ||
| return register(cls, func=func) | ||
|
|
||
| @classmethod | ||
| def deregister(cls, func): | ||
| # type: (Callable) -> None | ||
| """Alias for deregistering a listener for this event type.""" | ||
| deregister(cls, func) | ||
|
|
||
| if config._raise: | ||
| @span.validator # type: ignore | ||
| def check_span(self, attribute, value): | ||
| assert isinstance(value, Span) | ||
|
|
||
| @integration.validator # type: ignore | ||
| def check_integration(self, attribute, value): | ||
| assert value in config._config | ||
|
|
||
|
|
||
| @attr.s(frozen=True) | ||
| class WebRequest(IntegrationEvent): | ||
| """ | ||
| The WebRequest event is emitted by web framework integrations before the WebResponse event. | ||
| """ | ||
| method = attr.ib(type=str) | ||
| url = attr.ib(type=str) | ||
| headers = attr.ib(type=Mapping[str, str], factory=dict) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to be picky here, but the type is wrong AFAIK.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 agreed! I will apply the changes. |
||
| query = attr.ib(type=Optional[str], default=None) | ||
|
|
||
| if config._raise: | ||
| @method.validator # type: ignore | ||
| def check_method(self, attribute, value): | ||
| assert value in ("HEAD", "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "PROPFIND", "TRACE", "CONNECT") | ||
|
|
||
| @url.validator # type: ignore | ||
| def check_url(self, attribute, value): | ||
| compat.parse.urlparse(value) | ||
|
|
||
|
|
||
| @attr.s(frozen=True) | ||
| class WebResponse(IntegrationEvent): | ||
| """ | ||
| The WebResponse event is emitted by web frameworks after the WebRequest event. | ||
| """ | ||
| status_code = attr.ib(type=Union[int, str]) | ||
| status_msg = attr.ib(type=Optional[str], default=None) | ||
| headers = attr.ib(type=Mapping[str, str], factory=dict) | ||
|
|
||
| if config._raise: | ||
| @status_code.validator # type: ignore | ||
| def check_status_code(self, attribute, value): | ||
| int(value) | ||
|
|
||
|
|
||
| def emit(event): | ||
| # type: (IntegrationEvent) -> None | ||
| """Notify registered listeners about an event.""" | ||
| _HOOKS.emit(event.__class__, event) | ||
|
|
||
|
|
||
| def register(event_type, func=None): | ||
| # type: (Type[IntegrationEvent], Optional[Callable]) -> Optional[Callable] | ||
| """Register a function for a specific event type.""" | ||
| return _HOOKS.register(event_type, func) | ||
|
|
||
|
|
||
| def deregister(event_type, func): | ||
| # type: (Type[IntegrationEvent], Callable) -> None | ||
| """Deregister a function for an event type.""" | ||
| _HOOKS.deregister(event_type, func) | ||
Uh oh!
There was an error while loading. Please reload this page.