kinto 21.1.1__py3-none-any.whl → 23.0.0__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.
Potentially problematic release.
This version of kinto might be problematic. Click here for more details.
- kinto/core/initialization.py +2 -3
- kinto/core/metrics.py +4 -4
- kinto/plugins/prometheus.py +71 -50
- {kinto-21.1.1.dist-info → kinto-23.0.0.dist-info}/METADATA +2 -1
- {kinto-21.1.1.dist-info → kinto-23.0.0.dist-info}/RECORD +9 -9
- {kinto-21.1.1.dist-info → kinto-23.0.0.dist-info}/WHEEL +1 -1
- {kinto-21.1.1.dist-info → kinto-23.0.0.dist-info}/entry_points.txt +0 -0
- {kinto-21.1.1.dist-info → kinto-23.0.0.dist-info}/licenses/LICENSE +0 -0
- {kinto-21.1.1.dist-info → kinto-23.0.0.dist-info}/top_level.txt +0 -0
kinto/core/initialization.py
CHANGED
|
@@ -510,17 +510,16 @@ def setup_metrics(config):
|
|
|
510
510
|
request_labels = [
|
|
511
511
|
("method", request.method.lower()),
|
|
512
512
|
("endpoint", endpoint),
|
|
513
|
-
("status", str(status)),
|
|
514
513
|
] + metrics_matchdict_labels
|
|
515
514
|
|
|
516
515
|
# Count served requests.
|
|
517
|
-
metrics_service.count("request_summary", unique=request_labels)
|
|
516
|
+
metrics_service.count("request_summary", unique=request_labels + [("status", str(status))])
|
|
518
517
|
|
|
519
518
|
try:
|
|
520
519
|
current = utils.msec_time()
|
|
521
520
|
duration = current - request._received_at
|
|
522
521
|
metrics_service.timer(
|
|
523
|
-
"
|
|
522
|
+
"request_duration_seconds",
|
|
524
523
|
value=duration,
|
|
525
524
|
labels=request_labels,
|
|
526
525
|
)
|
kinto/core/metrics.py
CHANGED
|
@@ -13,7 +13,7 @@ class IMetricsService(Interface):
|
|
|
13
13
|
|
|
14
14
|
def timer(key):
|
|
15
15
|
"""
|
|
16
|
-
Watch execution time.
|
|
16
|
+
Watch execution time in seconds.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
19
|
def observe(self, key, value, labels=[]):
|
|
@@ -68,9 +68,9 @@ def watch_execution_time(metrics_service, obj, prefix="", classname=None):
|
|
|
68
68
|
method = getattr(obj, name)
|
|
69
69
|
is_method = isinstance(method, types.MethodType)
|
|
70
70
|
if not name.startswith("_") and is_method:
|
|
71
|
-
|
|
71
|
+
metric_name = f"{prefix}.{classname}.seconds"
|
|
72
72
|
labels = [("method", name)]
|
|
73
|
-
decorated_method = metrics_service.timer(
|
|
73
|
+
decorated_method = metrics_service.timer(metric_name, labels=labels)(method)
|
|
74
74
|
setattr(obj, name, decorated_method)
|
|
75
75
|
|
|
76
76
|
|
|
@@ -88,7 +88,7 @@ def listener_with_timer(config, key, func):
|
|
|
88
88
|
# not listed in the `initialization_sequence` setting.
|
|
89
89
|
return func(*args, **kwargs)
|
|
90
90
|
# If metrics are enabled, monitor execution time of listeners.
|
|
91
|
-
with metrics_service.timer(key):
|
|
91
|
+
with metrics_service.timer(key + ".seconds" if not key.endswith(".seconds") else key):
|
|
92
92
|
return func(*args, **kwargs)
|
|
93
93
|
|
|
94
94
|
return wrapped
|
kinto/plugins/prometheus.py
CHANGED
|
@@ -53,7 +53,7 @@ class Timer:
|
|
|
53
53
|
"""
|
|
54
54
|
A decorator to time the execution of a function. It will use the
|
|
55
55
|
`prometheus_client.Histogram` to record the time taken by the function
|
|
56
|
-
in
|
|
56
|
+
in seconds. The histogram is passed as an argument to the
|
|
57
57
|
constructor.
|
|
58
58
|
|
|
59
59
|
Main limitation: it does not support `labels` on the decorator.
|
|
@@ -78,8 +78,8 @@ class Timer:
|
|
|
78
78
|
try:
|
|
79
79
|
return f(*args, **kwargs)
|
|
80
80
|
finally:
|
|
81
|
-
|
|
82
|
-
self.histogram.observe(
|
|
81
|
+
dt_sec = time_now() - start_time
|
|
82
|
+
self.histogram.observe(dt_sec)
|
|
83
83
|
|
|
84
84
|
return _wrapped
|
|
85
85
|
|
|
@@ -96,14 +96,22 @@ class Timer:
|
|
|
96
96
|
def stop(self):
|
|
97
97
|
if self._start_time is None: # pragma: nocover
|
|
98
98
|
raise RuntimeError("Timer has not started.")
|
|
99
|
-
|
|
100
|
-
self.histogram.observe(
|
|
99
|
+
dt_sec = time_now() - self._start_time
|
|
100
|
+
self.histogram.observe(dt_sec)
|
|
101
|
+
return self
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class NoOpHistogram: # pragma: no cover
|
|
105
|
+
def observe(self, value):
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
def labels(self, *args):
|
|
101
109
|
return self
|
|
102
110
|
|
|
103
111
|
|
|
104
112
|
@implementer(metrics.IMetricsService)
|
|
105
113
|
class PrometheusService:
|
|
106
|
-
def __init__(self, prefix="",
|
|
114
|
+
def __init__(self, prefix="", disabled_metrics=[], histogram_buckets=None):
|
|
107
115
|
prefix_clean = ""
|
|
108
116
|
if prefix:
|
|
109
117
|
# In GCP Console, the metrics are grouped by the first
|
|
@@ -112,26 +120,23 @@ class PrometheusService:
|
|
|
112
120
|
# (eg. `remote-settings` -> `remotesettings_`, `kinto_` -> `kinto_`)
|
|
113
121
|
prefix_clean = _fix_metric_name(prefix).replace("_", "") + "_"
|
|
114
122
|
self.prefix = prefix_clean.lower()
|
|
115
|
-
self.
|
|
116
|
-
|
|
117
|
-
def _exclude_labels(self, labels):
|
|
118
|
-
return [
|
|
119
|
-
(label_name, label_value)
|
|
120
|
-
for label_name, label_value in labels
|
|
121
|
-
if label_name not in self.exclude_labels
|
|
122
|
-
]
|
|
123
|
+
self.disabled_metrics = [m.replace(self.prefix, "") for m in disabled_metrics]
|
|
124
|
+
self.histogram_buckets = histogram_buckets
|
|
123
125
|
|
|
124
126
|
def timer(self, key, value=None, labels=[]):
|
|
125
127
|
global _METRICS
|
|
126
|
-
key = self.prefix + key
|
|
127
|
-
labels = self._exclude_labels(labels)
|
|
128
128
|
|
|
129
|
+
key = _fix_metric_name(key)
|
|
130
|
+
if key in self.disabled_metrics:
|
|
131
|
+
return Timer(histogram=NoOpHistogram())
|
|
132
|
+
|
|
133
|
+
key = self.prefix + key
|
|
129
134
|
if key not in _METRICS:
|
|
130
135
|
_METRICS[key] = prometheus_module.Histogram(
|
|
131
|
-
|
|
136
|
+
key,
|
|
132
137
|
f"Histogram of {key}",
|
|
133
|
-
registry=get_registry(),
|
|
134
138
|
labelnames=[label_name for label_name, _ in labels],
|
|
139
|
+
buckets=self.histogram_buckets,
|
|
135
140
|
)
|
|
136
141
|
|
|
137
142
|
if not isinstance(_METRICS[key], prometheus_module.Histogram):
|
|
@@ -139,7 +144,7 @@ class PrometheusService:
|
|
|
139
144
|
f"Metric {key} already exists with different type ({_METRICS[key]})"
|
|
140
145
|
)
|
|
141
146
|
|
|
142
|
-
timer = Timer(_METRICS[key])
|
|
147
|
+
timer = Timer(histogram=_METRICS[key])
|
|
143
148
|
timer.set_labels(labels)
|
|
144
149
|
|
|
145
150
|
if value is not None:
|
|
@@ -153,15 +158,17 @@ class PrometheusService:
|
|
|
153
158
|
|
|
154
159
|
def observe(self, key, value, labels=[]):
|
|
155
160
|
global _METRICS
|
|
156
|
-
key = self.prefix + key
|
|
157
|
-
labels = self._exclude_labels(labels)
|
|
158
161
|
|
|
162
|
+
key = _fix_metric_name(key)
|
|
163
|
+
if key in self.disabled_metrics:
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
key = self.prefix + key
|
|
159
167
|
if key not in _METRICS:
|
|
160
168
|
_METRICS[key] = prometheus_module.Summary(
|
|
161
|
-
|
|
169
|
+
key,
|
|
162
170
|
f"Summary of {key}",
|
|
163
171
|
labelnames=[label_name for label_name, _ in labels],
|
|
164
|
-
registry=get_registry(),
|
|
165
172
|
)
|
|
166
173
|
|
|
167
174
|
if not isinstance(_METRICS[key], prometheus_module.Summary):
|
|
@@ -177,10 +184,12 @@ class PrometheusService:
|
|
|
177
184
|
|
|
178
185
|
def count(self, key, count=1, unique=None):
|
|
179
186
|
global _METRICS
|
|
180
|
-
key = self.prefix + key
|
|
181
187
|
|
|
182
|
-
|
|
188
|
+
key = _fix_metric_name(key)
|
|
189
|
+
if key in self.disabled_metrics:
|
|
190
|
+
return
|
|
183
191
|
|
|
192
|
+
labels = []
|
|
184
193
|
if unique:
|
|
185
194
|
if isinstance(unique, str):
|
|
186
195
|
warnings.warn(
|
|
@@ -195,17 +204,16 @@ class PrometheusService:
|
|
|
195
204
|
label_name, label_value = unique.rsplit(".", 1)
|
|
196
205
|
unique = [(label_name, label_value)]
|
|
197
206
|
|
|
198
|
-
unique = self._exclude_labels(unique)
|
|
199
207
|
labels = [
|
|
200
208
|
(_fix_metric_name(label_name), label_value) for label_name, label_value in unique
|
|
201
209
|
]
|
|
202
210
|
|
|
211
|
+
key = self.prefix + key
|
|
203
212
|
if key not in _METRICS:
|
|
204
213
|
_METRICS[key] = prometheus_module.Counter(
|
|
205
|
-
|
|
214
|
+
key,
|
|
206
215
|
f"Counter of {key}",
|
|
207
216
|
labelnames=[label_name for label_name, _ in labels],
|
|
208
|
-
registry=get_registry(),
|
|
209
217
|
)
|
|
210
218
|
|
|
211
219
|
if not isinstance(_METRICS[key], prometheus_module.Counter):
|
|
@@ -234,6 +242,19 @@ def _reset_multiproc_folder_content(): # pragma: no cover
|
|
|
234
242
|
os.makedirs(PROMETHEUS_MULTIPROC_DIR, exist_ok=True)
|
|
235
243
|
|
|
236
244
|
|
|
245
|
+
def reset_registry():
|
|
246
|
+
# This is mainly useful in tests, where the plugin is included
|
|
247
|
+
# several times with different settings.
|
|
248
|
+
registry = get_registry()
|
|
249
|
+
|
|
250
|
+
for collector in _METRICS.values():
|
|
251
|
+
try:
|
|
252
|
+
registry.unregister(collector)
|
|
253
|
+
except KeyError: # pragma: no cover
|
|
254
|
+
pass
|
|
255
|
+
_METRICS.clear()
|
|
256
|
+
|
|
257
|
+
|
|
237
258
|
def includeme(config):
|
|
238
259
|
if prometheus_module is None:
|
|
239
260
|
error_msg = (
|
|
@@ -246,34 +267,34 @@ def includeme(config):
|
|
|
246
267
|
if not asbool(settings.get("prometheus_created_metrics_enabled", True)):
|
|
247
268
|
prometheus_module.disable_created_metrics()
|
|
248
269
|
|
|
270
|
+
prefix = settings.get("prometheus_prefix", settings["project_name"])
|
|
271
|
+
disabled_metrics = aslist(settings.get("prometheus_disabled_metrics", ""))
|
|
272
|
+
|
|
273
|
+
# Default buckets for histogram metrics are (.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 2.5, 5.0, 7.5, 10.0, INF)
|
|
274
|
+
# we reduce it from 15 to 8 values by default here, and let the user override it if needed.
|
|
275
|
+
histogram_buckets_values = aslist(
|
|
276
|
+
settings.get(
|
|
277
|
+
"prometheus_histogram_buckets", "0.01 0.05 0.1 0.5 1.0 3.0 6.0 Inf"
|
|
278
|
+
) # Note: Inf is added by default.
|
|
279
|
+
)
|
|
280
|
+
histogram_buckets = [float(x) for x in histogram_buckets_values]
|
|
281
|
+
# Note: we don't need to check for INF or list size, it's done in the prometheus_client library.
|
|
282
|
+
|
|
283
|
+
get_registry() # Initialize the registry.
|
|
284
|
+
|
|
285
|
+
metrics_impl = PrometheusService(
|
|
286
|
+
prefix=prefix, disabled_metrics=disabled_metrics, histogram_buckets=histogram_buckets
|
|
287
|
+
)
|
|
288
|
+
|
|
249
289
|
config.add_api_capability(
|
|
250
290
|
"prometheus",
|
|
251
291
|
description="Prometheus metrics.",
|
|
252
292
|
url="https://github.com/Kinto/kinto/",
|
|
293
|
+
prefix=metrics_impl.prefix,
|
|
294
|
+
disabled_metrics=disabled_metrics,
|
|
253
295
|
)
|
|
254
296
|
|
|
255
297
|
config.add_route("prometheus_metrics", "/__metrics__")
|
|
256
298
|
config.add_view(metrics_view, route_name="prometheus_metrics")
|
|
257
299
|
|
|
258
|
-
|
|
259
|
-
# This is mainly useful in tests, where the plugin is included
|
|
260
|
-
# several times with different settings.
|
|
261
|
-
registry = get_registry()
|
|
262
|
-
|
|
263
|
-
for collector in _METRICS.values():
|
|
264
|
-
try:
|
|
265
|
-
registry.unregister(collector)
|
|
266
|
-
except KeyError: # pragma: no cover
|
|
267
|
-
pass
|
|
268
|
-
_METRICS.clear()
|
|
269
|
-
|
|
270
|
-
prefix = settings.get("prometheus_prefix", settings["project_name"])
|
|
271
|
-
|
|
272
|
-
# If we want to reduce the metrics cardinality, we can exclude certain
|
|
273
|
-
# labels (eg. records_id). This way all metrics will be grouped by the
|
|
274
|
-
# remaining labels.
|
|
275
|
-
exclude_labels = aslist(settings.get("prometheus_exclude_labels", ""))
|
|
276
|
-
|
|
277
|
-
config.registry.registerUtility(
|
|
278
|
-
PrometheusService(prefix=prefix, exclude_labels=exclude_labels), metrics.IMetricsService
|
|
279
|
-
)
|
|
300
|
+
config.registry.registerUtility(metrics_impl, metrics.IMetricsService)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kinto
|
|
3
|
-
Version:
|
|
3
|
+
Version: 23.0.0
|
|
4
4
|
Summary: Kinto Web Service - Store, Sync, Share, and Self-Host.
|
|
5
5
|
Author-email: Mozilla Services <developers@kinto-storage.org>
|
|
6
6
|
License: Copyright 2012 - Mozilla Foundation
|
|
@@ -70,6 +70,7 @@ Provides-Extra: dev
|
|
|
70
70
|
Requires-Dist: build; extra == "dev"
|
|
71
71
|
Requires-Dist: ruff; extra == "dev"
|
|
72
72
|
Requires-Dist: twine; extra == "dev"
|
|
73
|
+
Requires-Dist: uwsgi; extra == "dev"
|
|
73
74
|
Dynamic: license-file
|
|
74
75
|
|
|
75
76
|
Kinto
|
|
@@ -12,8 +12,8 @@ kinto/core/authorization.py,sha256=GywY25KEzuSSAI709dFHDfdLnKxy3SLEYGwW5FkQ7Qc,1
|
|
|
12
12
|
kinto/core/decorators.py,sha256=3SAPWXlyPNUSICZ9mz04bcN-UdbnDuFOtU0bQHHzLis,2178
|
|
13
13
|
kinto/core/errors.py,sha256=JXZjkPYjjC0I6x02d2VJRGeaQ2yZYS2zm5o7_ljfyes,8946
|
|
14
14
|
kinto/core/events.py,sha256=SYpXgKMtVjiD9fwYJA2Omdom9yA3nBqi9btdvU1I_nc,10345
|
|
15
|
-
kinto/core/initialization.py,sha256=
|
|
16
|
-
kinto/core/metrics.py,sha256=
|
|
15
|
+
kinto/core/initialization.py,sha256=sK_YSg6OcqCEIPAH--aiTnMD0ztV_90gkpxUI4v1LiM,26328
|
|
16
|
+
kinto/core/metrics.py,sha256=wlTThw_pSESrgwJfGdVBcM3r0b09gleZV4aSiu5pWq8,2768
|
|
17
17
|
kinto/core/openapi.py,sha256=92sZviff4NCxN0jMnu5lPUnF5iQbrKMGy7Cegf-VAME,3876
|
|
18
18
|
kinto/core/schema.py,sha256=d5L5TQynRYJPkZ8Mu2X7F72xEh6SKDbrHK1CNTdOf2E,3646
|
|
19
19
|
kinto/core/scripts.py,sha256=02SXVjo579W82AsDF8dyVCRxYVcrMFkjjaNVIgLChh0,1412
|
|
@@ -100,7 +100,7 @@ kinto/core/views/openapi.py,sha256=PgxplQX1D0zqzlvRxBvd5SzrNMJmsaLfDta_fh-Pr-A,9
|
|
|
100
100
|
kinto/core/views/version.py,sha256=-m5G_o0oHTpCgrtfFrHFve6Zqw_gs_szT0Bd8jnNmD4,1419
|
|
101
101
|
kinto/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
102
102
|
kinto/plugins/flush.py,sha256=poiBOLGXjml0xXHjqDMRdbXJSd6N3SL0mfeGK2vxeHY,812
|
|
103
|
-
kinto/plugins/prometheus.py,sha256=
|
|
103
|
+
kinto/plugins/prometheus.py,sha256=MXI79XQ9Uq_1hwAONgiySiKrLP-cwa26A_s4eeHrAvY,9621
|
|
104
104
|
kinto/plugins/statsd.py,sha256=k9sewYZUwm60k9Z799VxbShBP3uPwGVlImaGCPnIrkE,2801
|
|
105
105
|
kinto/plugins/accounts/__init__.py,sha256=2DeIaXJmMqRca3xVHeJ6xBWmeXAfrCdyg3EvK5jzIak,3670
|
|
106
106
|
kinto/plugins/accounts/authentication.py,sha256=pCb269FquKGFd6DH8AVTjFnBFlfxcDEYVyxhQp5Y08o,2117
|
|
@@ -141,9 +141,9 @@ kinto/views/contribute.py,sha256=PJoIMLj9_IszSjgZkaCd_TUjekDgNqjpmVTmRN9ztaA,983
|
|
|
141
141
|
kinto/views/groups.py,sha256=jOq5fX0-4lwZE8k1q5HME2tU7x9052rtBPF7YqcJ-Qg,3181
|
|
142
142
|
kinto/views/permissions.py,sha256=F0_eKx201WyLonXJ5vLdGKa9RcFKjvAihrEEhU1JuLw,9069
|
|
143
143
|
kinto/views/records.py,sha256=lYfACW2L8qcQoyYBD5IX-fTPjFWmGp7GjHq_U4InlyE,5037
|
|
144
|
-
kinto-
|
|
145
|
-
kinto-
|
|
146
|
-
kinto-
|
|
147
|
-
kinto-
|
|
148
|
-
kinto-
|
|
149
|
-
kinto-
|
|
144
|
+
kinto-23.0.0.dist-info/licenses/LICENSE,sha256=oNEIMTuTJzppR5ZEyi86yvvtSagveMYXTYFn56zF0Uk,561
|
|
145
|
+
kinto-23.0.0.dist-info/METADATA,sha256=_o35lUZjDWY1dFgcRi431FWEvSt20k_e1fnkry9e7NY,8768
|
|
146
|
+
kinto-23.0.0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
147
|
+
kinto-23.0.0.dist-info/entry_points.txt,sha256=3KlqBWPKY81mrCe_oX0I5s1cRO7Q53nCLbnVr5P9LH4,85
|
|
148
|
+
kinto-23.0.0.dist-info/top_level.txt,sha256=EG_YmbZL6FAug9VwopG7JtF9SvH_r0DEnFp-3twPPys,6
|
|
149
|
+
kinto-23.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|