c2cwsgiutils 6.1.0.dev105__py3-none-any.whl → 6.1.7.dev4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- c2cwsgiutils/__init__.py +14 -11
- c2cwsgiutils/acceptance/__init__.py +2 -3
- c2cwsgiutils/acceptance/connection.py +1 -2
- c2cwsgiutils/acceptance/image.py +17 -11
- c2cwsgiutils/acceptance/package-lock.json +306 -213
- c2cwsgiutils/acceptance/package.json +2 -2
- c2cwsgiutils/acceptance/print.py +7 -3
- c2cwsgiutils/acceptance/utils.py +1 -3
- c2cwsgiutils/auth.py +27 -25
- c2cwsgiutils/broadcast/__init__.py +15 -16
- c2cwsgiutils/broadcast/interface.py +3 -3
- c2cwsgiutils/broadcast/local.py +1 -0
- c2cwsgiutils/broadcast/redis.py +13 -12
- c2cwsgiutils/client_info.py +19 -1
- c2cwsgiutils/coverage_setup.py +4 -3
- c2cwsgiutils/db.py +35 -41
- c2cwsgiutils/db_maintenance_view.py +13 -13
- c2cwsgiutils/debug/__init__.py +2 -2
- c2cwsgiutils/debug/_listeners.py +2 -7
- c2cwsgiutils/debug/_views.py +20 -12
- c2cwsgiutils/debug/utils.py +9 -9
- c2cwsgiutils/errors.py +13 -15
- c2cwsgiutils/health_check.py +24 -30
- c2cwsgiutils/index.py +34 -13
- c2cwsgiutils/loader.py +21 -2
- c2cwsgiutils/logging_view.py +12 -12
- c2cwsgiutils/models_graph.py +0 -1
- c2cwsgiutils/pretty_json.py +0 -1
- c2cwsgiutils/prometheus.py +1 -7
- c2cwsgiutils/pyramid.py +0 -1
- c2cwsgiutils/pyramid_logging.py +1 -1
- c2cwsgiutils/redis_stats.py +9 -9
- c2cwsgiutils/redis_utils.py +19 -18
- c2cwsgiutils/request_tracking/__init__.py +13 -13
- c2cwsgiutils/request_tracking/_sql.py +0 -1
- c2cwsgiutils/scripts/genversion.py +5 -5
- c2cwsgiutils/scripts/stats_db.py +19 -17
- c2cwsgiutils/scripts/test_print.py +5 -5
- c2cwsgiutils/sentry.py +55 -20
- c2cwsgiutils/services.py +2 -2
- c2cwsgiutils/setup_process.py +0 -1
- c2cwsgiutils/sql_profiler/__init__.py +5 -6
- c2cwsgiutils/sql_profiler/_impl.py +18 -17
- c2cwsgiutils/sqlalchemylogger/README.md +30 -13
- c2cwsgiutils/sqlalchemylogger/handlers.py +12 -11
- c2cwsgiutils/stats_pyramid/__init__.py +1 -5
- c2cwsgiutils/stats_pyramid/_db_spy.py +2 -2
- c2cwsgiutils/stats_pyramid/_pyramid_spy.py +12 -1
- c2cwsgiutils/templates/index.html.mako +4 -1
- c2cwsgiutils/version.py +11 -5
- {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/LICENSE +1 -1
- {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/METADATA +18 -6
- c2cwsgiutils-6.1.7.dev4.dist-info/RECORD +67 -0
- {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/WHEEL +1 -1
- c2cwsgiutils-6.1.0.dev105.dist-info/RECORD +0 -67
- {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/entry_points.txt +0 -0
@@ -2,22 +2,39 @@ This module is used to ship logging records to an SQL database.
|
|
2
2
|
|
3
3
|
Currently only `sqlite` and `postgres_psycopg2` are fully supported.
|
4
4
|
|
5
|
-
To add the
|
5
|
+
To add the handler, setup it directly in your app's main function. You
|
6
|
+
can add it to an existing logger (setup in you `.ini` file),
|
7
|
+
or create a new logger by calling the `logging.getlogger` method.
|
6
8
|
|
9
|
+
```python
|
10
|
+
import logging
|
11
|
+
from c2cwsgiutils.sqlalchemylogger.handlers import SQLAlchemyHandler
|
12
|
+
|
13
|
+
def _setup_sqlalchemy_logger():
|
14
|
+
"""
|
15
|
+
Setup sqlalchemy logger.
|
16
|
+
"""
|
17
|
+
logger = logging.getLogger("A_LOGGER")
|
18
|
+
handler = SQLAlchemyHandler(
|
19
|
+
sqlalchemy_url={
|
20
|
+
# "url": "sqlite:///logger_db.sqlite3",
|
21
|
+
"url": "postgresql://postgres:password@localhost:5432/test",
|
22
|
+
"tablename": "test",
|
23
|
+
"tableargs": {"schema": "xyz"},
|
24
|
+
},
|
25
|
+
does_not_contain_expression="curl",
|
26
|
+
)
|
27
|
+
logger.addHandler(handler)
|
28
|
+
|
29
|
+
def main(_, **settings):
|
30
|
+
_setup_sqlalchemy_logger ()
|
31
|
+
...
|
7
32
|
```
|
8
|
-
[handlers]
|
9
|
-
keys = sqlalchemy_logger
|
10
|
-
|
11
|
-
[handler_sqlalchemy_logger]
|
12
|
-
class = c2cwsgiutils.sqlalchemylogger.handlers.SQLAlchemyHandler
|
13
|
-
#args = ({'url':'sqlite:///logger_db.sqlite3','tablename':'test'},'curl')
|
14
|
-
args = ({'url':'postgresql://postgres:password@localhost:5432/test','tablename':'test','tableargs': {'schema':'xyz'}},'curl')
|
15
|
-
level = NOTSET
|
16
|
-
formatter = generic
|
17
|
-
propagate = 0
|
18
|
-
```
|
19
33
|
|
20
|
-
|
34
|
+
Do not set up this sqlalchemy logger in you `.ini` file directly.
|
35
|
+
It won't work (multi process issue).
|
36
|
+
|
37
|
+
if the given credentials are sufficient, the handler will
|
21
38
|
create the DB, schema and table it needs directly.
|
22
39
|
|
23
40
|
In the above example the second parameter provided `'curl'` is a negative
|
@@ -14,7 +14,7 @@ from sqlalchemy_utils import create_database, database_exists
|
|
14
14
|
from c2cwsgiutils.sqlalchemylogger._filters import ContainsExpression, DoesNotContainExpression
|
15
15
|
from c2cwsgiutils.sqlalchemylogger._models import Base, create_log_class
|
16
16
|
|
17
|
-
|
17
|
+
_LOG = logging.getLogger(__name__)
|
18
18
|
|
19
19
|
|
20
20
|
class SQLAlchemyHandler(logging.Handler):
|
@@ -30,28 +30,28 @@ class SQLAlchemyHandler(logging.Handler):
|
|
30
30
|
contains_expression: str = "",
|
31
31
|
) -> None:
|
32
32
|
super().__init__()
|
33
|
-
#
|
33
|
+
# Initialize DB session
|
34
34
|
self.engine = create_engine(sqlalchemy_url["url"])
|
35
|
-
self.Log = create_log_class(
|
35
|
+
self.Log = create_log_class( # pylint: disable=invalid-name
|
36
36
|
tablename=sqlalchemy_url.get("tablename", "logs"),
|
37
37
|
tableargs=sqlalchemy_url.get("tableargs", None), # type: ignore
|
38
38
|
)
|
39
39
|
Base.metadata.bind = self.engine
|
40
40
|
self.session = sessionmaker(bind=self.engine)() # noqa
|
41
|
-
#
|
41
|
+
# Initialize log queue
|
42
42
|
self.log_queue: Any = queue.Queue()
|
43
|
-
#
|
43
|
+
# Initialize a thread to process the logs Asynchronously
|
44
44
|
self.condition = threading.Condition()
|
45
45
|
self.processor_thread = threading.Thread(target=self._processor, daemon=True)
|
46
46
|
self.processor_thread.start()
|
47
|
-
#
|
47
|
+
# Initialize filters
|
48
48
|
if does_not_contain_expression:
|
49
49
|
self.addFilter(DoesNotContainExpression(does_not_contain_expression))
|
50
50
|
if contains_expression:
|
51
51
|
self.addFilter(ContainsExpression(contains_expression))
|
52
52
|
|
53
53
|
def _processor(self) -> None:
|
54
|
-
|
54
|
+
_LOG.debug("%s: starting processor thread", __name__)
|
55
55
|
while True:
|
56
56
|
logs = []
|
57
57
|
time_since_last = time.perf_counter()
|
@@ -70,7 +70,7 @@ class SQLAlchemyHandler(logging.Handler):
|
|
70
70
|
):
|
71
71
|
self._write_logs(logs)
|
72
72
|
break
|
73
|
-
|
73
|
+
_LOG.debug("%s: stopping processor thread", __name__)
|
74
74
|
|
75
75
|
def _write_logs(self, logs: list[Any]) -> None:
|
76
76
|
try:
|
@@ -85,12 +85,13 @@ class SQLAlchemyHandler(logging.Handler):
|
|
85
85
|
except Exception as e: # pylint: disable=broad-except
|
86
86
|
# if we really cannot commit the log to DB, do not lock the
|
87
87
|
# thread and do not crash the application
|
88
|
-
|
88
|
+
_LOG.critical(e)
|
89
89
|
finally:
|
90
90
|
self.session.expunge_all()
|
91
91
|
|
92
92
|
def create_db(self) -> None:
|
93
|
-
|
93
|
+
"""Create the database if it does not exist."""
|
94
|
+
_LOG.info("%s: creating new database", __name__)
|
94
95
|
if not database_exists(self.engine.url):
|
95
96
|
create_database(self.engine.url)
|
96
97
|
# FIXME: we should not access directly the private __table_args__
|
@@ -101,7 +102,7 @@ class SQLAlchemyHandler(logging.Handler):
|
|
101
102
|
with self.engine.begin() as connection:
|
102
103
|
if not self.engine.dialect.has_schema(connection, self.Log.__table_args__["schema"]):
|
103
104
|
connection.execute(
|
104
|
-
sqlalchemy.schema.CreateSchema(self.Log.__table_args__["schema"]),
|
105
|
+
sqlalchemy.schema.CreateSchema(self.Log.__table_args__["schema"]),
|
105
106
|
)
|
106
107
|
Base.metadata.create_all(self.engine)
|
107
108
|
|
@@ -10,7 +10,6 @@ from c2cwsgiutils.stats_pyramid import _pyramid_spy
|
|
10
10
|
|
11
11
|
def init(config: pyramid.config.Configurator) -> None:
|
12
12
|
"""Initialize the whole stats module, for backward compatibility."""
|
13
|
-
|
14
13
|
warnings.warn("init function is deprecated; use includeme instead")
|
15
14
|
includeme(config)
|
16
15
|
|
@@ -20,17 +19,14 @@ def includeme(config: pyramid.config.Configurator) -> None:
|
|
20
19
|
Initialize the whole stats pyramid module.
|
21
20
|
|
22
21
|
Arguments:
|
23
|
-
|
24
22
|
config: The Pyramid config
|
25
23
|
"""
|
26
|
-
|
27
24
|
_pyramid_spy.init(config)
|
28
25
|
init_db_spy()
|
29
26
|
|
30
27
|
|
31
28
|
def init_db_spy() -> None:
|
32
29
|
"""Initialize the database spy."""
|
33
|
-
|
34
|
-
from . import _db_spy
|
30
|
+
from . import _db_spy # pylint: disable=import-outside-toplevel
|
35
31
|
|
36
32
|
_db_spy.init()
|
@@ -10,7 +10,7 @@ from sqlalchemy.orm import Session
|
|
10
10
|
|
11
11
|
from c2cwsgiutils import prometheus
|
12
12
|
|
13
|
-
|
13
|
+
_LOG = logging.getLogger(__name__)
|
14
14
|
|
15
15
|
_PROMETHEUS_DB_SUMMARY = prometheus_client.Summary(
|
16
16
|
prometheus.build_metric_name("database"),
|
@@ -71,7 +71,7 @@ def _create_sqlalchemy_timer_cb(what: str) -> Callable[..., Any]:
|
|
71
71
|
|
72
72
|
def after(*_args: Any, **_kwargs: Any) -> None:
|
73
73
|
_PROMETHEUS_DB_SUMMARY.labels({"query": what}).observe(time.perf_counter() - start)
|
74
|
-
|
74
|
+
_LOG.debug("Execute statement '%s' in %d.", what, time.perf_counter() - start)
|
75
75
|
|
76
76
|
return after
|
77
77
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import logging
|
1
2
|
import time
|
2
3
|
from typing import Callable, Optional
|
3
4
|
|
@@ -9,6 +10,8 @@ from pyramid.httpexceptions import HTTPException
|
|
9
10
|
|
10
11
|
from c2cwsgiutils import prometheus
|
11
12
|
|
13
|
+
_LOG = logging.getLogger(__name__)
|
14
|
+
|
12
15
|
_PROMETHEUS_PYRAMID_ROUTES_SUMMARY = prometheus_client.Summary(
|
13
16
|
prometheus.build_metric_name("pyramid_routes"),
|
14
17
|
"Pyramid routes",
|
@@ -61,6 +64,15 @@ def _create_finished_cb(
|
|
61
64
|
name = request.matched_route.name
|
62
65
|
if kind == "route":
|
63
66
|
_add_server_metric(request, "route", description=name)
|
67
|
+
if status >= 500:
|
68
|
+
_LOG.warning(
|
69
|
+
"Request %s %s %s route %s return status %s",
|
70
|
+
request.method,
|
71
|
+
request.path,
|
72
|
+
kind,
|
73
|
+
name,
|
74
|
+
status,
|
75
|
+
)
|
64
76
|
measure.labels(
|
65
77
|
method=request.method, route=name, status=status, group=str(status // 100 * 100)
|
66
78
|
).observe(time.process_time() - start)
|
@@ -86,7 +98,6 @@ def init(config: pyramid.config.Configurator) -> None: # pragma: nocover
|
|
86
98
|
Subscribe to Pyramid events in order to get some stats on route time execution.
|
87
99
|
|
88
100
|
Arguments:
|
89
|
-
|
90
101
|
config: The Pyramid config
|
91
102
|
"""
|
92
103
|
config.add_subscriber(_request_callback, pyramid.events.NewRequest)
|
@@ -24,7 +24,7 @@
|
|
24
24
|
crossorigin="anonymous"
|
25
25
|
referrerpolicy="no-referrer"
|
26
26
|
/>
|
27
|
-
<title>
|
27
|
+
<title>C2C WSGI Utils tools</title>
|
28
28
|
<style>
|
29
29
|
body {
|
30
30
|
margin-top: 0.5rem;
|
@@ -32,6 +32,9 @@
|
|
32
32
|
button, p {
|
33
33
|
margin-bottom: 0.5rem;
|
34
34
|
}
|
35
|
+
.row > h2 {
|
36
|
+
margin-top: 1rem;
|
37
|
+
}
|
35
38
|
</style>
|
36
39
|
</head>
|
37
40
|
<body>
|
c2cwsgiutils/version.py
CHANGED
@@ -8,7 +8,7 @@ from typing import Optional, cast
|
|
8
8
|
import prometheus_client
|
9
9
|
import pyramid.config
|
10
10
|
|
11
|
-
from c2cwsgiutils import config_utils, prometheus
|
11
|
+
from c2cwsgiutils import auth, config_utils, prometheus
|
12
12
|
|
13
13
|
_VERSIONS_PATH = "/app/versions.json"
|
14
14
|
_LOG = logging.getLogger(__name__)
|
@@ -41,17 +41,23 @@ def init(config: pyramid.config.Configurator) -> None:
|
|
41
41
|
includeme(config)
|
42
42
|
|
43
43
|
|
44
|
+
class _View:
|
45
|
+
def __init__(self, versions: dict[str, dict[str, str]]) -> None:
|
46
|
+
self.versions = versions
|
47
|
+
|
48
|
+
def __call__(self, request: pyramid.request.Request) -> dict[str, dict[str, str]]:
|
49
|
+
auth.auth_view(request)
|
50
|
+
return self.versions
|
51
|
+
|
52
|
+
|
44
53
|
def includeme(config: pyramid.config.Configurator) -> None:
|
45
54
|
"""Initialize the versions view."""
|
46
|
-
|
47
55
|
if os.path.isfile(_VERSIONS_PATH):
|
48
56
|
versions = _read_versions()
|
49
57
|
config.add_route(
|
50
58
|
"c2c_versions", config_utils.get_base_path(config) + r"/versions.json", request_method="GET"
|
51
59
|
)
|
52
|
-
config.add_view(
|
53
|
-
lambda request: versions, route_name="c2c_versions", renderer="fast_json", http_cache=0
|
54
|
-
)
|
60
|
+
config.add_view(_View(versions), route_name="c2c_versions", renderer="fast_json", http_cache=0)
|
55
61
|
_LOG.info("Installed the /versions.json service")
|
56
62
|
git_hash = versions["main"]["git_hash"]
|
57
63
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: c2cwsgiutils
|
3
|
-
Version: 6.1.
|
3
|
+
Version: 6.1.7.dev4
|
4
4
|
Summary: Common utilities for Camptocamp WSGI applications
|
5
5
|
Home-page: https://github.com/camptocamp/c2cwsgiutils
|
6
6
|
License: BSD-2-Clause
|
7
7
|
Keywords: geo,gis,sqlalchemy,orm,wsgi
|
8
8
|
Author: Camptocamp
|
9
9
|
Author-email: info@camptocamp.com
|
10
|
-
Requires-Python: >=3.
|
10
|
+
Requires-Python: >=3.10
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
12
12
|
Classifier: Environment :: Plugins
|
13
13
|
Classifier: Framework :: Pyramid
|
@@ -17,10 +17,10 @@ Classifier: License :: OSI Approved :: BSD License
|
|
17
17
|
Classifier: Operating System :: OS Independent
|
18
18
|
Classifier: Programming Language :: Python
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
20
|
-
Classifier: Programming Language :: Python :: 3.9
|
21
20
|
Classifier: Programming Language :: Python :: 3.10
|
22
21
|
Classifier: Programming Language :: Python :: 3.11
|
23
22
|
Classifier: Programming Language :: Python :: 3.12
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
24
24
|
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
25
25
|
Classifier: Typing :: Typed
|
26
26
|
Provides-Extra: alembic
|
@@ -64,7 +64,7 @@ Description-Content-Type: text/markdown
|
|
64
64
|
|
65
65
|
# Camptocamp WSGI utilities
|
66
66
|
|
67
|
-
This is a Python 3 library
|
67
|
+
This is a Python 3 library providing common tools for Camptocamp WSGI
|
68
68
|
applications:
|
69
69
|
|
70
70
|
- Provide prometheus metrics
|
@@ -725,11 +725,16 @@ A few other environment variables can be used to tune the info sent with each re
|
|
725
725
|
- `SENTRY_CLIENT_IGNORE_EXCEPTIONS`: list (coma separated) of exceptions to ignore (defaults to SystemExit)
|
726
726
|
- `SENTRY_TAG_...`: to add other custom tags
|
727
727
|
- `SENTRY_LEVEL`: starting from what logging level to send events to Sentry (defaults to ERROR)
|
728
|
-
- `SENTRY_TRACES_SAMPLE_RATE`: The percentage of events to send to sentry in order to compute the performance. Value between 0 and 1
|
728
|
+
- `SENTRY_TRACES_SAMPLE_RATE`: The percentage of events to send to sentry in order to compute the performance. Value between 0 and 1 (default is 0)
|
729
|
+
- `SENTRY_INTEGRATION_LOGGING`: If set to 0, the Sentry integration will not log anything (default is 1)
|
730
|
+
- `SENTRY_INTEGRATION_PYRAMID`: If set to 0, the Sentry integration with Pyramid will not be enabled (default is 1)
|
731
|
+
- `SENTRY_INTEGRATION_SQLALCHEMY`: If set to 0, the Sentry integration with SQLAlchemy will not be enabled (default is 1)
|
732
|
+
- `SENTRY_INTEGRATION_REDIS`: If set to 0, the Sentry integration with Redis will not be enabled (default is 1)
|
733
|
+
- `SENTRY_INTEGRATION_ASYNCIO`: If set to 0, the Sentry integration with asyncio will not be enabled (default is 1)
|
729
734
|
|
730
735
|
# Developer info
|
731
736
|
|
732
|
-
You will need `docker` (>=1.12.0), `docker
|
737
|
+
You will need `docker` (>=1.12.0), `docker compose` and
|
733
738
|
`make` installed on the machine to play with this project.
|
734
739
|
Check available versions of `docker-engine` with
|
735
740
|
`apt-get policy docker-engine` and eventually force install the
|
@@ -758,6 +763,13 @@ To make a release:
|
|
758
763
|
- Add the new branch name in the `.github/workflows/rebuild.yaml` and
|
759
764
|
`.github/workflows/audit.yaml` files.
|
760
765
|
|
766
|
+
## Pserve
|
767
|
+
|
768
|
+
Pserve will not set the headers in the environment then if you are behind a reverse proxy, you will have
|
769
|
+
wrong values in client information, you can force them by using the environment variables:
|
770
|
+
`C2CWSGIUTILS_FORCE_PROTO`, `C2CWSGIUTILS_FORCE_HOST` `C2CWSGIUTILS_FORCE_SERVER_NAME` and
|
771
|
+
`C2CWSGIUTILS_FORCE_REMOTE_ADDR`.
|
772
|
+
|
761
773
|
## Testing
|
762
774
|
|
763
775
|
### Screenshots
|
@@ -0,0 +1,67 @@
|
|
1
|
+
c2cwsgiutils/__init__.py,sha256=HVSc-4O8i2aB0ozEI4AI8Xsb-4S6fAwhl8uRhv-DsFg,4057
|
2
|
+
c2cwsgiutils/acceptance/__init__.py,sha256=TJA1yzmyPujkg80oj-LBj2ueOQVYL8HLW87pejWTIDY,1501
|
3
|
+
c2cwsgiutils/acceptance/connection.py,sha256=yqChhHBpYhQL0Cb7K8FqeP16jg1UtmxGAi6Tw1TXEbI,9783
|
4
|
+
c2cwsgiutils/acceptance/image.py,sha256=Wi4EXDTKZ-uyIIQFn8SpRpUTzbpj5LlCwSkLjcYRGTk,9269
|
5
|
+
c2cwsgiutils/acceptance/package-lock.json,sha256=uiNM1L8_IsK7G8A8f2qKpUF0za-tO6_RvgNN3cEDKwg,47777
|
6
|
+
c2cwsgiutils/acceptance/package.json,sha256=DiJUVhci1sP-qu71s3RzxcsF4GsZdo2ZOUeqX3148ss,101
|
7
|
+
c2cwsgiutils/acceptance/print.py,sha256=qdh6pqlHgkIjUCJxS3rcgpOV4fDk9RxFlkfH5aAwDsQ,2567
|
8
|
+
c2cwsgiutils/acceptance/screenshot.js,sha256=FAJYIWOLJFMm0MNggKzo3mIybtN-VtKLdMzPhQ9pO1g,2041
|
9
|
+
c2cwsgiutils/acceptance/utils.py,sha256=zLvWqqPLBGCzGAtmIqidao66BKmER_Du1AfKCEhoc-I,1892
|
10
|
+
c2cwsgiutils/auth.py,sha256=ljTUPYGpEkkDg6ifOegXS1Q1JlcRth0P5vbMCs7VK6k,9585
|
11
|
+
c2cwsgiutils/broadcast/__init__.py,sha256=mYiTVL34QkJkEjxURlDIE7bmwZaEPT9Lw9zMwbiVtL0,4470
|
12
|
+
c2cwsgiutils/broadcast/interface.py,sha256=AkDT_m0eXTQp3mmMLf9KRtpXnWoVhJpb_UNjCbHM-3I,665
|
13
|
+
c2cwsgiutils/broadcast/local.py,sha256=kQp6OWcRU-nx7uEBAXwdMum_rOz3LSj6fyL_R12QrMY,1139
|
14
|
+
c2cwsgiutils/broadcast/redis.py,sha256=xCcGSr7jr6QdFM-YZzFFaySQis1xKb0HqqbGR8qjSNM,5202
|
15
|
+
c2cwsgiutils/broadcast/utils.py,sha256=0fQZXPu3p_5LEJpGenJwiiMxECQjJhjZBjIkBk8h-ng,272
|
16
|
+
c2cwsgiutils/client_info.py,sha256=rvXQLyhma0kPoWQINwUzrxfG2gGIjQDNrxPUDRGJxpA,3916
|
17
|
+
c2cwsgiutils/config_utils.py,sha256=vkBu-3GQsE94NOBOvT5FE-Ij29EUrKnDsmdUdtu_yzo,1524
|
18
|
+
c2cwsgiutils/coverage_setup.py,sha256=BrdjYUmqYl1C-gHuKA7EI5gbQs8Dtdeb2eZKtzr-5L0,909
|
19
|
+
c2cwsgiutils/db.py,sha256=JT5F9Dqm2r0Jsh3w3CX79ngAUtakMLpf1secfN1nQnk,16106
|
20
|
+
c2cwsgiutils/db_maintenance_view.py,sha256=58F-p9drkhCI99GoLRPIqT5U-Pm8ckSSUEl-tNxMmjU,3088
|
21
|
+
c2cwsgiutils/debug/__init__.py,sha256=GkYNt2fU5PFykw9HmqPEwZrF2mTJumjSu54pp38EhOM,1325
|
22
|
+
c2cwsgiutils/debug/_listeners.py,sha256=-fk3KFeB_E4m_YFXJ5MfxuqfA1sWCje9p3FH_93WfXM,4248
|
23
|
+
c2cwsgiutils/debug/_views.py,sha256=EY-reJAs68wZu3D1DosNBE_DnY3vbD55k-jkCNOZ9MU,7751
|
24
|
+
c2cwsgiutils/debug/utils.py,sha256=sIKZHQ8empzxE2OI3h7Uce8cvv4O7AD1y_VYeZfLVCA,2320
|
25
|
+
c2cwsgiutils/errors.py,sha256=-hWLQ1qDlh9kn06-33U2c39BbOxuCvJIkBkdxriE5mo,6644
|
26
|
+
c2cwsgiutils/health_check.py,sha256=OhfPcApBht1qtBOX8e8pdeq3QwF4FbgGkofjqpl8GvQ,20068
|
27
|
+
c2cwsgiutils/index.py,sha256=zQTp2dlb50DZy0TZOPYDxJv84kivcYirswz7rFMbSDA,17988
|
28
|
+
c2cwsgiutils/loader.py,sha256=aDs_YOoiEc_vr94fnc3TjUklIGgIOBZdoYLAjQHgTpo,1393
|
29
|
+
c2cwsgiutils/logging_view.py,sha256=d0UkvYRGkVUMY9_vbjEzXmm8-6CCec2B43a3mJAqWyw,3370
|
30
|
+
c2cwsgiutils/models_graph.py,sha256=q5dW_gZ5iUZCzBya5Kpy57y9oqsG-rGi9AvrXCDgYqs,2679
|
31
|
+
c2cwsgiutils/pretty_json.py,sha256=WQlgNVeWPD_QMEjkNq5rFVGdFwQ7xDyICf0uxj0Hu2U,1697
|
32
|
+
c2cwsgiutils/profiler.py,sha256=3tIwoDSzOKQ06ug_U6j5VDR1BQ9auUOqdJRRLRhDoHw,739
|
33
|
+
c2cwsgiutils/prometheus.py,sha256=XV_SSm0nT09MD8EEl2a4xtd2busO3r--JyboU9OvWaQ,6576
|
34
|
+
c2cwsgiutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
+
c2cwsgiutils/pyramid.py,sha256=MnVMskHMlJ4KQDjDR7CQdYaH70YXOtJ-1ThTPBqa03c,1387
|
36
|
+
c2cwsgiutils/pyramid_logging.py,sha256=M4XtWQZStreEoyC5qlwxcDDKCp4PZOr9SN05GnaYvvA,3732
|
37
|
+
c2cwsgiutils/redis_stats.py,sha256=8OTVRcElESgM6qjN944MOjoYRb0FGcQgo3JmDglfpPw,1632
|
38
|
+
c2cwsgiutils/redis_utils.py,sha256=02QoBGSjfBwKsWk-4DrXT8119HuUJuV_ezW7bc-Rv8s,4734
|
39
|
+
c2cwsgiutils/request_tracking/__init__.py,sha256=9Fp505q5zKjqfm9MuM7BDiYsx_pdg4vViNAr43OWYuk,4132
|
40
|
+
c2cwsgiutils/request_tracking/_sql.py,sha256=ZOQ3hD5z-WasfBzNig75fjrCvw4tGr1rhWOv97iLYws,572
|
41
|
+
c2cwsgiutils/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
42
|
+
c2cwsgiutils/scripts/genversion.py,sha256=lpGqU5wNSKdoOMDwVjFvWJVPEzdk0P8Tpfk7NLcrTok,1990
|
43
|
+
c2cwsgiutils/scripts/stats_db.py,sha256=kGCWBpG6gp_yDH3eZwEOujrvlyM0g97po6-EyjV8SXU,10413
|
44
|
+
c2cwsgiutils/scripts/test_print.py,sha256=NSXc0a2DZvKXjZYc2yr6oF72PCpeyL3GJthNFxGErEA,2101
|
45
|
+
c2cwsgiutils/sentry.py,sha256=su_t2SHxx_zK-gQfotmDbgbSdwTQdFvkgJnqcrQU7ps,6494
|
46
|
+
c2cwsgiutils/services.py,sha256=AxdiH2S8gfEQpOY36R4WqKtJ-3P4OXhx0srTm5G5070,1569
|
47
|
+
c2cwsgiutils/setup_process.py,sha256=VSiyVaQ65btIEBql1sBCZpOjCr0QQjRbcVDY2I7GbLM,3426
|
48
|
+
c2cwsgiutils/sql_profiler/__init__.py,sha256=2bh5s4xqPLUl7EPnm75R1RDKtc098PgZLHkwHGfS-94,907
|
49
|
+
c2cwsgiutils/sql_profiler/_impl.py,sha256=6qkXMhDGcheCDwOH09gFJDrtXRsngkvm29icZWZMtMI,3797
|
50
|
+
c2cwsgiutils/sqlalchemylogger/README.md,sha256=qXfyhGC4Kbt-Ye_geTPm_1InpclhthmKZpc66rqB4as,2018
|
51
|
+
c2cwsgiutils/sqlalchemylogger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
52
|
+
c2cwsgiutils/sqlalchemylogger/_filters.py,sha256=OJQ9_WA-fd9fMZ7TUNFzHHTPI6msw2NVBl5RoeYFnGw,752
|
53
|
+
c2cwsgiutils/sqlalchemylogger/_models.py,sha256=A9SQ8AqUazCMemVjp5p_1x4bZG3LAYW9pOXT84FdNkE,1471
|
54
|
+
c2cwsgiutils/sqlalchemylogger/examples/example.py,sha256=n48dJdUi1FH1hfBMAbfHLGPSb1bOVD8pXMxXB57PnpQ,460
|
55
|
+
c2cwsgiutils/sqlalchemylogger/handlers.py,sha256=nr9-eQsZ5d0DHbtc4Ym0_faa7qg1dF44CsdoZtuuRZM,4878
|
56
|
+
c2cwsgiutils/static/favicon-16x16.png,sha256=LKk6RFvb3NlPIZdDfAodE8H9IN8KM6CMGnMx4vOHlUQ,887
|
57
|
+
c2cwsgiutils/static/favicon-32x32.png,sha256=i4ucx08zAZARd8e7JTMGK-gb5WcOmyuDN6IN4brsEOo,1216
|
58
|
+
c2cwsgiutils/stats_pyramid/__init__.py,sha256=alSRhpCa5Kh9JnMnR5XqcMqr5wyL8ogROprrfsIl_qU,786
|
59
|
+
c2cwsgiutils/stats_pyramid/_db_spy.py,sha256=A61t6VKIrRRIjbyZTldmAUl_Q3ZDVFYqyxjuntzmllc,2919
|
60
|
+
c2cwsgiutils/stats_pyramid/_pyramid_spy.py,sha256=mRiOmQXV9x8JjkGV4MsaC7sD3qO6dWUTog0bharLLD0,3517
|
61
|
+
c2cwsgiutils/templates/index.html.mako,sha256=cK8qGBDeQG5SiJJCfvL0oKpgacr7dPKx634AAQivmjA,1416
|
62
|
+
c2cwsgiutils/version.py,sha256=1ghPu-aKMJdfCSUrxgBENNqNQ-7JMKJr6tS14dDmW4Q,3110
|
63
|
+
c2cwsgiutils-6.1.7.dev4.dist-info/LICENSE,sha256=6bEOU0n7ued3SA-DQCsHQaACONMMRzGHmH5XhDVeD-U,1304
|
64
|
+
c2cwsgiutils-6.1.7.dev4.dist-info/METADATA,sha256=bNxv5REJhQ1RiSYrsuk-h7s28UfeJTZIIuoFWUXfHO0,34401
|
65
|
+
c2cwsgiutils-6.1.7.dev4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
66
|
+
c2cwsgiutils-6.1.7.dev4.dist-info/entry_points.txt,sha256=ujgqMTL1awN9qDg8WXmrF7m0fgR-hslUM6zKH86pvy0,703
|
67
|
+
c2cwsgiutils-6.1.7.dev4.dist-info/RECORD,,
|
@@ -1,67 +0,0 @@
|
|
1
|
-
c2cwsgiutils/__init__.py,sha256=YHZ6OY8BvFrZAoBpbEWmAZ-60nqDer_CKHgY-LSHAKs,3986
|
2
|
-
c2cwsgiutils/acceptance/__init__.py,sha256=vjtpPfu0kbXUOYMx15Z8713IfPFZA9XnkUKkIFtVj_M,1500
|
3
|
-
c2cwsgiutils/acceptance/connection.py,sha256=w478x_UiPNebOX-IC7UBgpSGbUYRZBjHsA-Vpqvtic0,9742
|
4
|
-
c2cwsgiutils/acceptance/image.py,sha256=5dVng5TaCGMYDl-ajZ5WkZdxo7_y2b8Jk7eJZJhPUZ4,8769
|
5
|
-
c2cwsgiutils/acceptance/package-lock.json,sha256=8LPXP_SEWSRAVNGPeS28bXsf6qqRUjtmeXgL3kAUtWM,45501
|
6
|
-
c2cwsgiutils/acceptance/package.json,sha256=COQIxLJd3AKXwHSqvr4sseQaE0mgA9Wxg0gkc7uh_3Q,101
|
7
|
-
c2cwsgiutils/acceptance/print.py,sha256=j5K1c2Kn0eEnhgdbZNBVkdscK02pQhtPIh6lJzHMJcM,2323
|
8
|
-
c2cwsgiutils/acceptance/screenshot.js,sha256=FAJYIWOLJFMm0MNggKzo3mIybtN-VtKLdMzPhQ9pO1g,2041
|
9
|
-
c2cwsgiutils/acceptance/utils.py,sha256=-NgLlG_oQj3P_ZiK293RG7ZHPumg0WrDwo_APOI3WG4,1851
|
10
|
-
c2cwsgiutils/auth.py,sha256=xHUOHQf2UL6xnplbZBa4KObC7Fn7kR6tWsETo6h79-w,9453
|
11
|
-
c2cwsgiutils/broadcast/__init__.py,sha256=5xxEhGnOJmq-bEbUUmNyvz_DAfrHG0ZNQgeTQFGYFCo,4361
|
12
|
-
c2cwsgiutils/broadcast/interface.py,sha256=jE8BSy9N7xnPmq5U0m852sFFhx46c7Uo9SyFJTCde9o,636
|
13
|
-
c2cwsgiutils/broadcast/local.py,sha256=24aIRdFOR2CXZfp_F2R_S1QW-yon3EyTM6TvljWVlP0,1083
|
14
|
-
c2cwsgiutils/broadcast/redis.py,sha256=sxBsYZtMNXMOck6a_Mcb3QZjjW4lPTxnImTfL1vv14g,5085
|
15
|
-
c2cwsgiutils/broadcast/utils.py,sha256=0fQZXPu3p_5LEJpGenJwiiMxECQjJhjZBjIkBk8h-ng,272
|
16
|
-
c2cwsgiutils/client_info.py,sha256=RsC2yT7NcHQNICO3WQNXayHkqi0rC85AvI6qNRXFTWw,3028
|
17
|
-
c2cwsgiutils/config_utils.py,sha256=vkBu-3GQsE94NOBOvT5FE-Ij29EUrKnDsmdUdtu_yzo,1524
|
18
|
-
c2cwsgiutils/coverage_setup.py,sha256=fES0sdhFy6oaeOCuP1qjjm7PQL9l_O8rUKZhRvRBRwQ,839
|
19
|
-
c2cwsgiutils/db.py,sha256=vDRxhmUy-hLs5EAfYFGUg0nzH0tiWWo5ZejpmdlutS4,16175
|
20
|
-
c2cwsgiutils/db_maintenance_view.py,sha256=ejSNCv7vZIDjXctDTWTXEYTnUYFVVNIecFLeDlCkDBA,3076
|
21
|
-
c2cwsgiutils/debug/__init__.py,sha256=80zdAZnE9cwgQW1odE2aOauIxYsG5CQpWvHPcslRue8,1239
|
22
|
-
c2cwsgiutils/debug/_listeners.py,sha256=sXXHbPHQaSRMrzUC2ryiSDsBXuTdVbpQOxmMmhZ3n90,4378
|
23
|
-
c2cwsgiutils/debug/_views.py,sha256=zUeIshxBshBrlTz0p1I1LUi6HiJBOAAiDPrlOJsziQA,7522
|
24
|
-
c2cwsgiutils/debug/utils.py,sha256=TPlJC5qKeFnvbgq1xjlfrrRgDcV5kIR69IPJgNcIZQY,2311
|
25
|
-
c2cwsgiutils/errors.py,sha256=xAJghvSBRH_KOQFcYrItGrCLIFVri60ohq_z1dyG63I,6725
|
26
|
-
c2cwsgiutils/health_check.py,sha256=elVgCf2HQd7GpL7j4NEipb4crYl_pEYMZZP03x1xuYc,19978
|
27
|
-
c2cwsgiutils/index.py,sha256=7kgL4U_SN8boNHpnpB18v4ofScp-fJunsbnHpxbWlow,16707
|
28
|
-
c2cwsgiutils/loader.py,sha256=x_yHRTDzzlQ61fHonWnnG01xdqFuXpbGZMNN--tN25U,622
|
29
|
-
c2cwsgiutils/logging_view.py,sha256=W6-dFTz00hLt6BGJ8V3-4ip4AdxTyPG2W5vQjIuKiQs,3357
|
30
|
-
c2cwsgiutils/models_graph.py,sha256=laip8EdhI2hoGZVAotdrsgMwiNbwsJPjknKkRq1eEq0,2680
|
31
|
-
c2cwsgiutils/pretty_json.py,sha256=f1-oecFX9hub1nD32mmZRjOTIxhV8bVSt3Meqw68sNU,1698
|
32
|
-
c2cwsgiutils/profiler.py,sha256=3tIwoDSzOKQ06ug_U6j5VDR1BQ9auUOqdJRRLRhDoHw,739
|
33
|
-
c2cwsgiutils/prometheus.py,sha256=ZjHMG0zIKKJaadNp6pkSjXVTLAQS9AjlNwBH8HNJnfY,6558
|
34
|
-
c2cwsgiutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
-
c2cwsgiutils/pyramid.py,sha256=H-b5abZvxt9MkMFjyWOjWzPa02YRhZR6LDiMCaYLq5s,1388
|
36
|
-
c2cwsgiutils/pyramid_logging.py,sha256=1PoEBzmCelAmLVSeyLeeYr87ZIi1g9_oisiwH6p-7P4,3731
|
37
|
-
c2cwsgiutils/redis_stats.py,sha256=triLtzryGXJKvCUw4TreYpF22BpUKPdrMp30ZGKsXwU,1545
|
38
|
-
c2cwsgiutils/redis_utils.py,sha256=OkgUqbZcuCa-LjcFXZ-cDN94dYi746P1FHRWExdYP8U,4615
|
39
|
-
c2cwsgiutils/request_tracking/__init__.py,sha256=YHNVB6GaAu175qC1L9GOFu99W0Xnt4kMNZIMTc34P0M,4040
|
40
|
-
c2cwsgiutils/request_tracking/_sql.py,sha256=47OtVn3g5QpCCWyl8w6V1xVjbf0ahrw4r9ijjRKXDz4,573
|
41
|
-
c2cwsgiutils/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
42
|
-
c2cwsgiutils/scripts/genversion.py,sha256=GKmD08-H83hiKqXxy4odABuWqD5gADs_YEzM3TzHxEA,1985
|
43
|
-
c2cwsgiutils/scripts/stats_db.py,sha256=QNwtEKznCgOKg4ZsAFED9ISS-THgdwD2km_oVoII5XU,10317
|
44
|
-
c2cwsgiutils/scripts/test_print.py,sha256=UeOZa7jTazgEq5BRJD6lq-u9K6G4movf-sOVKTEs1cQ,2096
|
45
|
-
c2cwsgiutils/sentry.py,sha256=-IzACZWI7YNi-dWtNrYlhdTysm8gRVzJSqK94wg3maU,5031
|
46
|
-
c2cwsgiutils/services.py,sha256=qz51oCZOC0Lj2_ig4UuHIm0ZZO3FfpFTxrXBWZ_oaNo,1567
|
47
|
-
c2cwsgiutils/setup_process.py,sha256=Ia9mVYnjiNPt1n3ue8j3SqAoaJUwhDuFlfya2kEubJI,3427
|
48
|
-
c2cwsgiutils/sql_profiler/__init__.py,sha256=_Zw5BO-0sN2tVbSwtyHwi8gkmhCtGW-F6agkENhYILM,877
|
49
|
-
c2cwsgiutils/sql_profiler/_impl.py,sha256=bNK16vRBHnaNQo5JfSdT-nXZ8WBUUJ5BvtCrINg0Aws,3703
|
50
|
-
c2cwsgiutils/sqlalchemylogger/README.md,sha256=WEyJSrBjedtX1FFrYiq4oMaWMt1fNxRkJYmJWnAoz3g,1552
|
51
|
-
c2cwsgiutils/sqlalchemylogger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
52
|
-
c2cwsgiutils/sqlalchemylogger/_filters.py,sha256=OJQ9_WA-fd9fMZ7TUNFzHHTPI6msw2NVBl5RoeYFnGw,752
|
53
|
-
c2cwsgiutils/sqlalchemylogger/_models.py,sha256=A9SQ8AqUazCMemVjp5p_1x4bZG3LAYW9pOXT84FdNkE,1471
|
54
|
-
c2cwsgiutils/sqlalchemylogger/examples/example.py,sha256=n48dJdUi1FH1hfBMAbfHLGPSb1bOVD8pXMxXB57PnpQ,460
|
55
|
-
c2cwsgiutils/sqlalchemylogger/handlers.py,sha256=Qul-Bebmxqt4KvFU4TqjUGnbmpAVBviF5pSV3duUqG0,4801
|
56
|
-
c2cwsgiutils/static/favicon-16x16.png,sha256=LKk6RFvb3NlPIZdDfAodE8H9IN8KM6CMGnMx4vOHlUQ,887
|
57
|
-
c2cwsgiutils/static/favicon-32x32.png,sha256=i4ucx08zAZARd8e7JTMGK-gb5WcOmyuDN6IN4brsEOo,1216
|
58
|
-
c2cwsgiutils/stats_pyramid/__init__.py,sha256=7P10LjLv3c-ObEDGuYmRF_RFt7fRmO80ruqTGQAyC6w,747
|
59
|
-
c2cwsgiutils/stats_pyramid/_db_spy.py,sha256=ZGRdrI17Bdl3mzaLjfPyAaEW3KK8Pikrgi-0WmH7zCs,2917
|
60
|
-
c2cwsgiutils/stats_pyramid/_pyramid_spy.py,sha256=P212MGGl2VV_7UU4AXZA-rOuF7ouaONRklZwpas2wc8,3209
|
61
|
-
c2cwsgiutils/templates/index.html.mako,sha256=Ey9ppHLe-eFGYXYPV5Z2WbMBSif86sYPiTviksnG7TI,1362
|
62
|
-
c2cwsgiutils/version.py,sha256=z4of1DDr6J7PDw4AUOz31Gp63khgXf3JfiIaoWUM-9I,2870
|
63
|
-
c2cwsgiutils-6.1.0.dev105.dist-info/LICENSE,sha256=rM6IWxociA3daRkXnNLYOxGndT5fbs3BfVZCA2Xgt-g,1304
|
64
|
-
c2cwsgiutils-6.1.0.dev105.dist-info/METADATA,sha256=oe493srEHdNM9rxmpZ49TnWmUpJKyfh5KQC8M2s8ilY,33516
|
65
|
-
c2cwsgiutils-6.1.0.dev105.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
66
|
-
c2cwsgiutils-6.1.0.dev105.dist-info/entry_points.txt,sha256=ujgqMTL1awN9qDg8WXmrF7m0fgR-hslUM6zKH86pvy0,703
|
67
|
-
c2cwsgiutils-6.1.0.dev105.dist-info/RECORD,,
|
File without changes
|