Hacking: do not translate log messages

Community has decided to do not translate log messages anymore.
The motivation behind removing translation jobs for log messages
is that when operators encounters any unfamiliar situations(e.g.
nova error, keystone error etc.), searching on the Internet
based on actual log content would have more results than searching
translated log messages.

In this patch I have added hacking rule to check that logs are
not translated.

Change-Id: I90d53d617aac6839c2f2ab119847cbf24a1300e0
This commit is contained in:
poojajadhav 2017-04-04 18:42:01 +05:30 committed by pooja jadhav
parent 12f91c29a7
commit 892e9b116c
3 changed files with 31 additions and 22 deletions

View File

@ -19,11 +19,10 @@ Masakari Specific Commandments
assertIsInstance(A, B). assertIsInstance(A, B).
- [M306] Change assertEqual(type(A), B) by optimal assert like - [M306] Change assertEqual(type(A), B) by optimal assert like
assertIsInstance(A, B) assertIsInstance(A, B)
- [M308] Validate that debug level logs are not translated. - [M308] Validate that log messages are not translated.
- [M309] Don't import translation in tests - [M309] Don't import translation in tests
- [M310] Setting CONF.* attributes directly in tests is forbidden. Use - [M310] Setting CONF.* attributes directly in tests is forbidden. Use
self.flags(option=value) instead. self.flags(option=value) instead.
- [M314] Log messages require translations!
- [M315] Method's default argument shouldn't be mutable - [M315] Method's default argument shouldn't be mutable
- [M316] Ensure that the _() function is explicitly imported to ensure proper translations. - [M316] Ensure that the _() function is explicitly imported to ensure proper translations.
- [M317] Ensure that jsonutils.%(fun)s must be used instead of json.%(fun)s - [M317] Ensure that jsonutils.%(fun)s must be used instead of json.%(fun)s

View File

@ -85,6 +85,15 @@ spawn_re = re.compile(
contextlib_nested = re.compile(r"^with (contextlib\.)?nested\(") contextlib_nested = re.compile(r"^with (contextlib\.)?nested\(")
doubled_words_re = re.compile( doubled_words_re = re.compile(
r"\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b") r"\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b")
_all_log_levels = {'critical', 'error', 'exception', 'info',
'warning', 'debug'}
_all_hints = {'_', '_LE', '_LI', '_LW', '_LC'}
log_translation_re = re.compile(
r".*LOG\.(%(levels)s)\(\s*(%(hints)s)\(" % {
'levels': '|'.join(_all_log_levels),
'hints': '|'.join(_all_hints),
})
def no_db_session_in_public_api(logical_line, filename): def no_db_session_in_public_api(logical_line, filename):
@ -139,21 +148,18 @@ def assert_equal_type(logical_line):
yield (0, "M306: assertEqual(type(A), B) sentences not allowed") yield (0, "M306: assertEqual(type(A), B) sentences not allowed")
def no_translate_debug_logs(logical_line, filename): def no_translate_logs(logical_line):
"""Check for 'LOG.debug(_(' """Check for 'LOG.*(_*("'
As per our translation policy, OpenStack no longer supports log translation, so we shouldn't
https://wiki.openstack.org/wiki/LoggingStandards#Log_Translation translate logs.
we shouldn't translate debug level logs.
* This check assumes that 'LOG' is a logger. * This check assumes that 'LOG' is a logger.
* Use filename so we can start enforcing this in specific folders instead
of needing to do so all at once.
M308 M308
""" """
if logical_line.startswith("LOG.debug(_("): if log_translation_re.match(logical_line):
yield(0, "M308 Don't translate debug level logs") yield(0, "M308: Log messages should not be translated")
def no_import_translation_in_tests(logical_line, filename): def no_import_translation_in_tests(logical_line, filename):
@ -384,7 +390,7 @@ def factory(register):
register(assert_true_instance) register(assert_true_instance)
register(assert_equal_type) register(assert_equal_type)
register(assert_raises_regexp) register(assert_raises_regexp)
register(no_translate_debug_logs) register(no_translate_logs)
register(no_setting_conf_directly_in_tests) register(no_setting_conf_directly_in_tests)
register(no_mutable_default_args) register(no_mutable_default_args)
register(check_explicit_underscore_import) register(check_explicit_underscore_import)

View File

@ -14,6 +14,7 @@
import textwrap import textwrap
import ddt
import mock import mock
import pep8 import pep8
@ -21,6 +22,7 @@ from masakari.hacking import checks
from masakari import test from masakari import test
@ddt.ddt
class HackingTestCase(test.NoDBTestCase): class HackingTestCase(test.NoDBTestCase):
"""This class tests the hacking checks in masakari.hacking.checks by """This class tests the hacking checks in masakari.hacking.checks by
passing strings to the check methods like the pep8/flake8 parser would. passing strings to the check methods like the pep8/flake8 parser would.
@ -151,16 +153,6 @@ class HackingTestCase(test.NoDBTestCase):
self.assertEqual(len(list(checks.assert_true_or_false_with_in( self.assertEqual(len(list(checks.assert_true_or_false_with_in(
"self.assertFalse(some in list1 and some2 in list2)"))), 0) "self.assertFalse(some in list1 and some2 in list2)"))), 0)
def test_no_translate_debug_logs(self):
self.assertEqual(len(list(checks.no_translate_debug_logs(
"LOG.debug(_('foo'))", "masakari/foo.py"))), 1)
self.assertEqual(len(list(checks.no_translate_debug_logs(
"LOG.debug('foo')", "masakari/foo.py"))), 0)
self.assertEqual(len(list(checks.no_translate_debug_logs(
"LOG.info(_('foo'))", "masakari/foo.py"))), 0)
def test_no_setting_conf_directly_in_tests(self): def test_no_setting_conf_directly_in_tests(self):
self.assertEqual(len(list(checks.no_setting_conf_directly_in_tests( self.assertEqual(len(list(checks.no_setting_conf_directly_in_tests(
"CONF.option = 1", "masakari/tests/test_foo.py"))), 1) "CONF.option = 1", "masakari/tests/test_foo.py"))), 1)
@ -431,3 +423,15 @@ class HackingTestCase(test.NoDBTestCase):
LOG.warning("LOG.warn is deprecated") LOG.warning("LOG.warn is deprecated")
""" """
self._assert_has_no_errors(code, checks.no_log_warn) self._assert_has_no_errors(code, checks.no_log_warn)
@ddt.data('LOG.info(_LI("Bad"))',
'LOG.warning(_LW("Bad"))',
'LOG.error(_LE("Bad"))',
'LOG.exception(_("Bad"))',
'LOG.debug(_("Bad"))',
'LOG.critical(_LC("Bad"))')
def test_no_translate_logs(self, log_statement):
self.assertEqual(1, len(list(checks.no_translate_logs(log_statement))))
errors = [(1, 0, 'M308')]
self._assert_has_errors(log_statement, checks.no_translate_logs,
expected_errors=errors)