@cryptotaxi247 / netdata-1 / commits / 481b2fe0e

Add a module for monitoring logind sessions.

'logind' is a daemon used for tracking active users and sessions on a system. By querying this, we can easily get counts of users and sessions on the system, and additionally differentiate by session type (graphical, console, or remote). This module uses the `loginctl` command to query the the service, and does some dead simple text processing on the output to extract the required information. In theory, we could query the DBus methods directly, but that would get us very little in terms of performance, so it's not worth the significantly higher complexity. This module requires zero configuration. The only thing that is required is for the user netdata is running as to be able to call `loginctl list-sessions --no-legend` and get reasonable output back.

Austin S. Hemmelgarn committed Jun 12, 2018 at 11:08 UTC 481b2fe0e6a90080130721bd8f6f5ff834b532db
7 files changed +215
conf.d/Makefile.am
+1
@@ -51,6 +51,7 @@ dist_pythonconfig_DATA = \
51 python.d/ipfs.conf \
52 python.d/isc_dhcpd.conf \
53 python.d/litespeed.conf \
54 + python.d/logind.conf \
55 python.d/mdstat.conf \
56 python.d/memcached.conf \
57 python.d/mongodb.conf \
conf.d/python.d.conf
+1
@@ -51,6 +51,7 @@ go_expvar: no
51 # ipfs: yes
52 # isc_dhcpd: yes
53 # litespeed: yes
54 +# logind: yes
55 # mdstat: yes
56 # memcached: yes
57 # mongodb: yes
conf.d/python.d/logind.conf new
+62
@@ -0,0 +1,62 @@
1 +# netdata python.d.plugin configuration for logind
2 +#
3 +# This file is in YaML format. Generally the format is:
4 +#
5 +# name: value
6 +#
7 +# There are 2 sections:
8 +# - global variables
9 +# - one or more JOBS
10 +#
11 +# JOBS allow you to collect values from multiple sources.
12 +# Each source will have its own set of charts.
13 +#
14 +# JOB parameters have to be indented (using spaces only, example below).
15 +
16 +# ----------------------------------------------------------------------
17 +# Global Variables
18 +# These variables set the defaults for all JOBs, however each JOB
19 +# may define its own, overriding the defaults.
20 +
21 +# update_every sets the default data collection frequency.
22 +# If unset, the python.d.plugin default is used.
23 +# update_every: 1
24 +
25 +# priority controls the order of charts at the netdata dashboard.
26 +# Lower numbers move the charts towards the top of the page.
27 +# If unset, the default for python.d.plugin is used.
28 +# priority: 60000
29 +
30 +# retries sets the number of retries to be made in case of failures.
31 +# If unset, the default for python.d.plugin is used.
32 +# Attempts to restore the service are made once every update_every
33 +# and only if the module has collected values in the past.
34 +# retries: 60
35 +
36 +# autodetection_retry sets the job re-check interval in seconds.
37 +# The job is not deleted if check fails.
38 +# Attempts to start the job are made once every autodetection_retry.
39 +# This feature is disabled by default.
40 +# autodetection_retry: 0
41 +
42 +# ----------------------------------------------------------------------
43 +# JOBS (data collection sources)
44 +#
45 +# The default JOBS share the same *name*. JOBS with the same name
46 +# are mutually exclusive. Only one of them will be allowed running at
47 +# any time. This allows autodetection to try several alternatives and
48 +# pick the one that works.
49 +#
50 +# Any number of jobs is supported.
51 +#
52 +# All python.d.plugin JOBS (for all its modules) support a set of
53 +# predefined parameters. These are:
54 +#
55 +# job_name:
56 +# name: myname # the JOB's name as it will appear at the
57 +# # dashboard (by default is the job_name)
58 +# # JOBs sharing a name are mutually exclusive
59 +# update_every: 1 # the JOB's data collection frequency
60 +# priority: 60000 # the JOB's order on the dashboard
61 +# retries: 60 # the JOB's number of restoration attempts
62 +# autodetection_retry: 0 # the JOB's re-check interval in seconds
python.d/Makefile.am
+1
@@ -39,6 +39,7 @@ dist_python_DATA = \
39 ipfs.chart.py \
40 isc_dhcpd.chart.py \
41 litespeed.chart.py \
42 + logind.chart.py \
43 mdstat.chart.py \
44 memcached.chart.py \
45 mongodb.chart.py \
python.d/README.md
+51
@@ -1059,6 +1059,57 @@ If no configuration is given, module will use "/tmp/lshttpd/".
1059
1060 ---
1061
1062 +# logind
1063 +
1064 +THis module monitors active sessions, users, and seats tracked by systemd-logind or elogind.
1065 +
1066 +It provides the following charts:
1067 +
1068 +1. **Sessions** Tracks the total number of sessions.
1069 + * Graphical: Local graphical sessions (running X11, or Wayland, or something else).
1070 + * Console: Local console sessions.
1071 + * Remote: Remote sessions.
1072 +
1073 +2. **Users** Tracks total number of unique user logins of each type.
1074 + * Graphical
1075 + * Console
1076 + * Remote
1077 +
1078 +3. **Seats** Total number of seats in use.
1079 + * Seats
1080 +
1081 +### configuration
1082 +
1083 +This module needs no configuration. Just make sure the netdata user
1084 +can run the `loginctl` command and get a session list without having to
1085 +specify a path.
1086 +
1087 +This will work with any command that can output data in the _exact_
1088 +same format as `loginctl list-sessions --no-legend`. If you have some
1089 +other command you want to use that outputs data in this format, you can
1090 +specify it using the `command` key like so:
1091 +
1092 +```yaml
1093 +command: '/path/to/other/command'
1094 +```
1095 +
1096 +### notes
1097 +
1098 +* This module's ability to trakck logins is dependent on what PAM services
1099 +are configured to register sessions with logind. In particular, for
1100 +most systems, it will only track TTY logins, local desktop logins,
1101 +and logins through remote shell connections.
1102 +
1103 +* The users chart counts _usernames_ not UID's. This is potentially
1104 +important in configurations where multiple users have the same UID.
1105 +
1106 +* The users chart counts any given user name up to once for _each_ type
1107 +of login. So if the same user has a graphical and a console login on a
1108 +system, they will show up once in the graphical count, and once in the
1109 +console count.
1110 +
1111 +---
1112 +
1113 # mdstat
1114
1115 Module monitor /proc/mdstat
python.d/logind.chart.py new
+81
@@ -0,0 +1,81 @@
1 +# -*- coding: utf-8 -*-
2 +# Description: logind netdata python.d module
3 +# Author: Austin S. Hemmelgarn (Ferroin)
4 +# SPDX-License-Identifier: GPL-3.0+
5 +
6 +import os
7 +import sys
8 +
9 +from bases.FrameworkServices.ExecutableService import ExecutableService
10 +
11 +PRIORITY = 40000
12 +
13 +ORDER = ['sessions', 'users', 'seats']
14 +
15 +CHARTS = {
16 + 'sessions': {
17 + 'options': [None, 'Logind Sessions', 'sessions', 'sessions', 'logind.sessions', 'stacked'],
18 + 'lines': [
19 + ['sessions_graphical', 'Graphical', 'absolute', 1, 1],
20 + ['sessions_console', 'Console', 'absolute', 1, 1],
21 + ['sessions_remote', 'Remote', 'absolute', 1, 1]
22 + ]
23 + },
24 + 'users': {
25 + 'options': [None, 'Logind Users', 'users', 'users', 'logind.users', 'stacked'],
26 + 'lines': [
27 + ['users_graphical', 'Graphical', 'absolute', 1, 1],
28 + ['users_console', 'Console', 'absolute', 1, 1],
29 + ['users_remote', 'Remote', 'absolute', 1, 1]
30 + ]
31 + },
32 + 'seats': {
33 + 'options': [None, 'Logind Seats', 'seats', 'seats', 'logind.seats', 'line'],
34 + 'lines': [
35 + ['seats', 'Active Seats', 'absolute', 1, 1]
36 + ]
37 + }
38 +}
39 +
40 +
41 +class Service(ExecutableService):
42 + def __init__(self, configuration=None, name=None):
43 + ExecutableService.__init__(self, configuration=configuration, name=name)
44 + self.command = 'loginctl list-sessions --no-legend'
45 + self.order = ORDER
46 + self.definitions = CHARTS
47 +
48 + def _get_data(self):
49 + ret = {
50 + 'sessions_graphical': 0,
51 + 'sessions_console': 0,
52 + 'sessions_remote': 0,
53 + }
54 + users = {
55 + 'graphical': list(),
56 + 'console': list(),
57 + 'remote': list()
58 + }
59 + seats = list()
60 + data = self._get_raw_data()
61 +
62 + for item in data:
63 + fields = item.split()
64 + if len(fields) == 3:
65 + users['remote'].append(fields[2])
66 + ret['sessions_remote'] += 1
67 + elif len(fields) == 4:
68 + users['graphical'].append(fields[2])
69 + ret['sessions_graphical'] += 1
70 + seats.append(fields[3])
71 + elif len(fields) == 5:
72 + users['console'].append(fields[2])
73 + ret['sessions_console'] += 1
74 + seats.append(fields[3])
75 +
76 + ret['users_graphical'] = len(set(users['graphical']))
77 + ret['users_console'] = len(set(users['console']))
78 + ret['users_remote'] = len(set(users['remote']))
79 + ret['seats'] = len(set(seats))
80 +
81 + return ret
web/dashboard_info.js
+18
@@ -390,6 +390,12 @@ netdataDashboard.menu = {
390 title: '1-Wire Sensors',
391 icon: '<i class="fas fa-thermometer-half"></i>',
392 info: 'Data derived from <a href="https://en.wikipedia.org/wiki/1-Wire">1-Wire</a> sensors. Currently temperature sensors are automatically detected.'
393 + },
394 +
395 + 'logind': {
396 + title: 'Logind'
397 + icon: '<i class="fas fa-user"></i>',
398 + info: undefined
399 }
400 };
401
@@ -2152,6 +2158,18 @@ netdataDashboard.context = {
2158
2159 'w1sensor.temp': {
2160 info: 'Temperature derived from 1-Wire temperature sensors.'
2161 + },
2162 +
2163 + 'logind.sessions': {
2164 + info: 'Shows the number of active sessions of each type tracked by logind.'
2165 + },
2166 +
2167 + 'logind.users': {
2168 + info: 'Shows the number of active users of each type tracked by logind.'
2169 + },
2170 +
2171 + 'logind.seats': {
2172 + info: 'Shows the number of active seats tracked by logind. Each seat corresponds to a combination of a display device and input device providing a physical presence for the system.'
2173 }
2174
2175 // ------------------------------------------------------------------------