Daniel Fainberg
Lead maintainer
tool_monitoringThe tool_monitoring Plugin makes it easy to integrate standard monitoring setups (such as Prometheus & Grafana) with any running Moodle instance.
Development started at the 2025 Moodle Moot DACH DevCamp, where the project won 1st prize, showing strong community demand for a standardized monitoring solution for Moodle.

metric class and register it for collection.The minimum supported Moodle version is 5.0 (build 2025041400).
You install tool_monitoring just like any other Moodle plugin. Starting with Moodle 5.1, it belongs in the public/admin/tool/monitoring directory. (For Moodle 5.0 it goes into admin/tool/monitoring.)
For example, using git from the root directory of your Moodle 5.1+ installation:
$ git clone \
https://github.com/daniil-berg/moodle-tool_monitoring.git \
public/admin/tool/monitoring
For other options and general plugin installation instructions, see the official Moodle documentation.
The admin dashboard can be found at /admin/tool/monitoring or by navigating to Site administration > Plugins > Admin tools > Monitoring > Overview.

There you can view all registered metrics, enable/disable them, add/remove metric tags, and configure some metrics individually.
Out of the box, tool_monitoring comes with the following metrics:
| Name | Description | Partitioned by | Configurable? |
|---|---|---|---|
courses |
Current number of courses. | visible (true/false) |
no |
overdue_tasks |
Number of tasks that should have run already but have not | type (adhoc/scheduled) |
no |
quiz_attempts_in_progress |
Number of ongoing quiz attempts with an approaching deadline | - | yes |
user_accounts |
Current number of user accounts | auth (available methods), suspended (true/false), deleted (true/false) |
no |
users_online |
Number of users that have recently accessed the site | time_window (last user access time to count, multiple configurable) |
yes |
Note: Any Moodle component can add its own custom metrics. (See the section "Adding a custom metric" for details.) Once a metric is registered, it will be listed in the dashboard as well.
Some metrics have their own specific configuration options. As an example, the pre-installed users_online metric has configurable time windows for counting users' most recent access.
To configure it, click on the gear icon next to it on the dashboard. A config page for that metric will open that looks like this:

All metrics share basic settings, namely the enabled/disabled state and associated tags. But for configurable metrics there can be arbitrary additional form fields.
In this example, the users_online metric has an input field for the time windows in seconds. The form validates the input to be a comma-separated list of positive integers. During export a separate labeled metric value will be produced for every specified time window.
After modifying the form data, clicking the "Save changes" button redirects you back to the dashboard.
The pre-installed Prometheus exporter has its own settings under Site administration > Plugins > Admin tools > Monitoring > Available Exporters > Prometheus Exporter.
The actual Prometheus endpoint is immediately accessible and can be reached at the route /monitoringexporter_prometheus/metrics. So if your Moodle web root is https://example.com, the full URL will look like this:
https://example.com/monitoringexporter_prometheus/metrics
Important: This relies on the router and your webserver being properly configured. If not, the endpoint is reached at
/r.php/monitoringexporter_prometheus/metrics. See the relevant Moodle documentation for details.
That endpoint can be secured by specifying an access token (shared secret) in the monitoringexporter_prometheus | prometheus_token setting.
Warning: The endpoint is unauthenticated by default. Until a
prometheus_tokenis set, anyone who can reach the URL can see all enabled metrics with no credentials. Even though by default all new metrics are disabled, a token should be set before exposing the endpoint to any untrusted network.
When a token is set, the route handler expects it in the Authorization header in the conventional Authorization: Bearer <token> format. If no matching header line is found, it falls back to the token query parameter.
Caution: Secrets passed via query parameter can leak into server logs. We strongly advise passing the access token via the
Authorizationheader. See the Prometheus configuration section for an example.
Sometimes it is useful to not export all available metrics at the same time. Perhaps some of your metrics are cheap and quick to calculate, allowing tight scrape intervals, while others would impact performance too much if the exporter were called too often. Or maybe you have different export destinations for some metrics.
Whatever the use case, tool_monitoring allows you to easily group metrics by leveraging Moodle's Tag API. You can assign arbitrary tags (scoped to their own distinct "metrics" tag area) to any metric. Exporters can then provide a parameter to filter the produced metrics by the tags they carry. For example, the included Prometheus exporter accepts a tag query parameter in the URL. Passing a single tag name will filter out all metrics that do not carry that tag. Passing a comma-separated list of tags will ensure only metrics that carry all of those tags will be exported. (Note the AND-condition being applied here.) For implementation details, take a look at the Prometheus exporter class.
To assign tags to a metric, go to its configuration page. Then simply enter the tag names in the "Tags" field.

You can add multiple tags at once by putting a comma after each one. Clicking the "Save changes" button redirects you back to the dashboard. You'll notice the tags you just added show up in the list there.

Clicking on one of them will filter the list of metrics accordingly.

The "Manage tags" button will bring you Moodle's usual tag overview/management page for the monitoring tag collection.
This assumes you have a Prometheus server already up and running. All you need to do is to add a job to the scrape_configs section in your prometheus.yml like this:
scrape_configs:
# Choose whatever unique job name you like.
- job_name: moodle
# The default scheme is HTTP.
scheme: https
# If you have set an access token, provide it here.
authorization:
credentials: 'super-secure-secret'
# Specify the full endpoint path. The default is just '/metrics'.
# If Moodle routing is not fully configured, you have to prepend '/r.php' to the path.
metrics_path: /monitoringexporter_prometheus/metrics
# Specify the target host.
static_configs:
- targets: ['example.com']
If you are making use of tags to group specific metrics, you can filter for them by also specifying the tag query parameter. Multiple tags can be specified by separating them with a comma. For example, to only scrape metrics that have both the hello and the world tag, you would add a params section like this:
scrape_configs:
- job_name: moodle-hello-world
params:
- tag: ['hello,world']
# Same config as above...
For exhaustive details about the various config options, see the official Prometheus documentation.
This assumes you have configured Prometheus as described above. You can import the example Grafana dashboard from docs/examples/grafana_dashboard.json into grafana:
Go to "Dashboards" > "New" and select "import" and select the json-file or paste its content there. Select the Prometheus data source and click "import".
A metric by popular definition, is a measure of something. This is also true in tool_monitoring, but here a metric also
metric sub-classs,Example:
Our pre-installed metric named user_accounts. It measures the current number of user accounts in the system and is a gauge type metric. In our implementation it produces multiple values.
Any single scalar (i.e. float|int) value produced by a metric is called a metric value.
Metric values can carry labels (see "label") and are encapsulated by the metric_value class.
There are currently only two types of metrics that tool_monitoring supports, gauges and counters.
The metric type is encapsulated by the metric_type enum.
A key-value-pair associated with a metric is referred to as a label. The pair is also referred to as label name and label value; both are strings.
The primary purpose of labels is to add dimensionality to metrics, i.e. have one metric produce multiple scalar values at a time. (See also the related Prometheus data model.) Described another way, they allow you to group multiple different but related metrics under the same metric name and distinguish them by their labels.
Labels can also be used to supplement a metric with structured meta-data/information.
Note: Although the labels are stored in the
metric_valueobject, they are conceptually closely associated with ametricbecause they are typically not expected to change from one measurement/calculation to the next (or at least very rarely).
Examples:
As mentioned above, our pre-installed user_accounts metric produces multiple values at any moment in time. This is because we added three dimensions to it:
auth partitions the metric by the authentication method associated with the user account. The possible label values are the names of the authentication plugins (e.g. manual or ldap).suspended distinguishes suspended from active user accounts. The possible label values are true and false.deleted distinguishes accounts that have been marked as deleted from the others. The possible label values are true and false.Assuming the Moodle instance has four different authentication methods in use, that metric will produce 4 " 2 " 2 = 16 values every time it is called. One for each co