Skip to content

feat: Task Hierarchy#102

Merged
monoxgas merged 3 commits into
mainfrom
feat/task-hierarchy
Jul 16, 2025
Merged

feat: Task Hierarchy#102
monoxgas merged 3 commits into
mainfrom
feat/task-hierarchy

Conversation

@monoxgas
Copy link
Copy Markdown
Contributor

@monoxgas monoxgas commented Jul 14, 2025

Key Changes:

  • Add task hierarchy and relationship tracking to span objects
  • Implement repr and str methods on span objects
  • Add navigation properties for parent/child task relationships

Added:

  • Task hierarchy properties: tasks, all_tasks, parent_task
  • Run-level task tracking with run.tasks and run.all_tasks
  • String representation methods for all span classes
  • .failed property to check span error status
  • Helper function _format_status for consistent status display

Changed:

  • Task span initialization now establishes parent-child relationships
  • Documentation updated to showcase new hierarchy features
  • Context management improved to maintain task relationships

Generated Summary:

  • Added a new section on "Task Hierarchy and Relationships" in both the runs.mdx and tasks.mdx documentation files.
  • Introduced code examples demonstrating how to manage and access tasks at different levels within a run and task context.
  • Implemented properties in the RunSpan and TaskSpan classes:
    • tasks: List of child tasks associated with a run or task.
    • all_tasks: Flattened list of all tasks, including subtasks, for comprehensive analysis.
    • parent_task: Reference to the parent task of a given task.
  • Enhanced the string representation (__repr__ and __str__) of the Span, RunSpan, and TaskSpan classes for better debugging and logging.
  • These changes provide improved visibility into task management, supporting clearer execution structures and potential performance analysis.
  • Helps users leverage task hierarchies in complex workflows, which may enhance debugging and task monitoring capabilities.

This summary was generated with ❤️ by rigging

@monoxgas monoxgas requested a review from Copilot July 14, 2025 04:31
@dreadnode-renovate-bot dreadnode-renovate-bot Bot added area/docs Changes to documentation and guides type/docs Documentation updates and improvements labels Jul 14, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds hierarchical tracking and representation features to span objects, enabling parent-child task relationships, run-level task aggregation, and improved debugging output.

  • Introduce tasks, all_tasks, and parent_task properties on RunSpan and TaskSpan for hierarchy navigation.
  • Implement __repr__, __str__, and a .failed property along with a _format_status helper for consistent span status formatting.
  • Update documentation in tasks.mdx and runs.mdx to illustrate the new hierarchy and usage patterns.

Reviewed Changes

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

File Description
dreadnode/tracing/span.py Added hierarchy properties, __repr__/__str__, status helper, and parent-child setup logic
docs/usage/tasks.mdx Added a section and examples for task hierarchy and relationships
docs/usage/runs.mdx Added a section and examples for run-level task hierarchy
Comments suppressed due to low confidence (1)

dreadnode/tracing/span.py:87

  • The new _format_status helper covers multiple branches (error with/without description and ok). Consider adding unit tests to verify each formatting path.
def _format_status(status: Status) -> str:

Comment thread dreadnode/tracing/span.py
def __repr__(self) -> str:
return (
f"{self.__class__.__name__}(name='{self._span_name}', id={self.span_id},"
f"label='{self._label}', status={_format_status(self.status)}, active={self.is_recording})"
Copy link

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

In __repr__, active references the is_recording method instead of calling it, so it prints a method object. Change self.is_recording to self.is_recording() to show the actual boolean status.

Suggested change
f"label='{self._label}', status={_format_status(self.status)}, active={self.is_recording})"
f"label='{self._label}', status={_format_status(self.status)}, active={self.is_recording()})"

Copilot uses AI. Check for mistakes.
Comment thread dreadnode/tracing/span.py
super().__init__(f"run.{run_id}.update", attributes, tracer, type="run_update")

def __repr__(self) -> str:
status = "active" if self.is_recording else "inactive"
Copy link

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

Here self.is_recording is a method, not a boolean property. Use self.is_recording() to correctly evaluate whether recording is active.

Copilot uses AI. Check for mistakes.
Comment thread dreadnode/tracing/span.py
num_objects = len(self._objects)
return (
f"RunSpan(name='{self._span_name}', id='{run_id}', "
f"project='{project}', status={_format_status(self.status)}, active={self.is_recording}, "
Copy link

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

Similar to above, active is using the is_recording method reference. It should be self.is_recording() to display the boolean state.

Suggested change
f"project='{project}', status={_format_status(self.status)}, active={self.is_recording}, "
f"project='{project}', status={_format_status(self.status)}, active={self.is_recording()}, "

Copilot uses AI. Check for mistakes.
Comment thread dreadnode/tracing/span.py
parent_info = f", parent_task='{parent_task_id}'" if parent_task_id else ""
return (
f"TaskSpan(name='{self._span_name}', label='{self._label}', "
f"run='{run_id}'{parent_info}, status={_format_status(self.status)}, active={self.is_recording}, "
Copy link

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

The active field is referencing the is_recording method rather than calling it, so it won't show the actual recording status. Update to self.is_recording().

Suggested change
f"run='{run_id}'{parent_info}, status={_format_status(self.status)}, active={self.is_recording}, "
f"run='{run_id}'{parent_info}, status={_format_status(self.status)}, active={self.is_recording()}, "

Copilot uses AI. Check for mistakes.
Comment thread dreadnode/tracing/span.py
return self._tasks

@property
def all_tasks(self) -> "list[TaskSpan[t.Any]]":
Copy link

Copilot AI Jul 14, 2025

Choose a reason for hiding this comment

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

[nitpick] The all_tasks recursion is duplicated in both RunSpan and TaskSpan. Extracting this logic into a shared utility or base class method would reduce duplication and ease future maintenance.

Copilot uses AI. Check for mistakes.
@monoxgas monoxgas merged commit b45cab2 into main Jul 16, 2025
8 checks passed
@monoxgas monoxgas deleted the feat/task-hierarchy branch July 16, 2025 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs Changes to documentation and guides type/docs Documentation updates and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants