mirror of
https://github.com/Jeffrey-Sardina/liberated-systemd.git
synced 2026-10-19 01:29:53 -05:00
logind: expose session and suspend metrics
logind now implements io.systemd.Metrics on /run/systemd/report/io.systemd.Login, via the new systemd-logind-metrics.socket, and reports: - io.systemd.Login.SessionsStarted: counter of sessions started since boot, by session class (field class=) - io.systemd.Login.CurrentSessions: gauge of current sessions, including those in closing state, by session class (field class=) - io.systemd.Login.SuspendCounter: counter of suspend cycles, as reported by the kernel in /sys/power/suspend_stats/ (field result=success|fail)
This commit is contained in:
1 parent
8242f08ecb
commit
5d7cb3878c
10 files changed
+312
-13
No files matched your search
@@ -1128,7 +1128,10 @@ manpages = [
|
||||
''],
|
||||
['systemd-keyutil', '1', [], ''],
|
||||
['systemd-localed.service', '8', ['systemd-localed'], 'ENABLE_LOCALED'],
|
||||
['systemd-logind.service', '8', ['systemd-logind'], 'ENABLE_LOGIND'],
|
||||
['systemd-logind.service',
|
||||
'8',
|
||||
['systemd-logind', 'systemd-logind-metrics.socket'],
|
||||
'ENABLE_LOGIND'],
|
||||
['systemd-loop@.service', '8', [], ''],
|
||||
['systemd-machine-id-commit.service', '8', [], ''],
|
||||
['systemd-machine-id-setup', '1', [], ''],
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
|
||||
<refentry id="systemd-logind.service" conditional='ENABLE_LOGIND'>
|
||||
<refentry id="systemd-logind.service" conditional='ENABLE_LOGIND'
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>systemd-logind.service</title>
|
||||
@@ -17,12 +18,14 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-logind.service</refname>
|
||||
<refname>systemd-logind-metrics.socket</refname>
|
||||
<refname>systemd-logind</refname>
|
||||
<refpurpose>Login manager</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>systemd-logind.service</filename></para>
|
||||
<para><filename>systemd-logind-metrics.socket</filename></para>
|
||||
<para><filename>/usr/lib/systemd/systemd-logind</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -104,6 +107,43 @@
|
||||
Desktop Environments</ulink>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Metrics</title>
|
||||
|
||||
<para><command>systemd-logind</command> is a metrics source for
|
||||
<citerefentry><refentrytitle>systemd-report</refentrytitle><manvolnum>1</manvolnum></citerefentry> and
|
||||
reports the following metrics:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>io.systemd.Login.CurrentSessions</literal></term>
|
||||
<listitem><para>A gauge metric with the number of current sessions. The metric field
|
||||
<varname>class</varname> is set to the session class, see <varname>$XDG_SESSION_CLASS</varname> in
|
||||
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v263"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>io.systemd.Login.SessionsStarted</literal></term>
|
||||
<listitem><para>A counter metric with the number of sessions started since boot, by session class.
|
||||
Sessions are counted under the class they have been created with. The metric field
|
||||
<varname>class</varname> is set as above. This counter is kept across restarts of the service, but
|
||||
reset on reboot.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v263"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>io.systemd.Login.SuspendCounter</literal></term>
|
||||
<listitem><para>A counter metric with the number of suspend cycles since boot. The metric field
|
||||
<varname>result</varname> is set to <literal>success</literal> or <literal>fail</literal>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v263"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Signal</title>
|
||||
<variablelist>
|
||||
|
||||
@@ -28,6 +28,7 @@ enable systemd-homed-activate.service
|
||||
enable systemd-journalctl-metrics.socket
|
||||
enable systemd-journald-audit.socket
|
||||
enable systemd-journald-metrics.socket
|
||||
enable systemd-logind-metrics.socket
|
||||
enable systemd-mountfsd.socket
|
||||
enable systemd-network-generator.service
|
||||
enable systemd-networkd.service
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-event.h"
|
||||
#include "sd-json.h"
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "argv-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "hashmap.h"
|
||||
#include "log.h"
|
||||
#include "logind.h"
|
||||
#include "logind-counters.h"
|
||||
#include "logind-metrics.h"
|
||||
#include "logind-session.h"
|
||||
#include "metrics.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "virt.h"
|
||||
|
||||
#define METRIC_IO_SYSTEMD_LOGIN_PREFIX "io.systemd.Login."
|
||||
|
||||
static int send_per_class(const MetricFamily *mf, sd_varlink *link, SessionClass class, uint64_t value) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *fields = NULL;
|
||||
int r;
|
||||
|
||||
r = sd_json_buildo(&fields, SD_JSON_BUILD_PAIR_STRING("class", session_class_to_string(class)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return metric_build_send_unsigned(mf, link, /* object= */ NULL, value, fields);
|
||||
}
|
||||
|
||||
static int current_sessions_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
uint64_t n[_SESSION_CLASS_MAX] = {};
|
||||
Session *s;
|
||||
int r;
|
||||
|
||||
assert(mf);
|
||||
assert(link);
|
||||
|
||||
/* Sessions in closing state are included */
|
||||
HASHMAP_FOREACH(s, m->sessions)
|
||||
if (s->started && s->class >= 0)
|
||||
n[s->class]++;
|
||||
|
||||
for (SessionClass c = 0; c < _SESSION_CLASS_MAX; c++) {
|
||||
if (c == SESSION_NONE)
|
||||
continue;
|
||||
|
||||
r = send_per_class(mf, link, c, n[c]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sessions_started_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
assert(mf);
|
||||
assert(link);
|
||||
|
||||
if (!m->counters)
|
||||
return 0;
|
||||
|
||||
for (SessionClass c = 0; c < _SESSION_CLASS_MAX; c++) {
|
||||
if (c == SESSION_NONE)
|
||||
continue;
|
||||
|
||||
r = send_per_class(mf, link, c, m->counters->n_sessions_started[c]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int suspend_counter_generate(const MetricFamily *mf, sd_varlink *link, void *userdata) {
|
||||
int r;
|
||||
|
||||
assert(mf);
|
||||
assert(link);
|
||||
|
||||
if (detect_container() > 0)
|
||||
return 0;
|
||||
|
||||
FOREACH_STRING(result, "success", "fail") {
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
uint64_t v;
|
||||
|
||||
p = strjoin("/sys/power/suspend_stats/", result);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = read_one_line_file(p, &s);
|
||||
if (r == -ENOENT) {
|
||||
log_debug_errno(r, "%s does not exist, not reporting suspend counters.", p);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read %s: %m", p);
|
||||
|
||||
r = safe_atou64(s, &v);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse %s: %m", p);
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *fields = NULL;
|
||||
r = sd_json_buildo(&fields, SD_JSON_BUILD_PAIR_STRING("result", result));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = metric_build_send_unsigned(mf, link, /* object= */ NULL, v, fields);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const MetricFamily login_metric_family_table[] = {
|
||||
/* Keep metrics ordered alphabetically */
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_LOGIN_PREFIX "CurrentSessions",
|
||||
.description = "Number of current sessions, including closing ones, by session class",
|
||||
.type = METRIC_FAMILY_TYPE_GAUGE,
|
||||
.generate = current_sessions_generate,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_LOGIN_PREFIX "SessionsStarted",
|
||||
.description = "Number of sessions started since boot, by session class",
|
||||
.type = METRIC_FAMILY_TYPE_COUNTER,
|
||||
.generate = sessions_started_generate,
|
||||
},
|
||||
{
|
||||
.name = METRIC_IO_SYSTEMD_LOGIN_PREFIX "SuspendCounter",
|
||||
.description = "Number of suspend cycles since boot, by result (result=success|fail)",
|
||||
.type = METRIC_FAMILY_TYPE_COUNTER,
|
||||
.generate = suspend_counter_generate,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static int vl_method_metrics_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
return metrics_method_describe(login_metric_family_table, link, parameters, flags, userdata);
|
||||
}
|
||||
|
||||
static int vl_method_metrics_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
return metrics_method_list(login_metric_family_table, link, parameters, flags, userdata);
|
||||
}
|
||||
|
||||
int manager_metrics_init(Manager *m, int fd) {
|
||||
_unused_ _cleanup_close_ int fd_close = fd; /* take possession */
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->metrics_varlink_server)
|
||||
return 0;
|
||||
|
||||
if (fd < 0 && invoked_by_systemd()) {
|
||||
log_debug("systemd-logind-metrics.socket seems to be disabled, not installing metrics varlink server.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
|
||||
r = metrics_setup_varlink_server(
|
||||
&s,
|
||||
SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA,
|
||||
m->event,
|
||||
SD_EVENT_PRIORITY_NORMAL,
|
||||
vl_method_metrics_list,
|
||||
vl_method_metrics_describe,
|
||||
m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up metrics varlink server: %m");
|
||||
|
||||
if (fd < 0) {
|
||||
r = sd_varlink_server_listen_address(
|
||||
s,
|
||||
"/run/systemd/report/io.systemd.Login",
|
||||
0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||
if (ERRNO_IS_NEG_PRIVILEGE(r)) {
|
||||
log_warning_errno(r, "Failed to bind to metrics varlink socket, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
r = sd_varlink_server_listen_fd(s, fd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to metrics varlink socket: %m");
|
||||
|
||||
TAKE_FD(fd_close);
|
||||
m->metrics_varlink_server = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void manager_metrics_done(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
m->metrics_varlink_server = sd_varlink_server_unref(m->metrics_varlink_server);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "logind-forward.h"
|
||||
|
||||
int manager_metrics_init(Manager *m, int fd);
|
||||
void manager_metrics_done(Manager *m);
|
||||
+23
-11
@@ -31,6 +31,7 @@
|
||||
#include "logind-counters.h"
|
||||
#include "logind-dbus.h"
|
||||
#include "logind-device.h"
|
||||
#include "logind-metrics.h"
|
||||
#include "logind-seat.h"
|
||||
#include "logind-session-device.h"
|
||||
#include "logind-user.h"
|
||||
@@ -174,6 +175,7 @@ static Manager* manager_free(Manager *m) {
|
||||
hashmap_free(m->polkit_registry);
|
||||
|
||||
manager_varlink_done(m);
|
||||
manager_metrics_done(m);
|
||||
|
||||
m->counters = munmap_safe(m->counters, sizeof(*m->counters));
|
||||
|
||||
@@ -530,8 +532,8 @@ static int manager_attach_session_fd_one_consume(Manager *m, const char *fdname,
|
||||
s = hashmap_get(m->sessions, id);
|
||||
if (!s) {
|
||||
/* If the session doesn't exist anymore, let's simply close this fd. */
|
||||
r = log_debug_errno(SYNTHETIC_ERRNO(ENXIO),
|
||||
"Cannot attach fd '%s' to unknown session '%s', ignoring.", fdname, id);
|
||||
log_debug("Cannot attach fd '%s' to unknown session '%s', ignoring.", fdname, id);
|
||||
r = 0;
|
||||
goto fail_close;
|
||||
}
|
||||
|
||||
@@ -588,12 +590,13 @@ static int manager_enumerate_sessions(Manager *m) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int manager_enumerate_fds(Manager *m, int *ret_varlink_fd) {
|
||||
static int manager_enumerate_fds(Manager *m, int *ret_varlink_fd, int *ret_metrics_fd) {
|
||||
_cleanup_strv_free_ char **fdnames = NULL;
|
||||
int varlink_fd = -EBADF, n, r = 0;
|
||||
int varlink_fd = -EBADF, metrics_fd = -EBADF, n;
|
||||
|
||||
assert(m);
|
||||
assert(ret_varlink_fd);
|
||||
assert(ret_metrics_fd);
|
||||
|
||||
n = sd_listen_fds_with_names(/* unset_environment= */ true, &fdnames);
|
||||
if (n < 0)
|
||||
@@ -608,13 +611,18 @@ static int manager_enumerate_fds(Manager *m, int *ret_varlink_fd) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RET_GATHER(r, manager_attach_session_fd_one_consume(m, fdnames[i], fd));
|
||||
if (streq(fdnames[i], "varlink-metrics")) {
|
||||
assert(metrics_fd < 0);
|
||||
metrics_fd = fd;
|
||||
continue;
|
||||
}
|
||||
|
||||
(void) manager_attach_session_fd_one_consume(m, fdnames[i], fd);
|
||||
}
|
||||
|
||||
if (r >= 0)
|
||||
*ret_varlink_fd = varlink_fd;
|
||||
|
||||
return r;
|
||||
*ret_varlink_fd = varlink_fd;
|
||||
*ret_metrics_fd = metrics_fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_enumerate_inhibitors(Manager *m) {
|
||||
@@ -1219,7 +1227,7 @@ static int manager_dispatch_reload_signal(sd_event_source *s, const struct signa
|
||||
}
|
||||
|
||||
static int manager_startup(Manager *m) {
|
||||
_cleanup_close_ int varlink_fd = -EBADF;
|
||||
_cleanup_close_ int varlink_fd = -EBADF, metrics_fd = -EBADF;
|
||||
int r;
|
||||
Seat *seat;
|
||||
Session *session;
|
||||
@@ -1279,7 +1287,7 @@ static int manager_startup(Manager *m) {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Session enumeration failed: %m");
|
||||
|
||||
r = manager_enumerate_fds(m, &varlink_fd);
|
||||
r = manager_enumerate_fds(m, &varlink_fd, &metrics_fd);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "File descriptor enumeration failed: %m");
|
||||
|
||||
@@ -1295,6 +1303,10 @@ static int manager_startup(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = manager_metrics_init(m, TAKE_FD(metrics_fd));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
manager_load_scheduled_shutdown(m);
|
||||
|
||||
/* Remove stale objects before we start them */
|
||||
|
||||
@@ -140,6 +140,7 @@ typedef struct Manager {
|
||||
dual_timestamp init_ts;
|
||||
|
||||
sd_varlink_server *varlink_server;
|
||||
sd_varlink_server *metrics_varlink_server;
|
||||
|
||||
LoginCounters *counters;
|
||||
} Manager;
|
||||
|
||||
@@ -16,6 +16,7 @@ systemd_logind_export_sources = files(
|
||||
'logind-dbus.c',
|
||||
'logind-device.c',
|
||||
'logind-inhibit.c',
|
||||
'logind-metrics.c',
|
||||
'logind-polkit.c',
|
||||
'logind-seat-dbus.c',
|
||||
'logind-seat.c',
|
||||
|
||||
@@ -538,6 +538,10 @@ units = [
|
||||
'conditions' : ['ENABLE_LOCALED'],
|
||||
'symlinks' : ['dbus-org.freedesktop.locale1.service'],
|
||||
},
|
||||
{
|
||||
'file': 'systemd-logind-metrics.socket',
|
||||
'conditions': ['ENABLE_LOGIND'],
|
||||
},
|
||||
{
|
||||
'file': 'systemd-logind-varlink.socket',
|
||||
'conditions': ['ENABLE_LOGIND'],
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=User Login Management Metrics Varlink Socket
|
||||
Documentation=man:systemd-logind.service(8)
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/systemd/report/io.systemd.Login
|
||||
FileDescriptorName=varlink-metrics
|
||||
SocketMode=0666
|
||||
Service=systemd-logind.service
|
||||
XAttrEntryPoint=user.varlink=entrypoint
|
||||
XAttrListen=user.varlink=listen
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
Reference in new issue
Block a user