structlog-throttling 1.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.
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
from structlog import DropEvent
|
|
7
|
+
from structlog.typing import EventDict
|
|
8
|
+
|
|
9
|
+
from .throttlers import ThrottlerProtocol, TimeThrottler
|
|
10
|
+
|
|
11
|
+
_T = typing.TypeVar("_T", bound=ThrottlerProtocol)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"LogTimeThrottler",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LogTimeThrottler:
|
|
19
|
+
"""Drop logs when throttled based on time in between calls.
|
|
20
|
+
|
|
21
|
+
This should generally be close to the top of your processor chain so that processors
|
|
22
|
+
run in a log that will ultimately be throttled.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
key: Unique key in the ``event_dict`` to determine if log should be throttled.
|
|
26
|
+
every_seconds: How long to throttle logs for, in seconds.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, key: str, every_seconds: int | float) -> None:
|
|
30
|
+
self.key = key
|
|
31
|
+
self.throttler = TimeThrottler(every_seconds)
|
|
32
|
+
|
|
33
|
+
def __call__(self, _: logging.Logger, __: str, event_dict: EventDict) -> EventDict:
|
|
34
|
+
if self.throttler.is_throttled(event_dict[self.key]):
|
|
35
|
+
raise DropEvent
|
|
36
|
+
return event_dict
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
import typing
|
|
5
|
+
import weakref
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class _Hashable(typing.Protocol):
|
|
9
|
+
def __hash__(self) -> int: ...
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ThrottlerProtocol(typing.Protocol):
|
|
13
|
+
def is_throttled(self, key: str) -> bool: ...
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _Link:
|
|
17
|
+
"""A link in a doubly-linked list"""
|
|
18
|
+
|
|
19
|
+
__slots__ = "at", "previous", "next", "__weakref__"
|
|
20
|
+
previous: "_Link" | None
|
|
21
|
+
next: "_Link" | None
|
|
22
|
+
at: float | None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TimeThrottler:
|
|
26
|
+
"""A throttler for time-based throttling."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, every_seconds: int | float) -> None:
|
|
29
|
+
self.every = every_seconds
|
|
30
|
+
|
|
31
|
+
self._last: _Link | None = None
|
|
32
|
+
self._indexes = weakref.WeakValueDictionary()
|
|
33
|
+
|
|
34
|
+
def is_throttled(self, key: _Hashable) -> bool:
|
|
35
|
+
"""Determine whether ``key`` is throttled.
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
>>> tt = TimeThrottler(every_seconds=1)
|
|
39
|
+
>>> tt.is_throttled("event")
|
|
40
|
+
False
|
|
41
|
+
>>> tt.is_throttled("event")
|
|
42
|
+
True
|
|
43
|
+
>>> tt.is_throttled("another-event")
|
|
44
|
+
False
|
|
45
|
+
>>> tt.is_throttled("another-event")
|
|
46
|
+
True
|
|
47
|
+
>>> time.sleep(1)
|
|
48
|
+
>>> tt.is_throttled("event")
|
|
49
|
+
False
|
|
50
|
+
>>> tt.is_throttled("another-event")
|
|
51
|
+
False
|
|
52
|
+
"""
|
|
53
|
+
now = time.monotonic()
|
|
54
|
+
|
|
55
|
+
if key not in self._indexes:
|
|
56
|
+
new = _Link()
|
|
57
|
+
new.at = now
|
|
58
|
+
# Stores a weak reference
|
|
59
|
+
self._indexes[key] = new
|
|
60
|
+
|
|
61
|
+
if self._last:
|
|
62
|
+
# 'next' is a weak reference
|
|
63
|
+
self._last.next = self._indexes[key]
|
|
64
|
+
# 'previous' is not
|
|
65
|
+
new.previous = self._last
|
|
66
|
+
|
|
67
|
+
self._last = new
|
|
68
|
+
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
link = self._indexes[key]
|
|
72
|
+
if (now - link.at) >= self.every:
|
|
73
|
+
del link
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
return True
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: structlog-throttling
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Log throttling utilities for structlog.
|
|
5
|
+
Keywords: structlog,throttling,throttle
|
|
6
|
+
License-Expression: MIT OR Apache-2.0
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: System :: Logging
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Dist: structlog>=25.5.0
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Project-URL: GitHub, https://github.com/tomasfarias/structlog-throttling
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# *structlog-throttling*: Throttling for [structlog](https://www.structlog.org/) loggers
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
structlog_throttling/__init__.py,sha256=KtJ2XWBLHTNeOBHq5r6OR7-m8Kmk570EEXItCTineco,133
|
|
2
|
+
structlog_throttling/processors.py,sha256=b61N6jsAOYno4usPuRxtDYxe6gjEsGl4wCqCaF3LPX8,1043
|
|
3
|
+
structlog_throttling/throttlers.py,sha256=hLqWLNp7OGRswy480C8YcwqDD04cRAeahwO5ezFZeOo,1885
|
|
4
|
+
structlog_throttling-1.0.0.dist-info/WHEEL,sha256=DpNsHFUm_gffZe1FgzmqwuqiuPC6Y-uBCzibcJcdupM,78
|
|
5
|
+
structlog_throttling-1.0.0.dist-info/METADATA,sha256=SioRAzLRDnXn4HqJh5VVBW5tBUMKwj5lZkkuIPnQdyk,992
|
|
6
|
+
structlog_throttling-1.0.0.dist-info/RECORD,,
|