Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
蜕变的菜鸟
glances
提交
ccf4d8ad
G
glances
项目概览
蜕变的菜鸟
/
glances
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
glances
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ccf4d8ad
编写于
1月 28, 2014
作者:
N
Nicolas Hennion
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
All plugins work in server mode but not the getAll function
上级
05c675d7
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
412 addition
and
350 deletion
+412
-350
glances/README.txt
glances/README.txt
+1
-1
glances/__init__.py
glances/__init__.py
+3
-3
glances/core/glances_main.py
glances/core/glances_main.py
+1
-1
glances/core/glances_server.py
glances/core/glances_server.py
+19
-95
glances/core/glances_stats.py
glances/core/glances_stats.py
+137
-0
glances/plugins/_processes.py
glances/plugins/_processes.py
+196
-0
glances/plugins/glances_diskio.py
glances/plugins/glances_diskio.py
+4
-3
glances/plugins/glances_fs.py
glances/plugins/glances_fs.py
+3
-3
glances/plugins/glances_hddtemp.py
glances/plugins/glances_hddtemp.py
+3
-3
glances/plugins/glances_mem.py
glances/plugins/glances_mem.py
+1
-0
glances/plugins/glances_network.py
glances/plugins/glances_network.py
+5
-3
glances/plugins/glances_now.py
glances/plugins/glances_now.py
+4
-2
glances/plugins/glances_plugin.py
glances/plugins/glances_plugin.py
+10
-3
glances/plugins/glances_processcount.py
glances/plugins/glances_processcount.py
+8
-199
glances/plugins/glances_processlist.py
glances/plugins/glances_processlist.py
+7
-30
glances/plugins/glances_sensors.py
glances/plugins/glances_sensors.py
+9
-3
glances/plugins/glances_system.py
glances/plugins/glances_system.py
+1
-1
未找到文件。
glances/README.txt
浏览文件 @
ccf4d8ad
...
...
@@ -8,7 +8,7 @@ If you are lookink for user manual, please follow this link: https://github.com/
__init__.py Global module init
__main__.py Entry point for module
core/
glances_
core
.py Main script to rule them up...
glances_
main
.py Main script to rule them up...
glances_globals.py Share variables uppon modules
glances_config.py Manage configuration file
glances_timer.py Manage timer
...
...
glances/__init__.py
浏览文件 @
ccf4d8ad
...
...
@@ -20,11 +20,11 @@
# Import Glances libs
# Note: others Glances libs will be imported optionnaly
from
.core.glances_
core
import
GlancesCore
from
.core.glances_
main
import
GlancesMain
def
main
(
argv
=
None
):
# Create the Glances
core
instance
core
=
Glances
Core
()
# Create the Glances
main
instance
core
=
Glances
Main
()
# Glances can be ran in standalone, client or server mode
if
(
core
.
is_standalone
()):
...
...
glances/core/glances_
core
.py
→
glances/core/glances_
main
.py
浏览文件 @
ccf4d8ad
...
...
@@ -56,7 +56,7 @@ if psutil_version < (0, 5, 0):
print
(
'PsUtil 0.5.1 or higher is needed. Glances cannot start.'
)
sys
.
exit
(
1
)
class
Glances
Core
(
object
):
class
Glances
Main
(
object
):
"""
Main class to manage Glances instance
"""
...
...
glances/core/glances_server.py
浏览文件 @
ccf4d8ad
...
...
@@ -156,14 +156,17 @@ class GlancesInstance():
def
getAll
(
self
):
# Update and return all the stats
self
.
__update__
()
# !!! Not work has expected compare to v1
return
json
.
dumps
(
self
.
stats
.
getAll
())
def
getAllLimits
(
self
):
# Return all the limits
# !!! Not implemented
return
json
.
dumps
(
limits
.
getAll
())
def
getAllMonitored
(
self
):
# Return the processes monitored list
# !!! Not implemented
return
json
.
dumps
(
monitors
.
getAll
())
def
__getattr__
(
self
,
item
):
...
...
@@ -172,6 +175,8 @@ class GlancesInstance():
The goal is to dynamicaly generate the API get'Stats'() methods
"""
# print "!!! __getattr__ in the GlancesInstance classe"
# print "!!! Method: %s" % item
header
=
'get'
# Check if the attribute starts with 'get'
if
(
item
.
startswith
(
header
)):
...
...
@@ -188,101 +193,20 @@ class GlancesInstance():
# Default behavior
raise
AttributeError
(
item
)
# !!! Check the 2.0 cover before deleted the following comments
# def getSystem(self):
# # Return operating system info
# # No need to update...
# #~ self.__update__()
# return json.dumps(self.stats.getSystem())
# def getCore(self):
# # Update and return number of Core
# self.__update__()
# return json.dumps(self.stats.getCore())
# def getCpu(self):
# # Update and return CPU stats
# self.__update__()
# return json.dumps(self.stats.getCpu())
# def getLoad(self):
# # Update and return LOAD stats
# self.__update__()
# return json.dumps(self.stats.getLoad())
# def getMem(self):
# # Update and return MEM stats
# self.__update__()
# return json.dumps(self.stats.getMem())
# def getMemSwap(self):
# # Update and return MEMSWAP stats
# self.__update__()
# return json.dumps(self.stats.getMemSwap())
# def getSensors(self):
# # Update and return SENSORS stats
# self.__update__()
# return json.dumps(self.stats.getSensors())
# def getHDDTemp(self):
# # Update and return HDDTEMP stats
# self.__update__()
# return json.dumps(self.stats.getHDDTemp())
# def getNetwork(self):
# # Update and return NET stats
# self.__update__()
# return json.dumps(self.stats.getNetwork())
# def getDiskIO(self):
# # Update and return DISK IO stats
# self.__update__()
# return json.dumps(self.stats.getDiskIO())
# def getFs(self):
# # Update and return FS stats
# self.__update__()
# return json.dumps(self.stats.getFs())
# def getProcessCount(self):
# # Update and return ProcessCount stats
# self.__update__()
# return json.dumps(self.stats.getProcessCount())
# def getProcessList(self):
# # Update and return ProcessList stats
# self.__update__()
# return json.dumps(self.stats.getProcessList())
# def getBatPercent(self):
# # Update and return total batteries percent stats
# self.__update__()
# return json.dumps(self.stats.getBatPercent())
# def getNow(self):
# # Update and return current date/hour
# self.__update__()
# return json.dumps(self.stats.getNow().strftime(_("%Y-%m-%d %H:%M:%S")))
# def getUptime(self):
# # Update and return system uptime
# self.__update__()
# return json.dumps(self.stats.getUptime().strftime(_("%Y-%m-%d %H:%M:%S")))
# def __getTimeSinceLastUpdate(self, IOType):
# assert(IOType in ['net', 'disk', 'process_disk'])
# return getTimeSinceLastUpdate(IOType)
# def getNetTimeSinceLastUpdate(self):
# return getTimeSinceLastUpdate('net')
# def getDiskTimeSinceLastUpdate(self):
# return getTimeSinceLastUpdate('net')
# def getProcessDiskTimeSinceLastUpdate(self):
# return getTimeSinceLastUpdate('process_disk')
#!!! How to implement theses method in v2 ?
# def __getTimeSinceLastUpdate(self, IOType):
# assert(IOType in ['net', 'disk', 'process_disk'])
# return getTimeSinceLastUpdate(IOType)
# def getNetTimeSinceLastUpdate(self):
# return getTimeSinceLastUpdate('net')
# def getDiskTimeSinceLastUpdate(self):
# return getTimeSinceLastUpdate('net')
# def getProcessDiskTimeSinceLastUpdate(self):
# return getTimeSinceLastUpdate('process_disk')
class
GlancesServer
():
...
...
glances/core/glances_stats.py
0 → 100644
浏览文件 @
ccf4d8ad
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Glances - An eye on your system
#
# Copyright (C) 2014 Nicolargo <nicolas@nicolargo.com>
#
# Glances 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 3 of the License, or
# (at your option) any later version.
#
# Glances is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Import system libs
import
sys
import
os
import
collections
# Import Glances libs
from
..core.glances_globals
import
*
class
GlancesStats
:
"""
This class store, update and give stats
"""
# Internal dictionnary with all plugins instances
_plugins
=
{}
def
__init__
(
self
):
"""
Init the stats
"""
# Load the plugins
self
.
load_plugins
()
def
__getattr__
(
self
,
item
):
"""
Overwrite the getattr in case of attribute is not found
The goal is to dynamicaly generate the API get'Stats'() methods
"""
# print "!!! __getattr__ in the GlancesStats classe"
# print "!!! Method: %s" % item
header
=
'get'
# Check if the attribute starts with 'get'
if
(
item
.
startswith
(
header
)):
# Get the plugin name
plugname
=
item
[
len
(
header
):].
lower
()
# Get the plugin instance
plugin
=
self
.
_plugins
[
plugname
]
# !!! Debug
# print "Check if method get_stats exist for plugin %s" % plugname
# print self._plugins
# print plugin
if
(
hasattr
(
plugin
,
'get_stats'
)):
# The method get_stats exist, return it
return
getattr
(
plugin
,
'get_stats'
)
else
:
# The method get_stats is not found for the plugin
raise
AttributeError
(
item
)
else
:
# Default behavior
raise
AttributeError
(
item
)
def
load_plugins
(
self
):
"""
Load all plugins in the "plugins" folder
"""
plug_dir
=
os
.
path
.
join
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)),
"../plugins"
)
sys
.
path
.
insert
(
0
,
plug_dir
)
header
=
"glances_"
for
plug
in
os
.
listdir
(
plug_dir
):
if
(
plug
.
startswith
(
header
)
and
plug
.
endswith
(
".py"
)
and
plug
!=
(
header
+
"plugin.py"
)):
# Import the plugin
m
=
__import__
(
os
.
path
.
basename
(
plug
)[:
-
3
])
# Add the plugin to the dictionnary
# The key is the plugin name
# for example, the file glances_xxx.py
# generate self._plugins_list["xxx"] = ...
plugname
=
os
.
path
.
basename
(
plug
)[
len
(
header
):
-
3
].
lower
()
self
.
_plugins
[
plugname
]
=
m
.
Plugin
()
def
__update__
(
self
,
input_stats
):
"""
Update the stats
"""
# For each plugins, call the update method
for
p
in
self
.
_plugins
:
self
.
_plugins
[
p
].
update
()
# !!! Debug
# print "Update plugin %s" % p
# print self._plugins[p].get_stats()
class
GlancesStatsServer
(
GlancesStats
):
def
__init__
(
self
):
# Init the stats
GlancesStats
.
__init__
(
self
)
# Init the all_stats dict used by the server
# all_stats is a dict of dicts filled by the server
self
.
all_stats
=
collections
.
defaultdict
(
dict
)
def
update
(
self
,
input_stats
=
{}):
"""
Update the stats
"""
# Update the stats
GlancesStats
.
__update__
(
self
,
input_stats
)
for
p
in
self
.
_plugins
:
self
.
all_stats
[
p
]
=
self
.
_plugins
[
p
].
get_stats
()
def
getAll
(
self
):
return
self
.
all_stats
\ No newline at end of file
glances/plugins/_processes.py
0 → 100644
浏览文件 @
ccf4d8ad
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Glances - An eye on your system
#
# Copyright (C) 2014 Nicolargo <nicolas@nicolargo.com>
#
# Glances 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 3 of the License, or
# (at your option) any later version.
#
# Glances is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from
psutil
import
process_iter
,
AccessDenied
,
NoSuchProcess
from
glances.core.glances_globals
import
is_BSD
,
is_Mac
,
is_Windows
from
glances_plugin
import
getTimeSinceLastUpdate
from
glances.core.glances_timer
import
Timer
class
GlancesGrabProcesses
:
"""
Get processed stats using the PsUtil lib
"""
def
__init__
(
self
,
cache_timeout
=
60
):
"""
Init the class to collect stats about processes
"""
# Add internals caches because PSUtil do not cache all the stats
# See: https://code.google.com/p/psutil/issues/detail?id=462
self
.
username_cache
=
{}
self
.
cmdline_cache
=
{}
# The internals caches will be cleaned each 'cache_timeout' seconds
self
.
cache_timeout
=
cache_timeout
self
.
cache_timer
=
Timer
(
self
.
cache_timeout
)
# Init the io dict
# key = pid
# value = [ read_bytes_old, write_bytes_old ]
self
.
io_old
=
{}
def
__get_process_stats
(
self
,
proc
):
"""
Get process statistics
"""
procstat
=
{}
# Process ID
procstat
[
'pid'
]
=
proc
.
pid
# Process name (cached by PSUtil)
procstat
[
'name'
]
=
proc
.
name
# Process username (cached with internal cache)
try
:
self
.
username_cache
[
procstat
[
'pid'
]]
except
:
try
:
self
.
username_cache
[
procstat
[
'pid'
]]
=
proc
.
username
except
KeyError
:
try
:
self
.
username_cache
[
procstat
[
'pid'
]]
=
proc
.
uids
.
real
except
KeyError
:
self
.
username_cache
[
procstat
[
'pid'
]]
=
"?"
procstat
[
'username'
]
=
self
.
username_cache
[
procstat
[
'pid'
]]
# Process command line (cached with internal cache)
try
:
self
.
cmdline_cache
[
procstat
[
'pid'
]]
except
:
self
.
cmdline_cache
[
procstat
[
'pid'
]]
=
' '
.
join
(
proc
.
cmdline
)
procstat
[
'cmdline'
]
=
self
.
cmdline_cache
[
procstat
[
'pid'
]]
# Process status
procstat
[
'status'
]
=
str
(
proc
.
status
)[:
1
].
upper
()
# Process nice
procstat
[
'nice'
]
=
proc
.
get_nice
()
# Process memory
procstat
[
'memory_info'
]
=
proc
.
get_memory_info
()
procstat
[
'memory_percent'
]
=
proc
.
get_memory_percent
()
# Process CPU
procstat
[
'cpu_times'
]
=
proc
.
get_cpu_times
()
procstat
[
'cpu_percent'
]
=
proc
.
get_cpu_percent
(
interval
=
0
)
# Process network connections (TCP and UDP) (Experimental)
# !!! High CPU consumption
# try:
# procstat['tcp'] = len(proc.get_connections(kind="tcp"))
# procstat['udp'] = len(proc.get_connections(kind="udp"))
# except:
# procstat['tcp'] = 0
# procstat['udp'] = 0
# Process IO
# procstat['io_counters'] is a list:
# [read_bytes, write_bytes, read_bytes_old, write_bytes_old, io_tag]
# If io_tag = 0 > Access denied (display "?")
# If io_tag = 1 > No access denied (display the IO rate)
# Note Disk IO stat not available on Mac OS
if
not
is_Mac
:
try
:
# Get the process IO counters
proc_io
=
proc
.
get_io_counters
()
io_new
=
[
proc_io
.
read_bytes
,
proc_io
.
write_bytes
]
except
AccessDenied
:
# Access denied to process IO (no root account)
# Put 0 in all values (for sort) and io_tag = 0 (for display)
procstat
[
'io_counters'
]
=
[
0
,
0
]
+
[
0
,
0
]
io_tag
=
0
else
:
# For IO rate computation
# Append saved IO r/w bytes
try
:
procstat
[
'io_counters'
]
=
io_new
+
self
.
io_old
[
procstat
[
'pid'
]]
except
KeyError
:
procstat
[
'io_counters'
]
=
io_new
+
[
0
,
0
]
# then save the IO r/w bytes
self
.
io_old
[
procstat
[
'pid'
]]
=
io_new
io_tag
=
1
# Append the IO tag (for display)
procstat
[
'io_counters'
]
+=
[
io_tag
]
return
procstat
def
update
(
self
):
self
.
processlist
=
[]
self
.
processcount
=
{
'total'
:
0
,
'running'
:
0
,
'sleeping'
:
0
,
'thread'
:
0
}
# Get the time since last update
time_since_update
=
getTimeSinceLastUpdate
(
'process_disk'
)
# For each existing process...
for
proc
in
process_iter
():
try
:
# Get stats using the PSUtil
procstat
=
self
.
__get_process_stats
(
proc
)
# Add a specific time_since_update stats for bitrate
procstat
[
'time_since_update'
]
=
time_since_update
# ignore the 'idle' process on Windows and *BSD
# ignore the 'kernel_task' process on OS X
# waiting for upstream patch from psutil
if
(
is_BSD
and
procstat
[
'name'
]
==
'idle'
or
is_Windows
and
procstat
[
'name'
]
==
'System Idle Process'
or
is_Mac
and
procstat
[
'name'
]
==
'kernel_task'
):
continue
# Update processcount (global statistics)
try
:
self
.
processcount
[
str
(
proc
.
status
)]
+=
1
except
KeyError
:
# Key did not exist, create it
self
.
processcount
[
str
(
proc
.
status
)]
=
1
else
:
self
.
processcount
[
'total'
]
+=
1
# Update thread number (global statistics)
try
:
self
.
processcount
[
'thread'
]
+=
proc
.
get_num_threads
()
except
:
pass
except
(
NoSuchProcess
,
AccessDenied
):
continue
else
:
# Update processlist
self
.
processlist
.
append
(
procstat
)
# Clean internals caches if timeout is reached
if
(
self
.
cache_timer
.
finished
()):
self
.
username_cache
=
{}
self
.
cmdline_cache
=
{}
# Restart the timer
self
.
cache_timer
.
reset
()
def
getcount
(
self
):
return
self
.
processcount
def
getlist
(
self
):
return
self
.
processlist
# Create a GlancesGrabProcesses instance shared between
# processcount and processlist plugins
processes
=
GlancesGrabProcesses
()
glances/plugins/glances_diskio.py
浏览文件 @
ccf4d8ad
...
...
@@ -81,6 +81,7 @@ class Plugin(GlancesPlugin):
def
get_stats
(
self
):
# Return the stats object for the RPC API
# Sort it by disk name
# Convert it to string
return
str
(
sorted
(
self
.
stats
,
key
=
lambda
network
:
network
[
'disk_name'
]))
# !!! Sort it by disk name (why do it here ? Better in client side ?)
self
.
stats
=
sorted
(
self
.
stats
,
key
=
lambda
network
:
network
[
'disk_name'
])
return
GlancesPlugin
.
get_stats
(
self
)
\ No newline at end of file
glances/plugins/glances_fs.py
浏览文件 @
ccf4d8ad
...
...
@@ -46,9 +46,9 @@ class Plugin(GlancesPlugin):
def
get_stats
(
self
):
# Return the stats object for the RPC API
#
Sort it by mount name
# Convert it to string
return
str
(
sorted
(
self
.
stats
,
key
=
lambda
network
:
network
[
'mnt_point'
])
)
#
!!! Sort it by mount name (why do it here ? Better in client side ?)
self
.
stats
=
sorted
(
self
.
stats
,
key
=
lambda
network
:
network
[
'mnt_point'
])
return
GlancesPlugin
.
get_stats
(
self
)
class
glancesGrabFs
:
...
...
glances/plugins/glances_hddtemp.py
浏览文件 @
ccf4d8ad
...
...
@@ -47,9 +47,9 @@ class Plugin(GlancesPlugin):
def
get_stats
(
self
):
# Return the stats object for the RPC API
#
Sort it by label name
# Convert it to string
return
str
(
sorted
(
self
.
stats
,
key
=
lambda
sensors
:
sensors
[
'label'
])
)
#
!!! Sort it by label name (why do it here ? Better in client side ?)
self
.
stats
=
sorted
(
self
.
stats
,
key
=
lambda
sensors
:
sensors
[
'label'
])
return
GlancesPlugin
.
get_stats
(
self
)
class
glancesGrabHDDTemp
:
...
...
glances/plugins/glances_mem.py
浏览文件 @
ccf4d8ad
...
...
@@ -90,3 +90,4 @@ class Plugin(GlancesPlugin):
'cached'
:
cached
}
else
:
self
.
stats
=
{}
glances/plugins/glances_network.py
浏览文件 @
ccf4d8ad
...
...
@@ -19,6 +19,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Import system libs
import
json
try
:
# psutil >= 1.0.0
from
psutil
import
net_io_counters
...
...
@@ -100,6 +102,6 @@ class Plugin(GlancesPlugin):
def
get_stats
(
self
):
# Return the stats object for the RPC API
#
Sort it by interface name
# Convert it to string
return
str
(
sorted
(
self
.
stats
,
key
=
lambda
network
:
network
[
'interface_name'
])
)
#
!!! Sort it by interface name (why do it here ? Better in client side ?)
self
.
stats
=
sorted
(
self
.
stats
,
key
=
lambda
network
:
network
[
'interface_name'
])
return
GlancesPlugin
.
get_stats
(
self
)
glances/plugins/glances_now.py
浏览文件 @
ccf4d8ad
...
...
@@ -29,7 +29,7 @@ class Plugin(GlancesPlugin):
Glances' Core Plugin
Get current date/time
stats is
date
(string)
stats is (string)
"""
def
__init__
(
self
):
...
...
@@ -42,4 +42,6 @@ class Plugin(GlancesPlugin):
"""
# Now
self
.
stats
=
datetime
.
now
()
# Had to convert it to string because datetime is not JSON serializable
self
.
stats
=
datetime
.
now
().
strftime
(
_
(
"%Y-%m-%d %H:%M:%S"
))
glances/plugins/glances_plugin.py
浏览文件 @
ccf4d8ad
...
...
@@ -18,6 +18,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import
json
from
time
import
time
# Global list to manage the elapsed time
...
...
@@ -46,11 +47,17 @@ class GlancesPlugin(object):
# Init the stat list
self
.
stats
=
None
def
__repr__
(
self
):
# Return the raw stats
return
self
.
stats
def
__str__
(
self
):
# Return the human-readable stats
return
str
(
self
.
stats
)
def
get_stats
(
self
):
# Return the stats object for the RPC API
# Had to convert it to string
return
str
(
self
.
stats
)
# Return the stats object in JSON format for the RPC API
return
json
.
dumps
(
self
.
stats
)
glances/plugins/glances_processcount.py
浏览文件 @
ccf4d8ad
...
...
@@ -18,18 +18,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# !!! Not optimized because both processcount and processlist
# !!! grab all processes.
# !!! Action: create a new file globalprocesses.py with a global
# !!! variable instance of GlancesGrabProcesses classes and share
# !!! it between the two plugins
from
psutil
import
process_iter
,
AccessDenied
,
NoSuchProcess
from
glances.core.glances_globals
import
is_BSD
,
is_Mac
,
is_Windows
from
glances.core.glances_timer
import
Timer
from
glances_plugin
import
GlancesPlugin
,
getTimeSinceLastUpdate
from
glances_plugin
import
GlancesPlugin
from
_processes
import
processes
class
Plugin
(
GlancesPlugin
):
"""
...
...
@@ -41,196 +31,15 @@ class Plugin(GlancesPlugin):
def
__init__
(
self
):
GlancesPlugin
.
__init__
(
self
)
#
Init the process class
self
.
glancesgrabprocesses
=
GlancesGrabProcesses
()
#
Nothing else to do...
# 'processes' is already init in the _processes.py script
def
update
(
self
):
"""
Update processes stats
"""
self
.
glancesgrabprocesses
.
update
()
self
.
stats
=
self
.
glancesgrabprocesses
.
getcount
()
# processcount = self.glancesgrabprocesses.getcount()
# process = self.glancesgrabprocesses.getlist()
# if not hasattr(self, 'process'):
# self.processcount = {}
# self.process = []
# else:
# self.processcount = processcount
# self.process = process
def
get_stats
(
self
):
# Return the stats object for the RPC API
# Sort it by mount name
# Convert it to string
return
str
(
self
.
stats
)
class
GlancesGrabProcesses
:
"""
Get processed stats using the PsUtil lib
"""
def
__init__
(
self
,
cache_timeout
=
60
):
"""
Init the class to collect stats about processes
"""
# Add internals caches because PSUtil do not cache all the stats
# See: https://code.google.com/p/psutil/issues/detail?id=462
self
.
username_cache
=
{}
self
.
cmdline_cache
=
{}
# The internals caches will be cleaned each 'cache_timeout' seconds
self
.
cache_timeout
=
cache_timeout
self
.
cache_timer
=
Timer
(
self
.
cache_timeout
)
# Init the io dict
# key = pid
# value = [ read_bytes_old, write_bytes_old ]
self
.
io_old
=
{}
def
__get_process_stats
(
self
,
proc
):
"""
Get process statistics
"""
procstat
=
{}
# Process ID
procstat
[
'pid'
]
=
proc
.
pid
# Process name (cached by PSUtil)
procstat
[
'name'
]
=
proc
.
name
# Process username (cached with internal cache)
try
:
self
.
username_cache
[
procstat
[
'pid'
]]
except
:
try
:
self
.
username_cache
[
procstat
[
'pid'
]]
=
proc
.
username
except
KeyError
:
try
:
self
.
username_cache
[
procstat
[
'pid'
]]
=
proc
.
uids
.
real
except
KeyError
:
self
.
username_cache
[
procstat
[
'pid'
]]
=
"?"
procstat
[
'username'
]
=
self
.
username_cache
[
procstat
[
'pid'
]]
# Process command line (cached with internal cache)
try
:
self
.
cmdline_cache
[
procstat
[
'pid'
]]
except
:
self
.
cmdline_cache
[
procstat
[
'pid'
]]
=
' '
.
join
(
proc
.
cmdline
)
procstat
[
'cmdline'
]
=
self
.
cmdline_cache
[
procstat
[
'pid'
]]
# Process status
procstat
[
'status'
]
=
str
(
proc
.
status
)[:
1
].
upper
()
# Process nice
procstat
[
'nice'
]
=
proc
.
get_nice
()
# Process memory
procstat
[
'memory_info'
]
=
proc
.
get_memory_info
()
procstat
[
'memory_percent'
]
=
proc
.
get_memory_percent
()
# Process CPU
procstat
[
'cpu_times'
]
=
proc
.
get_cpu_times
()
procstat
[
'cpu_percent'
]
=
proc
.
get_cpu_percent
(
interval
=
0
)
# Process network connections (TCP and UDP) (Experimental)
# !!! High CPU consumption
# try:
# procstat['tcp'] = len(proc.get_connections(kind="tcp"))
# procstat['udp'] = len(proc.get_connections(kind="udp"))
# except:
# procstat['tcp'] = 0
# procstat['udp'] = 0
# Process IO
# procstat['io_counters'] is a list:
# [read_bytes, write_bytes, read_bytes_old, write_bytes_old, io_tag]
# If io_tag = 0 > Access denied (display "?")
# If io_tag = 1 > No access denied (display the IO rate)
# Note Disk IO stat not available on Mac OS
if
not
is_Mac
:
try
:
# Get the process IO counters
proc_io
=
proc
.
get_io_counters
()
io_new
=
[
proc_io
.
read_bytes
,
proc_io
.
write_bytes
]
except
AccessDenied
:
# Access denied to process IO (no root account)
# Put 0 in all values (for sort) and io_tag = 0 (for display)
procstat
[
'io_counters'
]
=
[
0
,
0
]
+
[
0
,
0
]
io_tag
=
0
else
:
# For IO rate computation
# Append saved IO r/w bytes
try
:
procstat
[
'io_counters'
]
=
io_new
+
self
.
io_old
[
procstat
[
'pid'
]]
except
KeyError
:
procstat
[
'io_counters'
]
=
io_new
+
[
0
,
0
]
# then save the IO r/w bytes
self
.
io_old
[
procstat
[
'pid'
]]
=
io_new
io_tag
=
1
# Append the IO tag (for display)
procstat
[
'io_counters'
]
+=
[
io_tag
]
return
procstat
def
update
(
self
):
self
.
processlist
=
[]
self
.
processcount
=
{
'total'
:
0
,
'running'
:
0
,
'sleeping'
:
0
,
'thread'
:
0
}
# Get the time since last update
time_since_update
=
getTimeSinceLastUpdate
(
'process_disk'
)
# For each existing process...
for
proc
in
process_iter
():
try
:
# Get stats using the PSUtil
procstat
=
self
.
__get_process_stats
(
proc
)
# Add a specific time_since_update stats for bitrate
procstat
[
'time_since_update'
]
=
time_since_update
# ignore the 'idle' process on Windows and *BSD
# ignore the 'kernel_task' process on OS X
# waiting for upstream patch from psutil
if
(
is_BSD
and
procstat
[
'name'
]
==
'idle'
or
is_Windows
and
procstat
[
'name'
]
==
'System Idle Process'
or
is_Mac
and
procstat
[
'name'
]
==
'kernel_task'
):
continue
# Update processcount (global statistics)
try
:
self
.
processcount
[
str
(
proc
.
status
)]
+=
1
except
KeyError
:
# Key did not exist, create it
self
.
processcount
[
str
(
proc
.
status
)]
=
1
else
:
self
.
processcount
[
'total'
]
+=
1
# Update thread number (global statistics)
try
:
self
.
processcount
[
'thread'
]
+=
proc
.
get_num_threads
()
except
:
pass
except
(
NoSuchProcess
,
AccessDenied
):
continue
else
:
# Update processlist
self
.
processlist
.
append
(
procstat
)
# Clean internals caches if timeout is reached
if
(
self
.
cache_timer
.
finished
()):
self
.
username_cache
=
{}
self
.
cmdline_cache
=
{}
# Restart the timer
self
.
cache_timer
.
reset
()
def
getcount
(
self
):
return
self
.
processcount
def
getlist
(
self
):
return
self
.
processlist
# !!! Update is call twisse (one for processcount and one for processlist)
processes
.
update
()
self
.
stats
=
processes
.
getcount
()
glances/plugins/glances_processlist.py
浏览文件 @
ccf4d8ad
...
...
@@ -18,18 +18,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# !!! Not optimized because both processcount and processlist
# !!! grab all processes.
# !!! Action: create a new file globalprocesses.py with a global
# !!! variable instance of GlancesGrabProcesses classes and share
# !!! it between the two plugins
from
psutil
import
process_iter
,
AccessDenied
,
NoSuchProcess
from
glances.core.glances_globals
import
is_BSD
,
is_Mac
,
is_Windows
from
glances.core.glances_timer
import
Timer
from
glances_plugin
import
GlancesPlugin
,
getTimeSinceLastUpdate
from
glances_processcount
import
GlancesGrabProcesses
from
glances_plugin
import
GlancesPlugin
from
_processes
import
processes
class
Plugin
(
GlancesPlugin
):
...
...
@@ -42,8 +32,8 @@ class Plugin(GlancesPlugin):
def
__init__
(
self
):
GlancesPlugin
.
__init__
(
self
)
#
Init the process class
self
.
glancesgrabprocesses
=
GlancesGrabProcesses
()
#
Nothing else to do...
# 'processes' is already init in the _processes.py script
def
update
(
self
):
...
...
@@ -51,20 +41,7 @@ class Plugin(GlancesPlugin):
Update processes stats
"""
self
.
glancesgrabprocesses
.
update
()
self
.
stats
=
self
.
glancesgrabprocesses
.
getlist
()
# processcount = self.glancesgrabprocesses.getcount()
# process = self.glancesgrabprocesses.getlist()
# if not hasattr(self, 'process'):
# self.processcount = {}
# self.process = []
# else:
# self.processcount = processcount
# self.process = process
# !!! Update is call twisse (one for processcount and one for processlist)
processes
.
update
()
self
.
stats
=
processes
.
getlist
()
def
get_stats
(
self
):
# Return the stats object for the RPC API
# Convert it to string
return
str
(
self
.
stats
)
glances/plugins/glances_sensors.py
浏览文件 @
ccf4d8ad
...
...
@@ -19,6 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Import system libs
from
sets
import
Set
# sensors library (optional; Linux-only)
try
:
import
sensors
...
...
@@ -52,9 +53,9 @@ class Plugin(GlancesPlugin):
def
get_stats
(
self
):
# Return the stats object for the RPC API
#
Sort it by label name
# Convert it to string
return
str
(
sorted
(
self
.
stats
,
key
=
lambda
sensors
:
sensors
[
'label'
])
)
#
!!! Sort it by label name (why do it here ? Better in client side ?)
self
.
stats
=
sorted
(
self
.
stats
,
key
=
lambda
sensors
:
sensors
[
'label'
])
return
GlancesPlugin
.
get_stats
(
self
)
class
glancesGrabSensors
:
...
...
@@ -73,6 +74,9 @@ class glancesGrabSensors:
else
:
self
.
initok
=
True
self
.
sensors_list
=
[]
def
__update__
(
self
):
"""
Update the stats
...
...
@@ -89,11 +93,13 @@ class glancesGrabSensors:
sensors_current
[
'label'
]
=
feature
.
label
[:
20
]
sensors_current
[
'value'
]
=
int
(
feature
.
get_value
())
self
.
sensors_list
.
append
(
sensors_current
)
def
get
(
self
):
self
.
__update__
()
return
self
.
sensors_list
def
quit
(
self
):
if
self
.
initok
:
sensors
.
cleanup
()
\ No newline at end of file
glances/plugins/glances_
host
.py
→
glances/plugins/glances_
system
.py
浏览文件 @
ccf4d8ad
...
...
@@ -27,7 +27,7 @@ from glances_plugin import GlancesPlugin
class
Plugin
(
GlancesPlugin
):
"""
Glances' Host Plugin
Glances' Host
/System
Plugin
stats is a dict
"""
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录