wrapture-instrumentation 1.0.0.dev2__tar.gz → 1.0.0.dev4__tar.gz
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.
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/CHANGES.md +5 -2
- {wrapture_instrumentation-1.0.0.dev2/src/wrapture_instrumentation.egg-info → wrapture_instrumentation-1.0.0.dev4}/PKG-INFO +2 -2
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/pyproject.toml +1 -1
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/__init__.py +1 -1
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/README.md +7 -4
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/app.py +27 -48
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4/src/wrapture_instrumentation.egg-info}/PKG-INFO +2 -2
- wrapture_instrumentation-1.0.0.dev4/src/wrapture_instrumentation.egg-info/requires.txt +1 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_request_options.py +13 -7
- wrapture_instrumentation-1.0.0.dev2/src/wrapture_instrumentation.egg-info/requires.txt +0 -1
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/LICENSE +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/MANIFEST.in +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/README.md +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/TESTING.md +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/demo/__init__.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/demo/framework_flask.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/demo/template_jinja2.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/setup.cfg +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/__init__.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/blueprints.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/common.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/scaffold.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/framework_flask/templating.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/py.typed +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/template_jinja2/README.md +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/template_jinja2/__init__.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation/template_jinja2/environment.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation.egg-info/SOURCES.txt +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation.egg-info/dependency_links.txt +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation.egg-info/entry_points.txt +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation.egg-info/not-zip-safe +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/src/wrapture_instrumentation.egg-info/top_level.txt +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/__init__.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/conftest.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/__init__.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/portal.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/shop.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_apply_remove.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_class.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_lifecycle.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_registration.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_templating.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/framework_flask/test_tracing.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/template_jinja2/__init__.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/template_jinja2/test_apply_remove.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/template_jinja2/test_class.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/template_jinja2/test_registration.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/template_jinja2/test_rendering.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/template_jinja2/test_with_flask.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/test_package.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/test_wsgi.py +0 -0
- {wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/wsgi.py +0 -0
|
@@ -15,7 +15,9 @@ In development.
|
|
|
15
15
|
|
|
16
16
|
- Flask (`flask`, Flask 3.x): every request records as one tree
|
|
17
17
|
through the recording WSGI middleware installed at construction,
|
|
18
|
-
annotated with the matched route pattern and endpoint
|
|
18
|
+
annotated with the matched route pattern and endpoint (the route
|
|
19
|
+
is what wrapture's OpenTelemetry export names the span by, as
|
|
20
|
+
`http.route`); every view
|
|
19
21
|
function is observed as it registers and labelled by its endpoint
|
|
20
22
|
(blueprints and `MethodView`s included); lifecycle callbacks and
|
|
21
23
|
error handlers are observed however they register; and failures
|
|
@@ -29,6 +31,7 @@ In development.
|
|
|
29
31
|
settings switch the optional layers, all on by default:
|
|
30
32
|
`lifecycle`, `handled_errors` and `templates`; two more shape what
|
|
31
33
|
a recorded request carries: `ignore_paths` (path globs whose
|
|
32
|
-
requests record nothing, request and
|
|
34
|
+
requests record nothing at all, request and everything beneath it
|
|
35
|
+
alike) and `redact`
|
|
33
36
|
(query parameters masked by name on top of the built-in sensitive
|
|
34
37
|
set).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wrapture-instrumentation
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev4
|
|
4
4
|
Summary: Instrumentation for common Python packages, applied through wrapture.
|
|
5
5
|
Author-email: Graham Dumpleton <Graham.Dumpleton@gmail.com>
|
|
6
6
|
License-Expression: BSD-2-Clause
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
17
17
|
Requires-Python: >=3.12
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: wrapture>=1.0.
|
|
20
|
+
Requires-Dist: wrapture>=1.0.0a12
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
23
|
# wrapture-instrumentation
|
|
@@ -71,7 +71,10 @@ GET /shaky (portal.wsgi_app) -> '422 UNPROCESSABLE ENTITY' !! ValueError [671
|
|
|
71
71
|
matched route pattern (`route = "/quote/<item>"`) and endpoint
|
|
72
72
|
(`endpoint = "quoted"`), the low-cardinality keys to group by; the
|
|
73
73
|
raw path stays as the per-request detail. A request that matched no
|
|
74
|
-
route (a 404) has neither key.
|
|
74
|
+
route (a 404) has neither key. wrapture's OpenTelemetry export
|
|
75
|
+
reads `route` as the semantic-convention `http.route` and names the
|
|
76
|
+
request span by it (`GET /quote/<item>`), so a backend groups by
|
|
77
|
+
endpoint rather than by URL.
|
|
75
78
|
|
|
76
79
|
- Every view function is observed as its route registers, wherever it
|
|
77
80
|
came from: plain functions, `view_func` by keyword or position,
|
|
@@ -138,7 +141,7 @@ a layer:
|
|
|
138
141
|
|
|
139
142
|
| Setting | Default | Controls |
|
|
140
143
|
| ------- | ------- | -------- |
|
|
141
|
-
| `ignore_paths` | `[]` | Request paths not to record, as path globs (`"/health"`, `"/static/*"`). A matching request runs and answers as normal but records nothing: the
|
|
144
|
+
| `ignore_paths` | `[]` | Request paths not to record, as path globs (`"/health"`, `"/static/*"`). A matching request runs and answers as normal but records nothing at all: the request event is skipped and everything beneath it is silenced for the request's whole extent, its view, lifecycle callbacks, error handlers and template renders included, so no stray roots appear. It is wrapture's `filter_requests(ignore={"path": [...]})` with `tree=True` on the middleware. |
|
|
142
145
|
| `redact` | `[]` | Query string parameters to mask by name in the recorded query, on top of the built-in sensitive set (passwords, tokens, keys and session ids are always masked). The parameter still reaches the application; only the recording is masked. |
|
|
143
146
|
| `lifecycle` | `true` | Observing before/after/teardown callbacks as they register. Every registered callback runs on every request (extensions register these liberally: user loaders, session cleanup, header stamping), so this is the layer to switch off when the trees are noisier than they are informative. The callbacks still run; they run unobserved. |
|
|
144
147
|
| `handled_errors` | `true` | Noting an exception a registered handler absorbed against its request. The handler's own run is core and stays observed either way. |
|
|
@@ -163,8 +166,8 @@ lifecycle = false
|
|
|
163
166
|
- Flask signals: blinker plumbing; bind the receivers ad hoc with
|
|
164
167
|
wrapture if you need them.
|
|
165
168
|
- `jsonify`, `send_file`, `send_static_file`: response plumbing;
|
|
166
|
-
static file traffic is better excluded wholesale
|
|
167
|
-
`ignore_paths
|
|
169
|
+
static file traffic is better excluded wholesale with
|
|
170
|
+
`ignore_paths`.
|
|
168
171
|
|
|
169
172
|
## How it patches
|
|
170
173
|
|
|
@@ -8,7 +8,10 @@ their own calls.
|
|
|
8
8
|
instance's wsgi_app attribute, the documented place Flask middleware
|
|
9
9
|
goes, so every request records as one "request" event however the
|
|
10
10
|
instance was made: module level, an application factory, several
|
|
11
|
-
applications in one process.
|
|
11
|
+
applications in one process. The ignore_paths setting rides on the
|
|
12
|
+
middleware as a filter_requests() filter with tree=True, so an
|
|
13
|
+
ignored request records nothing at all, its view, callbacks and
|
|
14
|
+
template renders included.
|
|
12
15
|
|
|
13
16
|
- Flask.add_url_rule substitutes wrapture.observed(view_func) as
|
|
14
17
|
routes register, labelled with the route's endpoint, so every view
|
|
@@ -64,7 +67,6 @@ manager, take the whole thing down again.
|
|
|
64
67
|
|
|
65
68
|
from __future__ import annotations
|
|
66
69
|
|
|
67
|
-
import fnmatch
|
|
68
70
|
from collections.abc import Callable, Sequence
|
|
69
71
|
from typing import Any
|
|
70
72
|
|
|
@@ -73,42 +75,24 @@ import wrapture
|
|
|
73
75
|
from .common import observing_registration
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
def _declines(ignore_paths: Sequence[str]) -> Callable[..., bool] | None:
|
|
77
|
-
"""The when= predicate for the ignore_paths setting, or None when
|
|
78
|
-
the setting is empty: record unless the request path matches one
|
|
79
|
-
of the globs. Shared by the middleware and the observed views, so
|
|
80
|
-
an ignored request records neither its request event nor its
|
|
81
|
-
view."""
|
|
82
|
-
|
|
83
|
-
if not ignore_paths:
|
|
84
|
-
return None
|
|
85
|
-
|
|
86
|
-
patterns = tuple(ignore_paths)
|
|
87
|
-
|
|
88
|
-
def wanted(instance: Any, args: tuple[Any, ...], kwargs: Any) -> bool:
|
|
89
|
-
# The view form of the predicate: read the path from the
|
|
90
|
-
# request context (the middleware form gets the environ
|
|
91
|
-
# directly and never reaches here). A call outside a request
|
|
92
|
-
# context is not an ignorable request; record it.
|
|
93
|
-
|
|
94
|
-
from flask import has_request_context, request
|
|
95
|
-
|
|
96
|
-
if not has_request_context():
|
|
97
|
-
return True
|
|
98
|
-
|
|
99
|
-
return not any(
|
|
100
|
-
fnmatch.fnmatchcase(request.path, pattern) for pattern in patterns
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
return wanted
|
|
104
|
-
|
|
105
|
-
|
|
106
78
|
def wrap_app(ignore_paths: Sequence[str], redact: Sequence[str]) -> Callable[..., Any]:
|
|
107
79
|
"""Build the Flask.__init__ decorator that installs the recording
|
|
108
80
|
middleware on each new instance's wsgi_app, carrying the
|
|
109
|
-
ignore_paths and redact settings into it.
|
|
81
|
+
ignore_paths and redact settings into it.
|
|
82
|
+
|
|
83
|
+
ignore_paths becomes a filter_requests() filter on the middleware's
|
|
84
|
+
when=, with tree=True so that a declined request silences
|
|
85
|
+
everything beneath it for its whole extent; without the flag the
|
|
86
|
+
request's view, callbacks and renders would still record, each as
|
|
87
|
+
a parentless root. tree= is only valid alongside a when=, so both
|
|
88
|
+
are left unset when there is nothing to ignore.
|
|
89
|
+
"""
|
|
110
90
|
|
|
111
|
-
|
|
91
|
+
request_filter = (
|
|
92
|
+
wrapture.filter_requests(ignore={"path": list(ignore_paths)})
|
|
93
|
+
if ignore_paths
|
|
94
|
+
else None
|
|
95
|
+
)
|
|
112
96
|
policy = wrapture.redact(*redact) if redact else None
|
|
113
97
|
|
|
114
98
|
def install(
|
|
@@ -122,7 +106,8 @@ def wrap_app(ignore_paths: Sequence[str], redact: Sequence[str]) -> Callable[...
|
|
|
122
106
|
instance.wsgi_app = wrapture.WSGIMiddleware(
|
|
123
107
|
instance.wsgi_app,
|
|
124
108
|
label=f"{instance.name}.wsgi_app",
|
|
125
|
-
when=
|
|
109
|
+
when=request_filter,
|
|
110
|
+
tree=request_filter is not None,
|
|
126
111
|
capture_args=policy,
|
|
127
112
|
)
|
|
128
113
|
|
|
@@ -147,34 +132,28 @@ def _endpoint(args: tuple[Any, ...], kwargs: dict[str, Any], view: Any) -> str:
|
|
|
147
132
|
return str(endpoint) if endpoint is not None else view.__name__
|
|
148
133
|
|
|
149
134
|
|
|
150
|
-
def wrap_view(
|
|
135
|
+
def wrap_view() -> Callable[..., Any]:
|
|
151
136
|
"""Build the add_url_rule transformer that substitutes an observed
|
|
152
137
|
view function, labelled by its endpoint, into each registration.
|
|
153
138
|
|
|
154
139
|
The signature is add_url_rule(rule, endpoint=None, view_func=None,
|
|
155
140
|
...), so the view is either the view_func keyword or the third
|
|
156
141
|
positional argument; a registration without a view (an endpoint
|
|
157
|
-
name alone) passes through untouched. The
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
name alone) passes through untouched. The view needs no predicate
|
|
143
|
+
of its own: an ignored request is silenced beneath the middleware,
|
|
144
|
+
view included.
|
|
160
145
|
"""
|
|
161
146
|
|
|
162
|
-
when = _declines(ignore_paths)
|
|
163
|
-
|
|
164
147
|
def transform(
|
|
165
148
|
args: tuple[Any, ...], kwargs: dict[str, Any]
|
|
166
149
|
) -> tuple[tuple[Any, ...], dict[str, Any]]:
|
|
167
150
|
if kwargs.get("view_func") is not None:
|
|
168
151
|
view = kwargs["view_func"]
|
|
169
|
-
observed = wrapture.observed(
|
|
170
|
-
view, label=_endpoint(args, kwargs, view), when=when
|
|
171
|
-
)
|
|
152
|
+
observed = wrapture.observed(view, label=_endpoint(args, kwargs, view))
|
|
172
153
|
kwargs = dict(kwargs, view_func=observed)
|
|
173
154
|
elif len(args) >= 3 and args[2] is not None:
|
|
174
155
|
view = args[2]
|
|
175
|
-
observed = wrapture.observed(
|
|
176
|
-
view, label=_endpoint(args, kwargs, view), when=when
|
|
177
|
-
)
|
|
156
|
+
observed = wrapture.observed(view, label=_endpoint(args, kwargs, view))
|
|
178
157
|
args = (*args[:2], observed, *args[3:])
|
|
179
158
|
|
|
180
159
|
return args, kwargs
|
|
@@ -261,7 +240,7 @@ def instrument(module: Any, instrumentation: wrapture.Instrumentation) -> None:
|
|
|
261
240
|
)
|
|
262
241
|
|
|
263
242
|
registrar = wrapture.binding(module.Flask, "add_url_rule", when=False)
|
|
264
|
-
registrar.on_call.transforms_args(wrap_view(
|
|
243
|
+
registrar.on_call.transforms_args(wrap_view())
|
|
265
244
|
|
|
266
245
|
router = wrapture.binding(module.Flask, "preprocess_request", when=False)
|
|
267
246
|
router.on_call.decorates(annotate_route)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wrapture-instrumentation
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev4
|
|
4
4
|
Summary: Instrumentation for common Python packages, applied through wrapture.
|
|
5
5
|
Author-email: Graham Dumpleton <Graham.Dumpleton@gmail.com>
|
|
6
6
|
License-Expression: BSD-2-Clause
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
17
17
|
Requires-Python: >=3.12
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: wrapture>=1.0.
|
|
20
|
+
Requires-Dist: wrapture>=1.0.0a12
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
23
|
# wrapture-instrumentation
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wrapture>=1.0.0a12
|
|
@@ -12,7 +12,8 @@ from wrapture_instrumentation.framework_flask import FlaskInstrumentation
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def make_probe() -> flask.Flask:
|
|
15
|
-
"""An application with a health endpoint beside a working route
|
|
15
|
+
"""An application with a health endpoint beside a working route,
|
|
16
|
+
and a lifecycle callback that runs on every request."""
|
|
16
17
|
|
|
17
18
|
app = flask.Flask("probe")
|
|
18
19
|
|
|
@@ -22,6 +23,10 @@ def make_probe() -> flask.Flask:
|
|
|
22
23
|
def work() -> str:
|
|
23
24
|
return "done"
|
|
24
25
|
|
|
26
|
+
def stamp() -> None:
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
app.before_request(stamp)
|
|
25
30
|
app.add_url_rule("/health", "health", health)
|
|
26
31
|
app.add_url_rule("/static/<name>", "asset", lambda name: name)
|
|
27
32
|
app.add_url_rule("/work", "work", work)
|
|
@@ -30,10 +35,10 @@ def make_probe() -> flask.Flask:
|
|
|
30
35
|
|
|
31
36
|
|
|
32
37
|
def test_ignored_paths_record_nothing_and_still_answer() -> None:
|
|
33
|
-
# An ignored request leaves no events at all: the middleware
|
|
34
|
-
# the request
|
|
35
|
-
#
|
|
36
|
-
# runs and answers.
|
|
38
|
+
# An ignored request leaves no events at all: the middleware's
|
|
39
|
+
# filter declines the request with tree=True, so the view and the
|
|
40
|
+
# lifecycle callback beneath it are silenced rather than left as
|
|
41
|
+
# stray roots. The application still runs and answers.
|
|
37
42
|
|
|
38
43
|
with (
|
|
39
44
|
instrumentation(FlaskInstrumentation, ignore_paths=["/health", "/static/*"]),
|
|
@@ -53,6 +58,7 @@ def test_ignored_paths_record_nothing_and_still_answer() -> None:
|
|
|
53
58
|
|
|
54
59
|
assert [(event.kind, event.label or event.path) for event in tape.all] == [
|
|
55
60
|
("request", "probe.wsgi_app"),
|
|
61
|
+
("call", f"{__name__}:make_probe.<locals>.stamp"),
|
|
56
62
|
("call", "work"),
|
|
57
63
|
]
|
|
58
64
|
|
|
@@ -67,7 +73,7 @@ def test_redact_masks_named_query_parameters() -> None:
|
|
|
67
73
|
):
|
|
68
74
|
request(make_probe(), "GET", "/work", query="voucher=SECRET50&limit=5&token=t")
|
|
69
75
|
|
|
70
|
-
|
|
76
|
+
seen = tape.all[0]
|
|
71
77
|
assert seen.data["query"] == "voucher=<redacted>&limit=5&token=<redacted>"
|
|
72
78
|
assert "SECRET50" not in repr(seen.data)
|
|
73
79
|
|
|
@@ -101,6 +107,6 @@ def test_defaults_ignore_nothing_and_redact_only_the_built_ins() -> None:
|
|
|
101
107
|
with instrumentation(FlaskInstrumentation), timeline() as tape:
|
|
102
108
|
request(make_probe(), "GET", "/health", query="voucher=v&api_key=k")
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
seen = tape.all[0]
|
|
105
111
|
assert seen.data["path"] == "/health"
|
|
106
112
|
assert seen.data["query"] == "voucher=v&api_key=<redacted>"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
wrapture>=1.0.0a5
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/demo/__init__.py
RENAMED
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/demo/framework_flask.py
RENAMED
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/demo/template_jinja2.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/__init__.py
RENAMED
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/test_package.py
RENAMED
|
File without changes
|
{wrapture_instrumentation-1.0.0.dev2 → wrapture_instrumentation-1.0.0.dev4}/tests/test_wsgi.py
RENAMED
|
File without changes
|
|
File without changes
|