Skip to content

Use the short error.type name in workflow observability to match other spans and Python#697

Open
PratikDhanave wants to merge 2 commits into
microsoft:mainfrom
PratikDhanaveFork:short-error-type-workflow-observability
Open

Use the short error.type name in workflow observability to match other spans and Python#697
PratikDhanave wants to merge 2 commits into
microsoft:mainfrom
PratikDhanaveFork:short-error-type-workflow-observability

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

What

Workflow observability spans set the error.type and build.error.type attributes using reflect.TypeOf(err).String() at three sites in workflow/internal/observability/observability.go (CaptureError, BuildErrorAttributes, ErrorAttributes). For errors.New that yields *errors.errorString and for fmt.Errorf(...: %w) it yields *fmt.wrapError.

This replaces those calls with otelx.ErrorTypeName(err) (the reflect import is dropped and internal/otelx added). The err == nil guards are unchanged.

Why

Every other error.type site in the repo already uses otelx.ErrorTypeName — see provider/otelprovider/otel.go and agent/harness/toolautocall/autocall.go. ErrorTypeName formats %T and strips through the last dot, producing the short unqualified name (errorString, wrapError), and is documented to match Python's type(exception).__name__.

Before this change the same error.type attribute carried errorString on provider/tool spans but *errors.errorString on workflow spans — an intra-repo inconsistency and a cross-SDK parity break with the Python SDK. This aligns the workflow path with the provider/tool paths and with Python.

Tests

Added workflow/internal/observability/observability_test.go:

  • ErrorAttributes(errors.New("boom")) and BuildErrorAttributes(...) assert the type value equals errorString, not *errors.errorString.
  • A wrapped fmt.Errorf("ctx: %w", ...) asserts wrapError, not *fmt.wrapError.
  • CaptureError is driven through StartWorkflowRun with a fake tracer/span and asserts the captured error.type equals errorString.

go build ./..., go vet ./workflow/internal/observability/..., and go test ./workflow/internal/observability/... all pass; the new tests fail before the fix and pass after.

Copilot AI review requested due to automatic review settings July 24, 2026 02:10
@PratikDhanave
PratikDhanave requested a review from a team as a code owner July 24, 2026 02:10
@PratikDhanave
PratikDhanave force-pushed the short-error-type-workflow-observability branch from 3c66382 to d1b750a Compare July 24, 2026 02:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns workflow observability span attributes with the rest of the repo (and Python SDK parity) by emitting short, unqualified error.type / build.error.type names via otelx.ErrorTypeName instead of reflect.TypeOf(err).String().

Changes:

  • Replace reflect.TypeOf(err).String() with otelx.ErrorTypeName(err) in workflow CaptureError, BuildErrorAttributes, and ErrorAttributes.
  • Drop the reflect import and add internal/otelx dependency for workflow observability.
  • Add unit tests covering short type names for ErrorAttributes, BuildErrorAttributes, and CaptureError via StartWorkflowRun using a fake tracer/span.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
workflow/internal/observability/observability.go Switch workflow error-type attributes to use otelx.ErrorTypeName for consistent short error.type values.
workflow/internal/observability/observability_test.go Add tests asserting short error type names for workflow observability attributes and capture path.
Comments suppressed due to low confidence (1)

workflow/internal/observability/observability_test.go:53

  • This test asserts the exact stdlib-internal wrapped error type name ("wrapError"), which is not a stable API surface and may change between Go versions. Consider asserting the “short/unqualified” property instead to avoid version-coupled failures.
	wrapped := fmt.Errorf("ctx: %w", errors.New("boom"))
	attrs = observability.BuildErrorAttributes(wrapped)
	if got := attributeValue(t, attrs, observability.TagBuildErrorType); got != "wrapError" {
		t.Errorf("wrapped build.error.type = %q, want %q", got, "wrapError")
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +36 to +40
wrapped := fmt.Errorf("ctx: %w", errors.New("boom"))
attrs = observability.ErrorAttributes(wrapped)
if got := attributeValue(t, attrs, observability.TagErrorType); got != "wrapError" {
t.Errorf("wrapped error.type = %q, want %q", got, "wrapError")
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 23bbbaf: the wrapped-error cases now assert the observable requirement (a non-empty, unqualified/short type name with no package qualifier) instead of the stdlib-internal wrapError name, so the test won't break across Go releases.

Comment on lines +81 to +82
_, activity := telemetry.StartWorkflowRun(context.Background(), observability.WorkflowMetadata{ID: "wf"})
activity.CaptureError(errors.New("boom"))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 23bbbaf: switched to t.Context() for consistency with provider/otelprovider/otel_test.go.

@github-actions github-actions Bot added the parity-approved Go API consistency review found no parity issues label Jul 24, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

The workflow observability spans set error.type/build.error.type via
reflect.TypeOf(err).String(), yielding qualified names like
*errors.errorString and *fmt.wrapError. Every other error.type site in
the repo (otelprovider, tool auto-call) uses otelx.ErrorTypeName, which
returns the short unqualified name (errorString, wrapError) to match
Python's type(exception).__name__.

Switch the three workflow sites to otelx.ErrorTypeName so the same
attribute is consistent across provider, tool, and workflow spans and
aligned with the Python SDK.
Assert the observable unqualified/short type-name requirement instead of a
stdlib-internal type name (wrapError) that is not a public API, and propagate
a cancellable t.Context() in the CaptureError test.
@PratikDhanave
PratikDhanave force-pushed the short-error-type-workflow-observability branch from 23bbbaf to 5b5fc16 Compare July 24, 2026 09:34
@github-actions

Copy link
Copy Markdown
Contributor

Parity Review: ✅ Approved

This PR only modifies workflow/internal/observability/observability.go (an unexported internal package) and adds a corresponding test file. No exported Go APIs are added, removed, or changed.

Cross-SDK parity: The change explicitly improves parity. It replaces reflect.TypeOf(err).String() (which produced *errors.errorString) with otelx.ErrorTypeName(err) (which produces errorString), aligning the workflow observability path with:

  • Other intra-repo spans (provider/otelprovider/otel.go, agent/harness/toolautocall/autocall.go) that already use otelx.ErrorTypeName
  • Python SDK convention where type(exception).__name__ yields the short unqualified name

No public-api-change label is warranted — this is a pure internal implementation fix. The parity-approved label is correctly present and retained.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

Generated by Go API Consistency Review Agent · 14.7 AIC · ⌖ 5.61 AIC · ⊞ 5.9K ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parity-approved Go API consistency review found no parity issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants