Skip to content

Commit

Permalink
Merge pull request #89 from ZeroPhone/ZPUI-40
Browse files Browse the repository at this point in the history
[WIP] Log management through config file
  • Loading branch information
CRImier committed Feb 2, 2018
2 parents 64489bc + 12a83bf commit 8d69b37
Show file tree
Hide file tree
Showing 11 changed files with 345 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,4 @@ config.json
# We ship do_not_load files in some directories, but do not track user-created files
# (only user-removed ones)
do_not_load
log_conf.ini
74 changes: 74 additions & 0 deletions apps/settings/logging_ui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
i = None
o = None

from collections import OrderedDict
import logging

import helpers.logger as log_system

logger_alias_map = (("root","Main launcher"),
("input.input","Input system"),
("apps.app_manager","App manager"),
("context_manager","Context manager"),
("emulator","Emulator"),
("helpers.logger","Logging system"))

logger_alias_map = OrderedDict(logger_alias_map)

from ui import Menu, Listbox

def get_logger_names():
return log_system.get_logger_names()

def prettify_logger_names(names):
name_mapping = OrderedDict()
for name in names:
if name in logger_alias_map:
# We have a defined name for this logger
name_mapping[name] = logger_alias_map[name]
elif name.startswith("ui."):
# This is an UI logger
element_name = name[len("ui."):].capitalize()
name_mapping[name] = "UI - {}".format(element_name)
elif name.startswith("apps."):
# This is an app logger
app_name, module_name = name.rsplit(".", 2)[1:]
app_name = app_name.capitalize().replace("_", " ")
name_mapping[name] = '{} app - {}'.format(app_name, module_name)
elif name.startswith("input.drivers") or name.startswith("output.drivers"):
# This is a driver logger
driver_name = name.rsplit(".", 1)[1].capitalize().replace("_", " ")
name_mapping[name] = '{} driver'.format(driver_name)
else:
# Fallback - name is not know and we can't yet prettify it
name_mapping[name] = name
return name_mapping

def get_available_levels():
return [ key.lower() for key in logging._levelNames.keys() if isinstance(key, basestring) ]

def select_loglevel(current):
available_levels = get_available_levels()
lb_contents = [[level.capitalize(), level] for level in available_levels]
lb = Listbox(lb_contents, i, o, "Loglevel selection listbox")
lb.start_pointer = available_levels.index(current.lower())
return lb.activate()

def change_loglevel(logger_name, current_level):
new_level = select_loglevel(current_level)
if new_level is not None:
assert (new_level in get_available_levels())
log_system.LoggingConfig().set_level(logger_name, new_level)
log_system.LoggingConfig().reload_config()

def get_menu_contents():
logger_names = get_logger_names()
pretty_logger_names = prettify_logger_names(logger_names)
sorted_names = sorted(pretty_logger_names.items(), key=lambda x: x[1])
for i, (name, pname) in enumerate(sorted_names):
l = log_system.get_log_level_for_logger(name)
sorted_names[i] = (name, pname, l)
return [["{}:{}".format(l[:1], pname), lambda x=name, y=l:change_loglevel(x, y)] for name, pname, l in sorted_names]

def config_logging():
Menu([], i, o, contents_hook=get_menu_contents).activate()
22 changes: 12 additions & 10 deletions apps/settings/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import os
import signal
from subprocess import check_output
Expand All @@ -13,6 +12,8 @@
from ui import Menu, PrettyPrinter, DialogBox, TextProgressBar, Listbox
from helpers.logger import setup_logger

import logging_ui

menu_name = "Settings"
logger = setup_logger(__name__, "info")

Expand Down Expand Up @@ -218,19 +219,20 @@ def pick_branch(self):
#TODO: run tests?


def settings():
git_updater = GitUpdater()
c = [["Update ZPUI", git_updater.update],
["Select branch", git_updater.pick_branch]]
Menu(c, i, o, "ZPUI settings menu").activate()


callback = settings
i = None # Input device
o = None # Output device


def init_app(input, output):
global i, o
i = input
o = output
logging_ui.i = i
logging_ui.o = o

def callback():
git_updater = GitUpdater()
c = [["Update ZPUI", git_updater.update],
["Select branch", git_updater.pick_branch],
#["Submit logs", logging_ui.submit_logs],
["Logging settings", logging_ui.config_logging]]
Menu(c, i, o, "ZPUI settings menu").activate()
41 changes: 35 additions & 6 deletions docs/howto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,40 @@ In ``app/main.py``:
------------

Add logging to your app
-----------------------

In case your application does something more complicated than printing a sentence
on the display and exiting, you might need to add logging - so that users can then
look through the ZPUI history, figure out what was it that went wrong, and maybe
submit a bugreport to you!

.. code-block:: python
from helpers import setup_logger # Importing the needed function
logger = setup_logger(__name__, "warning") # Getting a logger for your app,
# default level is "warning" - this level controls logging statements that
# will be displayed (and saved in the logfile) by default.
...
try:
command = "my_awesome_script"
logger.info("Calling the '{}' command".format(command))
output = call(command)
logger.debug("Finished executing the command")
for value in output.split():
if value not in expected_values:
logger.warning("Unexpected value {} found when parsing command output; proceeding".format(value))
except:
logger.exception("Exception while calling the command!")
# .exception will also log the details of the exception after your message
Config (and other) files
========================

How to get path to a file in the app directory?
-----------------------------------------------
Get path to a file in the app directory
---------------------------------------

Say, you have a ``my_song.mp3`` file shipped with your app. However, in order to use
that file from your code, you have to refer to that file using a path relative to the
Expand All @@ -69,8 +98,8 @@ In case of your app having nested folders, you can also give multiple arguments
------------

How to read JSON from a ``config.json`` file located in the app directory?
--------------------------------------------------------------------------
Read JSON from a ``config.json`` file located in the app directory
------------------------------------------------------------------

.. code-block:: python
Expand All @@ -82,8 +111,8 @@ How to read JSON from a ``config.json`` file located in the app directory?
------------

How to read a ``config.json`` file, and restore it to defaults if it can't be read?
-----------------------------------------------------------------------------------
Read a ``config.json`` file, and restore it to defaults if it can't be read
---------------------------------------------------------------------------

.. code-block:: python
Expand Down
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Guides:
* :doc:`App development - how to ... ? <howto>`
* :doc:`ZPUI configuration files <config>`
* :doc:`Hacking on UI <hacking_ui>`
* :doc:`Logging configuration <logging_config>`

References:
===========
Expand Down Expand Up @@ -43,6 +44,7 @@ References:
ui.rst
helpers.rst
hacking_ui.rst
logging.rst
app_mgmt.rst
docs_development.rst
contact.rst
26 changes: 26 additions & 0 deletions docs/logging.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.. _logging_config:

Logging configuration
#####################

Changing log levels
===================

In case of problems with ZPUI, logs can help you understand it - especially when
the problem is not easily repeatable. To enable verbose logging for a particular
system/app/driver, go to ``"Settings"->"Logging settings"`` menu, then click on
the part of ZPUI that you're interested in and pick "Debug". From now on, that part
of ZPUI will log a lot more in ``zpui.log`` files - which you can then read through,
or send to the developers.

Alternatively, you can change the log_conf.ini file directly. In it, add a new
section for the app you want to learn, like this:

.. code-block:: ini
[path.to.code.file]
level = debug
``path.to.code.file`` would be the Python-style path to the module you want to debug,
for example, ``input.input``, ``context_manager`` or ``apps.network_apps.wpa_cli``.

0 comments on commit 8d69b37

Please sign in to comment.