-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* initial timer class and context manager * change log rotation defaults * Timer.elapsed_time_formatted property * implement duration logging in deployment
- Loading branch information
1 parent
b2a7961
commit 6f9a5dd
Showing
4 changed files
with
164 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Copyright (c) 2022 Food-X Technologies | ||
# | ||
# This file is part of foodx_devops_tools. | ||
# | ||
# You should have received a copy of the MIT License along with | ||
# foodx_devops_tools. If not, see <https://opensource.org/licenses/MIT>. | ||
|
||
"""Utilities for maintaining timing information.""" | ||
|
||
import contextlib | ||
import datetime | ||
import logging | ||
import time | ||
import typing | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
T = typing.TypeVar("T", bound="Timer") | ||
|
||
|
||
class Timer: | ||
"""A simple relative monotonic timer.""" | ||
|
||
def __init__(self: T) -> None: | ||
"""Construct ``Timer`` object.""" | ||
self.start_time_seconds: float = 0.0 | ||
self.stop_time_seconds: float = 0.0 | ||
|
||
def start(self: T) -> None: | ||
"""Record the start time.""" | ||
self.start_time_seconds = time.monotonic() | ||
|
||
def stop(self: T) -> None: | ||
"""Record the stop time.""" | ||
self.stop_time_seconds = time.monotonic() | ||
|
||
@property | ||
def elapsed_time_seconds(self: T) -> float: | ||
"""Calculate the elapsed time interval in seconds.""" | ||
return self.stop_time_seconds - self.start_time_seconds | ||
|
||
@property | ||
def elapsed_time_formatted(self: T) -> str: | ||
"""Calculate the elapsed time and format into a string.""" | ||
return str(datetime.timedelta(seconds=self.elapsed_time_seconds)) | ||
|
||
def log_duration( | ||
self: T, this_log: logging.Logger, iteration_context: str | ||
) -> None: | ||
"""Log the elapsed time of the iteration.""" | ||
this_log.info( | ||
f"{iteration_context} " | ||
f"elapsed time, {self.elapsed_time_formatted}" | ||
) | ||
|
||
|
||
@contextlib.contextmanager | ||
def timing( | ||
this_log: logging.Logger, | ||
iteration_context: str, | ||
) -> typing.Generator[Timer, None, Timer]: | ||
"""Manage the context of calculating a time interval.""" | ||
this_timer = Timer() | ||
this_timer.start() | ||
|
||
yield this_timer | ||
|
||
this_timer.stop() | ||
this_timer.log_duration(this_log, iteration_context) | ||
|
||
return this_timer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright (c) 2022 Food-X Technologies | ||
# | ||
# This file is part of foodx_devops_tools. | ||
# | ||
# You should have received a copy of the MIT License along with | ||
# foodx_devops_tools. If not, see <https://opensource.org/licenses/MIT>. | ||
|
||
import logging | ||
import time | ||
|
||
from foodx_devops_tools.profiling import timing | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def test_clean(mocker): | ||
mocker.patch( | ||
"foodx_devops_tools.profiling.time.monotonic", side_effect=[1.2, 3.5] | ||
) | ||
|
||
with timing(log, "some.context") as t: | ||
time.sleep(0.2) | ||
|
||
assert t.elapsed_time_seconds == 2.3 | ||
assert t.elapsed_time_formatted == "0:00:02.300000" |