Skip to content

Commit 0f1a4bd

Browse files
committed
address PR feedback
1 parent 65708ff commit 0f1a4bd

File tree

2 files changed

+89
-46
lines changed

2 files changed

+89
-46
lines changed

google/api_core/client_logging.py

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,62 +10,76 @@
1010
RESPONSE_MESSAGE = "Receiving response "
1111

1212
# TODO(https://github.com/googleapis/python-api-core/issues/761): Update this list to support additional logging fields
13-
_recognized_logging_fields = ["httpRequest", "rpcName", "serviceName"] # Additional fields to be Logged.
13+
_recognized_logging_fields = [
14+
"httpRequest",
15+
"rpcName",
16+
"serviceName",
17+
] # Additional fields to be Logged.
18+
1419

1520
def logger_configured(logger):
16-
return logger.handlers != [] or logger.level != logging.NOTSET or logger.propagate == False
21+
return (
22+
logger.handlers != []
23+
or logger.level != logging.NOTSET
24+
or logger.propagate == False
25+
)
26+
1727

1828
def initialize_logging():
19-
global _LOGGING_INITIALIZED
20-
if _LOGGING_INITIALIZED:
21-
return
22-
scopes = os.getenv("GOOGLE_SDK_PYTHON_LOGGING_SCOPE")
23-
setup_logging(scopes)
24-
_LOGGING_INITIALIZED = True
29+
global _LOGGING_INITIALIZED
30+
if _LOGGING_INITIALIZED:
31+
return
32+
scopes = os.getenv("GOOGLE_SDK_PYTHON_LOGGING_SCOPE", "")
33+
setup_logging(scopes)
34+
_LOGGING_INITIALIZED = True
35+
2536

2637
def parse_logging_scopes(scopes):
27-
if not scopes:
28-
return []
29-
# TODO(https://github.com/googleapis/python-api-core/issues/759): check if the namespace is a valid namespace.
30-
# TODO(b/380481951): Support logging multiple scopes.
31-
# TODO(b/380483756): Raise or log a warning for an invalid scope.
32-
namespaces = [scopes]
33-
return namespaces
38+
if not scopes:
39+
return []
40+
# TODO(https://github.com/googleapis/python-api-core/issues/759): check if the namespace is a valid namespace.
41+
# TODO(b/380481951): Support logging multiple scopes.
42+
# TODO(b/380483756): Raise or log a warning for an invalid scope.
43+
namespaces = [scopes]
44+
return namespaces
45+
3446

3547
def configure_defaults(logger):
36-
if not logger_configured(logger):
48+
if not logger_configured(logger):
3749
console_handler = logging.StreamHandler()
3850
logger.setLevel("DEBUG")
3951
logger.propagate = False
4052
formatter = StructuredLogFormatter()
4153
console_handler.setFormatter(formatter)
4254
logger.addHandler(console_handler)
4355

56+
4457
def setup_logging(scopes=[]):
45-
58+
4659
# only returns valid logger scopes (namespaces)
4760
# this list has at most one element.
48-
logger_names = parse_logging_scopes(scopes)
61+
logger_names = parse_logging_scopes(scopes)
4962

5063
for namespace in logger_names:
51-
# This will either create a module level logger or get the reference of the base logger instantiated above.
52-
logger = logging.getLogger(namespace)
64+
# This will either create a module level logger or get the reference of the base logger instantiated above.
65+
logger = logging.getLogger(namespace)
5366

54-
# Configure default settings.
55-
configure_defaults(logger)
67+
# Configure default settings.
68+
configure_defaults(logger)
5669

5770
# disable log propagation at base logger level to the root logger only if a base logger is not already configured via code changes.
5871
base_logger = logging.getLogger(_BASE_LOGGER_NAME)
5972
if not logger_configured(base_logger):
6073
base_logger.propagate = False
6174

75+
6276
class StructuredLogFormatter(logging.Formatter):
6377
def format(self, record):
6478
log_obj = {
65-
'timestamp': self.formatTime(record),
66-
'severity': record.levelname,
67-
'name': record.name,
68-
'message': record.getMessage(),
79+
"timestamp": self.formatTime(record),
80+
"severity": record.levelname,
81+
"name": record.name,
82+
"message": record.getMessage(),
6983
}
7084

7185
for field_name in _recognized_logging_fields:

tests/unit/test_client_logging.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,95 @@
11
import logging
22
import pytest
3+
import mock
34

4-
from google.api_core.client_logging import setup_logging
5+
from google.api_core.client_logging import (
6+
setup_logging,
7+
parse_logging_scopes,
8+
initialize_logging,
9+
)
510

6-
# TODO: We should not be testing against the "google" logger
7-
# and should mock `base_logger` instead.
811

912
def reset_logger(scope):
1013
logger = logging.getLogger(scope)
1114
logger.handlers = []
1215
logger.setLevel(logging.NOTSET)
1316
logger.propagate = True
14-
17+
18+
1519
def test_setup_logging_w_no_scopes():
16-
setup_logging()
17-
base_logger = logging.getLogger("google")
18-
assert base_logger.handlers == []
19-
assert base_logger.propagate == False
20-
assert base_logger.level == logging.NOTSET
20+
with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foo"):
21+
setup_logging()
22+
base_logger = logging.getLogger("foo")
23+
assert base_logger.handlers == []
24+
assert base_logger.propagate == False
25+
assert base_logger.level == logging.NOTSET
2126

2227
reset_logger("google")
2328

2429

2530
def test_setup_logging_w_base_scope():
26-
setup_logging("google")
27-
base_logger = logging.getLogger("google")
31+
with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foo"):
32+
setup_logging("foo")
33+
base_logger = logging.getLogger("foo")
2834
assert isinstance(base_logger.handlers[0], logging.StreamHandler)
2935
assert base_logger.propagate == False
3036
assert base_logger.level == logging.DEBUG
3137

3238
reset_logger("google")
3339

40+
3441
def test_setup_logging_w_module_scope():
35-
setup_logging("google.foo")
36-
37-
base_logger = logging.getLogger("google")
42+
with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foo"):
43+
setup_logging("foo.bar")
44+
45+
base_logger = logging.getLogger("foo")
3846
assert base_logger.handlers == []
3947
assert base_logger.propagate == False
4048
assert base_logger.level == logging.NOTSET
4149

42-
module_logger = logging.getLogger("google.foo")
50+
module_logger = logging.getLogger("foo.bar")
4351
assert isinstance(module_logger.handlers[0], logging.StreamHandler)
4452
assert module_logger.propagate == False
4553
assert module_logger.level == logging.DEBUG
4654

47-
4855
reset_logger("google")
4956
reset_logger("google.foo")
5057

58+
5159
def test_setup_logging_w_incorrect_scope():
52-
setup_logging("foo")
53-
54-
base_logger = logging.getLogger("google")
60+
with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foo"):
61+
setup_logging("abc")
62+
63+
base_logger = logging.getLogger("foo")
5564
assert base_logger.handlers == []
5665
assert base_logger.propagate == False
5766
assert base_logger.level == logging.NOTSET
5867

5968
# TODO(https://github.com/googleapis/python-api-core/issues/759): update test once we add logic to ignore an incorrect scope.
60-
logger = logging.getLogger("foo")
69+
logger = logging.getLogger("abc")
6170
assert isinstance(logger.handlers[0], logging.StreamHandler)
6271
assert logger.propagate == False
6372
assert logger.level == logging.DEBUG
6473

6574
reset_logger("google")
6675
reset_logger("foo")
76+
77+
78+
def test_initialize_logging():
79+
80+
with mock.patch("os.getenv", return_value="foo.bar"):
81+
with mock.patch("google.api_core.client_logging._BASE_LOGGER_NAME", "foo"):
82+
initialize_logging()
83+
84+
base_logger = logging.getLogger("foo")
85+
assert base_logger.handlers == []
86+
assert base_logger.propagate == False
87+
assert base_logger.level == logging.NOTSET
88+
89+
module_logger = logging.getLogger("foo.bar")
90+
assert isinstance(module_logger.handlers[0], logging.StreamHandler)
91+
assert module_logger.propagate == False
92+
assert module_logger.level == logging.DEBUG
93+
94+
reset_logger("google")
95+
reset_logger("google.foo")

0 commit comments

Comments
 (0)