From c94e590d181b8776d3a8230cef24399fa7c2f080 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 15:52:52 +0200 Subject: [PATCH 01/18] Enhance SQLAlchemyHandler with delay_startup feature Add delay_startup option to SQLAlchemyHandler initialization. --- c2cwsgiutils/sqlalchemylogger/handlers.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 423e4eff6..7566b5ae5 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -33,9 +33,22 @@ def __init__( sqlalchemy_url: dict[str, str], does_not_contain_expression: str = "", contains_expression: str = "", + delay_startup = False, ) -> None: """Initialize the SQLAlchemyHandler.""" super().__init__() + + if delay_startup: + self.sqlalchemy_url = sqlalchemy_url + self.does_not_contain_expression = does_not_contain_expression + self.contains_expression = contains_expression + else: + self._start(sqlalchemy_url, does_not_contain_expression, contains_expression) + + def start(self): + self._start(self.sqlalchemy_url, self.does_not_contain_expression, self.contains_expression) + + def _start(self, sqlalchemy_url, does_not_contain_expression, contains_expression): # Initialize DB session self.engine = create_engine(sqlalchemy_url["url"]) self.Log = create_log_class( # pylint: disable=invalid-name From 1544bdbea5d2d5ec06acb61960f944fac66b4119 Mon Sep 17 00:00:00 2001 From: "geo-ghci-int[bot]" <146321879+geo-ghci-int[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 13:57:41 +0000 Subject: [PATCH 02/18] Apply pre-commit fix From the artifact of the previous workflow run --- c2cwsgiutils/sqlalchemylogger/handlers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 7566b5ae5..b1052faa2 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -33,7 +33,7 @@ def __init__( sqlalchemy_url: dict[str, str], does_not_contain_expression: str = "", contains_expression: str = "", - delay_startup = False, + delay_startup=False, ) -> None: """Initialize the SQLAlchemyHandler.""" super().__init__() @@ -47,7 +47,7 @@ def __init__( def start(self): self._start(self.sqlalchemy_url, self.does_not_contain_expression, self.contains_expression) - + def _start(self, sqlalchemy_url, does_not_contain_expression, contains_expression): # Initialize DB session self.engine = create_engine(sqlalchemy_url["url"]) From 34d82c40dc24ae15bca5fd1ac1dc4f0726ac1c8f Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:04:46 +0200 Subject: [PATCH 03/18] Update README with Gunicorn configuration example Added usage instructions for configuring SQLAlchemyLogger with Gunicorn. --- c2cwsgiutils/sqlalchemylogger/README.md | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index ac4549c41..0ee1195b4 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -63,3 +63,30 @@ if __name__ == '__main__': # logs after a timeout time.sleep(2) ``` + +# Use with forking server (ex: gunicorn) + +snippet for configuration with gunicorn and paste: + +production.ini +``` +[handler_sqlalchemylogger] +class = c2cwsgiutils.sqlalchemylogger.handlers.SQLAlchemyHandler +args = ({'url':'postgresql://','tablename':'logs','tableargs': {'schema':'logs'}, 'delay_start': true},'healthcheck') +level = NOTSET +formatter = generic +propagate = 0 +``` + +gunicorn.conf.py +``` +def post_fork(server, worker): + import logging + logger = logging.getHandlerByName('sqlalchemylogger') + logger.start() +``` + +The gunicorn must be started with this config file: +``` +gunicorn -c gunicorn.conf.py [...] +``` From 355e39dd2a26b0a992ce429394e5b8c177b5b210 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:06:04 +0200 Subject: [PATCH 04/18] Fix condition for delay_startup in SQLAlchemyHandler --- c2cwsgiutils/sqlalchemylogger/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index b1052faa2..5fe62d856 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -38,7 +38,7 @@ def __init__( """Initialize the SQLAlchemyHandler.""" super().__init__() - if delay_startup: + if sqlalchemy_url.get('delay_startup', False): self.sqlalchemy_url = sqlalchemy_url self.does_not_contain_expression = does_not_contain_expression self.contains_expression = contains_expression From 6b751f7a3f35d6ee12cc261d8eacbca060d44534 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:06:28 +0200 Subject: [PATCH 05/18] Fix typo in README for SQLAlchemyHandler args --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index 0ee1195b4..1a6602684 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -72,7 +72,7 @@ production.ini ``` [handler_sqlalchemylogger] class = c2cwsgiutils.sqlalchemylogger.handlers.SQLAlchemyHandler -args = ({'url':'postgresql://','tablename':'logs','tableargs': {'schema':'logs'}, 'delay_start': true},'healthcheck') +args = ({'url':'postgresql://','tablename':'logs','tableargs': {'schema':'logs'}, 'delay_startup': true},'healthcheck') level = NOTSET formatter = generic propagate = 0 From 0488dc2a2f708826d8be49d004711fbc45c37430 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:07:52 +0200 Subject: [PATCH 06/18] Update handlers.py --- c2cwsgiutils/sqlalchemylogger/handlers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 5fe62d856..398370b09 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -33,7 +33,6 @@ def __init__( sqlalchemy_url: dict[str, str], does_not_contain_expression: str = "", contains_expression: str = "", - delay_startup=False, ) -> None: """Initialize the SQLAlchemyHandler.""" super().__init__() From 1857110a3045ac790ec2702e6b418f0482b5a5c6 Mon Sep 17 00:00:00 2001 From: "geo-ghci-int[bot]" <146321879+geo-ghci-int[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 14:09:28 +0000 Subject: [PATCH 07/18] Apply pre-commit fix From the artifact of the previous workflow run --- c2cwsgiutils/sqlalchemylogger/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index 1a6602684..227ee0ec8 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -69,6 +69,7 @@ if __name__ == '__main__': snippet for configuration with gunicorn and paste: production.ini + ``` [handler_sqlalchemylogger] class = c2cwsgiutils.sqlalchemylogger.handlers.SQLAlchemyHandler @@ -79,6 +80,7 @@ propagate = 0 ``` gunicorn.conf.py + ``` def post_fork(server, worker): import logging @@ -87,6 +89,7 @@ def post_fork(server, worker): ``` The gunicorn must be started with this config file: + ``` gunicorn -c gunicorn.conf.py [...] ``` From 4e273b71bee874dac8d070b6b9a88629f2975966 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:33:34 +0200 Subject: [PATCH 08/18] Add startup flag to prevent multiple initializations --- c2cwsgiutils/sqlalchemylogger/handlers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 398370b09..88b0f5153 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -37,6 +37,7 @@ def __init__( """Initialize the SQLAlchemyHandler.""" super().__init__() + self.started = False if sqlalchemy_url.get('delay_startup', False): self.sqlalchemy_url = sqlalchemy_url self.does_not_contain_expression = does_not_contain_expression @@ -48,6 +49,10 @@ def start(self): self._start(self.sqlalchemy_url, self.does_not_contain_expression, self.contains_expression) def _start(self, sqlalchemy_url, does_not_contain_expression, contains_expression): + if self.started: + # only start once + return + # Initialize DB session self.engine = create_engine(sqlalchemy_url["url"]) self.Log = create_log_class( # pylint: disable=invalid-name @@ -67,6 +72,7 @@ def _start(self, sqlalchemy_url, does_not_contain_expression, contains_expressio self.addFilter(DoesNotContainExpression(does_not_contain_expression)) if contains_expression: self.addFilter(ContainsExpression(contains_expression)) + self.started = True def _processor(self) -> None: _LOG.debug("%s: starting processor thread", __name__) From 5f4f8508c2edc81f0e9402a657fc482198dfbc7f Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:34:28 +0200 Subject: [PATCH 09/18] Fix case of 'delay_startup' in README.md production.ini file seems to follow python dict conventions --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index 227ee0ec8..12838f95f 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -73,7 +73,7 @@ production.ini ``` [handler_sqlalchemylogger] class = c2cwsgiutils.sqlalchemylogger.handlers.SQLAlchemyHandler -args = ({'url':'postgresql://','tablename':'logs','tableargs': {'schema':'logs'}, 'delay_startup': true},'healthcheck') +args = ({'url':'postgresql://','tablename':'logs','tableargs': {'schema':'logs'}, 'delay_startup': True},'healthcheck') level = NOTSET formatter = generic propagate = 0 From c5fc7577e6db2b44e719a5307d49ae3dc05c7b04 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:59:11 +0200 Subject: [PATCH 10/18] CI comments for typing Add type hints to start and _start methods --- c2cwsgiutils/sqlalchemylogger/handlers.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 88b0f5153..88817e285 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -45,10 +45,16 @@ def __init__( else: self._start(sqlalchemy_url, does_not_contain_expression, contains_expression) - def start(self): + def start(self) -> None: + """Force startup of logger in case of delayed startup""" self._start(self.sqlalchemy_url, self.does_not_contain_expression, self.contains_expression) - def _start(self, sqlalchemy_url, does_not_contain_expression, contains_expression): + def _start( + self, + sqlalchemy_url: dict[str, str], + does_not_contain_expression: str, + contains_expression: str, + ) -> None: if self.started: # only start once return From 62e9d7dc68695acd227c93808ca8921ae70782a8 Mon Sep 17 00:00:00 2001 From: "geo-ghci-int[bot]" <146321879+geo-ghci-int[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 08:13:40 +0000 Subject: [PATCH 11/18] Apply pre-commit fix From the artifact of the previous workflow run --- c2cwsgiutils/sqlalchemylogger/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 88817e285..41a8003e9 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -38,7 +38,7 @@ def __init__( super().__init__() self.started = False - if sqlalchemy_url.get('delay_startup', False): + if sqlalchemy_url.get("delay_startup", False): self.sqlalchemy_url = sqlalchemy_url self.does_not_contain_expression = does_not_contain_expression self.contains_expression = contains_expression From d7c41f0ae7642ecefcd8c20d4c2338a0efabe9da Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Fri, 24 Jul 2026 11:53:23 +0200 Subject: [PATCH 12/18] Adjust docstring to requirements - full stop needed --- c2cwsgiutils/sqlalchemylogger/handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/handlers.py b/c2cwsgiutils/sqlalchemylogger/handlers.py index 41a8003e9..dbea05102 100644 --- a/c2cwsgiutils/sqlalchemylogger/handlers.py +++ b/c2cwsgiutils/sqlalchemylogger/handlers.py @@ -46,7 +46,7 @@ def __init__( self._start(sqlalchemy_url, does_not_contain_expression, contains_expression) def start(self) -> None: - """Force startup of logger in case of delayed startup""" + """Force startup of logger in case of delayed startup.""" self._start(self.sqlalchemy_url, self.does_not_contain_expression, self.contains_expression) def _start( From 021a2b0f1b16e184cc1b1420a8695d1dbcc24d8b Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:21:47 +0200 Subject: [PATCH 13/18] Update c2cwsgiutils/sqlalchemylogger/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stéphane Brunner --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index 12838f95f..f7c665010 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -81,7 +81,7 @@ propagate = 0 gunicorn.conf.py -``` +```python def post_fork(server, worker): import logging logger = logging.getHandlerByName('sqlalchemylogger') From bba546e0595f3ee5fb7df9e9cee7a2c509a66b6a Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:21:56 +0200 Subject: [PATCH 14/18] Update c2cwsgiutils/sqlalchemylogger/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stéphane Brunner --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index f7c665010..70d71fb15 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -64,7 +64,7 @@ if __name__ == '__main__': time.sleep(2) ``` -# Use with forking server (ex: gunicorn) +## Use with forking server (ex: `gunicorn`) snippet for configuration with gunicorn and paste: From 5fbf37839cc4414e6b2452ff0f036cd9290d6b45 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:22:05 +0200 Subject: [PATCH 15/18] Update c2cwsgiutils/sqlalchemylogger/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stéphane Brunner --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index 70d71fb15..688f77af0 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -66,7 +66,7 @@ if __name__ == '__main__': ## Use with forking server (ex: `gunicorn`) -snippet for configuration with gunicorn and paste: +Snippet for configuration with `gunicorn` and `paste`: production.ini From 9fe1ae03a433b973f8dcd9d340631b794a389529 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:22:15 +0200 Subject: [PATCH 16/18] Update c2cwsgiutils/sqlalchemylogger/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stéphane Brunner --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index 688f77af0..e6362d72b 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -79,7 +79,7 @@ formatter = generic propagate = 0 ``` -gunicorn.conf.py +`gunicorn.conf.py`: ```python def post_fork(server, worker): From bdfc1e0a8bf1f000a6e1e2581ddb6a084135e672 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:22:25 +0200 Subject: [PATCH 17/18] Update c2cwsgiutils/sqlalchemylogger/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stéphane Brunner --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index e6362d72b..a70ed1bfd 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -90,6 +90,6 @@ def post_fork(server, worker): The gunicorn must be started with this config file: -``` +```bash gunicorn -c gunicorn.conf.py [...] ``` From 113580c0a38b423175459180d127ca89b150dff2 Mon Sep 17 00:00:00 2001 From: Moritz Kirmse <61978301+mki-c2c@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:22:44 +0200 Subject: [PATCH 18/18] Update c2cwsgiutils/sqlalchemylogger/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Stéphane Brunner --- c2cwsgiutils/sqlalchemylogger/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c2cwsgiutils/sqlalchemylogger/README.md b/c2cwsgiutils/sqlalchemylogger/README.md index a70ed1bfd..2e49b9c43 100644 --- a/c2cwsgiutils/sqlalchemylogger/README.md +++ b/c2cwsgiutils/sqlalchemylogger/README.md @@ -68,7 +68,7 @@ if __name__ == '__main__': Snippet for configuration with `gunicorn` and `paste`: -production.ini +`production.ini`: ``` [handler_sqlalchemylogger]