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

Centralize logging #6434

Merged
merged 8 commits into from
Aug 26, 2020
Merged

Centralize logging #6434

merged 8 commits into from
Aug 26, 2020

Conversation

LysandreJik
Copy link
Member

The goal of this PR is to offer a better way to manage logging to the HuggingFace/transformers users. It's a very simple proposal: implement a single logger that is shared across all files, and implement three helper methods that can be used across the library and by users:

def get_logger():
    '''
    Returns the logger instance for the library, that can be managed as a traditional `logging` logger.
    '''

def get_verbosity():
    '''
    Returns the logger instance verbosity level. Used to manage what is printed, for example with tqdm loading bars.
    Same as doing:
        hf_logging.get_logger().getEffectiveLevel()
    '''

def set_verbosity(level: int):
    '''
    Sets the logger instance verbosity level. Used to set the desired verbosity level across the library.
    Same as doing:
        hf_logging.get_logger().setLevel(level)
    '''

Users can use these methods as such:

from transformers import hf_logging

logger = hf_logging.get_logger()

hf_logging.set_verbosity(hf_logging.INFO)
# same as doing
logger.setLevel(hf_logging.INFO)

The noteworthy additions/changes are shown below.

Comment on lines 55 to 67
def get_verbosity() -> int:
_configure_library_logger()
return _get_library_logger().getEffectiveLevel()


def set_verbosity(verbosity: int) -> None:
_configure_library_logger()
_get_library_logger().setLevel(verbosity)


def get_logger():
_configure_library_logger()
return _get_library_logger()
Copy link
Member Author

Choose a reason for hiding this comment

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

Three helper methods

Comment on lines 343 to 345
if tqdm_enabled is None:
tqdm_enabled = hf_logging.get_verbosity() <= hf_logging.INFO

Copy link
Member Author

Choose a reason for hiding this comment

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

tqdm can be enabled/disabled like so.

@codecov
Copy link

codecov bot commented Aug 12, 2020

Codecov Report

Merging #6434 into master will increase coverage by 0.46%.
The diff coverage is 91.58%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6434      +/-   ##
==========================================
+ Coverage   79.63%   80.09%   +0.46%     
==========================================
  Files         156      157       +1     
  Lines       28420    28471      +51     
==========================================
+ Hits        22631    22805     +174     
+ Misses       5789     5666     -123     
Impacted Files Coverage Δ
src/transformers/commands/convert.py 0.00% <0.00%> (ø)
src/transformers/commands/run.py 0.00% <0.00%> (ø)
src/transformers/commands/serving.py 0.00% <0.00%> (ø)
src/transformers/commands/train.py 0.00% <0.00%> (ø)
src/transformers/configuration_auto.py 93.18% <ø> (-0.30%) ⬇️
src/transformers/data/metrics/squad_metrics.py 0.00% <0.00%> (ø)
src/transformers/benchmark/benchmark_utils.py 69.50% <66.66%> (ø)
src/transformers/utils/logging.py 75.00% <75.00%> (ø)
src/transformers/__init__.py 99.28% <100.00%> (ø)
src/transformers/activations.py 90.00% <100.00%> (ø)
... and 132 more

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 461ae86...c81c035. Read the comment docs.

Copy link
Collaborator

@sgugger sgugger left a comment

Choose a reason for hiding this comment

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

I'm all for centralization. This looks like a nice improvement for the user, great work!
Didn't read the full diff, just a bit, since there is POC in the title :-) Ping me when it's the right time to do so.

@patrickvonplaten
Copy link
Contributor

Looks good to me as well! I'm thinking that it might be a good idea to create one helper function for each verbosity level:

hf_logger.set_info_verbosity()
hf_logger.set_warning_verbosity()
hf_logger.set_debug_verbosity()

These functions might be easier to remember...what do you think @LysandreJik ?

Copy link
Member

@thomwolf thomwolf left a comment

Choose a reason for hiding this comment

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

I like it but I think we should follow a bit more the example of optuna and have a 'root logger' (they have a MIT licence so feel free borrow (and credit!) their logging code).

Also we can add a few utilities to easily disable tqdm bar I think.



logger = logging.getLogger(__name__) # pylint: disable=invalid-name
logger = hf_logging.get_logger() # pylint: disable=invalid-name
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to keep some detail of the filename in which the log happened (cc @lhoestq).
Can we keep __name__ as an argument here?

@@ -733,7 +732,7 @@ def http_get(url, temp_file, proxies=None, resume_size=0, user_agent: Union[Dict
total=total,
initial=resume_size,
desc="Downloading",
disable=bool(logger.getEffectiveLevel() == logging.NOTSET),
disable=bool(logger.getEffectiveLevel() == hf_logging.NOTSET),
Copy link
Member

@thomwolf thomwolf Aug 24, 2020

Choose a reason for hiding this comment

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

This is a bit mouthful in my opinion.
Following @patrickvonplaten suggestion to had

hf_logger.set_verbosity_info()
hf_logger.set_verbosity_warning()
hf_logger.set_verbosity_debug()
hf_logger.set_verbosity_error()

Could we maybe expose utilities like:

hf_logger.is_verbosity_at_least_info()
hf_logger.is_verbosity_at_least_warning()
hf_logger.is_verbosity_at_least_debug()
hf_logger.is_verbosity_at_least_error()

?

_default_handler: Optional[logging.Handler] = None


def _get_library_logger() -> logging.Logger:
Copy link
Member

Choose a reason for hiding this comment

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

As mentioned above, can we still accept a name argument here and set the logger formatting to display it in addition to the name transformers?

I think we will probably need to follow more the approach of optuna (have a root logger etc)

@thomwolf
Copy link
Member

Looks good to me as well! I'm thinking that it might be a good idea to create one helper function for each verbosity level:

hf_logger.set_info_verbosity()
hf_logger.set_warning_verbosity()
hf_logger.set_debug_verbosity()

These functions might be easier to remember...what do you think @LysandreJik ?

For a simpler completion, I would rather call these:

hf_logger.set_verbosity_info()
hf_logger.set_verbosity_warning()
hf_logger.set_verbosity_debug()
hf_logger.set_verbosity_error()  # This one is important as well, to basically disactivate all infos/warnings

Copy link
Contributor

@jplu jplu left a comment

Choose a reason for hiding this comment

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

Awesome!! This new feature is more than welcome!

Copy link
Member Author

@LysandreJik LysandreJik left a comment

Choose a reason for hiding this comment

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

Following @thomwolf and @patrickvonplaten's reviews, added some helper methods and updated to be more similar to Optuna.

There is now a root logger with separate loggers for each file.

Comment on lines 36 to 38
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
hf_logging.set_verbosity_info()
logger = hf_logging.get_logger(__name__)
Copy link
Member Author

Choose a reason for hiding this comment

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

Example of helper method

@hamad8395

This comment was marked as spam.

@LysandreJik LysandreJik marked this pull request as ready for review August 25, 2020 16:02
@LysandreJik LysandreJik changed the title [POC] Centralize logging Centralize logging Aug 25, 2020
@@ -757,7 +756,7 @@ def http_get(url, temp_file, proxies=None, resume_size=0, user_agent: Union[Dict
total=total,
initial=resume_size,
desc="Downloading",
disable=bool(logger.getEffectiveLevel() == logging.NOTSET),
disable=hf_logging.get_verbosity() == hf_logging.NOTSET,
Copy link
Member

Choose a reason for hiding this comment

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

disable=bool(hf_logging.get_verbosity() > hf_logging.INFO)?

Comment on lines 104 to 117
def is_verbosity_at_least_info():
return get_verbosity() <= INFO


def is_verbosity_at_least_warning():
return get_verbosity() <= WARNING


def is_verbosity_at_least_debug():
return get_verbosity() <= DEBUG


def is_verbosity_at_least_error():
return get_verbosity() <= ERROR
Copy link
Member

Choose a reason for hiding this comment

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

Ok actually I think these ones will be not very useful (cf the tqdm in file_utils). Sorry for proposing them.

Copy link
Member

@thomwolf thomwolf left a comment

Choose a reason for hiding this comment

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

Awesome!

@@ -247,7 +247,7 @@ class TrainingArguments:

def __post_init__(self):
if self.disable_tqdm is None:
self.disable_tqdm = logger.getEffectiveLevel() > logging.WARN
self.disable_tqdm = logging.get_verbosity() <= logging.INFO
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand this change. Is the order different from logging? Also I'm pretty sure we want the progress bars at the info level.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yes, this was a mistake. Reverting.

LysandreJik and others added 3 commits August 26, 2020 08:40
@LysandreJik LysandreJik merged commit 77abd1e into master Aug 26, 2020
@LysandreJik LysandreJik deleted the hf-logging branch August 26, 2020 15:10
Zigur pushed a commit to Zigur/transformers that referenced this pull request Oct 26, 2020
* Logging

* Style

* hf_logging > utils.logging

* Address @thomwolf's comments

* Update test

* Update src/transformers/benchmark/benchmark_utils.py

Co-authored-by: Sylvain Gugger <35901082+sgugger@users.noreply.github.com>

* Revert bad change

Co-authored-by: Sylvain Gugger <35901082+sgugger@users.noreply.github.com>
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