Skip to content

feat: make it user configurable to display plans as tree renderer #1627

Open

Description

@milenkovicm

Is your feature request related to a problem or challenge? Please describe what you are trying to do.

job REST endpoint returns plans as single line per node:

curl -sv http://localhost:50050/api/job/8Am4heu |jq

{
  "job_id": "8Am4heu",
  "job_name": "",
  "job_status": "Completed. Produced 1 partition containing 1 row. Elapsed time: 13125 ms.",
  "status": "Completed",
  "num_stages": 1,
  "completed_stages": 1,
  "percent_complete": 100,
  "start_time": 1777541048696,
  "end_time": 1777541061821,
  "logical_plan": "Projection: Int64(1)\n  EmptyRelation: rows=1",
  "physical_plan": "ProjectionExec: expr=[1 as Int64(1)]\n  PlaceholderRowExec\n",
  "stage_plan": "ExecutionGraph[job_id=8Am4heu, session_id=32ab0721-562a-47fa-a420-7dcc24e59f91, available_tasks=0, is_successful=true]\n=========SuccessfulStage[stage_id=1.0, partitions=1]=========\nShuffleWriterExec: partitioning: None, metrics=[output_rows=1, input_rows=1, repart_time=1ns, write_time=1.67ms]\n  ProjectionExec: expr=[1 as Int64(1)], metrics=[output_rows=1, elapsed_compute=296.83µs, output_bytes=8.0 B, output_batches=1, expr_0_eval_time=168.71µs]\n    PlaceholderRowExec, metrics=[]\n"
}

Describe the solution you'd like

make it user configurable to return plans as tree renderer

displayable(running_stage.plan.as_ref()).indent(false).to_string()) -> displayable(running_stage.plan.as_ref()).tree_render() .to_string())

Describe alternatives you've considered

Additional context

Activity

  1. milenkovicm commented on Apr 30, 2026

    @milenkovicm
    ContributorAuthor

    cc @sandugood if you're interested

  2. sandugood commented on Apr 30, 2026

    @sandugood
    Contributor

    take

  3. milenkovicm commented on Apr 30, 2026

    @milenkovicm
    ContributorAuthor

    Cc @martin-g i guess it should not make problems on TUI

  4. martin-g commented on Apr 30, 2026

    @martin-g
    Member

    make it user configurable to return plans as tree renderer

    with a query parameter ?!

  5. sandugood commented on Apr 30, 2026

    @sandugood
    Contributor

    make it user configurable to return plans as tree renderer

    with a query parameter ?!

    I think query parameter seems good for this
    something like:
    api/job/8Am4heu?plan_format=tree

  6. milenkovicm commented on Apr 30, 2026

    @milenkovicm
    ContributorAuthor

    I have no preference, query parameter looks like good option. You have other preference?

  7. milenkovicm commented on Apr 30, 2026

    @milenkovicm
    ContributorAuthor

    Cc @danielhumanmod now we have explain and analyse maybe we could support tree renderer there as well?

  8. danielhumanmod commented on May 1, 2026

    @danielhumanmod
    Contributor

    Cc @danielhumanmod now we have explain and analyse maybe we could support tree renderer there as well?

    Yeah, that sounds like a good improvement.

    One thing I am thinking is how users should request the tree format for EXPLAIN / EXPLAIN ANALYZE.

    One option is to extend the SQL syntax, for example:

    EXPLAIN (FORMAT TREE) SELECT ...
    EXPLAIN ANALYZE (FORMAT TREE) SELECT ...

    Another option is to use a session config:

    let config = SessionConfig::new_with_ballista()
        .set_str("ballista.explain.plan_format", "tree")...
    
    or from SQL:
    
    SET ballista.explain.plan_format = 'tree';
    

    The first option seems nicer from a user-facing SQL perspective, while the second one may be smaller to introduce on the Ballista side. I’d be curious what the community prefers here.

  9. milenkovicm commented on May 1, 2026

    @milenkovicm
    ContributorAuthor

    @danielhumanmod current datafusion behaviour

    > explain format indent select 1;
    +---------------+--------------------------------------+
    | plan_type     | plan                                 |
    +---------------+--------------------------------------+
    | logical_plan  | Projection: Int64(1)                 |
    |               |   EmptyRelation: rows=1              |
    | physical_plan | ProjectionExec: expr=[1 as Int64(1)] |
    |               |   PlaceholderRowExec                 |
    |               |                                      |
    +---------------+--------------------------------------+
    2 row(s) fetched.
    Elapsed 0.003 seconds.
    
    > explain select 1;
    +---------------+-------------------------------+
    | plan_type     | plan                          |
    +---------------+-------------------------------+
    | physical_plan | ┌───────────────────────────┐ |
    |               | │       ProjectionExec      │ |
    |               | │    --------------------   │ |
    |               | │        Int64(1): 1        │ |
    |               | └─────────────┬─────────────┘ |
    |               | ┌─────────────┴─────────────┐ |
    |               | │     PlaceholderRowExec    │ |
    |               | └───────────────────────────┘ |
    |               |                               |
    +---------------+-------------------------------+
    

    https://datafusion.apache.org/user-guide/sql/explain.html

  10. danielhumanmod commented on May 1, 2026

    @danielhumanmod
    Contributor

    @danielhumanmod current datafusion behaviour

    > explain format indent select 1;
    +---------------+--------------------------------------+
    | plan_type     | plan                                 |
    +---------------+--------------------------------------+
    | logical_plan  | Projection: Int64(1)                 |
    |               |   EmptyRelation: rows=1              |
    | physical_plan | ProjectionExec: expr=[1 as Int64(1)] |
    |               |   PlaceholderRowExec                 |
    |               |                                      |
    +---------------+--------------------------------------+
    2 row(s) fetched.
    Elapsed 0.003 seconds.
    
    > explain select 1;
    +---------------+-------------------------------+
    | plan_type     | plan                          |
    +---------------+-------------------------------+
    | physical_plan | ┌───────────────────────────┐ |
    |               | │       ProjectionExec      │ |
    |               | │    --------------------   │ |
    |               | │        Int64(1): 1        │ |
    |               | └─────────────┬─────────────┘ |
    |               | ┌─────────────┴─────────────┐ |
    |               | │     PlaceholderRowExec    │ |
    |               | └───────────────────────────┘ |
    |               |                               |
    +---------------+-------------------------------+
    

    https://datafusion.apache.org/user-guide/sql/explain.html

    thanks for the information, very helpful. Didn't catch this doc at the first place🙏

  11. danielhumanmod commented on May 3, 2026

    @danielhumanmod
    Contributor

    Hey @milenkovicm when I was working on this, I realize that DF side missed the proto support for format field, we can adopt some workaround on our end, but maybe add support on DF will be better in the long run. Make a draft PR for this apache/datafusion#21994, appreciate if you could take a look when you have time, thanks!

  12. milenkovicm commented on May 11, 2026

    @milenkovicm
    ContributorAuthor

    apache/datafusion#21768 more things coming to EXPLAIN cc @danielhumanmod

  13. martin-g commented on May 18, 2026

    @martin-g
    Member

    Is there anything more to be done here ?

  14. milenkovicm commented on May 18, 2026

    @milenkovicm
    ContributorAuthor

    Yes, there is part needed on plans which can't be done before df 54

  15. adriangb commented on May 28, 2026

    @adriangb

    I think now that we cut the release branch we can make some breaking changes to the proto if needed?

  16. milenkovicm commented on May 28, 2026

    @milenkovicm
    ContributorAuthor

    please do @adriangb, its related to #21768 , is it ?

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions