Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECS-5104 Hutch-python feature: auto-close after timeout #385

Merged
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
9e03ced
Added new ipython_session_timer.py file to automatically time out idl…
janeliu-slac Jun 22, 2024
e6197eb
Updated ipy_config.InteractiveShellApp.extensions to include 'hutch_p…
janeliu-slac Jun 22, 2024
a2eac2d
Removed test values and replaced with actual values for maximum user …
janeliu-slac Jun 22, 2024
ace5003
Removed some other test data.
janeliu-slac Jun 22, 2024
9c1d3d3
Updated to set the maximum session duration to the session_duration v…
janeliu-slac Jun 25, 2024
7ede978
Added logic for new yaml value 'session_timer'.
janeliu-slac Jun 25, 2024
4455848
Added missing 'global max_idle_time' statement in def configure_timeo…
janeliu-slac Jun 25, 2024
7e9d351
Updated with a simpler way to set or cancel session timer.
janeliu-slac Jun 26, 2024
28920dd
Removed test code.
janeliu-slac Jun 26, 2024
1809287
Fixed synatx to be more pythonic.
janeliu-slac Jun 26, 2024
06ad824
Tried a new approach. Timer should be working now.
janeliu-slac Jun 27, 2024
0edcbba
Removed test values.
janeliu-slac Jun 27, 2024
e4b1fd7
Changed time.time to time.monotonic. Updated documentation. Changed l…
janeliu-slac Jun 27, 2024
a0f611f
Added 'session_timer' to VALID_KEYS to prevent warnings on startup.
janeliu-slac Jun 27, 2024
b2c187b
Removed previous release note (named incorrectly) and added new relea…
janeliu-slac Jun 28, 2024
548b8ef
Updated hardcoded time values to floating point numbers for consisten…
janeliu-slac Jun 28, 2024
d0bfee1
Merge branch 'master' into ECS-5104_ipython_session_timer
janeliu-slac Jun 28, 2024
d1d121d
Added new ipython_session_timer.py file to automatically time out idl…
janeliu-slac Jun 22, 2024
fdf997a
Updated ipy_config.InteractiveShellApp.extensions to include 'hutch_p…
janeliu-slac Jun 22, 2024
4010d8f
Removed test values and replaced with actual values for maximum user …
janeliu-slac Jun 22, 2024
302d05e
Removed some other test data.
janeliu-slac Jun 22, 2024
f229b9c
Updated to set the maximum session duration to the session_duration v…
janeliu-slac Jun 25, 2024
53acfab
Added logic for new yaml value 'session_timer'.
janeliu-slac Jun 25, 2024
64b644f
Added missing 'global max_idle_time' statement in def configure_timeo…
janeliu-slac Jun 25, 2024
73b1e36
Updated with a simpler way to set or cancel session timer.
janeliu-slac Jun 26, 2024
cc1da97
Removed test code.
janeliu-slac Jun 26, 2024
6396513
Fixed synatx to be more pythonic.
janeliu-slac Jun 26, 2024
78b7c58
Tried a new approach. Timer should be working now.
janeliu-slac Jun 27, 2024
6ca5371
Removed test values.
janeliu-slac Jun 27, 2024
89ce8ab
Changed time.time to time.monotonic. Updated documentation. Changed l…
janeliu-slac Jun 27, 2024
21ae070
Added 'session_timer' to VALID_KEYS to prevent warnings on startup.
janeliu-slac Jun 27, 2024
5e6fb81
Removed previous release note (named incorrectly) and added new relea…
janeliu-slac Jun 28, 2024
1d8a5f3
Updated hardcoded time values to floating point numbers for consisten…
janeliu-slac Jun 28, 2024
a083e29
In the release notes removed comments in API Changes. Nothing in this…
janeliu-slac Jun 28, 2024
78c8aa4
Merge remote-tracking branch 'origin/ECS-5104_ipython_session_timer' …
janeliu-slac Jun 28, 2024
323fe52
Renamed 385-ECS-5104_Hutch-python_feature:_auto-close_after_timeout.r…
janeliu-slac Jun 28, 2024
647b1b8
Replaced get_ipython() with the 'ipython' parameter passed in to IPyt…
janeliu-slac Jul 1, 2024
3a43139
Removed self._timer() function and replaced it with simple time.sleep…
janeliu-slac Jul 2, 2024
ae7ccaa
Added unit tests for ipython_session_timer.py.
janeliu-slac Jul 3, 2024
673df98
Removed unused import 'from IPython import get_ipython'.
janeliu-slac Jul 3, 2024
186d86e
Updated comments for clarity.
janeliu-slac Jul 3, 2024
67be8ec
Updated comments for clarity.
janeliu-slac Jul 3, 2024
5ee0778
Updated comments for clarity.
janeliu-slac Jul 3, 2024
cac9e36
Fixed a bunch of items from PR comments.
janeliu-slac Jul 3, 2024
8ad5a8f
Fixed issues from PR comments.
janeliu-slac Jul 3, 2024
ca8e9b2
Added the 'while(self.user_active)' statement back.
janeliu-slac Jul 9, 2024
70d75aa
Updated unit test for _start_session() function.
janeliu-slac Jul 10, 2024
d876afa
Updated class FakeIpython to handle ask_exit and pt_app.app.exit func…
janeliu-slac Jul 10, 2024
c764479
Updated name of test_start_session function.
janeliu-slac Jul 10, 2024
c6d118f
Replace previous changes with unittest.mock.MagicMock.
janeliu-slac Jul 10, 2024
8a09d3c
Added asserts to check session_timer.ip.ask_exit and session_timer.ip…
janeliu-slac Jul 10, 2024
70252f8
Fixed a few items.
janeliu-slac Jul 10, 2024
ebfa8c7
Merge branch 'master' into ECS-5104_ipython_session_timer
janeliu-slac Jul 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
385 ECS-5104 Hutch-python feature: auto-close after timeout
#################

API Changes
-----------
- Created an IPython extension that launches a daemon thread that runs an instance of IPythonSessionTimer class object.
janeliu-slac marked this conversation as resolved.
Show resolved Hide resolved

Features
--------
- Automatically timeout and closes hutch-python sessions after the user has been idle for a certain number of hours. The number of hours can be set in conf.yml for each hutch. If no value is set the default timeout duration is 48 hours.

Bugfixes
--------
- N/A

Maintenance
-----------
- N/A

Contributors
------------
- janeliu-slac
1 change: 1 addition & 0 deletions hutch_python/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def configure_ipython_session(args: HutchPythonArgs):
# Important Utilities
ipy_config.InteractiveShellApp.extensions = [
"hutch_python.ipython_log",
"hutch_python.ipython_session_timer",
"hutch_python.bug",
"hutch_python.pt_app_config"
]
Expand Down
1 change: 1 addition & 0 deletions hutch_python/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
'daq_type',
'daq_host',
'obj_config',
'session_timer',
)
NO_LOG_EXCEPTIONS = (KeyboardInterrupt, SystemExit)
LOG_DOMAINS = {".pcdsn", ".slac.stanford.edu"}
113 changes: 113 additions & 0 deletions hutch_python/ipython_session_timer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
This module modifies an ``ipython`` shell to automatically close if it has been
idle for a certain number of hours. Each hutch can configure their conf.yml
file to set a timeout duration. The default duration is 48 hours.
"""

import time
from threading import Thread

from IPython import get_ipython

max_idle_time = 172800.0 # number of seconds in 48 hours


def configure_timeout(session_timer):
global max_idle_time
if isinstance(session_timer, int) and session_timer > 0:
max_idle_time = session_timer


class IPythonSessionTimer:
'''
Class tracks the amount of time the current `InteractiveShell` instance (henceforth
called 'user session') has been idle and closes the session if more than 48
hours have passed.

Time is in seconds (floating point) since the epoch began. (In UNIX the
epoch started on January 1, 1970, 00:00:00 UTC)

Parameters
----------
ipython : ``IPython.terminal.interactiveshell.TerminalInteractiveShell``
The active ``ipython`` ``Shell``, perhaps the one returned by
``IPython.get_ipython()``.

Attributes
----------
curr_time: float
The current time in seconds.

max_idle_time: float
The maximum number of seconds a user session can be idle (default is
172800.0 seconds or 48 hours).

last_active_time: float
The time of the last user activity in this session.

idle_time: float
The amount of time the user session has been idle.
'''

def __init__(self, ipython):
global max_idle_time
janeliu-slac marked this conversation as resolved.
Show resolved Hide resolved
self.curr_time = 0.0
self.max_idle_time = 20.0 # max_idle_time
self.last_active_time = 0.0
self.idle_time = 0.0
self.user_active = False

ipython.events.register('pre_run_cell', self._set_user_active)
ipython.events.register('post_run_cell', self._set_user_inactive)

def _set_user_active(self):
self.user_active = True
self.last_active_time = time.monotonic()

def _set_user_inactive(self):
self.user_active = False
self.last_active_time = time.monotonic()

def _set_idle_time(self):
self.curr_time = time.monotonic()
self.idle_time = self.curr_time - self.last_active_time

def _timer(self, sleep_time):
time.sleep(sleep_time)

def _start_session(self):
# Check if idle_time has exceeded max_idle_time
while (self.idle_time < self.max_idle_time):
janeliu-slac marked this conversation as resolved.
Show resolved Hide resolved

# Check if user is active once every minute
while (self.user_active):
time.sleep(6)
janeliu-slac marked this conversation as resolved.
Show resolved Hide resolved
self.idle_time = 0

self._timer(self.max_idle_time - self.idle_time)
self._set_idle_time()

# Close the ipython session
print("This hutch-python session has timed out. Please start a new session.")

ip = get_ipython()
ip.ask_exit()
ip.pt_app.app.exit()


def load_ipython_extension(ipython):
"""
Initialize the `IPythonSessionTimer`.

This starts a timer that checks if the user session has been
idle for 48 hours or longer. If so, close the user session.

Parameters
----------
ipython: IPython.terminal.interactiveshell.TerminalInteractiveShell
The active ``ipython`` ``Shell``, the one returned by
``IPython.get_ipython()``.
"""
UserSessionTimer = IPythonSessionTimer(ipython)
t1 = Thread(target=UserSessionTimer._start_session, daemon=True)
janeliu-slac marked this conversation as resolved.
Show resolved Hide resolved
t1.start()
17 changes: 14 additions & 3 deletions hutch_python/load_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from pcdsdaq.sim import set_sim_mode as set_daq_sim
from pcdsdevices.interface import setup_preset_paths

import hutch_python.ipython_session_timer

from . import calc_defaults, plan_defaults, sim, log_setup
from .cache import LoadCache
Expand Down Expand Up @@ -202,7 +203,8 @@ def load_conf(conf, hutch_dir=None, args=None):
db = None
except KeyError:
db = None
logger.info('Missing db from conf. Will skip loading from shared database.')
logger.info(
'Missing db from conf. Will skip loading from shared database.')
janeliu-slac marked this conversation as resolved.
Show resolved Hide resolved

try:
load_level_setting = conf['load_level']
Expand Down Expand Up @@ -295,6 +297,15 @@ def load_conf(conf, hutch_dir=None, args=None):
daq_platform = 0
logger.info('Selected default hutch-python daq platform: 0')

# Set the session timeout duration
try:
hutch_python.ipython_session_timer.configure_timeout(
conf['session_timer'])
except KeyError:
hutch_python.ipython_session_timer.configure_timeout(172800)
logger.info(
'Missing session_timer value from conf. Set default value to 172800 seconds (48 hours).')

# Make cache namespace
cache = LoadCache((hutch or 'hutch') + '.db', hutch_dir=hutch_dir)

Expand Down Expand Up @@ -366,8 +377,8 @@ def load_conf(conf, hutch_dir=None, args=None):
logger.warning('Sim mode not implemented for lcls2 DAQ!')
logger.warning('Instantiating live DAQ!')
# Optional dependency
from psdaq.control.DaqControl import DaqControl # NOQA
from psdaq.control.BlueskyScan import BlueskyScan # NOQA
from psdaq.control.DaqControl import DaqControl # NOQA
from psdaq.control.BlueskyScan import BlueskyScan # NOQA
daq_control = DaqControl(
host=daq_host,
platform=daq_platform,
Expand Down
Loading