Skip to content

Commit

Permalink
emit kernel actions effects from server kernel manager
Browse files Browse the repository at this point in the history
  • Loading branch information
Zsailer committed Apr 7, 2023
1 parent 98172e9 commit 7ae3fa8
Showing 1 changed file with 82 additions and 6 deletions.
88 changes: 82 additions & 6 deletions jupyter_server/services/kernels/kernelmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
# Distributed under the terms of the Modified BSD License.
import asyncio
import os
import pathlib
import typing as t
import warnings
from collections import defaultdict
from datetime import datetime, timedelta
from functools import partial
from functools import partial, wraps
from typing import Dict as DictType
from typing import Optional

Expand Down Expand Up @@ -39,6 +40,7 @@
validate,
)

from jupyter_server import DEFAULT_EVENTS_SCHEMA_PATH
from jupyter_server._tz import isoformat, utcnow
from jupyter_server.prometheus.metrics import KERNEL_CURRENTLY_RUNNING_TOTAL
from jupyter_server.utils import ApiPath, import_item, to_os_path
Expand Down Expand Up @@ -675,7 +677,8 @@ async def cull_kernel_if_idle(self, kernel_id):

# AsyncMappingKernelManager inherits as much as possible from MappingKernelManager,
# overriding only what is different.
class AsyncMappingKernelManager(MappingKernelManager, AsyncMultiKernelManager): # type:ignore[misc]
# type:ignore[misc]
class AsyncMappingKernelManager(MappingKernelManager, AsyncMultiKernelManager):
"""An asynchronous mapping kernel manager."""

@default("kernel_manager_class")
Expand Down Expand Up @@ -713,11 +716,27 @@ class ServerKernelManager(AsyncIOLoopKernelManager):
None, allow_none=True, help="The current execution state of the kernel"
)
reason = Unicode("", help="The reason for the last failure against the kernel")

last_activity = Instance(datetime, help="The last activity on the kernel")

base_event_schemas = List([])
extra_event_schemas = List([])
event_logger = Instance(EventLogger).tag(config=True)
# A list of pathlib objects, each pointing at an event
# schema to register with this kernel manager's eventlogger.
# This trait should not be overridden.
@property
def core_event_schema_paths(self) -> t.List[pathlib.Path]:
return [DEFAULT_EVENTS_SCHEMA_PATH / "kernel_actions" / "v1.yaml"]

# This trait is intended for subclasses to override and define
# custom event schemas.
extra_event_schema_paths = List(
default_value=[],
help="""
A list of pathlib.Path objects pointing at to register with
the kernel manager's eventlogger.
""",
).tag(config=True)

event_logger = Instance(EventLogger)

@default("event_logger")
def _default_event_logger(self):
Expand All @@ -728,7 +747,7 @@ def _default_event_logger(self):
# If parent does not have an event logger, create one.
logger = EventLogger()
# Ensure that all the expected schemas are registered. If not, register them.
schemas = self.base_event_schemas + self.extra_event_schemas
schemas = self.core_event_schema_paths + self.extra_event_schema_paths
for schema_path in schemas:
# Try registering the event.
try:
Expand All @@ -739,4 +758,61 @@ def _default_event_logger(self):
return logger

def emit(self, schema_id, data):
"""Emit an event from the kernel manager."""
self.event_logger.emit(schema_id=schema_id, data=data)

@wraps(AsyncIOLoopKernelManager.start_kernel)
async def start_kernel(self, *args, **kwargs):
result = await super().start_kernel(*args, **kwargs)
self.emit(
schema_id="https://events.jupyter.org/jupyter_server/kernel_actions/v1",
data={
"kernel_id": self.kernel_id,
"kernel_name": self.kernel_name,
"action": "start",
"message": f"Kernel {self.kernel_id} was started.",
},
)
return result

@wraps(AsyncIOLoopKernelManager.interrupt_kernel)
async def interrupt_kernel(self, *args, **kwargs):
result = await super().interrupt_kernel(*args, **kwargs)
self.emit(
schema_id="https://events.jupyter.org/jupyter_server/kernel_actions/v1",
data={
"kernel_id": self.kernel_id,
"kernel_name": self.kernel_name,
"action": "interrupt",
"message": f"Kernel {self.kernel_id} was interrupted.",
},
)
return result

@wraps(AsyncIOLoopKernelManager.shutdown_kernel)
async def shutdown_kernel(self, *args, **kwargs):
result = await super().shutdown_kernel(*args, **kwargs)
self.emit(
schema_id="https://events.jupyter.org/jupyter_server/kernel_actions/v1",
data={
"kernel_id": self.kernel_id,
"kernel_name": self.kernel_name,
"action": "shutdown",
"message": f"Kernel {self.kernel_id} was shutdown.",
},
)
return result

@wraps(AsyncIOLoopKernelManager.restart_kernel)
async def restart_kernel(self, *args, **kwargs):
result = await super().restart_kernel(*args, **kwargs)
self.emit(
schema_id="https://events.jupyter.org/jupyter_server/kernel_actions/v1",
data={
"kernel_id": self.kernel_id,
"kernel_name": self.kernel_name,
"action": "restart",
"message": f"Kernel {self.kernel_id} was restarted.",
},
)
return result

0 comments on commit 7ae3fa8

Please sign in to comment.