diff --git a/README.rst b/README.rst index d8d7183..c66f98f 100644 --- a/README.rst +++ b/README.rst @@ -20,6 +20,7 @@ Plugin Status (*Experimental*, *Production*, or *D =================================== ====================================================== tutor-contrib-learner-dashboard-mfe Deprecated tutor-contrib-test-legacy-js "Production" (Supported For Developers) +tutor-contrib-scout-apm Experimental =================================== ====================================================== Getting Started diff --git a/plugins/tutor-contrib-scout-apm/.gitignore b/plugins/tutor-contrib-scout-apm/.gitignore new file mode 100644 index 0000000..f6a874f --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/.gitignore @@ -0,0 +1,7 @@ +.*.swp +!.gitignore +TODO +__pycache__ +*.egg-info/ +/build/ +/dist/ diff --git a/plugins/tutor-contrib-scout-apm/MANIFEST.in b/plugins/tutor-contrib-scout-apm/MANIFEST.in new file mode 100644 index 0000000..c8fc7f4 --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/MANIFEST.in @@ -0,0 +1 @@ +recursive-include tutor_scout_apm/patches * diff --git a/plugins/tutor-contrib-scout-apm/README.rst b/plugins/tutor-contrib-scout-apm/README.rst new file mode 100644 index 0000000..7dccbb3 --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/README.rst @@ -0,0 +1,35 @@ +Scout APM plugin for `Tutor `_ +============================================================== + +This plugin allows Open edX LMS and Studio site operators add support for Scout APM monitoring. + +Installation +------------ + +This will install the `Scout APM `_ plugin directly from Github:: + + pip install git+https://github.com/openedx/openedx-tutor-plugins.git#subdirectory=plugins/tutor-contrib-scout-apm + +Alternatively, you can clone the parent repository locally and install it from the checkout:: + + git clone https://github.com/openedx/openedx-tutor-plugins.git + cd openedx-tutor-plugins/plugins/tutor-contrib-scout-apm + pip install -e . + +Usage +----- + +Once installed, run the following commands to enable it:: + + tutor plugins enable scout-apm + tutor images build openedx-dev + +Add the following entries to your Tutor ``config.yml`` file: + +* ``SCOUT_KEY``: Get this from your Scout APM account. +* ``SCOUT_NAME``: A user friendly name for your application. It will have "| LMS" or "| Studio" appended to it. So if you put "Sumac Test Server", the two Scout apps being reported will be "Sumac Test Server | LMS" and "Sumac Test Server | Studio". + +License +------- + +This software is licensed under the terms of the AGPLv3. diff --git a/plugins/tutor-contrib-scout-apm/setup.py b/plugins/tutor-contrib-scout-apm/setup.py new file mode 100644 index 0000000..f385a3a --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/setup.py @@ -0,0 +1,60 @@ +import io +import os +from setuptools import setup, find_packages + +HERE = os.path.abspath(os.path.dirname(__file__)) + + +def load_readme(): + with io.open(os.path.join(HERE, "README.rst"), "rt", encoding="utf8") as f: + return f.read() + + +def load_about(): + about = {} + with io.open( + os.path.join(HERE, "tutor_scout_apm", "__about__.py"), + "rt", + encoding="utf-8", + ) as f: + exec(f.read(), about) # pylint: disable=exec-used + return about + + +ABOUT = load_about() + + +setup( + name="tutor-scout-apm", + version=ABOUT["__version__"], + url="https://github.com/openedx/openedx-tutor-plugins", + project_urls={ + "Code": "https://github.com/openedx/openedx-tutor-plugins", + "Issue tracker": "https://github.com/openedx/openedx-tutor-plugins/issues", + }, + license="AGPLv3", + author="David Ormsbee", + description="Scout APM plugin for Tutor", + long_description=load_readme(), + packages=find_packages(exclude=["tests*"]), + include_package_data=True, + python_requires=">=3.8", + install_requires=["tutor"], + extras_require={"dev": ["tutor[dev]>=16.0.0,<19.0.0"]}, + entry_points={ + "tutor.plugin.v1": [ + "scout-apm = tutor_scout_apm.plugin" + ] + }, + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Affero General Public License v3", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + ], +) diff --git a/plugins/tutor-contrib-scout-apm/tutor_scout_apm/__about__.py b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/__about__.py new file mode 100644 index 0000000..5becc17 --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/__about__.py @@ -0,0 +1 @@ +__version__ = "1.0.0" diff --git a/plugins/tutor-contrib-scout-apm/tutor_scout_apm/__init__.py b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-cms-common-settings b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-cms-common-settings new file mode 100644 index 0000000..b4efe87 --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-cms-common-settings @@ -0,0 +1,13 @@ +SCOUT_MONITOR = True +SCOUT_KEY = "{{ SCOUT_KEY }}" +SCOUT_NAME = "{{ SCOUT_NAME }} | Studio" + +# Prepend the Scout APM before everything else so that it can inject its +# monitoring. +INSTALLED_APPS.insert(0, "scout_apm.django") + +SCOUT_MIDDLEWARE = [ + "scout_apm.django.middleware.MiddlewareTimingMiddleware", + "scout_apm.django.middleware.ViewTimingMiddleware", +] +MIDDLEWARE = SCOUT_MIDDLEWARE + MIDDLEWARE diff --git a/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-dockerfile-post-python-requirements b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-dockerfile-post-python-requirements new file mode 100644 index 0000000..0d3100a --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-dockerfile-post-python-requirements @@ -0,0 +1,2 @@ +RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \ + pip install "scout-apm>=3.2.1,<4.0" diff --git a/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-lms-common-settings b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-lms-common-settings new file mode 100644 index 0000000..f09dcd7 --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/patches/openedx-lms-common-settings @@ -0,0 +1,13 @@ +SCOUT_MONITOR = True +SCOUT_KEY = "{{ SCOUT_KEY }}" +SCOUT_NAME = "{{ SCOUT_NAME }} | LMS" + +# Prepend the Scout APM before everything else so that it can inject its +# monitoring. +INSTALLED_APPS.insert(0, "scout_apm.django") + +SCOUT_MIDDLEWARE = [ + "scout_apm.django.middleware.MiddlewareTimingMiddleware", + "scout_apm.django.middleware.ViewTimingMiddleware", +] +MIDDLEWARE = SCOUT_MIDDLEWARE + MIDDLEWARE diff --git a/plugins/tutor-contrib-scout-apm/tutor_scout_apm/plugin.py b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/plugin.py new file mode 100644 index 0000000..8037798 --- /dev/null +++ b/plugins/tutor-contrib-scout-apm/tutor_scout_apm/plugin.py @@ -0,0 +1,46 @@ +from __future__ import annotations +from glob import glob +import os +import pkg_resources +import uuid + +from tutor import hooks as tutor_hooks + +from .__about__ import __version__ + +######################################## +# CONFIGURATION +######################################## + +tutor_hooks.Filters.CONFIG_DEFAULTS.add_item( + ("SCOUT_KEY", "") +) +tutor_hooks.Filters.CONFIG_DEFAULTS.add_item( + ("SCOUT_NAME", "") +) + +######################################## +# INITIALIZATION TASKS +######################################## + + +######################################## +# TEMPLATE RENDERING +######################################## + + +######################################## +# PATCH LOADING +######################################## + +# For each file in tutor_media/patches, +# apply a patch based on the file's name and contents. +patch_files = glob( + os.path.join( + pkg_resources.resource_filename("tutor_scout_apm", "patches"), + "*", + ) +) +for path in patch_files: + with open(path, encoding="utf-8") as patch_file: + tutor_hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read()))