Skip to content

macOS: Missing kernel.all.nusers metric #2456

@tallpsmith

Description

@tallpsmith

Problem

The pcp-uptime tool fails on macOS because the darwin PMDA is missing the kernel.all.nusers metric, which reports the number of currently logged-in users.

Current Behavior

On macOS, when running pcp-uptime:

$ pcp-uptime
# Fails because kernel.all.nusers metric is not available

However, the system uptime command works correctly:

$ uptime
12:53  up 9 days, 18:32, 15 users, load averages: 3.10 3.36 3.27
                          ^^^^^^^^

Root Cause

The pcp-uptime tool (src/pcp/uptime/pcp-uptime.py:91) requires three metrics:

  • kernel.all.uptime - available in darwin PMDA
  • kernel.all.load - available in darwin PMDA
  • kernel.all.nusers - MISSING in darwin PMDA

Analysis

Linux Implementation

The Linux PMDA implements this via src/pmdas/linux/login.c using the POSIX utmp API:

#include <utmp.h>

void refresh_login_info(struct login_info *up) {
    struct utmp *ut;
    setutent();
    while ((ut = getutent())) {
        if (ut->ut_type == USER_PROCESS) {
            if (ut->ut_user[0] == '\0')
                continue;
            up->nusers++;
        }
    }
    endutent();
}

macOS System API

macOS provides the utmpx extended API which is nearly identical to Linux's utmp API:

API Comparison:

Aspect Linux (utmp) macOS (utmpx)
Header #include <utmp.h> #include <utmpx.h>
Structure struct utmp struct utmpx
Open setutent() setutxent()
Read getutent() getutxent()
Close endutent() endutxent()
Database /var/run/utmp /var/run/utmpx
Fields ut_user, ut_type ut_user, ut_type (same)

The USER_PROCESS constant exists on both platforms with the same semantics.

Proposed Solution

Implement kernel.all.nusers (and related metrics) in the darwin PMDA using the utmpx API.

Implementation Plan

  1. Create new login module (src/pmdas/darwin/login.c and login.h):

    #include <utmpx.h>
    
    typedef struct login_info {
        unsigned int nusers;
        unsigned int nroots;      // bonus: count root logins
        unsigned int nsessions;   // bonus: total sessions
    } login_info_t;
    
    void refresh_login_info(login_info_t *up) {
        struct utmpx *ut;
        memset(up, 0, sizeof(login_info_t));
        
        setutxent();
        while ((ut = getutxent())) {
            if (ut->ut_type == USER_PROCESS) {
                if (ut->ut_user[0] == '\0')
                    continue;
                if (strcmp(ut->ut_user, "root") == 0)
                    up->nroots++;
                up->nusers++;
            }
            up->nsessions++;
        }
        endutxent();
    }
  2. Update darwin PMDA core (src/pmdas/darwin/pmda.c):

    • Add global variables:
      int mach_login_error = 0;
      login_info_t mach_login = { 0 };
    • Call refresh_login_info(&mach_login) in fetch callback
  3. Update metric definitions:

    • src/pmdas/darwin/metrics.c - add metric table entries
    • src/pmdas/darwin/pmns - add to namespace:
      kernel.all.nusers     DARWIN:12:142
      kernel.all.nroots     DARWIN:12:143  (bonus)
      kernel.all.nsessions  DARWIN:12:144  (bonus)
      
    • src/pmdas/darwin/help - add metric descriptions
    • src/pmdas/darwin/GNUmakefile - add login.c to sources

Additional Metrics (Bonus)

While implementing kernel.all.nusers, we can also provide:

  • kernel.all.nroots - count of root user logins (Linux has this)
  • kernel.all.nsessions - total session count (Linux has this)

This achieves full parity with the Linux PMDA.

Expected Outcome

After implementation:

  • pcp-uptime works correctly on macOS
  • ✓ Full metric parity with Linux for login tracking
  • ✓ macOS PCP installations are more complete
  • ✓ No breaking changes to existing metrics

Testing

The implementation can be validated by:

  1. Verifying metric availability: pminfo -f kernel.all.nusers
  2. Comparing with system uptime: uptime vs pcp-uptime
  3. Multiple user sessions (ssh, terminal, screen/tmux)
  4. Running existing QA tests

References

  • Linux implementation: src/pmdas/linux/login.c
  • macOS API documentation: man 3 getutxent, man 5 utmpx
  • POSIX standard: IEEE Std 1003.1 (utmpx)
  • pcp-uptime tool: src/pcp/uptime/pcp-uptime.py

Metadata

Metadata

Assignees

Labels

macOSFor issues specific or related to macOS

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions