feat(telemetry): attach called platform APIs to their step node on execution traces

Every host step now opens a stage scope, so observations recorded inside it (including cross-task plugin/RPC calls resolved through the execution registry) carry the owning step as parent; the pipeline lane records its own pipeline/run node so acks and replies issued outside the runner still hang off a node.
This commit is contained in:
Hyu
2026-10-01 18:10:42 +08:00
parent df64f83e12
commit 923ebe12af
12 changed files with 1798 additions and 489 deletions
+24 -2
View File
@@ -11,6 +11,21 @@ from .execution import record
processing_mode: ContextVar[str] = ContextVar('telemetry_processing_mode', default='none')
def result_failure_detail(result) -> str:
"""Pull a bounded human-readable reason out of a failed platform API result."""
raw = getattr(result, 'raw', result)
if isinstance(raw, dict):
for key in ('error', 'message', 'msg', 'detail', 'reason'):
value = raw.get(key)
if isinstance(value, str) and value.strip():
return value
if isinstance(value, dict):
for inner in ('message', 'msg', 'detail'):
if isinstance(value.get(inner), str) and value[inner].strip():
return value[inner]
return ''
def result_outcome(result):
# Empty returns do not prove a remote operation succeeded.
if result is None:
@@ -69,18 +84,24 @@ def observe_adapter(ap, context, adapter):
if action in declared:
observed_operation = action
outcome = 'unknown'
error_detail = ''
try:
result = await method(*args, **kwargs)
outcome = result_outcome(result)
if outcome != 'success':
error_detail = result_failure_detail(result)
return result
except asyncio.CancelledError:
outcome = 'cancelled'
error_detail = 'cancelled'
raise
except TimeoutError:
except TimeoutError as exc:
outcome = 'timeout'
error_detail = str(exc) or 'timeout'
raise
except Exception:
except Exception as exc:
outcome = 'failed'
error_detail = str(exc)
raise
finally:
record(
@@ -91,6 +112,7 @@ def observe_adapter(ap, context, adapter):
adapter=adapter.__class__.__name__,
mode=processing_mode.get(),
outcome=outcome,
error=error_detail,
)
return wrapped