horizon/horizon/notifications.py
Akihiro Motoki ced987815d Ensure log messages are not translated
Previously translated messages are included in log messages
and it was determined what language is chosen by users.
It makes difficult for operators to understand log messgaes.

This commit tries to use English messages for all log messages.
The following policies are applied based on the past discussions
in the bug 1406333 and related reviews.

- English messages are used for log messages.
- log messages include exception messages if possible
  to help operators identify what happens.
- Use ID rather than name for log messages
  as ID is much more unique compared to name.
- LOG.debug() in success code path are deleted.
  We don't log success messages in most places and API calls to
  back-end services can be logged from python bindings.

Change-Id: Ie554463908327435d886d0d0f1671fd327c0cd00
Closes-Bug: #1406333
2017-04-11 10:24:01 +00:00

153 lines
4.4 KiB
Python

# Copyright (C) 2015 Yahoo! Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import glob
import json
import logging
import os
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import messages
LOG = logging.getLogger(__name__)
_MESSAGES_CACHE = None
_MESSAGES_MTIME = None
class JSONMessage(object):
INFO = messages.info
SUCCESS = messages.success
WARNING = messages.warning
ERROR = messages.error
MESSAGE_LEVELS = {
'info': INFO,
'success': SUCCESS,
'warning': WARNING,
'error': ERROR
}
def __init__(self, path, fail_silently=False):
self._path = path
self._data = ''
self.failed = False
self.fail_silently = fail_silently
self.message = ''
self.level = self.INFO
self.level_name = 'info'
def _read(self):
with open(self._path, 'rb') as file_obj:
self._data = file_obj.read()
def _parse(self):
attrs = {}
try:
data = self._data.decode('utf-8')
attrs = json.loads(data)
except ValueError as exc:
self.failed = True
params = {'path': self._path, 'exception': exc}
if self.fail_silently:
LOG.warning("Message json file '%(path)s' is malformed. "
"%(exception)s", params)
else:
raise exceptions.MessageFailure(
_("Message json file '%(path)s' is malformed. "
"%(exception)s") % params)
else:
level_name = attrs.get('level', 'info')
if level_name in self.MESSAGE_LEVELS:
self.level_name = level_name
self.level = self.MESSAGE_LEVELS.get(self.level_name, self.INFO)
self.message = attrs.get('message', '')
def load(self):
"""Read and parse the message file."""
try:
self._read()
self._parse()
except Exception as exc:
self.failed = True
params = {'path': self._path, 'exception': exc}
if self.fail_silently:
LOG.warning("Error processing message json file '%(path)s': "
"%(exception)s", params)
else:
raise exceptions.MessageFailure(
_("Error processing message json file '%(path)s': "
"%(exception)s") % params)
def send_message(self, request):
if self.failed:
return
self.level(request, mark_safe(self.message))
def _is_path(path):
if os.path.exists(path) and os.path.isdir(path):
return True
else:
return False
def _get_processed_messages(messages_path):
msgs = list()
if not _is_path(messages_path):
LOG.error('%s is not a valid messages path.', messages_path)
return msgs
# Get all files from messages_path with .json extension
for fname in glob.glob(os.path.join(messages_path, '*.json')):
fpath = os.path.join(messages_path, fname)
msg = JSONMessage(fpath, fail_silently=True)
msg.load()
if not msg.failed:
msgs.append(msg)
return msgs
def process_message_notification(request, messages_path):
"""Process all the msg file found in the message directory"""
if not messages_path:
return
global _MESSAGES_CACHE
global _MESSAGES_MTIME
# NOTE (lhcheng): Cache the processed messages to avoid parsing
# the files every time. Check directory modification time if
# reload is necessary.
if (_MESSAGES_CACHE is None
or _MESSAGES_MTIME != os.path.getmtime(messages_path)):
_MESSAGES_CACHE = _get_processed_messages(messages_path)
_MESSAGES_MTIME = os.path.getmtime(messages_path)
for msg in _MESSAGES_CACHE:
msg.send_message(request)