[Sugar-devel] [PATCH] Add cpu and memory resource indicator to frame
Anish Mangal
anishmangal2002 at gmail.com
Wed Jul 28 15:39:17 EDT 2010
Thank you for reviewing this patch. However, after receiving feedback
from Py. I've modified some of its functionality. The two patches
attached implement that functionality. I've updated the parallel
thread "[DESIGN] Displaying the current status of system resources
(such as memory, cpu)" to augment further discussion on this.
--
Anish
On Sat, Jul 10, 2010 at 3:09 PM, Marco Pesenti Gritti <marco at marcopg.org> wrote:
> On 10 Jul 2010, at 08:43, Anish Mangal <anishmangal2002 at gmail.com> wrote:
>>> diff --git a/extensions/deviceicon/resources.py b/extensions/deviceicon/resources.py
>>> new file mode 100644
>>> index 0000000..7503bef
>>> --- /dev/null
>>> +++ b/extensions/deviceicon/resources.py
>>> @@ -0,0 +1,188 @@
>>> +# Copyright (C) Anish Mangal <anishmangal2002 at gmail.com>
>>> +#
>>> +# This program is free software; you can redistribute it and/or modify
>>> +# it under the terms of the GNU General Public License as published by
>>> +# the Free Software Foundation; either version 2 of the License, or
>>> +# (at your option) any later version.
>>> +#
>>> +# This program 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 General Public License for more details.
>>> +#
>>> +# You should have received a copy of the GNU General Public License
>>> +# along with this program; if not, write to the Free Software
>>> +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
>>> +
>>> +from gettext import gettext as _
>>> +import logging
>>> +import os
>>> +
>>> +import gobject
>>> +import gtk
>>> +import gconf
>>> +
>>> +from sugar.graphics.tray import TrayIcon
>>> +from sugar.graphics.xocolor import XoColor
>>> +from sugar.graphics.palette import Palette
>>> +from sugar.graphics import style
>>> +
>>> +from jarabe.frame.frameinvoker import FrameWidgetInvoker
>>> +
>>> +class DeviceView(TrayIcon):
>>> +
>>> + FRAME_POSITION_RELATIVE = 500
>>> +
>>> + def __init__(self):
>>> + client = gconf.client_get_default()
>>> + color = XoColor(client.get_string('/desktop/sugar/user/color'))
>>> + TrayIcon.__init__(self, icon_name='computer', xo_color=color)
>>> + self.set_palette_invoker(FrameWidgetInvoker(self))
>>> +
>>> + def create_palette(self):
>>> + palette = ResourcePalette(_('System resources'))
>>> + palette.set_group_id('frame')
>>> + return palette
>>> +
>>> +class ResourcePalette(Palette):
>>> +
>>> + def __init__(self, primary_text):
>>> + Palette.__init__(self, label=primary_text)
>>> +
>>> + self._popup_cb_id = self.connect('popup', self._popup_cb)
>>> + self._popdown_cb_id = self.connect('popdown', self._popdown_cb)
>>> +
>>> + self.vbox = gtk.VBox()
>>> + self.set_content(self.vbox)
>>> +
>>> + self._cpu_text = gtk.Label()
>>> + self.vbox.pack_start(self._cpu_text, padding=style.DEFAULT_PADDING)
>>> + self._cpu_text.show()
>>> +
>>> + self._cpu_bar = gtk.ProgressBar()
>>> + self._cpu_bar.set_size_request(
>>> + style.zoom(style.GRID_CELL_SIZE * 4), -1)
>>> + self.vbox.pack_start(self._cpu_bar, padding=style.DEFAULT_PADDING)
>>> + self._cpu_bar.show()
>>> +
>>> + self._memory_text = gtk.Label()
>>> + self.vbox.pack_start(self._memory_text, padding=style.DEFAULT_PADDING)
>>> + self._memory_text.show()
>>> +
>>> + self._memory_bar = gtk.ProgressBar()
>>> + self._memory_bar.set_size_request(
>>> + style.zoom(style.GRID_CELL_SIZE * 4), -1)
>>> + self.vbox.pack_start(self._memory_bar, padding=style.DEFAULT_PADDING)
>>> + self._memory_bar.show()
>>> +
>>> + self.vbox.show()
>>> +
>>> + try:
>>> + self._cpu_times = self._get_cpu_times_list()
>>> + except Exception:
>>> + logging.exception('An error ocurred while attempting to '
>>> + 'read /proc/stat')
>
> Which exceptions do you expect to happen and in which situations? Catch all exceptions are generally a bad idea.
>
>
>>> + self._remove_callbacks()
>>> +
>>> + def _get_cpu_times_list(self):
>>> + """Return various cpu times as read from /proc/stat
>>> +
>>> + This method returns the following cpu times measured
>>> + in jiffies (1/100 of a second for x86 systems)
>>> + as an ordered list of numbers - [user, nice,
>>> + system, idle, iowait] where,
>>> +
>>> + user: normal processes executing in user mode
>>> + nice: niced processes executing in user mode
>>> + system: processes executing in kernel mode
>>> + idle: twiddling thumbs
>>> + iowait: waiting for I/O to complete
>>> +
>>> + Note: For systems having 2 or more CPU's, the above
>>> + numbers would be the cumulative sum of these times
>>> + for all CPU's present in the system.
>>> +
>>> + """
>>> + return [int(count)
>>> + for count in file('/proc/stat').readline().split()[1:6]]
>>> +
>>> + def _percentage_cpu_available(self):
>>> + """
>>> + Return free CPU resources as a percentage
>>> +
>>> + """
>>> + _cpu_times_new = self._get_cpu_times_list()
>>> + _cpu_times_current = [(new - old)
>>> + for new, old in zip(_cpu_times_new, self._cpu_times)]
>>> + user, nice, system, idle, iowait = _cpu_times_current
>>> + cpu_free = (idle + iowait) * 100.0 / sum(_cpu_times_current)
>>> + self._cpu_times = self._get_cpu_times_list()
>>> + return cpu_free
>>> +
>>> + def _percentage_memory_available(self):
>>> + """
>>> + Return free memory as a percentage
>>> +
>>> + """
>>> + for line in file('/proc/meminfo'):
>>> + name, value, unit = line.split()[:3]
>>> + if 'MemTotal:' == name:
>>> + total = int(value)
>>> + elif 'MemFree:' == name:
>>> + free = int(value)
>>> + elif 'Buffers:' == name:
>>> + buffers = int(value)
>>> + elif 'Cached:' == name:
>>> + cached = int(value)
>>> + elif 'Active:' == name:
>>> + break
>>> + return (free + buffers + cached) * 100.0 / total
>>> +
>>> + def __timer_cb(self):
>>> + try:
>>> + cpu_free = self._percentage_cpu_available()
>>> + memory_free = self._percentage_memory_available()
>>> + self._cpu_text.set_label(_('CPU free: %d%%' % cpu_free))
>>> + self._cpu_bar.set_fraction(cpu_free/100.0)
>
> Space around the operator
>
>>> + self._memory_text.set_label(_('Memory free: %d%%' % memory_free))
>>> + self._memory_bar.set_fraction(memory_free/100.0)
>
> Same
>
>
>>> + return True
>>> + except Exception:
>>> + logging.exception('An error ocurred while trying to '
>>> + 'retrieve resource usage statistics')
>>> + self._remove_callbacks()
>>> + return False
>
> Same here. Also the UI code should be moved outside the try so that we don't cover errors in it.
>
>>>
>>> + def _remove_callbacks(self):
>>> + """
>>> + Stop computing usage statistics and display and error message
>>> + since we've hit an exception.
>>> +
>>> + """
>>> + self.disconnect(self._popup_cb_id)
>>> + self.disconnect(self._popdown_cb_id)
>>> +
>>> + # Use the existing _cpu_text label to display the error. Remove
>>> + # everything else.
>>> + self._cpu_text.set_size_request(
>>> + style.zoom(style.GRID_CELL_SIZE * 4), -1)
>>> + self._cpu_text.set_line_wrap(True)
>>> + self._cpu_text.set_text(_('Cannot compute CPU and memory usage '
>>> + 'statistics!'))
>>> + self.vbox.remove(self._cpu_bar)
>>> + self.vbox.remove(self._memory_text)
>>> + self.vbox.remove(self._memory_bar)
>
> This method does a lot more than disconnecting callbacks. The naming should reflect that or the method should be split.
>
> Thanks!
> Marco
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Add-icons-for-memory-and-cpu-resource-indicator.patch
Type: text/x-patch
Size: 11936 bytes
Desc: not available
Url : http://lists.sugarlabs.org/archive/sugar-devel/attachments/20100729/6561bfc0/attachment-0002.bin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Add-cpu-and-memory-resource-indicator-to-frame.patch
Type: text/x-patch
Size: 9172 bytes
Desc: not available
Url : http://lists.sugarlabs.org/archive/sugar-devel/attachments/20100729/6561bfc0/attachment-0003.bin
More information about the Sugar-devel
mailing list