An object that, when called, returns ``int(time.time() * 1e6)`` when possible, but, if the value returned by ``time.time`` doesn't increase, drifts into the future and logs warnings. Exposed configuration attributes can be configured with arguments to ``__init__`` or by changing
| 26 | log = logging.getLogger(__name__) |
| 27 | |
| 28 | class MonotonicTimestampGenerator(object): |
| 29 | """ |
| 30 | An object that, when called, returns ``int(time.time() * 1e6)`` when |
| 31 | possible, but, if the value returned by ``time.time`` doesn't increase, |
| 32 | drifts into the future and logs warnings. |
| 33 | Exposed configuration attributes can be configured with arguments to |
| 34 | ``__init__`` or by changing attributes on an initialized object. |
| 35 | |
| 36 | .. versionadded:: 3.8.0 |
| 37 | """ |
| 38 | |
| 39 | warn_on_drift = True |
| 40 | """ |
| 41 | If true, log warnings when timestamps drift into the future as allowed by |
| 42 | :attr:`warning_threshold` and :attr:`warning_interval`. |
| 43 | """ |
| 44 | |
| 45 | warning_threshold = 1 |
| 46 | """ |
| 47 | This object will only issue warnings when the returned timestamp drifts |
| 48 | more than ``warning_threshold`` seconds into the future. |
| 49 | Defaults to 1 second. |
| 50 | """ |
| 51 | |
| 52 | warning_interval = 1 |
| 53 | """ |
| 54 | This object will only issue warnings every ``warning_interval`` seconds. |
| 55 | Defaults to 1 second. |
| 56 | """ |
| 57 | |
| 58 | def __init__(self, warn_on_drift=True, warning_threshold=1, warning_interval=1): |
| 59 | self.lock = Lock() |
| 60 | with self.lock: |
| 61 | self.last = 0 |
| 62 | self._last_warn = 0 |
| 63 | self.warn_on_drift = warn_on_drift |
| 64 | self.warning_threshold = warning_threshold |
| 65 | self.warning_interval = warning_interval |
| 66 | |
| 67 | def _next_timestamp(self, now, last): |
| 68 | """ |
| 69 | Returns the timestamp that should be used if ``now`` is the current |
| 70 | time and ``last`` is the last timestamp returned by this object. |
| 71 | Intended for internal and testing use only; to generate timestamps, |
| 72 | call an instantiated ``MonotonicTimestampGenerator`` object. |
| 73 | |
| 74 | :param int now: an integer to be used as the current time, typically |
| 75 | representing the current time in microseconds since the UNIX epoch |
| 76 | :param int last: an integer representing the last timestamp returned by |
| 77 | this object |
| 78 | """ |
| 79 | if now > last: |
| 80 | self.last = now |
| 81 | return now |
| 82 | else: |
| 83 | self._maybe_warn(now=now) |
| 84 | self.last = last + 1 |
| 85 | return self.last |