logger.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # Copyright (c) Alibaba, Inc. and its affiliates.
  2. import importlib.util as iutil
  3. import logging
  4. import os
  5. from typing import Optional
  6. init_loggers = {}
  7. formatter = logging.Formatter(
  8. '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  9. default_log_level = int(os.getenv('MODELSCOPE_LOG_LEVEL', str(logging.INFO)))
  10. logging.getLogger('numba').setLevel(logging.INFO)
  11. def get_logger(log_file: Optional[str] = None,
  12. log_level: int = default_log_level,
  13. file_mode: str = 'w'):
  14. """ Get logging logger
  15. Args:
  16. log_file: Log filename, if specified, file handler will be added to
  17. logger
  18. log_level: Logging level.
  19. file_mode: Specifies the mode to open the file, if filename is
  20. specified (if filemode is unspecified, it defaults to 'w').
  21. """
  22. logger_name = __name__.split('.')[0]
  23. logger = logging.getLogger(logger_name)
  24. logger.propagate = False
  25. if logger_name in init_loggers:
  26. add_file_handler_if_needed(logger, log_file, file_mode, log_level)
  27. if logger.level != log_level:
  28. logger.setLevel(log_level)
  29. return logger
  30. # handle duplicate logs to the console
  31. # Starting in 1.8.0, PyTorch DDP attaches a StreamHandler <stderr> (NOTSET)
  32. # to the root logger. As logger.propagate is True by default, this root
  33. # level handler causes logging messages from rank>0 processes to
  34. # unexpectedly show up on the console, creating much unwanted clutter.
  35. # To fix this issue, we set the root logger's StreamHandler, if any, to log
  36. # at the ERROR level.
  37. torch_dist = False
  38. is_worker0 = True
  39. if iutil.find_spec('torch') is not None:
  40. from modelscope.utils.torch_utils import is_dist, is_master
  41. torch_dist = is_dist()
  42. is_worker0 = is_master()
  43. if torch_dist:
  44. for handler in logger.root.handlers:
  45. if type(handler) is logging.StreamHandler:
  46. handler.setLevel(logging.ERROR)
  47. stream_handler = logging.StreamHandler()
  48. handlers = [stream_handler]
  49. if is_worker0 and log_file is not None:
  50. file_handler = logging.FileHandler(log_file, file_mode)
  51. handlers.append(file_handler)
  52. for handler in handlers:
  53. handler.setFormatter(formatter)
  54. handler.setLevel(log_level)
  55. logger.addHandler(handler)
  56. if is_worker0:
  57. logger.setLevel(log_level)
  58. else:
  59. logger.setLevel(logging.ERROR)
  60. init_loggers[logger_name] = True
  61. return logger
  62. def add_file_handler_if_needed(logger, log_file, file_mode, log_level):
  63. for handler in logger.handlers:
  64. if isinstance(handler, logging.FileHandler):
  65. return
  66. if iutil.find_spec('torch') is not None:
  67. from modelscope.utils.torch_utils import is_master
  68. is_worker0 = is_master()
  69. else:
  70. is_worker0 = True
  71. if is_worker0 and log_file is not None:
  72. file_handler = logging.FileHandler(log_file, file_mode)
  73. file_handler.setFormatter(formatter)
  74. file_handler.setLevel(log_level)
  75. logger.addHandler(file_handler)