Skip to content

Jupyter server telemetry and event logging #352

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

Closed
wants to merge 78 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
344bb57
Add initial eventlog hook
yuvipanda Jul 7, 2019
a0f40ea
Install jupyter_telemetry from source
yuvipanda Jul 7, 2019
96bf2f0
Set up an eventlog API endpoint
yuvipanda Jul 7, 2019
06b91e0
Use different naming convention & add test for it
yuvipanda Jul 7, 2019
716ff1b
Don't use f-strings
yuvipanda Jul 7, 2019
8e122fc
Derive JSON Schema files from YAML files
yuvipanda Jul 9, 2019
f9a0dfb
Keep event schemas in YAML
yuvipanda Jul 9, 2019
c7428e8
Depend on the jupyter_telemetry package
yuvipanda Jul 9, 2019
9437e88
read schemas from new utils function
Zsailer Oct 1, 2019
6e3c80c
Add fix for tables in RTD theme sphinx docs.
Zsailer Oct 1, 2019
4035fd5
add event schema auto-documentation to jupyter notebook docs
Zsailer Oct 1, 2019
23d50a3
format paths in recorded events
Zsailer Oct 1, 2019
3c94970
add documentation for eventlog endpoint
Zsailer Oct 1, 2019
e76c91b
return exception as 400 error in eventlog endpoint
Zsailer Oct 1, 2019
2ce7c54
normalize path in emitted event
Zsailer Oct 1, 2019
5794d31
initial tests
Zsailer May 19, 2020
7c9d3d5
add initial telemetry docs
Zsailer May 19, 2020
ef8573d
fix jupyter_telemetry dependency
Zsailer May 19, 2020
ea9e352
point telemetry at correct dev branch
Zsailer May 19, 2020
b06f7d6
add tests for eventlog
kiendang Oct 20, 2020
38712f9
Enable CodeQL runs on all pushed branches
kevin-bates Nov 5, 2020
9e18c8e
Nested shells should not be login (#5247) (#5565)
dlukes Jul 1, 2020
66962b5
Improve login shell heuristics
dlukes Jul 3, 2020
293bff0
Allow toggling auth for prometheus metrics
yuvipanda Nov 18, 2020
679683c
Merge pull request #343 from kevin-bates/port-5565-5588
Zsailer Dec 1, 2020
c45d7f3
Merge pull request #344 from yuvipanda/prometheus-auth
Zsailer Dec 1, 2020
f13a22b
Merge pull request #333 from kevin-bates/codeql-pushed-branches
Zsailer Dec 1, 2020
d865e59
Fix upgrade packaging dependencies build step
Dec 3, 2020
ca492c1
Merge pull request #354 from mwakaba2/fix-tests-setup
Zsailer Dec 3, 2020
20c84e8
sync _redirect_safe with upstream
minrk Dec 9, 2020
1858bb5
Restore pytest plugin from pytest-jupyter
kevin-bates Dec 10, 2020
28f784b
Merge pull request #360 from kevin-bates/restore-pytest-plugin
Zsailer Dec 10, 2020
1cfc211
[DRAFT] Asynchronous Contents API
Oct 30, 2020
ca60bcf
Add asynchronous support section
Nov 12, 2020
3a97a6a
Create AsyncFileContentsManager
Nov 12, 2020
24dd618
Use jp prefix for fixtures
Nov 17, 2020
6bd874d
Remove condition for testing python 3.5
Nov 17, 2020
5a521e3
Add new async classes to serverapp
Nov 17, 2020
0afe5b1
Fix lint errors
Nov 17, 2020
3bc0feb
Skip test for windows
Nov 19, 2020
9be92d8
Create AsyncLargeFileManager
Nov 20, 2020
564325e
Create AsyncGenericFileCheckpoints
Nov 20, 2020
188fc3c
Make handlers compatible with async CMs
Dec 3, 2020
b19edc0
update docs and configs
Dec 4, 2020
01500bd
Checkpoints: Make all not implemented methods async
Dec 4, 2020
bd057ef
Update docs
Dec 4, 2020
7d863f3
Update jupyter_server/services/contents/fileio.py
Zsailer Dec 10, 2020
6fef2a8
Merge pull request #324 from mwakaba2/async-contents-api
Zsailer Dec 10, 2020
d05aebe
update changelog for 1.1.0 release
Zsailer Dec 11, 2020
082fc38
remove changelog from docs to reduce duplicity
Zsailer Dec 11, 2020
f55926e
remove references to changelog
Zsailer Dec 11, 2020
3bb4caa
Merge pull request #362 from Zsailer/changelog
Zsailer Dec 11, 2020
921508b
Release 1.1.0
Zsailer Dec 11, 2020
a3a3a46
Back to dev version
Zsailer Dec 11, 2020
7554712
Fix: await dir_exists
Dec 15, 2020
b328e0a
Merge pull request #363 from mwakaba2/fix-async-contents-api
kevin-bates Dec 16, 2020
85e4abc
Merge pull request from GHSA-9f66-54xg-pc2c
Zsailer Dec 16, 2020
506e10b
Release 1.1.1
Zsailer Dec 16, 2020
7f81846
Back to dev version
Zsailer Dec 16, 2020
adcfa25
Add initial eventlog hook
yuvipanda Jul 7, 2019
6870c34
Install jupyter_telemetry from source
yuvipanda Jul 7, 2019
86d9bcb
Set up an eventlog API endpoint
yuvipanda Jul 7, 2019
ed746b6
Use different naming convention & add test for it
yuvipanda Jul 7, 2019
e58531f
Don't use f-strings
yuvipanda Jul 7, 2019
913215a
Derive JSON Schema files from YAML files
yuvipanda Jul 9, 2019
a921ff0
Keep event schemas in YAML
yuvipanda Jul 9, 2019
54b3594
Depend on the jupyter_telemetry package
yuvipanda Jul 9, 2019
5a82794
read schemas from new utils function
Zsailer Oct 1, 2019
e9ffb47
Add fix for tables in RTD theme sphinx docs.
Zsailer Oct 1, 2019
f08cc24
add event schema auto-documentation to jupyter notebook docs
Zsailer Oct 1, 2019
9262194
format paths in recorded events
Zsailer Oct 1, 2019
5ed4652
add documentation for eventlog endpoint
Zsailer Oct 1, 2019
791dbba
return exception as 400 error in eventlog endpoint
Zsailer Oct 1, 2019
80682e8
normalize path in emitted event
Zsailer Oct 1, 2019
b10174f
initial tests
Zsailer May 19, 2020
1bbb705
add initial telemetry docs
Zsailer May 19, 2020
c69bdd9
add tests for eventlog
kiendang Oct 20, 2020
b6db850
Resolve conflicts
kiendang Dec 17, 2020
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
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ name: "CodeQL"

on:
push:
branches: [ master ]
branches: [ '*' ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
architecture: 'x64'
- name: Upgrade packaging dependencies
run: |
pip install --upgrade pip setuptools wheel
pip install --upgrade pip setuptools wheel --user
- name: Get pip cache dir
id: pip-cache
run: |
Expand Down
11 changes: 2 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
MANIFEST
docs/source/operators/events
build
dist
_build
docs/man/*.gz
docs/source/api/generated
docs/source/config.rst
docs/gh-pages
notebook/i18n/*/LC_MESSAGES/*.mo
notebook/i18n/*/LC_MESSAGES/nbjs.json
notebook/static/components
notebook/static/style/*.min.css*
notebook/static/*/js/built/
notebook/static/*/built/
notebook/static/built/
notebook/static/*/js/main.min.js*
notebook/static/lab/*bundle.js
docs/source/events
node_modules
*.py[co]
__pycache__
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.1.0] - 2020-12-11

[Full Changelog](https://github.com/jupyter-server/jupyter_server/compare/1.0.10...1.1.0)

**Merged pull requests:**

- Restore pytest plugin from pytest-jupyter [\#360](https://github.com/jupyter-server/jupyter_server/pull/360) ([kevin-bates](https://github.com/kevin-bates))
- Fix upgrade packaging dependencies build step [\#354](https://github.com/jupyter-server/jupyter_server/pull/354) ([mwakaba2](https://github.com/mwakaba2))
- Await \_connect and inline read\_messages callback to \_connect [\#350](https://github.com/jupyter-server/jupyter_server/pull/350) ([ricklamers](https://github.com/ricklamers))
- Update release instructions and dev version [\#348](https://github.com/jupyter-server/jupyter_server/pull/348) ([kevin-bates](https://github.com/kevin-bates))
- Fix test\_trailing\_slash [\#346](https://github.com/jupyter-server/jupyter_server/pull/346) ([kevin-bates](https://github.com/kevin-bates))
- Apply security advisory fix to master [\#345](https://github.com/jupyter-server/jupyter_server/pull/345) ([kevin-bates](https://github.com/kevin-bates))
- Allow toggling auth for prometheus metrics [\#344](https://github.com/jupyter-server/jupyter_server/pull/344) ([yuvipanda](https://github.com/yuvipanda))
- Port Notebook PRs 5565 and 5588 - terminal shell heuristics [\#343](https://github.com/jupyter-server/jupyter_server/pull/343) ([kevin-bates](https://github.com/kevin-bates))
- Port gateway updates from notebook \(PRs 5317 and 5484\) [\#341](https://github.com/jupyter-server/jupyter_server/pull/341) ([kevin-bates](https://github.com/kevin-bates))
- add check\_origin handler to gateway WebSocketChannelsHandler [\#340](https://github.com/jupyter-server/jupyter_server/pull/340) ([ricklamers](https://github.com/ricklamers))
- Remove pytest11 entrypoint and plugin, require tornado 6.1, remove asyncio patch, CI work [\#339](https://github.com/jupyter-server/jupyter_server/pull/339) ([bollwyvl](https://github.com/bollwyvl))
- Switch fixtures to use those in pytest-jupyter to avoid collisions [\#335](https://github.com/jupyter-server/jupyter_server/pull/335) ([kevin-bates](https://github.com/kevin-bates))
- Enable CodeQL runs on all pushed branches [\#333](https://github.com/jupyter-server/jupyter_server/pull/333) ([kevin-bates](https://github.com/kevin-bates))
- Asynchronous Contents API [\#324](https://github.com/jupyter-server/jupyter_server/pull/324) ([mwakaba2](https://github.com/mwakaba2))



## [1.0.6] - 2020-11-18

1.0.6 is a security release, fixing one vulnerability:
Expand Down
6 changes: 6 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ include setupbase.py
# include everything in package_data
recursive-include jupyter_server *

# Event Schemas
graft jupyter_server/event-schemas

# Event Schemas
graft jupyter_server/event-schemas

# Documentation
graft docs
exclude docs/\#*
Expand Down
3 changes: 2 additions & 1 deletion docs/doc-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ prometheus_client
sphinxcontrib_github_alt
sphinxcontrib-openapi
sphinxemoji
git+https://github.com/pandas-dev/pydata-sphinx-theme.git@master
git+https://github.com/pandas-dev/pydata-sphinx-theme.git@master
jupyter_telemetry_sphinxext
3 changes: 2 additions & 1 deletion docs/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ dependencies:
- sphinxcontrib_github_alt
- sphinxcontrib-openapi
- sphinxemoji
- git+https://github.com/pandas-dev/pydata-sphinx-theme.git@master
- git+https://github.com/pandas-dev/pydata-sphinx-theme.git@master
- sphinx-jsonschema
13 changes: 13 additions & 0 deletions docs/source/_static/theme_overrides.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* override table width restrictions */
@media screen and (min-width: 767px) {

.wy-table-responsive table td {
/* !important prevents the common CSS stylesheets from overriding
this as on RTD they are loaded after this stylesheet */
white-space: normal !important;
}

.wy-table-responsive {
overflow: visible !important;
}
}
14 changes: 12 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@
'sphinx.ext.mathjax',
'IPython.sphinxext.ipython_console_highlighting',
'sphinxcontrib_github_alt',
'sphinxcontrib.openapi',
'sphinxemoji.sphinxemoji'
'jupyter_telemetry_sphinxext'
]

# Add any paths that contain templates here, relative to this directory.
Expand Down Expand Up @@ -208,6 +207,12 @@
# since it is needed to properly generate _static in the build directory
html_static_path = ['_static']

html_context = {
'css_files': [
'_static/theme_overrides.css', # override wide tables in RTD theme
],
}

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
Expand Down Expand Up @@ -371,3 +376,8 @@

# import before any doc is built, so _ is guaranteed to be injected
import jupyter_server.transutils

# Jupyter telemetry configuration values.
jupyter_telemetry_schema_source = "../jupyter_server/event-schemas" # Path is relative to conf.py
jupyter_telemetry_schema_output = "source/operators/events" # Path is relative to conf.py
jupyter_telemetry_index_title = "Telemetry Event Schemas" # Title of the index page that lists all found schemas.
31 changes: 26 additions & 5 deletions docs/source/developers/contents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,19 +192,19 @@ methods:
ContentsManager.is_hidden

You may be required to specify a Checkpoints object, as the default one,
``FileCheckpoints``, could be incompatible with your custom
``FileCheckpoints``, could be incompatible with your custom
ContentsManager.

Customizing Checkpoints
-----------------------
.. currentmodule:: jupyter_server.services.contents.checkpoints

Customized Checkpoint definitions allows behavior to be
Customized Checkpoint definitions allows behavior to be
altered and extended.

The ``Checkpoints`` and ``GenericCheckpointsMixin`` classes
(from :mod:`jupyter_server.services.contents.checkpoints`)
have reusable code and are intended to be used together,
have reusable code and are intended to be used together,
but require the following methods to be implemented.

.. autosummary::
Expand All @@ -220,7 +220,7 @@ No-op example
~~~~~~~~~~~~~

Here is an example of a no-op checkpoints object - note the mixin
comes first. The docstrings indicate what each method should do or
comes first. The docstrings indicate what each method should do or
return for a more complete implementation.

.. code-block:: python
Expand All @@ -238,7 +238,7 @@ return for a more complete implementation.
def delete_checkpoint(self, checkpoint_id, path):
"""deletes a checkpoint for a file"""
def list_checkpoints(self, path):
"""returns a list of checkpoint models for a given file,
"""returns a list of checkpoint models for a given file,
default just does one per file
"""
return []
Expand Down Expand Up @@ -267,3 +267,24 @@ ContentsManager.
.. _NBFormat: https://nbformat.readthedocs.io/en/latest/index.html
.. _PGContents: https://github.com/quantopian/pgcontents
.. _PostgreSQL: https://www.postgresql.org/

Asynchronous Support
--------------------

An asynchronous version of the Contents API is available to run slow IO processes concurrently.

- :class:`~manager.AsyncContentsManager`
- :class:`~filemanager.AsyncFileContentsManager`
- :class:`~largefilemanager.AsyncLargeFileManager`
- :class:`~checkpoints.AsyncCheckpoints`
- :class:`~checkpoints.AsyncGenericCheckpointsMixin`

.. note::

.. _contentfree:

In most cases, the non-asynchronous Contents API is performant for local filesystems.
However, if the Jupyter Notebook web application is interacting with a high-latent virtual filesystem, you may see performance gains by using the asynchronous version.
For example, if you're experiencing terminal lag in the web application due to the slow and blocking file operations, the asynchronous version can reduce the lag.
Before opting in, comparing both non-async and async options' performances is recommended.

4 changes: 1 addition & 3 deletions docs/source/developers/dependency.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
Depending on Jupyter Server
===========================

If your project depends directly on Jupyter Server, be sure to watch Jupyter Server's :ref:`Change Log <changelog>` and pin your project to a version that works for your application. Major releases represent possible backwards-compatibility breaking API changes or features.
If your project depends directly on Jupyter Server, be sure to watch Jupyter Server's ChangeLog and pin your project to a version that works for your application. Major releases represent possible backwards-compatibility breaking API changes or features.

When a new major version in released on PyPI, a branch for that version will be created in this repository, and the version of the master branch will be bumped to the next major version number. That way, the master branch always reflects the latest un-released version.

To see the changes between releases, checkout the :ref:`Change Log <changelog>`.

To install the latest patch of a given version:

.. code-block:: console
Expand Down
1 change: 0 additions & 1 deletion docs/source/developers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ These pages target people writing Jupyter Web applications and server extensions
extensions
savehooks
contents
../other/changelog
61 changes: 61 additions & 0 deletions docs/source/eventlog.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Eventlogging and Telemetry
==========================

The Notebook Server can be configured to record structured events from a running server using Jupyter's `Telemetry System`_. The types of events that the Notebook Server emits are defined by `JSON schemas`_ listed below_ emitted as JSON data, defined and validated by the JSON schemas listed below.


.. _logging: https://docs.python.org/3/library/logging.html
.. _`Telemetry System`: https://github.com/jupyter/telemetry
.. _`JSON schemas`: https://json-schema.org/

Emitting Server Events
----------------------

Event logging is handled by its ``Eventlog`` 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
2. ``allows_schemas``: tells the EventLog *which* events should be recorded. No events are emitted by default; all recorded events must be listed here.

Here's a basic example for emitting events from the `contents` service:

.. code-block::

import logging

c.EventLog.handlers = [
logging.FileHandler('event.log'),
]

c.EventLog.allowed_schemas = [
'hub.jupyter.org/server-action'
]

The output is a file, ``"event.log"``, with events recorded as JSON data.

`eventlog` endpoint
-------------------

The Notebook Server provides a public REST endpoint for external applications to validate and log events
through the Server's Event Log.

To log events, send a `POST` request to the `/api/eventlog` endpoint. The body of the request should be a
JSON blog and is required to have the follow keys:

1. `'schema'` : the event's schema ID.
2. `'version'` : the version of the event's schema.
3. `'event'` : the event data in JSON format.

Events that are validated by this endpoint must have their schema listed in the `allowed_schemas` trait listed above.

.. _below:


Server Event schemas
--------------------

.. toctree::
:maxdepth: 2

events/index
3 changes: 2 additions & 1 deletion docs/source/operators/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ These pages are targeted at people using, configuring, and/or deploying multiple
configuring-extensions
migrate-from-nbserver
public-server
security
security
telemetry
61 changes: 61 additions & 0 deletions docs/source/operators/telemetry.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Telemetry and Eventlogging
==========================

Jupyter Server can be configured to record structured events from a running server using Jupyter's `Telemetry System`_. The types of events that the Server emits are defined by `JSON schemas`_ listed below_ emitted as JSON data, defined and validated by the JSON schemas listed below.


.. _logging: https://docs.python.org/3/library/logging.html
.. _`Telemetry System`: https://github.com/jupyter/telemetry
.. _`JSON schemas`: https://json-schema.org/

Emitting Server Events
----------------------

Event logging is handled by its ``Eventlog`` 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
2. ``allows_schemas``: tells the EventLog *which* events should be recorded. No events are emitted by default; all recorded events must be listed here.

Here's a basic example for emitting events from the `contents` service:

.. code-block::

import logging

c.EventLog.handlers = [
logging.FileHandler('event.log'),
]

c.EventLog.allowed_schemas = [
'hub.jupyter.org/server-action'
]

The output is a file, ``"event.log"``, with events recorded as JSON data.

`eventlog` endpoint
-------------------

The Notebook Server provides a public REST endpoint for external applications to validate and log events
through the Server's Event Log.

To log events, send a `POST` request to the `/api/eventlog` endpoint. The body of the request should be a
JSON blog and is required to have the follow keys:

1. `'schema'` : the event's schema ID.
2. `'version'` : the version of the event's schema.
3. `'event'` : the event data in JSON format.

Events that are validated by this endpoint must have their schema listed in the `allowed_schemas` trait listed above.

.. _below:


Server Event schemas
--------------------

.. toctree::
:maxdepth: 2

events/index
Loading