WSGIServerMetrics

Description:

Enable Python access to Apache scoreboard data via mod_wsgi.server_metrics() from embedded mode.

Syntax:

WSGIServerMetrics On|Off

Default:

Off

Context:

server config

Controls whether the mod_wsgi.server_metrics() Python API is allowed to return Apache scoreboard data when called from code running in embedded mode (Apache child processes). With the default Off, the function returns None. With On, it returns a Python dictionary describing the current state of every Apache child process and worker slot known to the scoreboard.

The directive does not control whether the scoreboard itself is populated. Apache populates it unconditionally as part of normal request handling (the same data mod_status reads). The directive gates only the Python-side access to that data; turning it on does not impose any additional cost on requests that do not call the function.

This directive only affects calls made from embedded mode. To allow mod_wsgi.server_metrics() to return data when called from a daemon process, use the server-metrics option on the WSGIDaemonProcess directive instead. The two settings are independent: a daemon process group is gated only by its own server-metrics= option, and this directive’s value does not propagate to daemon process groups as a default. Different daemon groups can be allowed or denied scoreboard access individually by setting the option differently on each WSGIDaemonProcess directive.

For most modern deployments, daemon mode is the preferred deployment method, in which case configure scoreboard access via WSGIDaemonProcess rather than this directive.

What the call returns

When both gates are open, mod_wsgi.server_metrics() returns a dictionary shaped roughly as follows:

{
    "server_limit": 256,
    "thread_limit": 25,
    "running_generation": 0,
    "restart_time": 1715242800.0,
    "current_time": 1715243000.0,
    "running_time": 200,
    "processes": [
        {
            "process_num": 0,
            "pid": 12345,
            "generation": 0,
            "quiescing": False,
            "workers": [
                {
                    "thread_num": 0,
                    "generation": 0,
                    "status": "Ready",
                    "access_count": 1024,
                    "bytes_served": 8388608,
                    "start_time": 1715242800.0,
                    "stop_time": 1715242850.0,
                    "last_used": 1715242999.0,
                    "client": "192.0.2.5",
                    "request": "GET /api/users HTTP/1.1",
                    "vhost": "www.example.com:443",
                },
                ...
            ],
        },
        ...
    ],
}

Each call walks server_limit × thread_limit scoreboard entries and constructs a fresh Python object graph, so callers polling at high frequency on large servers should expect a low-millisecond cost per invocation. Apache’s scoreboard slot strings are length bounded but not otherwise filtered, so the client, request, and vhost fields should be treated as untrusted input by any consumer.

Security considerations

The data returned includes the client IP, the request line (HTTP method, path, query string, and protocol), and the vhost name for every worker slot - including workers currently servicing other requests for other applications hosted by the same Apache instance. Anything carried in a URL is therefore visible to any code holding the scoreboard read capability:

  • Query-string parameters, including session identifiers, API keys, OAuth codes, and password-reset tokens that some applications still pass through URL parameters.

  • Request paths that themselves encode sensitive identifiers (account IDs, document IDs).

  • Source IP addresses of every active client.

If multiple WSGI applications share one Apache instance, code running with scoreboard access can observe live request data from every other application on the same server. The independence of the embedded-mode directive and the per-daemon-group option is the lever for limiting that exposure: enable scoreboard access in exactly the contexts that have a direct, justified need for it, and leave it off everywhere else.

A reasonable defensive posture for shared hosting:

  • Leave WSGIServerMetrics Off (the default) unless code in embedded mode needs to consume the API.

  • For daemon mode, set server-metrics=on only on the specific daemon process group that runs the consumer (typically a service-script process behind --service-script or WSGIImportScript); leave every other daemon process group at the default of off.

  • Treat any process with scoreboard access, and any URL it serves, as having scoreboard-reader privilege; gate access to that URL with authentication, IP allow-listing, or an internal-only virtual host as appropriate.

See also

  • WSGIDaemonProcess for the per-daemon-group server-metrics=on option.

  • WSGIImportScript for service-script processes, which are the typical place to call mod_wsgi.server_metrics() when the consumer is itself hosted by mod_wsgi.

  • Hosting WebSocket Applications for an end-to-end example: a service-script sidecar that polls mod_wsgi.server_metrics() and pushes the snapshot over a WebSocket to a browser dashboard.