From 481ca7c6d0843a20eb155f75aba2ea875456dc03 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 25 Mar 2025 11:53:13 -0400 Subject: [PATCH 1/6] Evolve observability documentation --- README.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d5355c981..5bccb7786 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ informal introduction to the features and their implementation. - [Worker Shutdown](#worker-shutdown) - [Testing](#testing-1) - [Workflow Replay](#workflow-replay) - - [OpenTelemetry Support](#opentelemetry-support) + - [Observability](#observability) - [Protobuf 3.x vs 4.x](#protobuf-3x-vs-4x) - [Known Compatibility Issues](#known-compatibility-issues) - [gevent Patching](#gevent-patching) @@ -1344,10 +1344,31 @@ async def check_past_histories(my_client: Client): ) ``` -### OpenTelemetry Support +### Observability -OpenTelemetry support requires the optional `opentelemetry` dependencies which are part of the `opentelemetry` extra. -When using `pip`, running +See https://github.com/temporalio/samples-python/tree/main/open_telemetry for a sample demonstrating collection of +metrics and tracing data emitted by the SDK. + +#### Metrics + +The SDK emits various metrics by default: see https://docs.temporal.io/references/sdk-metrics. By default, these are +emitted with attributes `namespace`, `task_queue`, `workflow_type` / `activity_type`, and +`service_name=temporal-core-sdk`. To emit additional attributes with all metrics, pass +[global_tags](https://python.temporal.io/temporalio.runtime.TelemetryConfig.html#global_tags) when creating the +[TelemetryConfig](https://python.temporal.io/temporalio.runtime.TelemetryConfig.html). + +For emitting custom metrics, the SDK makes a metric meter available: +- In Workflow code, use https://python.temporal.io/temporalio.workflow.html#metric_meter +- In Activity code, use https://python.temporal.io/temporalio.activity.html#metric_meter +- In normal application code, use https://python.temporal.io/temporalio.runtime.Runtime.html#metric_meter + +The attributes emitted by these default to `namespace`, `task_queue`, and `workflow_type`/`activity_type`; use +`with_additional_attributes` to create a meter emitting additional attributes. + +#### Tracing + +Tracing support requires the optional `opentelemetry` dependencies which are part of the `opentelemetry` extra. When +using `pip`, running pip install 'temporalio[opentelemetry]' From 2c634565d8452e85322bd47176e5a5a44ec63d3d Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 25 Mar 2025 12:35:21 -0400 Subject: [PATCH 2/6] Code review suggestions --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5bccb7786..6f4082eb3 100644 --- a/README.md +++ b/README.md @@ -1351,9 +1351,8 @@ metrics and tracing data emitted by the SDK. #### Metrics -The SDK emits various metrics by default: see https://docs.temporal.io/references/sdk-metrics. By default, these are -emitted with attributes `namespace`, `task_queue`, `workflow_type` / `activity_type`, and -`service_name=temporal-core-sdk`. To emit additional attributes with all metrics, pass +The SDK emits various metrics by default: see https://docs.temporal.io/references/sdk-metrics. To configure additional +attributes to be emitted with all metrics, pass [global_tags](https://python.temporal.io/temporalio.runtime.TelemetryConfig.html#global_tags) when creating the [TelemetryConfig](https://python.temporal.io/temporalio.runtime.TelemetryConfig.html). @@ -1365,7 +1364,7 @@ For emitting custom metrics, the SDK makes a metric meter available: The attributes emitted by these default to `namespace`, `task_queue`, and `workflow_type`/`activity_type`; use `with_additional_attributes` to create a meter emitting additional attributes. -#### Tracing +#### OpenTelemetry Tracing Tracing support requires the optional `opentelemetry` dependencies which are part of the `opentelemetry` extra. When using `pip`, running From b636d3af56c349464c508eb794570bedb88a1093 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 25 Mar 2025 14:57:07 -0400 Subject: [PATCH 3/6] npx doctoc README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6f4082eb3..58e775da1 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,8 @@ informal introduction to the features and their implementation. - [Testing](#testing-1) - [Workflow Replay](#workflow-replay) - [Observability](#observability) + - [Metrics](#metrics) + - [OpenTelemetry Tracing](#opentelemetry-tracing) - [Protobuf 3.x vs 4.x](#protobuf-3x-vs-4x) - [Known Compatibility Issues](#known-compatibility-issues) - [gevent Patching](#gevent-patching) From 832e30d3108f29609856457fafdfbaf3294b0c54 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Wed, 26 Mar 2025 08:30:36 -0400 Subject: [PATCH 4/6] Use features@main --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd7dd2c1e..2b079e60b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,9 +109,8 @@ jobs: # Runs the sdk features repo tests with this repo's current SDK code features-tests: - uses: temporalio/features/.github/workflows/python.yaml@uv + uses: temporalio/features/.github/workflows/python.yaml@main with: python-repo-path: ${{github.event.pull_request.head.repo.full_name}} version: ${{github.event.pull_request.head.ref}} version-is-repo-ref: true - features-repo-ref: uv From 434a3140e489049a7c3b2dd3bf4ceaa2ed056b6b Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Wed, 26 Mar 2025 08:59:28 -0400 Subject: [PATCH 5/6] Update tests to expect uuid version 7 from server --- tests/worker/test_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 665a5393e..2480c3f6e 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -222,7 +222,7 @@ async def test_workflow_info(client: Client, env: WorkflowEnvironment): assert info["retry_policy"] == json.loads( json.dumps(dataclasses.asdict(retry_policy), default=str) ) - assert uuid.UUID(info["run_id"]).version == 4 + assert uuid.UUID(info["run_id"]).version == 7 assert info["run_timeout"] is None datetime.fromisoformat(info["start_time"]) assert info["task_queue"] == worker.task_queue From 5ef02eab21bff56cda05dc96445bd24e3365a743 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Wed, 26 Mar 2025 17:19:33 -0400 Subject: [PATCH 6/6] Skip failing tests https://github.com/temporalio/sdk-java/issues/2459 --- tests/worker/test_activity.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/worker/test_activity.py b/tests/worker/test_activity.py index b17a0650f..e69557c8e 100644 --- a/tests/worker/test_activity.py +++ b/tests/worker/test_activity.py @@ -611,7 +611,12 @@ async def some_activity(param1: SomeClass2, param2: str) -> str: assert activity_param1 == SomeClass2(foo="str1", bar=SomeClass1(foo=123)) -async def test_activity_heartbeat_details(client: Client, worker: ExternalWorker): +async def test_activity_heartbeat_details( + client: Client, worker: ExternalWorker, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip("https://github.com/temporalio/sdk-java/issues/2459") + @activity.defn async def some_activity() -> str: info = activity.info() @@ -698,8 +703,11 @@ def picklable_heartbeat_details_activity() -> str: async def test_sync_activity_thread_heartbeat_details( - client: Client, worker: ExternalWorker + client: Client, worker: ExternalWorker, env: WorkflowEnvironment ): + if env.supports_time_skipping: + pytest.skip("https://github.com/temporalio/sdk-java/issues/2459") + with concurrent.futures.ThreadPoolExecutor( max_workers=default_max_concurrent_activities ) as executor: @@ -714,8 +722,11 @@ async def test_sync_activity_thread_heartbeat_details( async def test_sync_activity_process_heartbeat_details( - client: Client, worker: ExternalWorker + client: Client, worker: ExternalWorker, env: WorkflowEnvironment ): + if env.supports_time_skipping: + pytest.skip("https://github.com/temporalio/sdk-java/issues/2459") + with concurrent.futures.ProcessPoolExecutor() as executor: result = await _execute_workflow_with_activity( client, @@ -1066,8 +1077,14 @@ async def test_activity_async_success( @pytest.mark.parametrize("use_task_token", [True, False]) async def test_activity_async_heartbeat_and_fail( - client: Client, worker: ExternalWorker, use_task_token: bool + client: Client, + worker: ExternalWorker, + env: WorkflowEnvironment, + use_task_token: bool, ): + if env.supports_time_skipping: + pytest.skip("https://github.com/temporalio/sdk-java/issues/2459") + wrapper = AsyncActivityWrapper() # Start task w/ max attempts 2, wait for info, send heartbeat, fail task = asyncio.create_task(