Skip to content

Commit 2d556bb

Browse files
harsh543claude
andcommitted
test: parameterize activity logging tests, revert unrelated README changes
- Merge test_activity_logging and test_activity_logging_flatten_mode into a single pytest-parameterized test covering dict and flatten modes - Revert README import path changes that were unrelated to this PR Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 2307d25 commit 2d556bb

File tree

2 files changed

+39
-67
lines changed

2 files changed

+39
-67
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ from temporalio import workflow
164164

165165
# Import our activity, passing it through the sandbox
166166
with workflow.unsafe.imports_passed_through():
167-
from activities import say_hello
167+
from .activities import say_hello
168168

169169
@workflow.defn
170170
class SayHello:
@@ -184,8 +184,8 @@ from temporalio.client import Client
184184
from temporalio.worker import Worker
185185

186186
# Import the activity and workflow from our other files
187-
from activities import say_hello
188-
from workflows import SayHello
187+
from .activities import say_hello
188+
from .workflows import SayHello
189189

190190
async def main():
191191
# Create client connected to server at the given address
@@ -220,7 +220,7 @@ import asyncio
220220
from temporalio.client import Client
221221

222222
# Import the workflow from the previous code
223-
from workflows import SayHello
223+
from .workflows import SayHello
224224

225225
async def main():
226226
# Create client connected to server at the given address

tests/worker/test_activity.py

Lines changed: 35 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,91 +1008,63 @@ async def some_activity():
10081008
)
10091009

10101010

1011+
@pytest.mark.parametrize("temporal_extra_mode", ["dict", "flatten"])
10111012
async def test_activity_logging(
10121013
client: Client,
10131014
worker: ExternalWorker,
10141015
shared_state_manager: SharedStateManager,
1016+
temporal_extra_mode: str,
10151017
):
1016-
@activity.defn
1017-
async def say_hello(name: str) -> str:
1018-
activity.logger.info(f"Called with arg: {name}")
1019-
return f"Hello, {name}!"
1020-
1021-
# Create a queue, add handler to logger, call normal activity, then check
1022-
handler = logging.handlers.QueueHandler(queue.Queue())
1023-
with LogHandler.apply(activity.logger.base_logger, handler):
1024-
activity.logger.base_logger.setLevel(logging.INFO)
1025-
result = await _execute_workflow_with_activity(
1026-
client,
1027-
worker,
1028-
say_hello,
1029-
"Temporal",
1030-
shared_state_manager=shared_state_manager,
1031-
)
1032-
assert result.result == "Hello, Temporal!"
1033-
records: list[logging.LogRecord] = list(handler.queue.queue) # type: ignore
1034-
assert len(records) > 0
1035-
assert records[-1].message.startswith(
1036-
"Called with arg: Temporal ({'activity_id': '"
1037-
)
1038-
assert records[-1].__dict__["temporal_activity"]["activity_type"] == "say_hello"
1039-
1040-
1041-
async def test_activity_logging_flatten_mode(
1042-
client: Client,
1043-
worker: ExternalWorker,
1044-
shared_state_manager: SharedStateManager,
1045-
):
1046-
"""Test that activity logger flatten mode produces OTel-safe scalar attributes."""
1018+
"""Test that activity logger produces correct log records for each extra mode."""
10471019

10481020
@activity.defn
1049-
async def say_hello_flatten(name: str) -> str:
1021+
async def say_hello(name: str) -> str:
10501022
activity.logger.info(f"Called with arg: {name}")
10511023
return f"Hello, {name}!"
10521024

10531025
original_mode = activity.logger.temporal_extra_mode
1054-
activity.logger.temporal_extra_mode = "flatten"
1026+
activity.logger.temporal_extra_mode = temporal_extra_mode
10551027

10561028
handler = logging.handlers.QueueHandler(queue.Queue())
1057-
activity.logger.base_logger.addHandler(handler)
1058-
prev_level = activity.logger.base_logger.level
1059-
activity.logger.base_logger.setLevel(logging.INFO)
10601029
try:
1061-
result = await _execute_workflow_with_activity(
1062-
client,
1063-
worker,
1064-
say_hello_flatten,
1065-
"Temporal",
1066-
shared_state_manager=shared_state_manager,
1067-
)
1030+
with LogHandler.apply(activity.logger.base_logger, handler):
1031+
activity.logger.base_logger.setLevel(logging.INFO)
1032+
result = await _execute_workflow_with_activity(
1033+
client,
1034+
worker,
1035+
say_hello,
1036+
"Temporal",
1037+
shared_state_manager=shared_state_manager,
1038+
)
10681039
finally:
1069-
activity.logger.base_logger.removeHandler(handler)
1070-
activity.logger.base_logger.setLevel(prev_level)
10711040
activity.logger.temporal_extra_mode = original_mode
10721041

10731042
assert result.result == "Hello, Temporal!"
10741043
records: list[logging.LogRecord] = list(handler.queue.queue) # type: ignore
10751044
assert len(records) > 0
10761045
record = records[-1]
10771046

1078-
# Should NOT have nested dict
1079-
assert "temporal_activity" not in record.__dict__
1080-
1081-
# Should have flattened keys with temporal.activity prefix
1082-
assert record.__dict__["temporal.activity.activity_type"] == "say_hello_flatten"
1083-
assert "temporal.activity.activity_id" in record.__dict__
1084-
assert "temporal.activity.workflow_id" in record.__dict__
1085-
assert "temporal.activity.workflow_run_id" in record.__dict__
1086-
assert "temporal.activity.namespace" in record.__dict__
1087-
assert "temporal.activity.task_queue" in record.__dict__
1088-
assert record.__dict__["temporal.activity.attempt"] == 1
1089-
1090-
# Verify all temporal.activity.* values are primitives (OTel-safe)
1091-
for key, value in record.__dict__.items():
1092-
if key.startswith("temporal.activity."):
1093-
assert isinstance(
1094-
value, (str, int, float, bool, type(None))
1095-
), f"Key {key} has non-primitive value: {type(value)}"
1047+
if temporal_extra_mode == "dict":
1048+
# Dict mode appends context to message and uses nested dict
1049+
assert record.message.startswith("Called with arg: Temporal ({'activity_id': '")
1050+
assert record.__dict__["temporal_activity"]["activity_type"] == "say_hello"
1051+
else:
1052+
# Flatten mode uses OTel-safe scalar attributes
1053+
assert "temporal_activity" not in record.__dict__
1054+
assert record.__dict__["temporal.activity.activity_type"] == "say_hello"
1055+
assert "temporal.activity.activity_id" in record.__dict__
1056+
assert "temporal.activity.workflow_id" in record.__dict__
1057+
assert "temporal.activity.workflow_run_id" in record.__dict__
1058+
assert "temporal.activity.namespace" in record.__dict__
1059+
assert "temporal.activity.task_queue" in record.__dict__
1060+
assert record.__dict__["temporal.activity.attempt"] == 1
1061+
1062+
# Verify all temporal.activity.* values are primitives (OTel-safe)
1063+
for key, value in record.__dict__.items():
1064+
if key.startswith("temporal.activity."):
1065+
assert isinstance(
1066+
value, (str, int, float, bool, type(None))
1067+
), f"Key {key} has non-primitive value: {type(value)}"
10961068

10971069

10981070
async def test_activity_worker_shutdown(

0 commit comments

Comments
 (0)