mirror of https://github.com/nicolargo/glances.git
Enhance process "extended stats" display (in Curses interface) #2225
This commit is contained in:
commit
e0a052c53e
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
|
|
@ -15,10 +15,15 @@ Filtered view:
|
|||
|
||||
.. image:: ../_static/processlist-filter.png
|
||||
|
||||
Extended view:
|
||||
|
||||
.. image:: ../_static/processlist-extended.png
|
||||
|
||||
The process view consists of 3 parts:
|
||||
|
||||
- Processes summary
|
||||
- Monitored processes list (optional)
|
||||
- Monitored processes list (optional, only in standalone mode)
|
||||
- Extended stats for the selected process (optional)
|
||||
- Processes list
|
||||
|
||||
The processes summary line displays:
|
||||
|
|
@ -56,12 +61,15 @@ You can also set the sort key in the UI:
|
|||
* - c
|
||||
- --sort-processes cpu_percent
|
||||
- Sort by CPU
|
||||
* - e
|
||||
- N/A
|
||||
- Pin the process and display extended stats
|
||||
* - i
|
||||
- --sort-processes io_counters
|
||||
- Sort by DISK I/O
|
||||
* - j
|
||||
- --programs
|
||||
- Accumulate processes by program
|
||||
- Accumulate processes by program (extended stats disable in this mode)
|
||||
* - m
|
||||
- --sort-processes memory_percent
|
||||
- Sort by MEM
|
||||
|
|
|
|||
516
docs/api.rst
516
docs/api.rst
|
|
@ -74,7 +74,7 @@ Get plugin stats::
|
|||
"refresh": 3.0,
|
||||
"regex": True,
|
||||
"result": None,
|
||||
"timer": 0.8202648162841797},
|
||||
"timer": 0.8183016777038574},
|
||||
{"count": 0,
|
||||
"countmax": 20.0,
|
||||
"countmin": None,
|
||||
|
|
@ -83,7 +83,7 @@ Get plugin stats::
|
|||
"refresh": 3.0,
|
||||
"regex": True,
|
||||
"result": None,
|
||||
"timer": 0.820155143737793}]
|
||||
"timer": 0.8182027339935303}]
|
||||
|
||||
Get a specific field::
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ Get a specific item when field matchs the given value::
|
|||
"refresh": 3.0,
|
||||
"regex": True,
|
||||
"result": None,
|
||||
"timer": 0.8202648162841797}]}
|
||||
"timer": 0.8183016777038574}]}
|
||||
|
||||
GET core
|
||||
--------
|
||||
|
|
@ -131,19 +131,19 @@ Get plugin stats::
|
|||
"ctx_switches": 0,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 71.8,
|
||||
"idle": 70.9,
|
||||
"interrupts": 0,
|
||||
"iowait": 0.2,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"nice": 0.0,
|
||||
"soft_interrupts": 0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"syscalls": 0,
|
||||
"system": 3.9,
|
||||
"system": 4.0,
|
||||
"time_since_update": 1,
|
||||
"total": 29.2,
|
||||
"user": 24.1}
|
||||
"total": 29.8,
|
||||
"user": 25.2}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ Fields descriptions:
|
|||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/3/cpu/total
|
||||
{"total": 29.2}
|
||||
{"total": 29.8}
|
||||
|
||||
GET diskio
|
||||
----------
|
||||
|
|
@ -211,58 +211,29 @@ GET docker
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/docker
|
||||
{"containers": [{"Command": ["/whoamI"],
|
||||
"Id": "12b96990d8485d7cb37dbb54a3fb28207169654191701575f9d6bcf2cfc4c2e4",
|
||||
"Image": ["emilevauge/whoami:latest"],
|
||||
"Status": "running",
|
||||
"Uptime": "1 weeks",
|
||||
"cpu": {"total": 0.0},
|
||||
"cpu_percent": 0.0,
|
||||
"io": {},
|
||||
"io_r": None,
|
||||
"io_w": None,
|
||||
"key": "name",
|
||||
"memory": {},
|
||||
"memory_usage": None,
|
||||
"name": "docker-compose_whoami_1",
|
||||
"network": {},
|
||||
"network_rx": None,
|
||||
"network_tx": None},
|
||||
{"Command": ["/bin/sh",
|
||||
"-c",
|
||||
"python3 -m glances -C /etc/glances.conf "
|
||||
"$GLANCES_OPT"],
|
||||
"Id": "ca7c2a050209ed12bdc8de20719423b4b6bc819e7f02e7ef0f44ff4e2f3ba0e3",
|
||||
"Image": ["nicolargo/glances:dev"],
|
||||
"Status": "running",
|
||||
"Uptime": "1 weeks",
|
||||
"cpu": {"total": 0.0},
|
||||
"cpu_percent": 0.0,
|
||||
"io": {},
|
||||
"io_r": None,
|
||||
"io_w": None,
|
||||
"key": "name",
|
||||
"memory": {},
|
||||
"memory_usage": None,
|
||||
"name": "docker-compose_monitoring_1",
|
||||
"network": {},
|
||||
"network_rx": None,
|
||||
"network_tx": None},
|
||||
{"Command": ["docker-entrypoint.sh", "mongod"],
|
||||
{"containers": [{"Command": ["docker-entrypoint.sh", "mongod"],
|
||||
"Id": "c3a1bb27858df965e1c524c6ef33c0fd26d765cae5bcd90fbe9e662b703a52aa",
|
||||
"Image": ["mongo:latest"],
|
||||
"Status": "running",
|
||||
"Uptime": "1 months",
|
||||
"cpu": {"total": 0.0},
|
||||
"cpu_percent": 0.0,
|
||||
"io": {},
|
||||
"io": {"cumulative_ior": 847872,
|
||||
"cumulative_iow": 53813248,
|
||||
"time_since_update": 1},
|
||||
"io_r": None,
|
||||
"io_w": None,
|
||||
"key": "name",
|
||||
"memory": {},
|
||||
"memory_usage": None,
|
||||
"memory": {"cache": None,
|
||||
"limit": 7836196864,
|
||||
"max_usage": None,
|
||||
"rss": None,
|
||||
"usage": 23642112},
|
||||
"memory_usage": 23642112,
|
||||
"name": "docker-mongo_mongo_1",
|
||||
"network": {},
|
||||
"network": {"cumulative_rx": 37744307,
|
||||
"cumulative_tx": 28244833,
|
||||
"time_since_update": 1},
|
||||
"network_rx": None,
|
||||
"network_tx": None},
|
||||
{"Command": ["tini",
|
||||
|
|
@ -340,13 +311,13 @@ Get plugin stats::
|
|||
|
||||
# curl http://localhost:61208/api/3/fs
|
||||
[{"device_name": "/dev/mapper/ubuntu--gnome--vg-root",
|
||||
"free": 53523116032,
|
||||
"free": 53470863360,
|
||||
"fs_type": "ext4",
|
||||
"key": "mnt_point",
|
||||
"mnt_point": "/",
|
||||
"percent": 76.8,
|
||||
"size": 243334156288,
|
||||
"used": 177423585280},
|
||||
"used": 177475837952},
|
||||
{"device_name": "zsfpool",
|
||||
"free": 41811968,
|
||||
"fs_type": "zfs",
|
||||
|
|
@ -365,13 +336,13 @@ Get a specific item when field matchs the given value::
|
|||
|
||||
# curl http://localhost:61208/api/3/fs/mnt_point//
|
||||
{"/": [{"device_name": "/dev/mapper/ubuntu--gnome--vg-root",
|
||||
"free": 53523116032,
|
||||
"free": 53470863360,
|
||||
"fs_type": "ext4",
|
||||
"key": "mnt_point",
|
||||
"mnt_point": "/",
|
||||
"percent": 76.8,
|
||||
"size": 243334156288,
|
||||
"used": 177423585280}]}
|
||||
"used": 177475837952}]}
|
||||
|
||||
GET ip
|
||||
------
|
||||
|
|
@ -397,7 +368,10 @@ GET load
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/load
|
||||
{"cpucore": 4, "min1": 0.63525390625, "min15": 1.3359375, "min5": 1.08349609375}
|
||||
{"cpucore": 4,
|
||||
"min1": 0.79833984375,
|
||||
"min15": 0.7431640625,
|
||||
"min5": 0.8056640625}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
|
|
@ -409,7 +383,7 @@ Fields descriptions:
|
|||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/3/load/min1
|
||||
{"min1": 0.63525390625}
|
||||
{"min1": 0.79833984375}
|
||||
|
||||
GET mem
|
||||
-------
|
||||
|
|
@ -417,16 +391,16 @@ GET mem
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/mem
|
||||
{"active": 2453286912,
|
||||
"available": 3052646400,
|
||||
"buffers": 129122304,
|
||||
"cached": 3469373440,
|
||||
"free": 3052646400,
|
||||
"inactive": 4119760896,
|
||||
"percent": 61.0,
|
||||
"shared": 455708672,
|
||||
{"active": 2350882816,
|
||||
"available": 2422988800,
|
||||
"buffers": 131072000,
|
||||
"cached": 2795134976,
|
||||
"free": 2422988800,
|
||||
"inactive": 3522777088,
|
||||
"percent": 69.1,
|
||||
"shared": 685944832,
|
||||
"total": 7836196864,
|
||||
"used": 4783550464}
|
||||
"used": 5413208064}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
|
|
@ -453,13 +427,13 @@ GET memswap
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/memswap
|
||||
{"free": 5701988352,
|
||||
"percent": 29.5,
|
||||
"sin": 8590413824,
|
||||
"sout": 14424719360,
|
||||
{"free": 5875109888,
|
||||
"percent": 27.3,
|
||||
"sin": 8760786944,
|
||||
"sout": 14506393600,
|
||||
"time_since_update": 1,
|
||||
"total": 8082419712,
|
||||
"used": 2380431360}
|
||||
"used": 2207309824}
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
|
|
@ -483,29 +457,29 @@ Get plugin stats::
|
|||
|
||||
# curl http://localhost:61208/api/3/network
|
||||
[{"alias": None,
|
||||
"cumulative_cx": 1100113578,
|
||||
"cumulative_rx": 550056789,
|
||||
"cumulative_tx": 550056789,
|
||||
"cx": 7802,
|
||||
"cumulative_cx": 1140515614,
|
||||
"cumulative_rx": 570257807,
|
||||
"cumulative_tx": 570257807,
|
||||
"cx": 5342,
|
||||
"interface_name": "lo",
|
||||
"is_up": True,
|
||||
"key": "interface_name",
|
||||
"rx": 3901,
|
||||
"rx": 2671,
|
||||
"speed": 0,
|
||||
"time_since_update": 1,
|
||||
"tx": 3901},
|
||||
"tx": 2671},
|
||||
{"alias": None,
|
||||
"cumulative_cx": 35336641046,
|
||||
"cumulative_rx": 34139736267,
|
||||
"cumulative_tx": 1196904779,
|
||||
"cx": 32563,
|
||||
"cumulative_cx": 36011739106,
|
||||
"cumulative_rx": 34790353651,
|
||||
"cumulative_tx": 1221385455,
|
||||
"cx": 24457,
|
||||
"interface_name": "wlp2s0",
|
||||
"is_up": True,
|
||||
"key": "interface_name",
|
||||
"rx": 22311,
|
||||
"rx": 18960,
|
||||
"speed": 0,
|
||||
"time_since_update": 1,
|
||||
"tx": 10252}]
|
||||
"tx": 5497}]
|
||||
|
||||
Fields descriptions:
|
||||
|
||||
|
|
@ -535,24 +509,23 @@ Get a specific field::
|
|||
"br-ef0a06c4e10f",
|
||||
"veth9910148",
|
||||
"veth5e7315e",
|
||||
"veth24ae93e",
|
||||
"vethb59ceaa"]}
|
||||
"veth24ae93e"]}
|
||||
|
||||
Get a specific item when field matchs the given value::
|
||||
|
||||
# curl http://localhost:61208/api/3/network/interface_name/lo
|
||||
{"lo": [{"alias": None,
|
||||
"cumulative_cx": 1100113578,
|
||||
"cumulative_rx": 550056789,
|
||||
"cumulative_tx": 550056789,
|
||||
"cx": 7802,
|
||||
"cumulative_cx": 1140515614,
|
||||
"cumulative_rx": 570257807,
|
||||
"cumulative_tx": 570257807,
|
||||
"cx": 5342,
|
||||
"interface_name": "lo",
|
||||
"is_up": True,
|
||||
"key": "interface_name",
|
||||
"rx": 3901,
|
||||
"rx": 2671,
|
||||
"speed": 0,
|
||||
"time_since_update": 1,
|
||||
"tx": 3901}]}
|
||||
"tx": 2671}]}
|
||||
|
||||
GET now
|
||||
-------
|
||||
|
|
@ -560,7 +533,7 @@ GET now
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/now
|
||||
"2023-03-11 10:42:32 CET"
|
||||
"2023-03-11 17:30:43 CET"
|
||||
|
||||
GET percpu
|
||||
----------
|
||||
|
|
@ -571,28 +544,28 @@ Get plugin stats::
|
|||
[{"cpu_number": 0,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 21.0,
|
||||
"idle": 22.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 3.0,
|
||||
"total": 79.0,
|
||||
"user": 68.0},
|
||||
"system": 1.0,
|
||||
"total": 78.0,
|
||||
"user": 67.0},
|
||||
{"cpu_number": 1,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 83.0,
|
||||
"idle": 81.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 0.0,
|
||||
"total": 17.0,
|
||||
"system": 2.0,
|
||||
"total": 19.0,
|
||||
"user": 7.0}]
|
||||
|
||||
Get a specific field::
|
||||
|
|
@ -612,7 +585,7 @@ Get plugin stats::
|
|||
"port": 0,
|
||||
"refresh": 30,
|
||||
"rtt_warning": None,
|
||||
"status": 0.004165,
|
||||
"status": 0.003449,
|
||||
"timeout": 3}]
|
||||
|
||||
Get a specific field::
|
||||
|
|
@ -629,7 +602,7 @@ Get a specific item when field matchs the given value::
|
|||
"port": 0,
|
||||
"refresh": 30,
|
||||
"rtt_warning": None,
|
||||
"status": 0.004165,
|
||||
"status": 0.003449,
|
||||
"timeout": 3}]}
|
||||
|
||||
GET processcount
|
||||
|
|
@ -638,12 +611,12 @@ GET processcount
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/processcount
|
||||
{"pid_max": 0, "running": 1, "sleeping": 326, "thread": 1637, "total": 396}
|
||||
{"pid_max": 0, "running": 1, "sleeping": 319, "thread": 1542, "total": 387}
|
||||
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/3/processcount/total
|
||||
{"total": 396}
|
||||
{"total": 387}
|
||||
|
||||
GET processlist
|
||||
---------------
|
||||
|
|
@ -653,15 +626,15 @@ Get plugin stats::
|
|||
# curl http://localhost:61208/api/3/processlist
|
||||
[{"cmdline": ["/snap/firefox/2391/usr/lib/firefox/firefox"],
|
||||
"cpu_percent": 0.0,
|
||||
"cpu_times": [77.73, 21.94, 28.88, 6.46, 0.0],
|
||||
"cpu_times": [1287.11, 419.09, 1097.08, 148.64, 0.0],
|
||||
"gids": [1000, 1000, 1000],
|
||||
"io_counters": [351327232, 423739392, 0, 0, 0],
|
||||
"io_counters": [502609920, 1333940224, 0, 0, 0],
|
||||
"key": "pid",
|
||||
"memory_info": [448016384, 3489435648, 179822592, 626688, 0, 589619200, 0],
|
||||
"memory_percent": 5.71726810563191,
|
||||
"memory_info": [509206528, 21605502976, 176431104, 626688, 0, 833679360, 0],
|
||||
"memory_percent": 6.498133429231825,
|
||||
"name": "firefox",
|
||||
"nice": 0,
|
||||
"num_threads": 104,
|
||||
"num_threads": 117,
|
||||
"pid": 846720,
|
||||
"status": "S",
|
||||
"time_since_update": 1,
|
||||
|
|
@ -686,12 +659,12 @@ Get plugin stats::
|
|||
"true",
|
||||
"tab"],
|
||||
"cpu_percent": 0.0,
|
||||
"cpu_times": [28.89, 5.0, 0.0, 0.0, 0.0],
|
||||
"cpu_times": [185.15, 34.08, 0.0, 0.0, 0.0],
|
||||
"gids": [1000, 1000, 1000],
|
||||
"io_counters": [4248576, 0, 0, 0, 0],
|
||||
"io_counters": [9207808, 0, 0, 0, 0],
|
||||
"key": "pid",
|
||||
"memory_info": [405463040, 3183603712, 85282816, 626688, 0, 623808512, 0],
|
||||
"memory_percent": 5.174232437456028,
|
||||
"memory_info": [435576832, 3219697664, 100659200, 626688, 0, 613511168, 0],
|
||||
"memory_percent": 5.558523344418112,
|
||||
"name": "WebExtensions",
|
||||
"nice": 0,
|
||||
"num_threads": 20,
|
||||
|
|
@ -705,181 +678,176 @@ Get a specific field::
|
|||
# curl http://localhost:61208/api/3/processlist/pid
|
||||
{"pid": [846720,
|
||||
846991,
|
||||
4150,
|
||||
847043,
|
||||
255919,
|
||||
4150,
|
||||
847035,
|
||||
255919,
|
||||
255685,
|
||||
847039,
|
||||
847858,
|
||||
859882,
|
||||
836010,
|
||||
255737,
|
||||
847051,
|
||||
849456,
|
||||
836010,
|
||||
847733,
|
||||
849713,
|
||||
285410,
|
||||
847007,
|
||||
258480,
|
||||
4473,
|
||||
847007,
|
||||
285410,
|
||||
422,
|
||||
875536,
|
||||
255627,
|
||||
849995,
|
||||
850278,
|
||||
850213,
|
||||
850165,
|
||||
255751,
|
||||
847507,
|
||||
258480,
|
||||
6074,
|
||||
255751,
|
||||
876641,
|
||||
876390,
|
||||
847507,
|
||||
876962,
|
||||
255664,
|
||||
850348,
|
||||
62850,
|
||||
877142,
|
||||
2512,
|
||||
4544,
|
||||
4035,
|
||||
846970,
|
||||
4544,
|
||||
847508,
|
||||
256270,
|
||||
422,
|
||||
258481,
|
||||
2512,
|
||||
596789,
|
||||
255769,
|
||||
596789,
|
||||
285072,
|
||||
95798,
|
||||
829345,
|
||||
2721,
|
||||
4585,
|
||||
255672,
|
||||
4413,
|
||||
789543,
|
||||
860282,
|
||||
285950,
|
||||
286011,
|
||||
4248,
|
||||
789544,
|
||||
255906,
|
||||
3955,
|
||||
286011,
|
||||
255906,
|
||||
255976,
|
||||
829380,
|
||||
4932,
|
||||
790774,
|
||||
2721,
|
||||
62850,
|
||||
829424,
|
||||
1635,
|
||||
1,
|
||||
789543,
|
||||
4325,
|
||||
4223,
|
||||
829380,
|
||||
829424,
|
||||
14455,
|
||||
1,
|
||||
4325,
|
||||
4331,
|
||||
4561,
|
||||
4223,
|
||||
4332,
|
||||
4561,
|
||||
4214,
|
||||
3351,
|
||||
4625,
|
||||
1660,
|
||||
1681,
|
||||
3351,
|
||||
1876,
|
||||
5299,
|
||||
3944,
|
||||
219792,
|
||||
14458,
|
||||
286108,
|
||||
1876,
|
||||
4327,
|
||||
3934,
|
||||
3944,
|
||||
5299,
|
||||
4182,
|
||||
4130,
|
||||
4659,
|
||||
4263,
|
||||
4445,
|
||||
4327,
|
||||
286108,
|
||||
4339,
|
||||
4233,
|
||||
4214,
|
||||
4137,
|
||||
2239,
|
||||
1682,
|
||||
129087,
|
||||
4182,
|
||||
4352,
|
||||
129101,
|
||||
4261,
|
||||
255632,
|
||||
3968,
|
||||
830552,
|
||||
823483,
|
||||
4130,
|
||||
17189,
|
||||
4377,
|
||||
129097,
|
||||
3968,
|
||||
1634,
|
||||
4352,
|
||||
1442,
|
||||
255633,
|
||||
1777,
|
||||
17189,
|
||||
1682,
|
||||
2179,
|
||||
117714,
|
||||
59511,
|
||||
4330,
|
||||
4452,
|
||||
1643,
|
||||
706956,
|
||||
17205,
|
||||
1655,
|
||||
219792,
|
||||
4659,
|
||||
4524,
|
||||
3700,
|
||||
706252,
|
||||
3966,
|
||||
4229,
|
||||
3971,
|
||||
1873,
|
||||
117714,
|
||||
4330,
|
||||
96102,
|
||||
2179,
|
||||
4201,
|
||||
285853,
|
||||
790786,
|
||||
1643,
|
||||
4192,
|
||||
1673,
|
||||
4334,
|
||||
4392,
|
||||
3966,
|
||||
4155,
|
||||
706252,
|
||||
4329,
|
||||
4443,
|
||||
1617,
|
||||
790709,
|
||||
4328,
|
||||
3700,
|
||||
4573,
|
||||
1675,
|
||||
4573,
|
||||
4485,
|
||||
285970,
|
||||
1661,
|
||||
4337,
|
||||
4050,
|
||||
285853,
|
||||
1631,
|
||||
4178,
|
||||
1666,
|
||||
4334,
|
||||
4166,
|
||||
1666,
|
||||
4348,
|
||||
4324,
|
||||
4335,
|
||||
285913,
|
||||
4045,
|
||||
4347,
|
||||
4443,
|
||||
285970,
|
||||
285913,
|
||||
4173,
|
||||
4192,
|
||||
4212,
|
||||
468,
|
||||
4212,
|
||||
3976,
|
||||
1885,
|
||||
1676,
|
||||
1626,
|
||||
1676,
|
||||
4314,
|
||||
1670,
|
||||
9703,
|
||||
1646,
|
||||
4119,
|
||||
1443,
|
||||
255649,
|
||||
850150,
|
||||
877118,
|
||||
3952,
|
||||
129099,
|
||||
49191,
|
||||
2020,
|
||||
255649,
|
||||
1633,
|
||||
4162,
|
||||
1441,
|
||||
14505,
|
||||
49179,
|
||||
3953,
|
||||
3701,
|
||||
3354,
|
||||
129100,
|
||||
1449,
|
||||
|
|
@ -887,32 +855,30 @@ Get a specific field::
|
|||
4579,
|
||||
1450,
|
||||
2472,
|
||||
3701,
|
||||
219931,
|
||||
49182,
|
||||
1618,
|
||||
843176,
|
||||
850347,
|
||||
877141,
|
||||
1804,
|
||||
49194,
|
||||
1803,
|
||||
790829,
|
||||
4323,
|
||||
2480,
|
||||
3707,
|
||||
4018,
|
||||
255635,
|
||||
285883,
|
||||
285777,
|
||||
285877,
|
||||
285883,
|
||||
872737,
|
||||
285835,
|
||||
285843,
|
||||
285784,
|
||||
285905,
|
||||
3945,
|
||||
285898,
|
||||
4820,
|
||||
839994,
|
||||
285898,
|
||||
2475,
|
||||
1447,
|
||||
2503,
|
||||
|
|
@ -1068,58 +1034,56 @@ Get a specific field::
|
|||
220752,
|
||||
220756,
|
||||
285941,
|
||||
818594,
|
||||
818595,
|
||||
818597,
|
||||
826942,
|
||||
829047,
|
||||
829048,
|
||||
829051,
|
||||
829052,
|
||||
829054,
|
||||
829104,
|
||||
840207,
|
||||
840738,
|
||||
841704,
|
||||
841808,
|
||||
843409,
|
||||
844084,
|
||||
844992,
|
||||
846598,
|
||||
848860,
|
||||
848861,
|
||||
849001,
|
||||
849187,
|
||||
850107,
|
||||
850250,
|
||||
850251,
|
||||
850252,
|
||||
850253,
|
||||
850254,
|
||||
850255,
|
||||
850273,
|
||||
850308]}
|
||||
859825,
|
||||
860163,
|
||||
860164,
|
||||
860166,
|
||||
860167,
|
||||
860169,
|
||||
860220,
|
||||
868345,
|
||||
871910,
|
||||
872852,
|
||||
873104,
|
||||
873258,
|
||||
873643,
|
||||
874420,
|
||||
874573,
|
||||
874834,
|
||||
874866,
|
||||
875114,
|
||||
875396,
|
||||
875564,
|
||||
876077,
|
||||
876089,
|
||||
876121,
|
||||
876528,
|
||||
876924,
|
||||
877134]}
|
||||
|
||||
Get a specific item when field matchs the given value::
|
||||
|
||||
# curl http://localhost:61208/api/3/processlist/pid/846720
|
||||
{"846720": [{"cmdline": ["/snap/firefox/2391/usr/lib/firefox/firefox"],
|
||||
"cpu_percent": 0.0,
|
||||
"cpu_times": [77.73, 21.94, 28.88, 6.46, 0.0],
|
||||
"cpu_times": [1287.11, 419.09, 1097.08, 148.64, 0.0],
|
||||
"gids": [1000, 1000, 1000],
|
||||
"io_counters": [351327232, 423739392, 0, 0, 0],
|
||||
"io_counters": [502609920, 1333940224, 0, 0, 0],
|
||||
"key": "pid",
|
||||
"memory_info": [448016384,
|
||||
3489435648,
|
||||
179822592,
|
||||
"memory_info": [509206528,
|
||||
21605502976,
|
||||
176431104,
|
||||
626688,
|
||||
0,
|
||||
589619200,
|
||||
833679360,
|
||||
0],
|
||||
"memory_percent": 5.71726810563191,
|
||||
"memory_percent": 6.498133429231825,
|
||||
"name": "firefox",
|
||||
"nice": 0,
|
||||
"num_threads": 104,
|
||||
"num_threads": 117,
|
||||
"pid": 846720,
|
||||
"status": "S",
|
||||
"time_since_update": 1,
|
||||
|
|
@ -1139,25 +1103,51 @@ GET quicklook
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/quicklook
|
||||
{"cpu": 29.2,
|
||||
{"cpu": 29.8,
|
||||
"cpu_hz": 3000000000.0,
|
||||
"cpu_hz_current": 1619193499.9999998,
|
||||
"cpu_hz_current": 1604295750.0,
|
||||
"cpu_name": "Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz",
|
||||
"mem": 61.0,
|
||||
"mem": 69.1,
|
||||
"percpu": [{"cpu_number": 0,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 21.0,
|
||||
"idle": 22.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 3.0,
|
||||
"total": 79.0,
|
||||
"user": 68.0},
|
||||
"system": 1.0,
|
||||
"total": 78.0,
|
||||
"user": 67.0},
|
||||
{"cpu_number": 1,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 81.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 2.0,
|
||||
"total": 19.0,
|
||||
"user": 7.0},
|
||||
{"cpu_number": 2,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 70.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 2.0,
|
||||
"total": 30.0,
|
||||
"user": 20.0},
|
||||
{"cpu_number": 3,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 83.0,
|
||||
|
|
@ -1167,41 +1157,15 @@ Get plugin stats::
|
|||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 0.0,
|
||||
"system": 5.0,
|
||||
"total": 17.0,
|
||||
"user": 7.0},
|
||||
{"cpu_number": 2,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 73.0,
|
||||
"iowait": 1.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 3.0,
|
||||
"total": 27.0,
|
||||
"user": 15.0},
|
||||
{"cpu_number": 3,
|
||||
"guest": 0.0,
|
||||
"guest_nice": 0.0,
|
||||
"idle": 82.0,
|
||||
"iowait": 0.0,
|
||||
"irq": 0.0,
|
||||
"key": "cpu_number",
|
||||
"nice": 0.0,
|
||||
"softirq": 0.0,
|
||||
"steal": 0.0,
|
||||
"system": 3.0,
|
||||
"total": 18.0,
|
||||
"user": 6.0}],
|
||||
"swap": 29.5}
|
||||
"swap": 27.3}
|
||||
|
||||
Get a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/3/quicklook/cpu
|
||||
{"cpu": 29.2}
|
||||
{"cpu": 29.8}
|
||||
|
||||
GET sensors
|
||||
-----------
|
||||
|
|
@ -1272,7 +1236,7 @@ GET uptime
|
|||
Get plugin stats::
|
||||
|
||||
# curl http://localhost:61208/api/3/uptime
|
||||
"55 days, 17:31:34"
|
||||
"56 days, 0:19:45"
|
||||
|
||||
GET all stats
|
||||
-------------
|
||||
|
|
@ -1288,33 +1252,33 @@ GET stats history
|
|||
History of a plugin::
|
||||
|
||||
# curl http://localhost:61208/api/3/cpu/history
|
||||
{"system": [["2023-03-11T10:42:33.484532", 3.9],
|
||||
["2023-03-11T10:42:34.566094", 3.9],
|
||||
["2023-03-11T10:42:35.669575", 1.0]],
|
||||
"user": [["2023-03-11T10:42:33.484526", 24.1],
|
||||
["2023-03-11T10:42:34.566090", 24.1],
|
||||
["2023-03-11T10:42:35.669571", 3.0]]}
|
||||
{"system": [["2023-03-11T17:30:44.653473", 4.0],
|
||||
["2023-03-11T17:30:45.724303", 4.0],
|
||||
["2023-03-11T17:30:46.822979", 0.9]],
|
||||
"user": [["2023-03-11T17:30:44.653466", 25.2],
|
||||
["2023-03-11T17:30:45.724298", 25.2],
|
||||
["2023-03-11T17:30:46.822974", 5.1]]}
|
||||
|
||||
Limit history to last 2 values::
|
||||
|
||||
# curl http://localhost:61208/api/3/cpu/history/2
|
||||
{"system": [["2023-03-11T10:42:34.566094", 3.9],
|
||||
["2023-03-11T10:42:35.669575", 1.0]],
|
||||
"user": [["2023-03-11T10:42:34.566090", 24.1],
|
||||
["2023-03-11T10:42:35.669571", 3.0]]}
|
||||
{"system": [["2023-03-11T17:30:45.724303", 4.0],
|
||||
["2023-03-11T17:30:46.822979", 0.9]],
|
||||
"user": [["2023-03-11T17:30:45.724298", 25.2],
|
||||
["2023-03-11T17:30:46.822974", 5.1]]}
|
||||
|
||||
History for a specific field::
|
||||
|
||||
# curl http://localhost:61208/api/3/cpu/system/history
|
||||
{"system": [["2023-03-11T10:42:33.484532", 3.9],
|
||||
["2023-03-11T10:42:34.566094", 3.9],
|
||||
["2023-03-11T10:42:35.669575", 1.0]]}
|
||||
{"system": [["2023-03-11T17:30:44.653473", 4.0],
|
||||
["2023-03-11T17:30:45.724303", 4.0],
|
||||
["2023-03-11T17:30:46.822979", 0.9]]}
|
||||
|
||||
Limit history for a specific field to last 2 values::
|
||||
|
||||
# curl http://localhost:61208/api/3/cpu/system/history
|
||||
{"system": [["2023-03-11T10:42:34.566094", 3.9],
|
||||
["2023-03-11T10:42:35.669575", 1.0]]}
|
||||
{"system": [["2023-03-11T17:30:45.724303", 4.0],
|
||||
["2023-03-11T17:30:46.822979", 0.9]]}
|
||||
|
||||
GET limits (used for thresholds)
|
||||
--------------------------------
|
||||
|
|
|
|||
|
|
@ -236,6 +236,13 @@ Examples of use:
|
|||
dest='enable_separator',
|
||||
help='enable separator in the UI',
|
||||
),
|
||||
parser.add_argument(
|
||||
'--disable-cursor',
|
||||
action='store_true',
|
||||
default=False,
|
||||
dest='disable_cursor',
|
||||
help='disable cursor (process selection) in the UI',
|
||||
),
|
||||
# Sort processes list
|
||||
parser.add_argument(
|
||||
'--sort-processes',
|
||||
|
|
@ -700,6 +707,11 @@ Examples of use:
|
|||
logger.critical("Process filter is only available in standalone mode")
|
||||
sys.exit(2)
|
||||
|
||||
# Cursor option is only available in standalone mode
|
||||
if not args.disable_cursor and not self.is_standalone():
|
||||
logger.critical("Cursor is only available in standalone mode")
|
||||
sys.exit(2)
|
||||
|
||||
# Disable HDDTemp if sensors are disabled
|
||||
if getattr(self.args, 'disable_sensors', False):
|
||||
disable(self.args, 'hddtemp')
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ class _GlancesCurses(object):
|
|||
self.ifCAREFUL_color2 = curses.color_pair(8) | A_BOLD
|
||||
self.ifWARNING_color2 = curses.color_pair(5) | A_BOLD
|
||||
self.ifCRITICAL_color2 = curses.color_pair(6) | A_BOLD
|
||||
self.ifINFO_color = curses.color_pair(8)
|
||||
self.filter_color = A_BOLD
|
||||
self.selected_color = A_BOLD
|
||||
|
||||
|
|
@ -301,6 +302,7 @@ class _GlancesCurses(object):
|
|||
self.ifCAREFUL_color2 = curses.A_UNDERLINE
|
||||
self.ifWARNING_color2 = A_BOLD
|
||||
self.ifCRITICAL_color2 = curses.A_REVERSE
|
||||
self.ifINFO_color = A_BOLD
|
||||
self.filter_color = A_BOLD
|
||||
self.selected_color = A_BOLD
|
||||
|
||||
|
|
@ -328,6 +330,7 @@ class _GlancesCurses(object):
|
|||
'CRITICAL_LOG': self.ifCRITICAL_color,
|
||||
'PASSWORD': curses.A_PROTECT,
|
||||
'SELECTED': self.selected_color,
|
||||
'INFO': self.ifINFO_color
|
||||
}
|
||||
|
||||
def set_cursor(self, value):
|
||||
|
|
@ -407,13 +410,15 @@ class _GlancesCurses(object):
|
|||
elif self.pressedkey == ord('9'):
|
||||
# '9' > Theme from black to white and reverse
|
||||
self._init_colors()
|
||||
elif self.pressedkey == ord('e'):
|
||||
elif self.pressedkey == ord('e') and not self.args.programs:
|
||||
# 'e' > Enable/Disable process extended
|
||||
self.args.enable_process_extended = not self.args.enable_process_extended
|
||||
if not self.args.enable_process_extended:
|
||||
glances_processes.disable_extended()
|
||||
else:
|
||||
glances_processes.enable_extended()
|
||||
# When a process is selected (and only in standalone mode), disable the cursor
|
||||
self.args.disable_cursor = self.args.enable_process_extended and self.args.is_standalone
|
||||
elif self.pressedkey == ord('E'):
|
||||
# 'E' > Erase the process filter
|
||||
glances_processes.process_filter = None
|
||||
|
|
@ -427,7 +432,7 @@ class _GlancesCurses(object):
|
|||
elif self.pressedkey == ord('-'):
|
||||
# '+' > Decrease process nice level
|
||||
self.decrease_nice_process = not self.decrease_nice_process
|
||||
elif self.pressedkey == ord('k'):
|
||||
elif self.pressedkey == ord('k') and not self.args.disable_cursor:
|
||||
# 'k' > Kill selected process (after confirmation)
|
||||
self.kill_process = not self.kill_process
|
||||
elif self.pressedkey == ord('w'):
|
||||
|
|
@ -451,11 +456,11 @@ class _GlancesCurses(object):
|
|||
# ">" (right arrow) navigation through process sort
|
||||
next_sort = (self.loop_position() + 1) % len(self._sort_loop)
|
||||
glances_processes.set_sort_key(self._sort_loop[next_sort], False)
|
||||
elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65:
|
||||
elif self.pressedkey == curses.KEY_UP or self.pressedkey == 65 and not self.args.disable_cursor:
|
||||
# 'UP' > Up in the server list
|
||||
if self.args.cursor_position > 0:
|
||||
self.args.cursor_position -= 1
|
||||
elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66:
|
||||
elif self.pressedkey == curses.KEY_DOWN or self.pressedkey == 66 and not self.args.disable_cursor:
|
||||
# 'DOWN' > Down in the server list
|
||||
# if self.args.cursor_position < glances_processes.max_processes - 2:
|
||||
if self.args.cursor_position < glances_processes.processes_count:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from glances.processes import glances_processes, sort_stats
|
|||
from glances.outputs.glances_unicode import unicode_message
|
||||
from glances.plugins.glances_core import Plugin as CorePlugin
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
from glances.programs import processes_to_programs
|
||||
from glances.outputs.glances_bars import Bar
|
||||
|
||||
|
||||
def seconds_to_hms(input_seconds):
|
||||
|
|
@ -146,9 +146,10 @@ class Plugin(GlancesPlugin):
|
|||
# Update stats using the standard system lib
|
||||
# Note: Update is done in the processcount plugin
|
||||
# Just return the processes list
|
||||
stats = glances_processes.getlist()
|
||||
if self.args.programs:
|
||||
stats = processes_to_programs(stats)
|
||||
stats = glances_processes.getlist(as_programs=True)
|
||||
else:
|
||||
stats = glances_processes.getlist()
|
||||
|
||||
elif self.input_method == 'snmp':
|
||||
# No SNMP grab for processes
|
||||
|
|
@ -353,11 +354,11 @@ class Plugin(GlancesPlugin):
|
|||
- selected is a tag=True if p is the selected process
|
||||
"""
|
||||
ret = [self.curse_new_line()]
|
||||
|
||||
# When a process is selected:
|
||||
# * display a special character at the beginning of the line
|
||||
# * underline the command name
|
||||
if args.is_standalone:
|
||||
ret.append(self.curse_add_line(unicode_message('PROCESS_SELECTOR') if selected else ' ', 'SELECTED'))
|
||||
ret.append(self.curse_add_line(unicode_message('PROCESS_SELECTOR') if (selected and not args.disable_cursor) else ' ', 'SELECTED'))
|
||||
|
||||
# CPU
|
||||
ret.append(self._get_process_curses_cpu(p, selected, args))
|
||||
|
|
@ -404,7 +405,7 @@ class Plugin(GlancesPlugin):
|
|||
cmdline = p.get('cmdline', '?')
|
||||
|
||||
try:
|
||||
process_decoration = 'PROCESS_SELECTED' if (selected and args.is_standalone) else 'PROCESS'
|
||||
process_decoration = 'PROCESS_SELECTED' if (selected and not args.disable_cursor) else 'PROCESS'
|
||||
if cmdline:
|
||||
path, cmd, arguments = split_cmdline(bare_process_name, cmdline)
|
||||
# Manage end of line in arguments (see #1692)
|
||||
|
|
@ -428,74 +429,14 @@ class Plugin(GlancesPlugin):
|
|||
logger.debug("Can not decode command line '{}' ({})".format(cmdline, e))
|
||||
ret.append(self.curse_add_line('', splittable=True))
|
||||
|
||||
# Add extended stats but only for the top processes
|
||||
if args.cursor_position == 0 and 'extended_stats' in p and args.enable_process_extended:
|
||||
# Left padding
|
||||
xpad = ' ' * 13
|
||||
# First line is CPU affinity
|
||||
if 'cpu_affinity' in p and p['cpu_affinity'] is not None:
|
||||
ret.append(self.curse_new_line())
|
||||
msg = xpad + 'CPU affinity: ' + str(len(p['cpu_affinity'])) + ' cores'
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
# Second line is memory info
|
||||
if 'memory_info' in p and p['memory_info'] is not None:
|
||||
ret.append(self.curse_new_line())
|
||||
msg = '{}Memory info: {}'.format(xpad, p['memory_info'])
|
||||
if 'memory_swap' in p and p['memory_swap'] is not None:
|
||||
msg += ' swap ' + self.auto_unit(p['memory_swap'], low_precision=False)
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
# Third line is for open files/network sessions
|
||||
msg = ''
|
||||
if 'num_threads' in p and p['num_threads'] is not None:
|
||||
msg += str(p['num_threads']) + ' threads '
|
||||
if 'num_fds' in p and p['num_fds'] is not None:
|
||||
msg += str(p['num_fds']) + ' files '
|
||||
if 'num_handles' in p and p['num_handles'] is not None:
|
||||
msg += str(p['num_handles']) + ' handles '
|
||||
if 'tcp' in p and p['tcp'] is not None:
|
||||
msg += str(p['tcp']) + ' TCP '
|
||||
if 'udp' in p and p['udp'] is not None:
|
||||
msg += str(p['udp']) + ' UDP'
|
||||
if msg != '':
|
||||
ret.append(self.curse_new_line())
|
||||
msg = xpad + 'Open: ' + msg
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
# Fourth line is IO nice level (only Linux and Windows OS)
|
||||
if 'ionice' in p and p['ionice'] is not None and hasattr(p['ionice'], 'ioclass'):
|
||||
ret.append(self.curse_new_line())
|
||||
msg = xpad + 'IO nice: '
|
||||
k = 'Class is '
|
||||
v = p['ionice'].ioclass
|
||||
# Linux: The scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle.
|
||||
# Windows: On Windows only ioclass is used and it can be set to 2 (normal), 1 (low) or 0 (very low).
|
||||
if WINDOWS:
|
||||
if v == 0:
|
||||
msg += k + 'Very Low'
|
||||
elif v == 1:
|
||||
msg += k + 'Low'
|
||||
elif v == 2:
|
||||
msg += 'No specific I/O priority'
|
||||
else:
|
||||
msg += k + str(v)
|
||||
else:
|
||||
if v == 0:
|
||||
msg += 'No specific I/O priority'
|
||||
elif v == 1:
|
||||
msg += k + 'Real Time'
|
||||
elif v == 2:
|
||||
msg += k + 'Best Effort'
|
||||
elif v == 3:
|
||||
msg += k + 'IDLE'
|
||||
else:
|
||||
msg += k + str(v)
|
||||
# value is a number which goes from 0 to 7.
|
||||
# The higher the value, the lower the I/O priority of the process.
|
||||
if hasattr(p['ionice'], 'value') and p['ionice'].value != 0:
|
||||
msg += ' (value %s/7)' % str(p['ionice'].value)
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
|
||||
return ret
|
||||
|
||||
def is_selected_process(self, args):
|
||||
return args.is_standalone and \
|
||||
self.args.enable_process_extended and \
|
||||
args.cursor_position is not None and \
|
||||
glances_processes.extended_process is not None
|
||||
|
||||
def msg_curse(self, args=None, max_width=None):
|
||||
"""Return the dict to display in the curse interface."""
|
||||
# Init the return message
|
||||
|
|
@ -507,6 +448,16 @@ class Plugin(GlancesPlugin):
|
|||
|
||||
# Compute the sort key
|
||||
process_sort_key = glances_processes.sort_key
|
||||
processes_list_sorted = self.__sort_stats(process_sort_key)
|
||||
|
||||
# Display extended stats for selected process
|
||||
#############################################
|
||||
|
||||
if self.is_selected_process(args):
|
||||
self.__msg_curse_extended_process(ret, glances_processes.extended_process)
|
||||
|
||||
# Display others processes list
|
||||
###############################
|
||||
|
||||
# Header
|
||||
self.__msg_curse_header(ret, process_sort_key, args)
|
||||
|
|
@ -515,10 +466,10 @@ class Plugin(GlancesPlugin):
|
|||
# Loop over processes (sorted by the sort key previously compute)
|
||||
# This is a Glances bottleneck (see flame graph),
|
||||
# get_process_curses_data should be optimzed
|
||||
i = 0
|
||||
for p in self.__sort_stats(process_sort_key):
|
||||
ret.extend(self.get_process_curses_data(p, i == args.cursor_position, args))
|
||||
i += 1
|
||||
for position, process in enumerate(processes_list_sorted):
|
||||
ret.extend(self.get_process_curses_data(process,
|
||||
position == args.cursor_position,
|
||||
args))
|
||||
|
||||
# A filter is set Display the stats summaries
|
||||
if glances_processes.process_filter is not None:
|
||||
|
|
@ -532,6 +483,116 @@ class Plugin(GlancesPlugin):
|
|||
# Return the message with decoration
|
||||
return ret
|
||||
|
||||
def __msg_curse_extended_process(self, ret, p):
|
||||
"""Get extended curses data for the selected process (see issue #2225)
|
||||
|
||||
The result depends of the process type (process or thread).
|
||||
|
||||
Input p is a dict with the following keys:
|
||||
{'status': 'S',
|
||||
'memory_info': pmem(rss=466890752, vms=3365347328, shared=68153344, text=659456, lib=0, data=774647808, dirty=0),
|
||||
'pid': 4980,
|
||||
'io_counters': [165385216, 0, 165385216, 0, 1],
|
||||
'num_threads': 20,
|
||||
'nice': 0,
|
||||
'memory_percent': 5.958135664449709,
|
||||
'cpu_percent': 0.0,
|
||||
'gids': pgids(real=1000, effective=1000, saved=1000),
|
||||
'cpu_times': pcputimes(user=696.38, system=119.98, children_user=0.0, children_system=0.0, iowait=0.0),
|
||||
'name': 'WebExtensions',
|
||||
'key': 'pid',
|
||||
'time_since_update': 2.1997854709625244,
|
||||
'cmdline': ['/snap/firefox/2154/usr/lib/firefox/firefox', '-contentproc', '-childID', '...'],
|
||||
'username': 'nicolargo',
|
||||
'cpu_min': 0.0,
|
||||
'cpu_max': 7.0,
|
||||
'cpu_mean': 3.2}
|
||||
"""
|
||||
if self.args.programs:
|
||||
self.__msg_curse_extended_process_program(ret, p)
|
||||
else:
|
||||
self.__msg_curse_extended_process_thread(ret, p)
|
||||
|
||||
def __msg_curse_extended_process_program(self, ret, p):
|
||||
# Title
|
||||
msg = "Pinned program {} ('e' to unpin)".format(p['name'])
|
||||
ret.append(self.curse_add_line(msg, "TITLE"))
|
||||
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
def __msg_curse_extended_process_thread(self, ret, p):
|
||||
# Title
|
||||
ret.append(self.curse_add_line("Pinned thread ", "TITLE"))
|
||||
ret.append(self.curse_add_line(p['name'], "UNDERLINE"))
|
||||
ret.append(self.curse_add_line(" ('e' to unpin)"))
|
||||
|
||||
# First line is CPU affinity
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_add_line(' CPU Min/Max/Mean: '))
|
||||
msg = '{: >7.1f}{: >7.1f}{: >7.1f}%'.format(p['cpu_min'], p['cpu_max'], p['cpu_mean'])
|
||||
ret.append(self.curse_add_line(msg, decoration='INFO'))
|
||||
if 'cpu_affinity' in p and p['cpu_affinity'] is not None:
|
||||
ret.append(self.curse_add_line(' Affinity: '))
|
||||
ret.append(self.curse_add_line(str(len(p['cpu_affinity'])), decoration='INFO'))
|
||||
ret.append(self.curse_add_line(' cores', decoration='INFO'))
|
||||
if 'ionice' in p and p['ionice'] is not None and hasattr(p['ionice'], 'ioclass'):
|
||||
msg = ' IO nice: '
|
||||
k = 'Class is '
|
||||
v = p['ionice'].ioclass
|
||||
# Linux: The scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle.
|
||||
# Windows: On Windows only ioclass is used and it can be set to 2 (normal), 1 (low) or 0 (very low).
|
||||
if WINDOWS:
|
||||
if v == 0:
|
||||
msg += k + 'Very Low'
|
||||
elif v == 1:
|
||||
msg += k + 'Low'
|
||||
elif v == 2:
|
||||
msg += 'No specific I/O priority'
|
||||
else:
|
||||
msg += k + str(v)
|
||||
else:
|
||||
if v == 0:
|
||||
msg += 'No specific I/O priority'
|
||||
elif v == 1:
|
||||
msg += k + 'Real Time'
|
||||
elif v == 2:
|
||||
msg += k + 'Best Effort'
|
||||
elif v == 3:
|
||||
msg += k + 'IDLE'
|
||||
else:
|
||||
msg += k + str(v)
|
||||
# value is a number which goes from 0 to 7.
|
||||
# The higher the value, the lower the I/O priority of the process.
|
||||
if hasattr(p['ionice'], 'value') and p['ionice'].value != 0:
|
||||
msg += ' (value %s/7)' % str(p['ionice'].value)
|
||||
ret.append(self.curse_add_line(msg, splittable=True))
|
||||
|
||||
# Second line is memory info
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_add_line(' MEM Min/Max/Mean: '))
|
||||
msg = '{: >7.1f}{: >7.1f}{: >7.1f}%'.format(p['memory_min'], p['memory_max'], p['memory_mean'])
|
||||
ret.append(self.curse_add_line(msg, decoration='INFO'))
|
||||
if 'memory_info' in p and p['memory_info'] is not None:
|
||||
ret.append(self.curse_add_line(' Memory info: '))
|
||||
for k in p['memory_info']._asdict():
|
||||
ret.append(self.curse_add_line(self.auto_unit(p['memory_info']._asdict()[k], low_precision=False), decoration='INFO', splittable=True))
|
||||
ret.append(self.curse_add_line(' ' + k + ' ', splittable=True))
|
||||
if 'memory_swap' in p and p['memory_swap'] is not None:
|
||||
ret.append(self.curse_add_line(self.auto_unit(p['memory_swap'], low_precision=False), decoration='INFO', splittable=True))
|
||||
ret.append(self.curse_add_line(' swap ', splittable=True))
|
||||
|
||||
# Third line is for open files/network sessions
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_add_line(' Open: '))
|
||||
for stat_prefix in ['num_threads', 'num_fds', 'num_handles', 'tcp', 'udp']:
|
||||
if stat_prefix in p and p[stat_prefix] is not None:
|
||||
ret.append(self.curse_add_line(str(p[stat_prefix]), decoration='INFO'))
|
||||
ret.append(self.curse_add_line(' {} '.format(stat_prefix.replace('num_', ''))))
|
||||
|
||||
ret.append(self.curse_new_line())
|
||||
ret.append(self.curse_new_line())
|
||||
|
||||
def __msg_curse_header(self, ret, process_sort_key, args=None):
|
||||
"""Build the header and add it to the ret dict."""
|
||||
sort_style = 'SORT'
|
||||
|
|
@ -578,10 +639,15 @@ class Plugin(GlancesPlugin):
|
|||
msg, sort_style if process_sort_key == 'io_counters' else 'DEFAULT', optional=True, additional=True
|
||||
)
|
||||
)
|
||||
if not self.args.programs:
|
||||
msg = self.layout_header['command'].format('Command', "('k' to kill)" if args.is_standalone else "")
|
||||
if args.is_standalone and not args.disable_cursor:
|
||||
if self.args.programs:
|
||||
shortkey = "('k' to kill)"
|
||||
else:
|
||||
shortkey = "('e' to pin | 'k' to kill)"
|
||||
else:
|
||||
msg = self.layout_header['command'].format('Programs', "('k' to kill)" if args.is_standalone else "")
|
||||
shortkey = ""
|
||||
msg = self.layout_header['command'].format("Programs" if self.args.programs else "Command",
|
||||
shortkey)
|
||||
ret.append(self.curse_add_line(msg, sort_style if process_sort_key == 'name' else 'DEFAULT'))
|
||||
|
||||
def __msg_curse_sum(self, ret, sep_char='_', mmm=None, args=None):
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from glances.compat import iterkeys
|
|||
from glances.globals import BSD, LINUX, MACOS, WINDOWS
|
||||
from glances.timer import Timer, getTimeSinceLastUpdate
|
||||
from glances.filter import GlancesFilter
|
||||
from glances.programs import processes_to_programs
|
||||
from glances.logger import logger
|
||||
|
||||
import psutil
|
||||
|
|
@ -37,6 +38,10 @@ class GlancesProcesses(object):
|
|||
|
||||
def __init__(self, cache_timeout=60):
|
||||
"""Init the class to collect stats about processes."""
|
||||
# Init the args, coming from the GlancesStandalone class
|
||||
# Should be set by the set_args method
|
||||
self.args = None
|
||||
|
||||
# Add internals caches because psutil do not cache all the stats
|
||||
# See: https://github.com/giampaolo/psutil/issues/462
|
||||
self.username_cache = {}
|
||||
|
|
@ -70,6 +75,7 @@ class GlancesProcesses(object):
|
|||
|
||||
# Extended stats for top process is enable by default
|
||||
self.disable_extended_tag = False
|
||||
self.extended_process = None
|
||||
|
||||
# Test if the system can grab io_counters
|
||||
try:
|
||||
|
|
@ -109,6 +115,10 @@ class GlancesProcesses(object):
|
|||
self._max_values = {}
|
||||
self.reset_max_values()
|
||||
|
||||
def set_args(self, args):
|
||||
"""Set args."""
|
||||
self.args = args
|
||||
|
||||
def reset_processcount(self):
|
||||
"""Reset the global process count"""
|
||||
self.processcount = {'total': 0, 'running': 0, 'sleeping': 0, 'thread': 0, 'pid_max': None}
|
||||
|
|
@ -247,6 +257,91 @@ class GlancesProcesses(object):
|
|||
for k in self._max_values_list:
|
||||
self._max_values[k] = 0.0
|
||||
|
||||
def get_extended_stats(self, proc):
|
||||
"""Get the extended stats for the given PID."""
|
||||
# - cpu_affinity (Linux, Windows, FreeBSD)
|
||||
# - ionice (Linux and Windows > Vista)
|
||||
# - num_ctx_switches (not available on Illumos/Solaris)
|
||||
# - num_fds (Unix-like)
|
||||
# - num_handles (Windows)
|
||||
# - memory_maps (only swap, Linux)
|
||||
# https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
|
||||
# - connections (TCP and UDP)
|
||||
# - CPU min/max/mean
|
||||
|
||||
# Set the extended stats list (OS dependant)
|
||||
extended_stats = ['cpu_affinity', 'ionice', 'num_ctx_switches']
|
||||
if LINUX:
|
||||
# num_fds only available on Unix system (see issue #1351)
|
||||
extended_stats += ['num_fds']
|
||||
if WINDOWS:
|
||||
extended_stats += ['num_handles']
|
||||
|
||||
ret = {}
|
||||
try:
|
||||
# Get the extended stats
|
||||
selected_process = psutil.Process(proc['pid'])
|
||||
ret = selected_process.as_dict(attrs=extended_stats, ad_value=None)
|
||||
|
||||
if LINUX:
|
||||
try:
|
||||
ret['memory_swap'] = sum([v.swap for v in selected_process.memory_maps()])
|
||||
except (psutil.NoSuchProcess, KeyError):
|
||||
# (KeyError catch for issue #1551)
|
||||
pass
|
||||
except (psutil.AccessDenied, NotImplementedError):
|
||||
# NotImplementedError: /proc/${PID}/smaps file doesn't exist
|
||||
# on kernel < 2.6.14 or CONFIG_MMU kernel configuration option
|
||||
# is not enabled (see psutil #533/glances #413).
|
||||
ret['memory_swap'] = None
|
||||
try:
|
||||
ret['tcp'] = len(selected_process.connections(kind="tcp"))
|
||||
ret['udp'] = len(selected_process.connections(kind="udp"))
|
||||
except (psutil.AccessDenied, psutil.NoSuchProcess):
|
||||
# Manage issue1283 (psutil.AccessDenied)
|
||||
ret['tcp'] = None
|
||||
ret['udp'] = None
|
||||
except (psutil.NoSuchProcess, ValueError, AttributeError) as e:
|
||||
logger.error('Can not grab extended stats ({})'.format(e))
|
||||
self.extended_process = None
|
||||
ret['extended_stats'] = False
|
||||
else:
|
||||
logger.debug('Grab extended stats for process {}'.format(proc['pid']))
|
||||
|
||||
# Compute CPU and MEM min/max/mean
|
||||
for stat_prefix in ['cpu', 'memory']:
|
||||
if stat_prefix + '_min' not in self.extended_process:
|
||||
ret[stat_prefix + '_min'] = proc[stat_prefix + '_percent']
|
||||
else:
|
||||
ret[stat_prefix + '_min'] = proc[stat_prefix + '_percent'] if proc[stat_prefix + '_min'] > proc[stat_prefix + '_percent'] else proc[stat_prefix + '_min']
|
||||
if stat_prefix + '_max' not in self.extended_process:
|
||||
ret[stat_prefix + '_max'] = proc[stat_prefix + '_percent']
|
||||
else:
|
||||
ret[stat_prefix + '_max'] = proc[stat_prefix + '_percent'] if proc[stat_prefix + '_max'] < proc[stat_prefix + '_percent'] else proc[stat_prefix + '_max']
|
||||
if stat_prefix + '_mean_sum' not in self.extended_process:
|
||||
ret[stat_prefix + '_mean_sum'] = proc[stat_prefix + '_percent']
|
||||
else:
|
||||
ret[stat_prefix + '_mean_sum'] = proc[stat_prefix + '_mean_sum'] + proc[stat_prefix + '_percent']
|
||||
if stat_prefix + '_mean_counter' not in self.extended_process:
|
||||
ret[stat_prefix + '_mean_counter'] = 1
|
||||
else:
|
||||
ret[stat_prefix + '_mean_counter'] = proc[stat_prefix + '_mean_counter'] + 1
|
||||
ret[stat_prefix + '_mean'] = ret[stat_prefix + '_mean_sum'] / ret[stat_prefix + '_mean_counter']
|
||||
|
||||
ret['extended_stats'] = True
|
||||
return ret
|
||||
|
||||
def is_selected_extended_process(self, position):
|
||||
"""Return True if the process is the selected one for extended stats."""
|
||||
return hasattr(self.args, 'programs') and \
|
||||
not self.args.programs and \
|
||||
hasattr(self.args, 'enable_process_extended') and \
|
||||
self.args.enable_process_extended and \
|
||||
not self.disable_extended_tag and \
|
||||
hasattr(self.args, 'cursor_position') and \
|
||||
position == self.args.cursor_position and \
|
||||
not self.args.disable_cursor
|
||||
|
||||
def update(self):
|
||||
"""Update the processes stats."""
|
||||
# Reset the stats
|
||||
|
|
@ -305,59 +400,25 @@ class GlancesProcesses(object):
|
|||
# Update the processcount
|
||||
self.update_processcount(self.processlist)
|
||||
|
||||
# Loop over processes and add metadata
|
||||
first = True
|
||||
for proc in self.processlist:
|
||||
# Get extended stats, only for top processes (see issue #403).
|
||||
if first and not self.disable_extended_tag:
|
||||
# - cpu_affinity (Linux, Windows, FreeBSD)
|
||||
# - ionice (Linux and Windows > Vista)
|
||||
# - num_ctx_switches (not available on Illumos/Solaris)
|
||||
# - num_fds (Unix-like)
|
||||
# - num_handles (Windows)
|
||||
# - memory_maps (only swap, Linux)
|
||||
# https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/
|
||||
# - connections (TCP and UDP)
|
||||
extended = {}
|
||||
try:
|
||||
top_process = psutil.Process(proc['pid'])
|
||||
extended_stats = ['cpu_affinity', 'ionice', 'num_ctx_switches']
|
||||
if LINUX:
|
||||
# num_fds only available on Unix system (see issue #1351)
|
||||
extended_stats += ['num_fds']
|
||||
if WINDOWS:
|
||||
extended_stats += ['num_handles']
|
||||
# Loop over processes and :
|
||||
# - add extended stats for selected process
|
||||
# - add metadata
|
||||
for position, proc in enumerate(self.processlist):
|
||||
# Extended stats
|
||||
################
|
||||
|
||||
# Get the extended stats
|
||||
extended = top_process.as_dict(attrs=extended_stats, ad_value=None)
|
||||
# Get the selected process when the 'e' key is pressed
|
||||
if self.is_selected_extended_process(position):
|
||||
self.extended_process = proc
|
||||
|
||||
if LINUX:
|
||||
try:
|
||||
extended['memory_swap'] = sum([v.swap for v in top_process.memory_maps()])
|
||||
except (psutil.NoSuchProcess, KeyError):
|
||||
# (KeyError catch for issue #1551)
|
||||
pass
|
||||
except (psutil.AccessDenied, NotImplementedError):
|
||||
# NotImplementedError: /proc/${PID}/smaps file doesn't exist
|
||||
# on kernel < 2.6.14 or CONFIG_MMU kernel configuration option
|
||||
# is not enabled (see psutil #533/glances #413).
|
||||
extended['memory_swap'] = None
|
||||
try:
|
||||
extended['tcp'] = len(top_process.connections(kind="tcp"))
|
||||
extended['udp'] = len(top_process.connections(kind="udp"))
|
||||
except (psutil.AccessDenied, psutil.NoSuchProcess):
|
||||
# Manage issue1283 (psutil.AccessDenied)
|
||||
extended['tcp'] = None
|
||||
extended['udp'] = None
|
||||
except (psutil.NoSuchProcess, ValueError, AttributeError) as e:
|
||||
logger.error('Can not grab extended stats ({})'.format(e))
|
||||
extended['extended_stats'] = False
|
||||
else:
|
||||
logger.debug('Grab extended stats for process {}'.format(proc['pid']))
|
||||
extended['extended_stats'] = True
|
||||
proc.update(extended)
|
||||
first = False
|
||||
# /End of extended stats
|
||||
# Grab extended stats only for the selected process (see issue #2225)
|
||||
if self.extended_process is not None and \
|
||||
proc['pid'] == self.extended_process['pid']:
|
||||
proc.update(self.get_extended_stats(self.extended_process))
|
||||
self.extended_process = proc
|
||||
|
||||
# Meta data
|
||||
###########
|
||||
|
||||
# PID is the key
|
||||
proc['key'] = 'pid'
|
||||
|
|
@ -424,9 +485,14 @@ class GlancesProcesses(object):
|
|||
"""Get the number of processes."""
|
||||
return self.processcount
|
||||
|
||||
def getlist(self, sorted_by=None):
|
||||
"""Get the processlist."""
|
||||
return self.processlist
|
||||
def getlist(self, sorted_by=None, as_programs=False):
|
||||
"""Get the processlist.
|
||||
By default, return the list of threads.
|
||||
If as_programs is True, return the list of programs."""
|
||||
if as_programs:
|
||||
return processes_to_programs(self.processlist)
|
||||
else:
|
||||
return self.processlist
|
||||
|
||||
@property
|
||||
def sort_key(self):
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ class GlancesStandalone(object):
|
|||
self.display_modules_list()
|
||||
sys.exit(0)
|
||||
|
||||
# The args is needed to get the selected process in the process list (Curses mode)
|
||||
glances_processes.set_args(args)
|
||||
|
||||
# If process extended stats is disabled by user
|
||||
if not args.enable_process_extended:
|
||||
logger.debug("Extended stats for top process are disabled")
|
||||
|
|
|
|||
Loading…
Reference in New Issue