-
-
Notifications
You must be signed in to change notification settings - Fork 262
Description
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 availableHowever, 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
-
Create new login module (
src/pmdas/darwin/login.candlogin.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(); }
-
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
- Add global variables:
-
Update metric definitions:
src/pmdas/darwin/metrics.c- add metric table entriessrc/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 descriptionssrc/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-uptimeworks 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:
- Verifying metric availability:
pminfo -f kernel.all.nusers - Comparing with system uptime:
uptimevspcp-uptime - Multiple user sessions (ssh, terminal, screen/tmux)
- 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