Page MenuHomeSoftware Heritage

D2418.id8563.diff
No OneTemporary

D2418.id8563.diff

diff --git a/requirements-http.txt b/requirements-http.txt
--- a/requirements-http.txt
+++ b/requirements-http.txt
@@ -7,3 +7,4 @@
msgpack > 0.5
python-dateutil
requests
+blinker # dependency of sentry-sdk[flask]
diff --git a/swh/core/api/gunicorn_config.py b/swh/core/api/gunicorn_config.py
new file mode 100644
--- /dev/null
+++ b/swh/core/api/gunicorn_config.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2019 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+"""Default values for gunicorn's configuration.
+
+Other packages may override them by importing `*` from this module
+and redefining functions and variables they want.
+
+May be imported by gunicorn using
+`--config 'python:swh.core.api.gunicorn_config'`."""
+
+import os
+
+
+def _init_sentry(
+ sentry_dsn, *, flask=True, integrations=None, extra_kwargs={}):
+ import sentry_sdk
+
+ integrations = integrations or []
+
+ if flask:
+ from sentry_sdk.integrations.flask import FlaskIntegration
+ integrations.append(FlaskIntegration())
+
+ sentry_sdk.init(
+ dsn=sentry_dsn,
+ integrations=integrations,
+ debug=bool(os.environ.get('SWH_SENTRY_DEBUG')),
+ **extra_kwargs,
+ )
+
+
+def post_fork(
+ server, worker, *, default_sentry_dsn=None, flask=True,
+ sentry_integrations=None, extra_sentry_kwargs={}):
+
+ # Initializes sentry as soon as possible in gunicorn's worker processes.
+ sentry_dsn = os.environ.get('SWH_SENTRY_DSN', default_sentry_dsn)
+ if sentry_dsn:
+ _init_sentry(
+ sentry_dsn, flask=flask, integrations=sentry_integrations,
+ extra_kwargs=extra_sentry_kwargs)
diff --git a/swh/core/api/tests/test_gunicorn.py b/swh/core/api/tests/test_gunicorn.py
new file mode 100644
--- /dev/null
+++ b/swh/core/api/tests/test_gunicorn.py
@@ -0,0 +1,77 @@
+# Copyright (C) 2019 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+import os
+from unittest.mock import patch
+
+import swh.core.api.gunicorn_config as gunicorn_config
+
+
+def test_post_fork_default():
+ with patch('sentry_sdk.init') as sentry_sdk_init:
+ gunicorn_config.post_fork(None, None)
+
+ sentry_sdk_init.assert_not_called()
+
+
+def test_post_fork_with_dsn_env():
+ flask_integration = object() # unique object to check for equality
+ with patch('sentry_sdk.integrations.flask.FlaskIntegration',
+ new=lambda: flask_integration):
+ with patch('sentry_sdk.init') as sentry_sdk_init:
+ with patch.dict(os.environ, {'SWH_SENTRY_DSN': 'test_dsn'}):
+ gunicorn_config.post_fork(None, None)
+
+ sentry_sdk_init.assert_called_once_with(
+ dsn='test_dsn',
+ integrations=[flask_integration],
+ debug=False,
+ )
+
+
+def test_post_fork_debug():
+ flask_integration = object() # unique object to check for equality
+ with patch('sentry_sdk.integrations.flask.FlaskIntegration',
+ new=lambda: flask_integration):
+ with patch('sentry_sdk.init') as sentry_sdk_init:
+ with patch.dict(os.environ, {'SWH_SENTRY_DSN': 'test_dsn',
+ 'SWH_SENTRY_DEBUG': '1'}):
+ gunicorn_config.post_fork(None, None)
+
+ sentry_sdk_init.assert_called_once_with(
+ dsn='test_dsn',
+ integrations=[flask_integration],
+ debug=True,
+ )
+
+
+def test_post_fork_no_flask():
+ with patch('sentry_sdk.init') as sentry_sdk_init:
+ with patch.dict(os.environ, {'SWH_SENTRY_DSN': 'test_dsn'}):
+ gunicorn_config.post_fork(None, None, flask=False)
+
+ sentry_sdk_init.assert_called_once_with(
+ dsn='test_dsn',
+ integrations=[],
+ debug=False,
+ )
+
+
+def test_post_fork_extras():
+ flask_integration = object() # unique object to check for equality
+ with patch('sentry_sdk.integrations.flask.FlaskIntegration',
+ new=lambda: flask_integration):
+ with patch('sentry_sdk.init') as sentry_sdk_init:
+ with patch.dict(os.environ, {'SWH_SENTRY_DSN': 'test_dsn'}):
+ gunicorn_config.post_fork(
+ None, None, sentry_integrations=['foo'],
+ extra_sentry_kwargs={'bar': 'baz'})
+
+ sentry_sdk_init.assert_called_once_with(
+ dsn='test_dsn',
+ integrations=['foo', flask_integration],
+ debug=False,
+ bar='baz',
+ )

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 14, 7:19 AM (10 h, 44 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3222314

Event Timeline