switch from jupyter-telemetry to jupyter-events

- id must be a URL
- change `record_event` to `emit`
This commit is contained in:
Min RK
2024-05-03 11:55:04 +02:00
parent c135e109ab
commit 335803d19f
6 changed files with 45 additions and 32 deletions

View File

@@ -1,27 +1,27 @@
# Event logging and telemetry
JupyterHub can be configured to record structured events from a running server using Jupyter's [Telemetry System]. The types of events that JupyterHub emits are defined by [JSON schemas] listed at the bottom of this page.
JupyterHub can be configured to record structured events from a running server using Jupyter's [Events System]. The types of events that JupyterHub emits are defined by [JSON schemas] listed at the bottom of this page.
## How to emit events
Event logging is handled by its `Eventlog` object. This leverages Python's standing [logging] library to emit, filter, and collect event data.
Event logging is handled by its `EventLogger` object. This leverages Python's standing [logging] library to emit, filter, and collect event data.
To begin recording events, you'll need to set two configurations:
> 1. `handlers`: tells the EventLog _where_ to route your events. This trait is a list of Python logging handlers that route events to the event log file.
> 2. `allows_schemas`: tells the EventLog _which_ events should be recorded. No events are emitted by default; all recorded events must be listed here.
> 1. `handlers`: tells the EventLogger _where_ to route your events. This trait is a list of Python logging handlers that route events to the event log file.
> 2. `allows_schemas`: tells the EventLogger _which_ events should be recorded. No events are emitted by default; all recorded events must be listed here.
Here's a basic example:
```
import logging
c.EventLog.handlers = [
c.EventLogger.handlers = [
logging.FileHandler('event.log'),
]
c.EventLog.allowed_schemas = [
'hub.jupyter.org/server-action'
c.EventLogger.allowed_schemas = [
'https://schema.jupyter.org/jupyterhub/events/server-action',
]
```
@@ -37,6 +37,15 @@ The output is a file, `"event.log"`, with events recorded as JSON data.
server-actions
```
:::{versionchanged} 5.0
JupyterHub 5.0 changes from the deprecated jupyter-telemetry to jupyter-events.
The main changes are:
- `EventLog` configuration is now called `EventLogger`
- The `hub.jupyter.org/server-action` schema is now called `https://schema.jupyter.org/jupyterhub/events/server-action`
:::
[json schemas]: https://json-schema.org/
[logging]: https://docs.python.org/3/library/logging.html
[telemetry system]: https://github.com/jupyter/telemetry
[events system]: https://jupyter-events.readthedocs.io

View File

@@ -21,6 +21,7 @@ from datetime import datetime, timedelta, timezone
from functools import partial
from getpass import getuser
from operator import itemgetter
from pathlib import Path
from textwrap import dedent
from typing import Optional
from urllib.parse import unquote, urlparse, urlunparse
@@ -29,7 +30,7 @@ import tornado.httpserver
import tornado.options
from dateutil.parser import parse as parse_date
from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader
from jupyter_telemetry.eventlog import EventLog
from jupyter_events.logger import EventLogger
from sqlalchemy.exc import OperationalError, SQLAlchemyError
from sqlalchemy.orm import joinedload
from tornado import gen, web
@@ -3251,13 +3252,10 @@ class JupyterHub(Application):
def init_eventlog(self):
"""Set up the event logging system."""
self.eventlog = EventLog(parent=self)
self.eventlog = EventLogger(parent=self)
for dirname, _, files in os.walk(os.path.join(here, 'event-schemas')):
for file in files:
if not file.endswith('.yaml'):
continue
self.eventlog.register_schema_file(os.path.join(dirname, file))
for schema in (Path(here) / "event-schemas").glob("**/*.yaml"):
self.eventlog.register_event_schema(schema)
def write_pid_file(self):
pid = os.getpid()

View File

@@ -1,4 +1,4 @@
"$id": hub.jupyter.org/server-action
"$id": https://schema.jupyter.org/jupyterhub/events/server-action
version: 1
title: JupyterHub server events
description: |

View File

@@ -1128,10 +1128,13 @@ class BaseHandler(RequestHandler):
SERVER_SPAWN_DURATION_SECONDS.labels(
status=ServerSpawnStatus.success
).observe(time.perf_counter() - spawn_start_time)
self.eventlog.record_event(
'hub.jupyter.org/server-action',
1,
{'action': 'start', 'username': user.name, 'servername': server_name},
self.eventlog.emit(
schema_id='https://schema.jupyter.org/jupyterhub/events/server-action',
data={
'action': 'start',
'username': user.name,
'servername': server_name,
},
)
proxy_add_start_time = time.perf_counter()
spawner._proxy_pending = True
@@ -1334,10 +1337,9 @@ class BaseHandler(RequestHandler):
SERVER_STOP_DURATION_SECONDS.labels(
status=ServerStopStatus.success
).observe(toc - tic)
self.eventlog.record_event(
'hub.jupyter.org/server-action',
1,
{
self.eventlog.emit(
schema_id='https://schema.jupyter.org/jupyterhub/events/server-action',
data={
'action': 'stop',
'username': user.name,
'servername': server_name,

View File

@@ -22,7 +22,7 @@ from traitlets.config import Config
# { ( '<schema id>', <version> ) : { <event_data> } }
valid_events = [
(
'hub.jupyter.org/server-action',
'https://schema.jupyter.org/jupyterhub/events/server-action',
1,
dict(action='start', username='test-username', servername='test-servername'),
)
@@ -32,7 +32,11 @@ valid_events = [
# { ( '<schema id>', <version> ) : { <event_data> } }
invalid_events = [
# Missing required keys
('hub.jupyter.org/server-action', 1, dict(action='start'))
(
'https://schema.jupyter.org/jupyterhub/events/server-action',
1,
dict(action='start'),
)
]
@@ -41,11 +45,11 @@ def eventlog_sink(app):
"""Return eventlog and sink objects"""
sink = io.StringIO()
handler = logging.StreamHandler(sink)
# Update the EventLog config with handler
# Update the EventLogger config with handler
cfg = Config()
cfg.EventLog.handlers = [handler]
cfg.EventLogger.handlers = [handler]
with mock.patch.object(app.config, 'EventLog', cfg.EventLog):
with mock.patch.object(app.config, 'EventLogger', cfg.EventLogger):
# recreate the eventlog object with our config
app.init_eventlog()
# return the sink from the fixture
@@ -59,7 +63,7 @@ def test_valid_events(eventlog_sink, schema, version, event):
eventlog, sink = eventlog_sink
eventlog.allowed_schemas = [schema]
# Record event
eventlog.record_event(schema, version, event)
eventlog.emit(schema_id=schema, data=event)
# Inspect consumed event
output = sink.getvalue()
assert output
@@ -75,4 +79,4 @@ def test_invalid_events(eventlog_sink, schema, version, event):
# Make sure an error is thrown when bad events are recorded
with pytest.raises(jsonschema.ValidationError):
recorded_event = eventlog.record_event(schema, version, event)
recorded_event = eventlog.emit(schema_id=schema, data=event)

View File

@@ -4,7 +4,7 @@ certipy>=0.1.2
idna
importlib_metadata>=3.6; python_version < '3.10'
jinja2>=2.11.0
jupyter_telemetry>=0.1.0
jupyter_events
oauthlib>=3.0
packaging
pamela>=1.1.0; sys_platform != 'win32'