Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement type-based API for progress records #13

Merged
merged 19 commits into from
Feb 7, 2020

Conversation

tkf
Copy link
Collaborator

@tkf tkf commented Jan 27, 2020

close #7

This PR implements add Progress type that holds the progress value (fraction), name, its ID, parent ID, and a flag indicating if the task is finished or not (done):

https://github.com/JunoLab/ProgressLogging.jl/blob/d1e1b0ebd9048227bf1dd76141b851c35cc1c8a4/src/ProgressLogging.jl#L65-L71

This API is based on @c42f's suggestion #7 (comment) and I added Base.print(::IO, ::Progress) method to it. This way, the progress information is somewhat readable even without proper progress monitor:

julia> @info Progress(uuid4(), 0.1)
[ Info: Progress: 10%

There is a bit of machinery in @logprogress to help producing log record that is compatible with both old (untyped) and new (typed) APIs.

Here is an example of nested progress bar handling implemented in TerminalLoggers.jl JuliaLogging/TerminalLoggers.jl#13

Peek 2020-01-26 19-04

@tkf
Copy link
Collaborator Author

tkf commented Jan 27, 2020

I'll add/fix tests once we agree on the API.

@tkf tkf requested a review from pfitzseb January 27, 2020 03:30
@tkf
Copy link
Collaborator Author

tkf commented Jan 27, 2020

@c42f It'd be nice if you can review this, too.

@oxinabox Are you also interested in this?

src/ProgressLogging.jl Outdated Show resolved Hide resolved
src/ProgressLogging.jl Outdated Show resolved Hide resolved
src/ProgressLogging.jl Outdated Show resolved Hide resolved
@tkf
Copy link
Collaborator Author

tkf commented Jan 29, 2020

@oxinabox Thanks for the review! What do you think about Progress struct? In particular, what do you think about fraction = NaN vs fraction = missing? #13 (comment)

Copy link
Member

@c42f c42f left a comment

Choose a reason for hiding this comment

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

This looks pretty great to me. Needs some tests I suppose.

- `id::UUID`: Identifier of the task whose progress is at `fraction`.
- `parentid::UUID`: The ID of the parent progress. It is set to
[`ProgressLogging.ROOTID`](@ref) when there is no parent progress.
This is used for representing progresses of nested tasks. Note that
Copy link
Member

Choose a reason for hiding this comment

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

The word "task" here could be confused with Task. Maybe we should call them "jobs" or some other less overloaded term?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I use words like "sub-tasks", "child tasks" and "parent task" just after this line. Do "sub-jobs", "child jobs" and "parent job" sound OK?

src/ProgressLogging.jl Outdated Show resolved Hide resolved
src/ProgressLogging.jl Outdated Show resolved Hide resolved
src/ProgressLogging.jl Outdated Show resolved Hide resolved
# To pass `Progress` value without breaking progress monitors with the
# previous `progress` key based specification, we create an abstract
# string type that has `Progress` attached to it. This is used as the
# third argument `message` of `Logging.handle_message`.
Copy link
Member

Choose a reason for hiding this comment

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

Clever! Would the plan be to remove this and just use bare Progress in the future?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think @pfitzseb wants to keep the original open/untyped API. I'm OK for keeping this as long as this compatible layer becomes annoying hard to maintain. ProgressString is somewhat already "too clever" but maybe it's within an OK range.

src/ProgressLogging.jl Show resolved Hide resolved
msgexpr = :($ProgressString($_asprogress(
$name,
$id_tmp,
$_parentid_var;
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I followed everything which was going on with interpolation and macro hygiene here!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think I had a trouble when using a macro inside a macro. I tend to give up fighting hygiene and escape the whole block when it happens. I'll see if I can avoid this after writing tests.

Copy link
Member

Choose a reason for hiding this comment

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

If you can make it neater by all means that would be great.

But I agree that sometimes manual escaping is just easier 😞

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So, I tried to avoid interpolation but it didn't work. Here is a MWE:

julia> macro f(x)
           esc(:($Base.@isdefined $x))
       end
@f (macro with 1 method)

julia> macro g(x)
           :(@isdefined $(esc(x)))
       end
@g (macro with 1 method)

julia> let a = 1
           @f a
       end
true

julia> let a = 1
           @g a
       end
ERROR: LoadError: MethodError: no method matching @isdefined(::LineNumberNode, ::Module, ::Expr)
Closest candidates are:
  @isdefined(::LineNumberNode, ::Module, ::Symbol) at reflection.jl:265
in expression starting at REPL[26]:2

We could use Expr(:isdefined, var) (or Expr(:islocal, var)) directly like Base is doing:
JuliaLang/julia@4800158#diff-121162110854f09c3be5b39209646009L353

But I prefer sticking with the high-level API @isdefined since Expr(:isdefined, :x) is listed only at lowered AST section: https://docs.julialang.org/en/latest/devdocs/ast/#Lowered-form-1

Copy link
Member

Choose a reason for hiding this comment

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

But I prefer sticking with the high-level API @isdefined

Yes the special forms without surface syntax are implementation details of Base so best to avoid them.

I expect the error here is because nested macros see the Expr(:esc, ...) from the parent macro and @isdefined can't deal with that. It's an unsolved problem (JuliaLang/julia#23221 and all that).

@oxinabox
Copy link
Member

@oxinabox Thanks for the review! What do you think about Progress struct? In particular, what do you think about fraction = NaN vs fraction = missing? #13 (comment)

When I did similar to this before in other places I usaed NaN, but using missing sounds much better.

@tkf
Copy link
Collaborator Author

tkf commented Jan 30, 2020

Actually I'm thinking to use nothing now #13 (comment)

@codecov-io
Copy link

codecov-io commented Jan 31, 2020

Codecov Report

Merging #13 into master will decrease coverage by 14.75%.
The diff coverage is 56.94%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master      #13       +/-   ##
===========================================
- Coverage   90.27%   75.52%   -14.76%     
===========================================
  Files           1        1               
  Lines          72      143       +71     
===========================================
+ Hits           65      108       +43     
- Misses          7       35       +28
Impacted Files Coverage Δ
src/ProgressLogging.jl 75.52% <56.94%> (-14.76%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0eae8c6...0805fff. Read the comment docs.

@tkf
Copy link
Collaborator Author

tkf commented Feb 1, 2020

I added/fixed the tests. I think this is good to go now if the code looks good.

Copy link
Member

@c42f c42f left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@tkf tkf changed the title RFC: Implement type-based API for progress records Implement type-based API for progress records Feb 7, 2020
@tkf tkf merged commit a84b0eb into JuliaLogging:master Feb 7, 2020
@tkf
Copy link
Collaborator Author

tkf commented Feb 7, 2020

@pfitzseb @c42f @oxinabox Thanks a lot for reviewing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New progress logging interface?
5 participants