Skip to content

Commit be4814a

Browse files
committed
Propagate tracing in system Nexus request headers
1 parent ff318a5 commit be4814a

16 files changed

Lines changed: 80 additions & 90 deletions

File tree

‎scripts/nex_gen_support.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,21 @@ def memo_to_proto(
167167
return message
168168

169169

170+
def header_from_proto(
171+
proto: common_pb2.Header,
172+
) -> collections.abc.Mapping[str, object]:
173+
return {key: _payload_to_value(value) for key, value in proto.fields.items()}
174+
175+
176+
def header_to_proto(
177+
header: collections.abc.Mapping[str, object],
178+
) -> common_pb2.Header:
179+
message = common_pb2.Header()
180+
for key, value in header.items():
181+
message.fields[key].CopyFrom(_value_to_payload(value))
182+
return message
183+
184+
170185
def duration_from_proto(proto: google.protobuf.duration_pb2.Duration) -> timedelta:
171186
return proto.ToTimedelta()
172187

‎temporalio/contrib/opentelemetry/_interceptor.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -833,11 +833,13 @@ async def start_nexus_operation(
833833
async def start_system_nexus_operation(
834834
self, input: temporalio.worker.StartSystemNexusOperationInput[Any, Any]
835835
) -> temporalio.workflow.NexusOperationHandle[Any]:
836-
self.root._completed_span(
837-
f"StartNexusOperation:{input.service}/{input.operation_name}",
838-
kind=opentelemetry.trace.SpanKind.CLIENT,
839-
add_to_outbound=input,
840-
)
836+
if hasattr(input.input, "headers"):
837+
input.input.headers = input.input.headers or {}
838+
self.root._completed_span(
839+
f"StartNexusOperation:{input.service}/{input.operation_name}",
840+
kind=opentelemetry.trace.SpanKind.CLIENT,
841+
add_to_outbound=cast(_InputWithHeaders, input.input),
842+
)
841843
return await super().start_system_nexus_operation(input)
842844

843845

‎temporalio/contrib/opentelemetry/_otel_interceptor.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,5 +608,6 @@ async def start_system_nexus_operation(
608608
f"StartNexusOperation:{input.service}/{input.operation_name}",
609609
kind=opentelemetry.trace.SpanKind.CLIENT,
610610
):
611-
input.headers = _context_to_headers(input.headers)
611+
if hasattr(input.input, "headers"):
612+
input.input.headers = _context_to_headers(input.input.headers or {})
612613
return await super().start_system_nexus_operation(input)

‎temporalio/converter/_payload_converter.py‎

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -613,26 +613,14 @@ def wrap(payload_converter: PayloadConverter) -> PayloadConverter:
613613
return _TemporalTransferTypePayloadConverter(payload_converter)
614614

615615
def to_payloads(
616-
self,
617-
values: Sequence[Any],
618-
headers: Mapping[str, temporalio.api.common.v1.Payload] | None = None,
616+
self, values: Sequence[Any]
619617
) -> list[temporalio.api.common.v1.Payload]:
620618
"""See base class."""
621619
transfer_type_values: list[Any] = []
622620
for value in values:
623621
converter = _get_transfer_type_converter(type(value))
624622
if converter is not None:
625623
value = converter.to_transfer_type(value)
626-
if (
627-
headers
628-
and isinstance(value, google.protobuf.message.Message)
629-
and "header" in value.DESCRIPTOR.fields_by_name
630-
):
631-
# System Nexus starts with generated models, so headers can only be
632-
# applied after conversion to a request protobuf and before encoding.
633-
temporalio.common._apply_headers(
634-
headers, getattr(value, "header").fields
635-
)
636624
transfer_type_values.append(value)
637625
return self._inner_payload_converter.to_payloads(transfer_type_values)
638626

‎temporalio/nexus/system/__init__.py‎

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import contextlib
1010
import contextvars
11-
from collections.abc import Iterator, Mapping, Sequence
11+
from collections.abc import Iterator, Sequence
1212
from dataclasses import dataclass
1313
from typing import Any
1414

@@ -91,31 +91,28 @@ class _SystemNexusPayloadConverter(temporalio.converter.PayloadConverter):
9191
"""Payload converter for system Nexus outer envelopes."""
9292

9393
_user_converters: _SystemNexusUserConverters
94-
_outer_payload_converter: _TemporalTransferTypePayloadConverter
95-
_headers: Mapping[str, temporalio.api.common.v1.Payload] | None
94+
_outer_payload_converter: temporalio.converter.PayloadConverter
9695

9796
def __init__(
9897
self,
9998
user_payload_converter: temporalio.converter.PayloadConverter,
10099
user_failure_converter: temporalio.converter.FailureConverter,
101-
headers: Mapping[str, temporalio.api.common.v1.Payload] | None = None,
102100
) -> None:
103101
"""Create a payload converter for system Nexus outer envelopes."""
104102
self._user_converters = _SystemNexusUserConverters(
105103
user_payload_converter, user_failure_converter
106104
)
107105

108-
self._outer_payload_converter = _TemporalTransferTypePayloadConverter(
106+
self._outer_payload_converter = _TemporalTransferTypePayloadConverter.wrap(
109107
_SystemNexusOuterPayloadConverter()
110108
)
111-
self._headers = headers
112109

113110
def to_payloads(
114111
self, values: Sequence[Any]
115112
) -> list[temporalio.api.common.v1.Payload]:
116113
"""See base class."""
117114
with _user_converter_context(self._user_converters):
118-
return self._outer_payload_converter.to_payloads(values, self._headers)
115+
return self._outer_payload_converter.to_payloads(values)
119116

120117
def from_payloads(
121118
self,
@@ -167,12 +164,9 @@ async def maybe_visit_payload(
167164
def _get_payload_converter( # pyright: ignore[reportUnusedFunction]
168165
user_payload_converter: temporalio.converter.PayloadConverter,
169166
user_failure_converter: temporalio.converter.FailureConverter,
170-
headers: Mapping[str, temporalio.api.common.v1.Payload] | None = None,
171167
) -> temporalio.converter.PayloadConverter:
172168
"""Return the fixed payload converter for system Nexus outer envelopes."""
173-
return _SystemNexusPayloadConverter(
174-
user_payload_converter, user_failure_converter, headers
175-
)
169+
return _SystemNexusPayloadConverter(user_payload_converter, user_failure_converter)
176170

177171

178172
def _get_serialization_context( # pyright: ignore[reportUnusedFunction]

‎temporalio/nexus/system/workflow_service/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by nex-gen. DO NOT EDIT!
1+
# Generated by nexgen. DO NOT EDIT!
22

33
from __future__ import annotations
44

‎temporalio/nexus/system/workflow_service/_support/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by nex-gen. DO NOT EDIT!
1+
# Generated by nexgen. DO NOT EDIT!
22

33
from __future__ import annotations
44

‎temporalio/nexus/system/workflow_service/_support/nex_gen_support.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,21 @@ def memo_to_proto(
167167
return message
168168

169169

170+
def header_from_proto(
171+
proto: common_pb2.Header,
172+
) -> collections.abc.Mapping[str, object]:
173+
return {key: _payload_to_value(value) for key, value in proto.fields.items()}
174+
175+
176+
def header_to_proto(
177+
header: collections.abc.Mapping[str, object],
178+
) -> common_pb2.Header:
179+
message = common_pb2.Header()
180+
for key, value in header.items():
181+
message.fields[key].CopyFrom(_value_to_payload(value))
182+
return message
183+
184+
170185
def duration_from_proto(proto: google.protobuf.duration_pb2.Duration) -> timedelta:
171186
return proto.ToTimedelta()
172187

‎temporalio/nexus/system/workflow_service/models.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by nex-gen. DO NOT EDIT!
1+
# Generated by nexgen. DO NOT EDIT!
22

33
from __future__ import annotations
44

@@ -17,6 +17,8 @@
1717
from ._support import (
1818
duration_from_proto,
1919
duration_to_proto,
20+
header_from_proto,
21+
header_to_proto,
2022
memo_from_proto,
2123
memo_to_proto,
2224
payload_from_proto,
@@ -133,6 +135,9 @@ def from_transfer_type(
133135
if proto.HasField("user_metadata")
134136
else None,
135137
namespace=proto.namespace,
138+
headers=header_from_proto(proto.header)
139+
if proto.HasField("header")
140+
else None,
136141
)
137142

138143
@typing_extensions.override
@@ -191,6 +196,8 @@ def to_transfer_type(
191196
)
192197
)
193198
message.namespace = value.namespace
199+
if value.headers is not None:
200+
message.header.CopyFrom(header_to_proto(value.headers))
194201
return message
195202

196203

@@ -226,6 +233,7 @@ class SignalWithStartWorkflowRequest:
226233
start_delay: datetime.timedelta | None = None
227234
user_metadata: UserMetadata | None = None
228235
namespace: str = dataclasses.field(default_factory=workflow_namespace)
236+
headers: collections.abc.Mapping[str, typing.Any] | None = None
229237

230238

231239
class _UserMetadataTransferTypeConverter(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# Generated by nex-gen. DO NOT EDIT!
1+
# Generated by nexgen. DO NOT EDIT!
22

33
from __future__ import annotations

0 commit comments

Comments
 (0)