Skip to content

Commit 9ca34e2

Browse files
Log Formatter (aws-cloudformation#190)
* add log_format argument * move set format condition * test test * add tests * lint pass
1 parent 45cdc5b commit 9ca34e2

File tree

5 files changed

+69
-6
lines changed

5 files changed

+69
-6
lines changed

src/cloudformation_cli_python_lib/hook.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,17 @@ def wrapper(self: Any, event: MutableMapping[str, Any], context: Any) -> Any:
6565

6666
class Hook:
6767
def __init__(
68-
self, type_name: str, type_configuration_model_cls: Type[BaseModel]
68+
self,
69+
type_name: str,
70+
type_configuration_model_cls: Type[BaseModel],
71+
log_format: Optional[logging.Formatter] = None,
6972
) -> None:
7073
self.type_name = type_name
7174
self._type_configuration_model_cls: Type[
7275
BaseModel
7376
] = type_configuration_model_cls
7477
self._handlers: MutableMapping[HookInvocationPoint, HandlerSignature] = {}
78+
self.log_format = log_format
7579

7680
def handler(
7781
self, invocation_point: HookInvocationPoint
@@ -247,7 +251,7 @@ def print_or_log(message: str) -> None:
247251

248252
metrics = MetricsPublisherProxy()
249253
if event.requestData.providerLogGroupName and provider_sess:
250-
HookProviderLogHandler.setup(event, provider_sess)
254+
HookProviderLogHandler.setup(event, provider_sess, self.log_format)
251255
logs_setup = True
252256
metrics.add_hook_metrics_publisher(
253257
provider_sess, event.hookTypeName, event.awsAccountId

src/cloudformation_cli_python_lib/log_delivery.py

+18-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ def _get_existing_logger(cls) -> Optional["ProviderLogHandler"]:
3535

3636
@classmethod
3737
def setup(
38-
cls, request: HandlerRequest, provider_sess: Optional[SessionProxy]
38+
cls,
39+
request: HandlerRequest,
40+
provider_sess: Optional[SessionProxy],
41+
log_format: Optional[logging.Formatter] = None,
3942
) -> None:
4043
log_group = request.requestData.providerLogGroupName
4144
if request.stackId and request.requestData.logicalResourceId:
@@ -50,11 +53,16 @@ def setup(
5053
# we just refresh the client with new creds
5154
log_handler.client = provider_sess.client("logs")
5255
return
56+
5357
# filter provider messages from platform
5458
provider = request.resourceType.replace("::", "_").lower()
5559
log_handler = cls(
5660
group=log_group, stream=stream_name, session=provider_sess
5761
)
62+
63+
if log_format:
64+
log_handler.setFormatter(log_format)
65+
5866
# add log handler to root, so that provider gets plugin logs too
5967
logging.getLogger().addHandler(log_handler)
6068
logging.getLogger().handlers[0].addFilter(ProviderFilter(provider))
@@ -114,7 +122,10 @@ def _get_existing_logger(cls) -> Optional["HookProviderLogHandler"]:
114122

115123
@classmethod
116124
def setup( # type: ignore
117-
cls, request: HookInvocationRequest, provider_sess: Optional[SessionProxy]
125+
cls,
126+
request: HookInvocationRequest,
127+
provider_sess: Optional[SessionProxy],
128+
log_format: Optional[logging.Formatter] = None,
118129
) -> None:
119130
log_group = request.requestData.providerLogGroupName
120131
if request.stackId and request.requestData.targetLogicalId:
@@ -129,11 +140,16 @@ def setup( # type: ignore
129140
# we just refresh the client with new creds
130141
log_handler.client = provider_sess.client("logs")
131142
return
143+
132144
# filter provider messages from platform
133145
provider = request.hookTypeName.replace("::", "_").lower()
134146
logging.getLogger().handlers[0].addFilter(ProviderFilter(provider))
135147
log_handler = cls(
136148
group=log_group, stream=stream_name, session=provider_sess
137149
)
150+
151+
if log_format:
152+
log_handler.setFormatter(log_format)
153+
138154
# add log handler to root, so that provider gets plugin logs too
139155
logging.getLogger().addHandler(log_handler)

src/cloudformation_cli_python_lib/resource.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,15 @@ def __init__(
6161
type_name: str,
6262
resouce_model_cls: Type[BaseModel],
6363
type_configuration_model_cls: Optional[Type[BaseModel]] = None,
64+
log_format: Optional[logging.Formatter] = None,
6465
) -> None:
6566
self.type_name = type_name
6667
self._model_cls: Type[BaseModel] = resouce_model_cls
6768
self._type_configuration_model_cls: Optional[
6869
Type[BaseModel]
6970
] = type_configuration_model_cls
7071
self._handlers: MutableMapping[Action, HandlerSignature] = {}
72+
self.log_format = log_format
7173

7274
def handler(self, action: Action) -> Callable[[HandlerSignature], HandlerSignature]:
7375
def _add_handler(f: HandlerSignature) -> HandlerSignature:
@@ -200,7 +202,7 @@ def print_or_log(message: str) -> None:
200202

201203
metrics = MetricsPublisherProxy()
202204
if event.requestData.providerLogGroupName and provider_sess:
203-
ProviderLogHandler.setup(event, provider_sess)
205+
ProviderLogHandler.setup(event, provider_sess, self.log_format)
204206
logs_setup = True
205207
metrics.add_metrics_publisher(provider_sess, event.resourceType)
206208

src/setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
setup(
55
name="cloudformation-cli-python-lib",
6-
version="2.1.12",
6+
version="2.1.13a1",
77
description=__doc__,
88
author="Amazon Web Services",
99
author_email="[email protected]",

tests/lib/log_delivery_test.py

+41
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ def setup_patches(mock_logger):
9090
)
9191

9292

93+
@pytest.fixture
94+
def mock_handler_set_formatter():
95+
patch__set_handler_formatter = patch.object(ProviderLogHandler, "setFormatter")
96+
patch__set_hook_handler_formatter = patch.object(
97+
HookProviderLogHandler, "setFormatter"
98+
)
99+
return patch__set_handler_formatter, patch__set_hook_handler_formatter
100+
101+
93102
@pytest.fixture
94103
def mock_provider_handler():
95104
plh = ProviderLogHandler(
@@ -197,6 +206,21 @@ def test_setup_existing_logger(setup_patches, mock_session):
197206
mock_log.return_value.addHandler.assert_not_called()
198207

199208

209+
def test_setup_with_formatter(setup_patches, mock_session, mock_handler_set_formatter):
210+
payload, _hook_payload, p_logger, p__get_logger, _p__get_hook_logger = setup_patches
211+
(
212+
p__set_handler_formatter,
213+
_p__set_hook_handler_formatter,
214+
) = mock_handler_set_formatter
215+
formatter = logging.Formatter()
216+
with p_logger as mock_log, p__get_logger as mock_get, p__set_handler_formatter as mock_set_formatter: # pylint: disable=C0301 # noqa: B950
217+
mock_get.return_value = None
218+
ProviderLogHandler.setup(payload, mock_session, formatter)
219+
mock_session.client.assert_called_once_with("logs")
220+
mock_log.return_value.addHandler.assert_called_once()
221+
mock_set_formatter.assert_called_once_with(formatter)
222+
223+
200224
def test_setup_without_log_group_should_not_set_up(mock_logger, mock_session):
201225
patch_logger = patch(
202226
"cloudformation_cli_python_lib.log_delivery.logging.getLogger",
@@ -387,6 +411,23 @@ def test_setup_existing_hook_logger(setup_patches, mock_session):
387411
mock_log.return_value.addHandler.assert_not_called()
388412

389413

414+
def test_setup_with_hook_formatter(
415+
setup_patches, mock_session, mock_handler_set_formatter
416+
):
417+
_payload, hook_payload, p_logger, p__get_logger, _p__get_hook_logger = setup_patches
418+
(
419+
_p__set_handler_formatter,
420+
p__set_hook_handler_formatter,
421+
) = mock_handler_set_formatter
422+
formatter = logging.Formatter()
423+
with p_logger as mock_log, p__get_logger as mock_get, p__set_hook_handler_formatter as mock_set_formatter: # pylint: disable=C0301 # noqa: B950
424+
mock_get.return_value = None
425+
HookProviderLogHandler.setup(hook_payload, mock_session, formatter)
426+
mock_session.client.assert_called_once_with("logs")
427+
mock_log.return_value.addHandler.assert_called_once()
428+
mock_set_formatter.assert_called_once_with(formatter)
429+
430+
390431
def test_setup_without_hook_log_group_should_not_set_up(mock_logger, mock_session):
391432
patch_logger = patch(
392433
"cloudformation_cli_python_lib.log_delivery.logging.getLogger",

0 commit comments

Comments
 (0)