Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-146-Support-colorful-execution-logging 2dd9830f5 -> 81bd26a7f


reworked the entire config process. it is now possible to config the styles and 
formats directly from the config file


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/81bd26a7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/81bd26a7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/81bd26a7

Branch: refs/heads/ARIA-146-Support-colorful-execution-logging
Commit: 81bd26a7fb453e02eab1e1b8100bb9c3057928cd
Parents: 2dd9830
Author: max-orlov <ma...@gigaspaces.com>
Authored: Wed Apr 26 00:24:37 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Wed Apr 26 00:24:37 2017 +0300

----------------------------------------------------------------------
 aria/cli/color.py                    |   5 +-
 aria/cli/commands/executions.py      |   6 +-
 aria/cli/commands/logs.py            |   3 +-
 aria/cli/config/config_template.yaml |  40 ++++++
 aria/cli/execution_logging.py        | 209 ++++++++++++------------------
 5 files changed, 130 insertions(+), 133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/81bd26a7/aria/cli/color.py
----------------------------------------------------------------------
diff --git a/aria/cli/color.py b/aria/cli/color.py
index 77bfe77..49675de 100644
--- a/aria/cli/color.py
+++ b/aria/cli/color.py
@@ -66,8 +66,7 @@ class Color(object):
 
     @classmethod
     def markup(cls, str_to_stylize, matches, schema):
-        modified_str = str_to_stylize
         for group_index in xrange(len(matches.regs)):
             match = matches.group(group_index)
-            modified_str = modified_str.replace(match, schema + match + 
cls.Back.RESET)
-        return modified_str
+            str_to_stylize = str_to_stylize.replace(match, schema + match + 
cls.Back.RESET)
+        return str_to_stylize

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/81bd26a7/aria/cli/commands/executions.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/executions.py b/aria/cli/commands/executions.py
index 3eb53ab..7f55e6a 100644
--- a/aria/cli/commands/executions.py
+++ b/aria/cli/commands/executions.py
@@ -149,8 +149,7 @@ def start(workflow_name,
     log_iterator = cli_logger.ModelLogIterator(model_storage, 
workflow_runner.execution_id)
     try:
         while execution_thread.is_alive():
-            with execution_logging.format(mark_pattern=mark_pattern):
-                execution_logging.log_list(log_iterator)
+            execution_logging.log_list(log_iterator, mark_pattern=mark_pattern)
             execution_thread.join(1)
 
     except KeyboardInterrupt:
@@ -158,8 +157,7 @@ def start(workflow_name,
 
     # It might be the case where some logs were written and the execution was 
terminated, thus we
     # need to drain the remaining logs.
-    with execution_logging.format(mark_pattern=mark_pattern):
-        execution_logging.log_list(log_iterator)
+    execution_logging.log_list(log_iterator, mark_pattern=mark_pattern)
 
     # raise any errors from the execution thread (note these are not workflow 
execution errors)
     execution_thread.raise_error_if_exists()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/81bd26a7/aria/cli/commands/logs.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/logs.py b/aria/cli/commands/logs.py
index 350a035..2f7f361 100644
--- a/aria/cli/commands/logs.py
+++ b/aria/cli/commands/logs.py
@@ -38,8 +38,7 @@ def list(execution_id, mark_pattern, model_storage, logger):
     logger.info('Listing logs for execution id {0}'.format(execution_id))
     log_iterator = ModelLogIterator(model_storage, execution_id)
 
-    with execution_logging.format(mark_pattern=mark_pattern):
-        any_logs = execution_logging.log_list(log_iterator)
+    any_logs = execution_logging.log_list(log_iterator, 
mark_pattern=mark_pattern)
 
     if not any_logs:
         logger.info('\tNo logs')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/81bd26a7/aria/cli/config/config_template.yaml
----------------------------------------------------------------------
diff --git a/aria/cli/config/config_template.yaml 
b/aria/cli/config/config_template.yaml
index 66c606e..b8bad3b 100644
--- a/aria/cli/config/config_template.yaml
+++ b/aria/cli/config/config_template.yaml
@@ -9,3 +9,43 @@ logging:
 
     # main logger of the cli. provides basic descriptions for executed 
operations.
     aria.cli.main: info
+
+  execution_logging:
+    formatting:
+      # According to verbosity level 0 - no verbose. 3 - high verbose
+      0: '{message}'
+      1: '{timestamp:%H:%M:%S} | {level[0]} | {message}'
+      2: '{timestamp:%H:%M:%S} | {level[0]} | {implementation} | {message}'
+      3: '{timestamp:%H:%M:%S} | {level[0]} | {implementation} | {inputs} | 
{message}'
+
+    styling:
+      enabled: true
+
+      level:
+        info: {'fore': 'lightmagenta_ex'}
+        debug: {'fore': 'lightmagenta_ex', 'style': 'dim'}
+        error: {'fore': 'red', 'style': 'bright'}
+      timestamp:
+       info: {'fore': 'lightmagenta_ex'}
+       debug: {'fore': 'lightmagenta_ex', 'style': 'dim'}
+       error: {'fore': 'red', 'style': 'bright'}
+      message:
+        info: {'fore': 'lightblue_ex'}
+        debug: {'fore': 'lightblue_ex', 'style': 'dim'}
+        error: {'fore': 'red', 'style': 'bright'}
+      implementation:
+        info: {'fore': 'lightblack_ex'}
+        debug: {'fore': 'lightblack_ex', 'style': 'dim'}
+        error: {'fore': 'red', 'style': 'bright'}
+      inputs:
+        info: {'fore': 'blue'}
+        debug: {'fore': 'blue', 'style': 'dim'}
+        error: {'fore': 'red', 'style': 'bright'}
+      traceback:
+        error: {'fore': 'red'}
+
+      marker: 'lightyellow_ex'
+      final_states:
+          success: {'fore': 'green'}
+          cancel: {'fore': 'yellow'}
+          fail: {'fore': 'red'}

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/81bd26a7/aria/cli/execution_logging.py
----------------------------------------------------------------------
diff --git a/aria/cli/execution_logging.py b/aria/cli/execution_logging.py
index ca966ec..66c7d9c 100644
--- a/aria/cli/execution_logging.py
+++ b/aria/cli/execution_logging.py
@@ -35,167 +35,136 @@ SUCCESS_STATE = 'success'
 CANCEL_STATE = 'cancel'
 FAIL_STATE = 'fail'
 
-
 _EXECUTION_BASE_PATTERN = "\'.*\' workflow execution "
 _SUCCESSFUL_EXECUTION_PATTERN = _EXECUTION_BASE_PATTERN + "succeeded"
 _FAILED_EXECUTION_PATTERN = _EXECUTION_BASE_PATTERN + "failed"
 _CANCELED_EXECUTION_PATTERN = _EXECUTION_BASE_PATTERN + "canceled"
 
-DEFAULT_FORMATTING = {
-    logger.NO_VERBOSE: {'message': '{message}'},
-    logger.LOW_VERBOSE: {
-        MESSAGE: '{timestamp} | {level} | {message}',
-        LEVEL: '{level[0]}',
-        TIMESTAMP: '%H:%M:%S',
-    },
-    logger.MEDIUM_VERBOSE: {
-        MESSAGE: '{timestamp} | {level} | {implementation} | {message} ',
-        LEVEL: '{level[0]}',
-        TIMESTAMP: '%H:%M:%S'
-    },
-    logger.HIGH_VERBOSE: {
-        MESSAGE: '{timestamp} | {level} | {implementation} | {inputs} | 
{message} ',
-        LEVEL: '{level[0]}',
-        TIMESTAMP: '%H:%M:%S'
-    },
-}
-
-DEFAULT_STYLING = {
-    LEVEL: {
-        'info': Color.Fore.LIGHTMAGENTA_EX,
-        'debug': Color.Schema(fore=Color.Fore.LIGHTMAGENTA_EX, 
style=Color.Style.DIM),
-        'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT),
-    },
-    TIMESTAMP: {
-        'info': Color.Fore.LIGHTMAGENTA_EX,
-        'debug': Color.Schema(fore=Color.Fore.LIGHTMAGENTA_EX, 
style=Color.Style.DIM),
-        'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT),
-    },
-    MESSAGE: {
-        'info': Color.Fore.LIGHTBLUE_EX,
-        'debug': Color.Schema(fore=Color.Fore.LIGHTBLUE_EX, 
style=Color.Style.DIM),
-        'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT),
-    },
-    IMPLEMENTATION: {
-        'info': Color.Fore.LIGHTBLACK_EX,
-        'debug': Color.Schema(fore=Color.Fore.LIGHTBLACK_EX, 
style=Color.Style.DIM),
-        'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT),
-    },
-    INPUTS: {
-        'info': Color.Fore.BLUE,
-        'debug': Color.Schema(fore=Color.Fore.BLUE, style=Color.Style.DIM),
-        'error': Color.Schema(fore=Color.Fore.RED, style=Color.Style.BRIGHT),
-    },
-    TRACEBACK: {'error': Color.Fore.RED},
-
-    MARKER: Color.Back.LIGHTYELLOW_EX,
-    FINAL_STATES: {
-        SUCCESS_STATE: Color.Fore.GREEN,
-        CANCEL_STATE: Color.Fore.YELLOW,
-        FAIL_STATE: Color.Fore.RED,
-    }
-}
+_TIMESTAMP_PATTERN = '.*({timestamp.*?}).*'
+_LEVEL_PATTERN = '.*({level.*?}).*'
+_MESSAGE_PATTERN = '.*({message.*?}).*'
+_IMPLEMENTATION_PATTERN = '.*({implementation.*?}).*'
+_INPUTS_PATTERN = '.*({inputs.*?}).*'
 
 _PATTERNS = {
     SUCCESS_STATE: re.compile(_SUCCESSFUL_EXECUTION_PATTERN),
     CANCEL_STATE: re.compile(_CANCELED_EXECUTION_PATTERN),
-    FAIL_STATE: re.compile(_FAILED_EXECUTION_PATTERN)
+    FAIL_STATE: re.compile(_FAILED_EXECUTION_PATTERN),
 
+    IMPLEMENTATION: re.compile(_IMPLEMENTATION_PATTERN),
+    LEVEL: re.compile(_LEVEL_PATTERN),
+    MESSAGE: re.compile(_MESSAGE_PATTERN),
+    INPUTS: re.compile(_INPUTS_PATTERN),
+    TIMESTAMP: re.compile(_TIMESTAMP_PATTERN)
 }
 
 
 class _StylizedLogs(object):
 
-    def __init__(self):
-        self._formats = DEFAULT_FORMATTING
-        self._styles = DEFAULT_STYLING
-        self._mark_pattern = None
+    def _update_implementation(self, str_, implementation, log_item, 
mark_pattern=None):
+        str_ = self._stylize(str_, implementation, log_item, IMPLEMENTATION)
+        return self._markup(str_, implementation, mark_pattern)
 
-    def _push(self, styles=None, formats=None, mark_pattern=None):
-        self._styles = styles or self._styles
-        self._formats = formats or self._formats
-        self._mark_pattern = mark_pattern
+    def _update_inputs(self, str_, inputs, log_item, mark_pattern=None):
+        str_ = self._stylize(str_, inputs, log_item, INPUTS)
+        return self._markup(str_, inputs, mark_pattern)
 
-    def _implementation(self, implementation, log_item):
-        return self._stylize(implementation, log_item, IMPLEMENTATION)
+    def _update_timestamp(self, str_, timestamp, log_item):
+        return self._stylize(str_, timestamp, log_item, TIMESTAMP)
 
-    def _inputs(self, inputs, log_item):
-        return self._stylize(inputs, log_item, INPUTS)
+    def _update_message(self, str_, message, log_item, mark_pattern):
+        str_ = self._stylize(str_, message, log_item, MESSAGE)
+        return self._markup(str_, message, mark_pattern)
 
-    def _timestamp(self, timestamp, log_item):
-        return self._stylize(timestamp, log_item, TIMESTAMP)
+    def _get_traceback(self, traceback, log_item):
+        schema = 
Color.Schema(**self._styles[TRACEBACK].get(log_item.level.lower(), {}))
+        return Color.stylize(traceback, schema)
 
-    def _message(self, message, log_item):
-        return self._stylize(message, log_item, MESSAGE)
+    def _update_level(self, str_, log_item):
+        return self._stylize(str_, log_item.level[0], log_item, LEVEL)
 
-    def _traceback(self, traceback, log_item):
-        return self._stylize(traceback, log_item, TRACEBACK)
+    def _stylize(self, str_, msg, log_item, msg_type):
+        matched_str = self._find_pattern(_PATTERNS[msg_type], str_)
+        if not matched_str:
+            return str_
 
-    def _level(self, log_item):
-        return self._stylize(log_item.level[0], log_item, LEVEL)
+        # if Styling was disabled
+        if not self._is_styling_enabled:
+            return str_.replace(matched_str, matched_str.format(**{msg_type: 
msg}))
 
-    def _stylize(self, msg, log_item, msg_type):
-        schema = (self._final_string_schema(log_item.msg) or
-                  self._styles[msg_type].get(log_item.level.lower(), ''))
-        return Color.stylize(msg, schema)
+        schema = Color.Schema(
+            **(self._end_execution_schema(log_item.msg) or
+               self._styles[msg_type].get(log_item.level.lower()) or
+               {})
+        )
+        colored_string = Color.stylize(matched_str, schema)
+        return str_.replace(matched_str, colored_string.format(**{msg_type: 
msg}))
 
-    def _markup(self, str_, original_message):
-        if self._mark_pattern is None:
+    def _markup(self, str_, original_message, mark_pattern):
+        if mark_pattern is None:
             return str_
         else:
-            regex_pattern = re.compile(self._mark_pattern)
-            matches = re.search(regex_pattern, original_message)
+            regex_pattern = re.compile(mark_pattern)
+            matches = re.search(regex_pattern, str(original_message))
             if not matches:
                 return str_
-            return Color.markup(str_, matches, self._styles[MARKER])
+            return Color.markup(str_, matches, 
Color.Schema(back=self._styles[MARKER]))
 
-    def _final_string_schema(self, original_message):
+    def _end_execution_schema(self, original_message):
+        if not self.is_workflow_log:
+            return
         for state, pattern in _PATTERNS.items():
             if re.match(pattern, original_message):
                 return self._styles[FINAL_STATES][state]
 
-    def __call__(self, item):
-        # If no formats are passed we revert to the default formats (per level)
-        formatting = self._formats.get(env.logging.verbosity_level,
-                                       
DEFAULT_FORMATTING[env.logging.verbosity_level])
-        msg = StringIO()
-        formatting_kwargs = dict(item=item)
+    def _find_pattern(self, pattern, field_value):
+        match = re.match(pattern, field_value)
+        if match:
+            return match.group(1)
+
+    @property
+    def _verbosity_level(self):
+        return env.logging.verbosity_level
+
+    @property
+    def _format(self):
+        return 
env.config._config['logging']['execution_logging']['formatting'][self._verbosity_level]
+
+    @property
+    def _styles(self):
+        return env.config._config['logging']['execution_logging']['styling']
 
-        # level
-        formatting_kwargs['level'] = self._level(item)
+    @property
+    def _is_styling_enabled(self):
+        return 
env.config._config['logging']['execution_logging']['styling'].get('enabled', 
False)
+
+    def __call__(self, item, mark_pattern):
 
         # implementation
         if item.task:
             # operation task
             implementation = item.task.implementation
             inputs = dict(i.unwrap() for i in item.task.inputs.values())
+            self.is_workflow_log = False
         else:
             # execution task
             implementation = item.execution.workflow_name
             inputs = dict(i.unwrap() for i in item.execution.inputs.values())
+            self.is_workflow_log = True
 
-        formatting_kwargs['implementation'] = self._markup(
-            self._implementation(implementation, item), implementation)
-        formatting_kwargs['inputs'] = self._markup(self._inputs(inputs, item), 
str(inputs))
-
-        # timestamp
-        if 'timestamp' in formatting:
-            timestamp = item.created_at.strftime(formatting['timestamp'])
-        else:
-            timestamp = item.created_at
-        formatting_kwargs['timestamp'] = self._timestamp(timestamp, item)
-
-        # message
-        formatting_kwargs['message'] = self._message(item.msg, item)
-
-        # The message would be marked out if containing the provided pattern
-        
msg.write(self._markup(formatting['message'].format(**formatting_kwargs), 
item.msg))
+        # TODO: use the is_workflow_log
+        str_ = self._update_level(self._format, item)
+        str_ = self._update_timestamp(str_, item.created_at, item)
+        str_ = self._update_message(str_, item.msg, item, mark_pattern)
+        str_ = self._update_inputs(str_, inputs, item, mark_pattern)
+        str_ = self._update_implementation(str_, implementation, item, 
mark_pattern)
 
+        msg = StringIO(str_)
         # Add the exception and the error msg.
         if item.traceback and env.logging.verbosity_level >= 
logger.MEDIUM_VERBOSE:
             msg.write(os.linesep)
             for line in item.traceback.splitlines(True):
-                msg.write(self._traceback('\t' + '|' + line, item))
+                msg.write(self._get_traceback('\t' + '|' + line, item))
 
         return msg.getvalue()
 
@@ -203,22 +172,14 @@ class _StylizedLogs(object):
 _stylize_log = _StylizedLogs()
 
 
-@contextmanager
-def format(styles=None, formats=None, mark_pattern=None):
-    original_styles = _stylize_log._styles
-    original_formats = _stylize_log._formats
-    _stylize_log._push(styles=styles, formats=formats, 
mark_pattern=mark_pattern)
-    yield
-    _stylize_log._push(styles=original_styles, formats=original_formats, 
mark_pattern=None)
-
-
-def log(item, *args, **kwargs):
-    return getattr(env.logging.logger, item.level.lower())(_stylize_log(item), 
*args, **kwargs)
+def log(item, mark_pattern=None, *args, **kwargs):
+    leveled_log = getattr(env.logging.logger, item.level.lower())
+    return leveled_log(_stylize_log(item, mark_pattern), *args, **kwargs)
 
 
-def log_list(iterator):
+def log_list(iterator, mark_pattern=None):
     any_logs = False
     for item in iterator:
-        log(item)
+        log(item, mark_pattern)
         any_logs = True
     return any_logs

Reply via email to