1import json 2import logging 3from unittest import mock 4 5from google.api_core.client_logging import ( 6 setup_logging, 7 initialize_logging, 8 StructuredLogFormatter, 9) 10 11 12def reset_logger(scope): 13 logger = logging.getLogger(scope) 14 logger.handlers = [] 15 logger.setLevel(logging.NOTSET) 16 logger.propagate = True 17 18 19def test_setup_logging_w_no_scopes(): 20 with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foogle"): 21 setup_logging() 22 base_logger = logging.getLogger("foogle") 23 assert base_logger.handlers == [] 24 assert not base_logger.propagate 25 assert base_logger.level == logging.NOTSET 26 27 reset_logger("foogle") 28 29 30def test_setup_logging_w_base_scope(): 31 with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foogle"): 32 setup_logging("foogle") 33 base_logger = logging.getLogger("foogle") 34 assert isinstance(base_logger.handlers[0], logging.StreamHandler) 35 assert not base_logger.propagate 36 assert base_logger.level == logging.DEBUG 37 38 reset_logger("foogle") 39 40 41def test_setup_logging_w_configured_scope(): 42 with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foogle"): 43 base_logger = logging.getLogger("foogle") 44 base_logger.propagate = False 45 setup_logging("foogle") 46 assert base_logger.handlers == [] 47 assert not base_logger.propagate 48 assert base_logger.level == logging.NOTSET 49 50 reset_logger("foogle") 51 52 53def test_setup_logging_w_module_scope(): 54 with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foogle"): 55 setup_logging("foogle.bar") 56 57 base_logger = logging.getLogger("foogle") 58 assert base_logger.handlers == [] 59 assert not base_logger.propagate 60 assert base_logger.level == logging.NOTSET 61 62 module_logger = logging.getLogger("foogle.bar") 63 assert isinstance(module_logger.handlers[0], logging.StreamHandler) 64 assert not module_logger.propagate 65 assert module_logger.level == logging.DEBUG 66 67 reset_logger("foogle") 68 reset_logger("foogle.bar") 69 70 71def test_setup_logging_w_incorrect_scope(): 72 with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foogle"): 73 setup_logging("abc") 74 75 base_logger = logging.getLogger("foogle") 76 assert base_logger.handlers == [] 77 assert not base_logger.propagate 78 assert base_logger.level == logging.NOTSET 79 80 # TODO(https://github.com/googleapis/python-api-core/issues/759): update test once we add logic to ignore an incorrect scope. 81 logger = logging.getLogger("abc") 82 assert isinstance(logger.handlers[0], logging.StreamHandler) 83 assert not logger.propagate 84 assert logger.level == logging.DEBUG 85 86 reset_logger("foogle") 87 reset_logger("abc") 88 89 90def test_initialize_logging(): 91 92 with mock.patch("os.getenv", return_value="foogle.bar"): 93 with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foogle"): 94 initialize_logging() 95 96 base_logger = logging.getLogger("foogle") 97 assert base_logger.handlers == [] 98 assert not base_logger.propagate 99 assert base_logger.level == logging.NOTSET 100 101 module_logger = logging.getLogger("foogle.bar") 102 assert isinstance(module_logger.handlers[0], logging.StreamHandler) 103 assert not module_logger.propagate 104 assert module_logger.level == logging.DEBUG 105 106 # Check that `initialize_logging()` is a no-op after the first time by verifying that user-set configs are not modified: 107 base_logger.propagate = True 108 module_logger.propagate = True 109 110 initialize_logging() 111 112 assert base_logger.propagate 113 assert module_logger.propagate 114 115 reset_logger("foogle") 116 reset_logger("foogle.bar") 117 118 119def test_structured_log_formatter(): 120 # TODO(https://github.com/googleapis/python-api-core/issues/761): Test additional fields when implemented. 121 record = logging.LogRecord( 122 name="Appelation", 123 level=logging.DEBUG, 124 msg="This is a test message.", 125 pathname="some/path", 126 lineno=25, 127 args=None, 128 exc_info=None, 129 ) 130 131 # Extra fields: 132 record.rpcName = "bar" 133 134 formatted_msg = StructuredLogFormatter().format(record) 135 parsed_msg = json.loads(formatted_msg) 136 137 assert parsed_msg["name"] == "Appelation" 138 assert parsed_msg["severity"] == "DEBUG" 139 assert parsed_msg["message"] == "This is a test message." 140 assert parsed_msg["rpcName"] == "bar" 141