-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from codex-team/feat/flask-support
feat: add flask support
- Loading branch information
Showing
9 changed files
with
268 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Flask integration | ||
|
||
This extension adds support for the [Flask](http://flask.pocoo.org/) web framework. | ||
|
||
## Installation | ||
|
||
```bash | ||
pip install hawkcatcher[flask] | ||
``` | ||
|
||
import Catcher module to your project. | ||
|
||
```python | ||
from hawkcatcher.modules.flask import HawkFlask | ||
``` | ||
|
||
```python | ||
hawk = HawkFlask( | ||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9qZWN0SWQiOiI1ZTZmNWM3NzAzOWI0MDAwMjNmZDViODAiLCJpYXQiOjE1ODQzNTY0NzF9.t-5Gelx3MgHVBrxTsoMyPQAdQ6ufVbPsts9zZLW3gM8") | ||
``` | ||
|
||
Now all global flask errors would be sent to Hawk. | ||
|
||
### Try-except | ||
|
||
If you want to catch errors in try-except blocks see [this](../README.md#try-except) | ||
|
||
## Manual sending | ||
|
||
You can send any error to Hawk. See [this](../README.md#manual-sending) | ||
|
||
### Event context | ||
|
||
See [this](../README.md#event-context) | ||
|
||
### Affected user | ||
|
||
See [this](../README.md#affected-user) | ||
|
||
### Addons | ||
|
||
When some event handled by Flask Catcher, it adds some addons to the event data for Hawk. | ||
|
||
| name | type | description | | ||
| --------- | ---- | ----------------- | | ||
| `url` | str | Request URL | | ||
| `method` | str | Request method | | ||
| `headers` | dict | Request headers | | ||
| `cookies` | dict | Request cookies | | ||
| `params` | dict | Request params | | ||
| `form` | dict | Request form | | ||
| `json` | dict | Request json data | | ||
|
||
## Init params | ||
|
||
To init Hawk Catcher just pass a project token. | ||
|
||
```python | ||
hawk = HawkFlask('1234567-abcd-8901-efgh-123456789012') | ||
``` | ||
|
||
### Additional params | ||
|
||
If you need to use custom Hawk server then pass a dictionary with params. | ||
|
||
```python | ||
hawk = HawkFlask({ | ||
'token': '1234567-abcd-8901-efgh-123456789012', | ||
'collector_endpoint': 'https://<id>.k1.hawk.so', | ||
}) | ||
``` | ||
|
||
Parameters: | ||
|
||
| name | type | required | description | | ||
| -------------------- | ------------------------- | ------------ | ---------------------------------------------------------------------------- | | ||
| `token` | str | **required** | Your project's Integration Token | | ||
| `release` | str | optional | Release name for Suspected Commits feature | | ||
| `collector_endpoint` | string | optional | Collector endpoint for sending event to | | ||
| `context` | dict | optional | Additional context to be send with every event | | ||
| `before_send` | Callable[[dict], None] | optional | This Method allows you to filter any data you don't want sending to Hawk | | ||
| `set_user` | Callable[[Request], User] | optional | This Method allows you to set user for every request by flask request object | | ||
| `with_addons` | bool | optional | Add framework addons to event data | | ||
|
||
## Requirements | ||
|
||
See [this](../README.md#requirements) | ||
|
||
And for flask you need: | ||
|
||
- Flask | ||
- blinker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
class InvalidHawkToken(Exception): | ||
pass | ||
|
||
class ModuleError(Exception): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from .flask import HawkFlask | ||
from .types import HawkCatcherSettings | ||
from .types import FlaskSettings | ||
|
||
hawk = HawkFlask() | ||
|
||
|
||
def init(*args, **kwargs): | ||
hawk.init(*args, **kwargs) | ||
|
||
|
||
def send(*args, **kwargs): | ||
hawk.send(*args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from ...core import Hawk | ||
from typing import Union | ||
from hawkcatcher.modules.flask.types import FlaskSettings, User, Addons | ||
from hawkcatcher.errors import ModuleError | ||
|
||
try: | ||
from flask.signals import got_request_exception | ||
from flask import Flask, request | ||
except ImportError: | ||
raise ModuleError("Flask is not installed") | ||
|
||
# class for catching errors in flask app | ||
class HawkFlask(Hawk): | ||
params: FlaskSettings = {} | ||
|
||
def init(self, settings: Union[str, FlaskSettings] = None) -> None: | ||
self.params = self.get_params(settings) | ||
got_request_exception.connect(self._handle_request_exception) | ||
|
||
@staticmethod | ||
def get_params(settings) -> Union[FlaskSettings, None]: | ||
hawk_params = Hawk.get_params(settings) | ||
|
||
if hawk_params is None: | ||
return None | ||
|
||
return { | ||
**hawk_params, | ||
'set_user': settings.get('set_user'), | ||
'with_addons': settings.get('with_addons', True) | ||
} | ||
|
||
def send(self, exception, context=None, user=None, addons=None): | ||
""" | ||
Method for manually send error to Hawk | ||
:param exception: exception | ||
:param context: additional context to send with error | ||
:param user: user information who faced with that event | ||
""" | ||
if addons is None: | ||
addons = self._set_addons() | ||
|
||
if user is None: | ||
user = self._set_user(request) | ||
|
||
super().send(exception, context, user, addons) | ||
|
||
def _handle_request_exception(self, sender: Flask, exception): | ||
""" | ||
Catch, prepare and send error | ||
:param sender: flask app | ||
:param exception: exception | ||
""" | ||
addons = self._set_addons() | ||
|
||
user = self._set_user(request) | ||
|
||
ctx = self.params.get('context', None) | ||
|
||
self.send(exception, ctx, user, addons) | ||
|
||
def _set_addons(self) -> Union[Addons, None]: | ||
""" | ||
Set flask addons to send with error | ||
""" | ||
addons: Union[Addons, None] = None | ||
|
||
if self.params.get('with_addons') == True: | ||
headers = dict(request.headers) | ||
cookies = dict(request.cookies) | ||
|
||
addons = { | ||
'flask': { | ||
'url': request.url, | ||
'method': request.method, | ||
'headers': headers, | ||
'cookies': cookies, | ||
'params': request.args, | ||
'form': request.form, | ||
'json': request.json | ||
} | ||
} | ||
|
||
return addons | ||
|
||
def _set_user(self, request) -> Union[User, None]: | ||
""" | ||
Set user information by set_user callback | ||
""" | ||
user = None | ||
|
||
if self.params.get('set_user') is not None: | ||
user = self.params['set_user'](request) | ||
|
||
return user | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from hawkcatcher.types import HawkCatcherSettings, User | ||
from typing import Callable, TypedDict | ||
from flask import Request | ||
|
||
class FlaskAddons(TypedDict): | ||
app: str # name of flask app | ||
url: str # url of request | ||
method: str # method of request | ||
headers: dict # headers of request | ||
cookies: dict # cookies of request | ||
params: dict # request params | ||
form: dict # request form data | ||
json: dict # request json data | ||
|
||
class Addons(TypedDict): | ||
flask: FlaskAddons | ||
|
||
class FlaskSettings(HawkCatcherSettings): | ||
"""Settings for Flask catcher for errors tracking""" | ||
|
||
set_user: Callable[[Request], User] # This hook allows you to identify user | ||
with_addons: bool = True # This parameter points if you want to send request data with error (cookies, headers, params, form, json) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,19 @@ | ||
from typing import TypedDict, Callable | ||
|
||
|
||
class User(TypedDict): | ||
"""User data for sending with event""" | ||
|
||
id: str # Internal user's identifier inside an app | ||
name: str # User public name | ||
image: str # User's public picture | ||
url: str # URL for user's details page | ||
|
||
class HawkCatcherSettings(TypedDict): | ||
"""Settings for Hawk catcher for errors tracking""" | ||
|
||
token: str # Hawk integration token | ||
collector_endpoint: str # Collector endpoint for sending event to | ||
release: str # Release name for Suspected Commits feature | ||
before_send: Callable[[dict], None] # This hook allows you to filter any data you don't want sending to Hawk | ||
context: dict # Additional context to be send with event |