Skip to content

Commit 99bf3ca

Browse files
author
Juliya Smith
authored
Fix/rm escs in log (#54)
1 parent cdb7fb2 commit 99bf3ca

File tree

3 files changed

+58
-11
lines changed

3 files changed

+58
-11
lines changed

src/code42cli/logger.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging, sys, traceback
22
from logging.handlers import RotatingFileHandler
33
from threading import Lock
4+
import copy
45

56
from code42cli.compat import str
67
from code42cli.util import get_user_project_path, is_interactive
@@ -79,6 +80,20 @@ def _get_user_error_logger():
7980
return _get_error_file_logger()
8081

8182

83+
class RedStderrHandler(logging.StreamHandler):
84+
"""Logging handler for logging error messages to stderr using red scary text prefixed by the
85+
word `ERROR`. For logging info to stderr, it will not add the scary red text."""
86+
def __init__(self):
87+
super(RedStderrHandler, self).__init__(sys.stderr)
88+
89+
def emit(self, record):
90+
if record.levelno == logging.ERROR:
91+
message = _get_red_error_text(record.msg)
92+
record = copy.copy(record)
93+
record.msg = message
94+
super(RedStderrHandler, self).emit(record)
95+
96+
8297
def _get_interactive_user_error_logger():
8398
"""This logger has two handlers, one for stderr and one for the error log file."""
8499
logger = logging.getLogger(u"code42_stderr_main")
@@ -87,7 +102,7 @@ def _get_interactive_user_error_logger():
87102

88103
with logger_deps_lock:
89104
if not logger_has_handlers(logger):
90-
stderr_handler = logging.StreamHandler(sys.stderr)
105+
stderr_handler = RedStderrHandler()
91106
stderr_formatter = _get_standard_formatter()
92107
stderr_handler.setFormatter(stderr_formatter)
93108

@@ -98,7 +113,7 @@ def _get_interactive_user_error_logger():
98113
add_handler_to_logger(logger, stderr_handler, stderr_formatter)
99114
add_handler_to_logger(logger, file_handler, file_formatter)
100115

101-
logger.setLevel(logging.ERROR)
116+
logger.setLevel(logging.INFO)
102117
return logger
103118
return logger
104119

@@ -139,14 +154,12 @@ def print_bold(self, message):
139154
self._info_logger.info(u"\033[1m{}\033[0m".format(message))
140155

141156
def print_and_log_error(self, message):
142-
"""For not interrupting stdout output. Excludes red text and 'ERROR: ' from `error()`.
143-
"""
144-
"""Logs red text to stderr and a log file."""
145-
self._user_error_logger.error(_get_red_error_text(message))
157+
"""Logs red error text to stderr and non-color messages to the log file."""
158+
self._user_error_logger.error(message)
146159

147160
def print_and_log_info(self, message):
148-
"""Logs red text to stderr and a log file."""
149-
self._user_error_logger.error(message)
161+
"""Prints to stderr and the log file."""
162+
self._user_error_logger.info(message)
150163

151164
def log_error(self, err):
152165
if err:
@@ -171,7 +184,7 @@ def log_verbose_error(self, invocation_str=None, http_request=None):
171184
prefix = (
172185
u"Exception occurred."
173186
if not invocation_str
174-
else "Exception occurred from input: '{}'.".format(invocation_str)
187+
else u"Exception occurred from input: '{}'.".format(invocation_str)
175188
)
176189
message = u"{}. See error below.".format(prefix)
177190
self.log_error(message)

tests/cmds/detectionlists/test_init.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def test_get_user_id_when_user_does_not_exist_logs_error(sdk_without_user, caplo
3636
try:
3737
get_user_id(sdk_without_user, "risky employee")
3838
except UserDoesNotExistError:
39-
assert "ERROR: User 'risky employee' does not exist." in caplog.text
39+
assert "User 'risky employee' does not exist." in caplog.text
4040

4141

4242
def test_update_user_adds_cloud_alias(sdk_with_user, profile):

tests/test_logger.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import logging
2+
from logging.handlers import RotatingFileHandler
23
from requests import Request
34

45
from code42cli.logger import (
56
add_handler_to_logger,
67
logger_has_handlers,
78
get_view_exceptions_location_message,
9+
RedStderrHandler,
810
CliLogger,
911
)
1012
from code42cli.util import get_user_project_path
@@ -39,10 +41,42 @@ def test_get_view_exceptions_location_message_returns_expected_message():
3941
assert actual == expected
4042

4143

44+
class TestRedStderrHandler(object):
45+
def test_emit_when_error_adds_red_text(self, mocker, caplog):
46+
handler = RedStderrHandler()
47+
record = mocker.MagicMock(spec=logging.LogRecord)
48+
record.msg = "TEST"
49+
record.levelno = logging.ERROR
50+
51+
logger = mocker.patch("logging.StreamHandler.emit")
52+
handler.emit(record)
53+
actual = logger.call_args[0][0].msg
54+
assert actual == "\x1b[91mERROR: TEST\x1b[0m"
55+
56+
def test_emit_when_info_does_not_alter(self, mocker, caplog):
57+
handler = RedStderrHandler()
58+
record = mocker.MagicMock(spec=logging.LogRecord)
59+
record.msg = "TEST"
60+
record.levelno = logging.INFO
61+
62+
logger = mocker.patch("logging.StreamHandler.emit")
63+
handler.emit(record)
64+
actual = logger.call_args[0][0].msg
65+
assert actual == "TEST"
66+
67+
4268
class TestCliLogger(object):
4369

4470
_logger = CliLogger()
4571

72+
def test_init_creates_user_error_logger_with_expected_handlers(self, mocker):
73+
is_interactive = mocker.patch("code42cli.logger.is_interactive")
74+
is_interactive.return_value = True
75+
logger = CliLogger()
76+
handler_types = [type(h) for h in logger._user_error_logger.handlers]
77+
assert RedStderrHandler in handler_types
78+
assert RotatingFileHandler in handler_types
79+
4680
def test_print_info_logs_expected_text_at_expected_level(self, caplog):
4781
with caplog.at_level(logging.INFO):
4882
self._logger.print_info("TEST")
@@ -59,7 +93,7 @@ def test_print_and_log_error_logs_expected_text_at_expected_level(self, caplog):
5993
assert "TEST" in caplog.text
6094

6195
def test_print_and_log_info_logs_expected_text_at_expected_level(self, caplog):
62-
with caplog.at_level(logging.ERROR):
96+
with caplog.at_level(logging.INFO):
6397
self._logger.print_and_log_info("TEST")
6498
assert "TEST" in caplog.text
6599

0 commit comments

Comments
 (0)