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

Logger #228

Merged
merged 122 commits into from
Sep 29, 2020
Merged

Logger #228

merged 122 commits into from
Sep 29, 2020

Conversation

wclodius2
Copy link
Contributor

The main files to focus on are src/stdlib_logger.f90, src/tests/logger/test_stdlib_logger.f90, and doc/specs/stdlib_logger.md. I have also updated the CMakeLists.txt, and Makefile.manual so they should compile with this branch, but my original testing was with a download of the current main branch and not this older one. Note I had some problems with the other source code when compiled with a couple years old version of ifort, but no problems with gfortran.

New documentation for the proposed stdlib_logger.f90 module. The documentation differs in style from that of the other modules in the following ways:
1. I thought it benefitted from an introduction giving an overview of the module
2. It has a section describing the constants used as error codes with a table summarizing the constants. The other modules do not appear to have significant public constants
3. It has a section summarizing the derived type. The other modules do not define a public derived type.
4. It has a section describing the `global_logger` variable. The other modules do not define a public variable.
5. It has a table summarizing the various procedures/methods in one place. I think using the module benefits from this summary
6. With the extra material the procedure/method description are one heading higher than in the other documentation. I don't think this is noticeable.
7. The "syntax" has the self argument at an awkward position. The other modules don't have the equivalent of the self argument, and I couldn't see another place to logically put it.
8. The "syntax" follows the standard in using a single pair of square brackets to delimit a run of optional arguments, rather than the other document's use of a pair of square brackets for each optional argument. This is easily changed.
9. The document follows the standard in identifying the class of each procedure.
10. I follow the standard in describing the intent of each argument. The other documentation omits that. This is easily changed.
11. I am wordier than the other documenters. This is hard to change.
12. I ended up upper casing only specifiers that are character strings. I can lower case those, upper case other specifiers or Fortran keywords easily. I just need specific guidance on how to upper/lower case.
The source code for the stdlib_logger.f90 module. It defines one derived type, several constants and procedures/methods to implement loggers, and one variable intended to serve as a global logger.
The test code is quite a bit of a mess. The procedures add_log_file, add_log_unit, and remove_log_unit have failure modes that are modified with a `stat` argument, and need to be tested to be sure the codes do not  wrongly add/remove a unit when the stat argument is not success, and ensure that the stat stat argument returns the correct error code. Any suggestions you have to improve it would be appreciated.
These won't overwrite existing files
@milancurcic
Copy link
Member

Great, thanks William, I will review it.

@jvdp1
Copy link
Member

jvdp1 commented Sep 3, 2020

Thank you @wclodius2 for this PR. I will review it this weekend

@wclodius2
Copy link
Contributor Author

wclodius2 commented Sep 5, 2020 via email

Copy link
Member

@jvdp1 jvdp1 left a comment

Choose a reason for hiding this comment

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

Thank you @wclodius2 for this PR. I reviewed the specs, and I like this proposition for a logger. I added several comments. Some of them could be applied at other parts of the specs.
I will review the rest later.

Copy link
Member

@jvdp1 jvdp1 left a comment

Choose a reason for hiding this comment

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

Here are some additional comments

@jvdp1
Copy link
Member

jvdp1 commented Sep 6, 2020 via email

@milancurcic
Copy link
Member

It was indeed to be more explicit, but also to follow the same logic as for the declaration of variables inside the derived type (private default), and of the module (private default too).

You're right, we should be consistent. Your suggested change is fine with me.

milancurcic and others added 3 commits September 6, 2020 20:44
Co-authored-by: Jeremie Vandenplas <[email protected]>
Co-authored-by: Jeremie Vandenplas <[email protected]>
Co-authored-by: Jeremie Vandenplas <[email protected]>
@milancurcic
Copy link
Member

I think I have committed all outstanding suggestions by @jvdp1 (Thank you!).

Considering the size of this PR and small number of reviewers, let's leave it open for another week or so before merging.

@jvdp1
Copy link
Member

jvdp1 commented Sep 20, 2020

Considering the size of this PR and small number of reviewers, let's leave it open for another week or so before merging.

I agree. I think it would be good to discuss it during the next monthly call.

@wclodius2
Copy link
Contributor Author

I have needed a breather, and you two have also put in a lot of useful work. One additional change I have thought of doing is to add an optional suffix argument so that stat, instate, errmsg, and iomsg can be output as part of one single write statement. However while they would be part of one write statement they would be output as separate lines using the new_line function. But I can put that off if you want. FWIW I intend to attend the monthly call this Friday.

@jvdp1
Copy link
Member

jvdp1 commented Sep 23, 2020

I have needed a breather, and you two have also put in a lot of useful work. One additional change I have thought of doing is to add an optional suffix argument so that stat, instate, errmsg, and iomsg can be output as part of one single write statement. However while they would be part of one write statement they would be output as separate lines using the new_line function.

This could solve indeed some potential issues with parallel programming. This proposition would be more robust IMO.
Anyway, I am happy with the actual code, and this option could be added in a next PR.

Made the error code name consistent with that used for my bitsets and error_codes modules, where for ease of lookup I put what is invalid before the invalid.
@milancurcic
Copy link
Member

If there are no objections, I'll merge this tomorrow into master.

If anybody would like more time to review, just write here.

Copy link
Member

@certik certik left a comment

Choose a reason for hiding this comment

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

Here is my review:

  • Overall I am fine with merging as is.

  • This is what I would consider a high level API. If there is demand, we can provide a low level API that does not use a derived type, thus passing all configuration as arguments. In this case such low level API might not be as useful.

  • Does this design allow to extend it in the future to write all logs into a string? That would be helpful for things like interactive usage in a Jupyter notebook, to send all logs over it it from the kernel.

  • I don't have an opinion on the more general issue of: unlike some of the other functionality in stdlib, such as statistics, linear algebra, special functions etc. where there is a lot of prior art (in scipy, matlab, etc.) regarding their API, this logger API is in some sense designed in this PR. As such, it is not clear this is the best design, and it doesn't have usage yet. Down the road, for such new APIs, it might make sense to implement them as fpm packages first. And only later "standardize" in stdlib. However, at the same time, this logger API is experimental. So I think there is no harm including it also, with the understanding that the API might change in the future as we gain experience using it.

@wclodius2
Copy link
Contributor Author

wclodius2 commented Sep 28, 2020 via email

@certik
Copy link
Member

certik commented Sep 28, 2020

I agree a lower level API might not be useful.

Regarding saving to a string, Python has a concept of Handlers: https://docs.python.org/3/howto/logging.html#useful-handlers, which allow to specify where the log messages are being written. You might decide to send them over a network, or do something else with them, and use standard output separately. So you cannot just redirect a standard output. The best interface would be to provide a user call back every time a message is written. That way users can overwrite this and do whatever they want.

@wclodius2
Copy link
Contributor Author

What could be done for "handlers" is define for the logger_type an internal array of procedure pointers with an interface say

interface
    subroutine logger_handle( string )
        character(*), intent(in) :: string
    end subroutine logger_handler
end interface

or define an array of class handler with a method

interface
    subroutine logger_handle( handle, string )
        class(handler), intent(in) :: handle
        character(*), intent(in) :: string
    end subroutine logger_handler
end interface

@milancurcic
Copy link
Member

Merging, thank you all and especially @wclodius2!

@milancurcic milancurcic merged commit d9f0c86 into fortran-lang:master Sep 29, 2020
@14NGiestas 14NGiestas mentioned this pull request May 5, 2022
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.

6 participants