logging.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #!/usr/bin/env python3
  2. # mypy: allow-untyped-defs
  3. # Copyright (c) Facebook, Inc. and its affiliates.
  4. # All rights reserved.
  5. #
  6. # This source code is licensed under the BSD-style license found in the
  7. # LICENSE file in the root directory of this source tree.
  8. import inspect
  9. import logging
  10. import os
  11. import warnings
  12. from typing import Optional
  13. from torch.distributed.elastic.utils.log_level import get_log_level
  14. def get_logger(name: Optional[str] = None):
  15. """
  16. Util function to set up a simple logger that writes
  17. into stderr. The loglevel is fetched from the LOGLEVEL
  18. env. variable or WARNING as default. The function will use the
  19. module name of the caller if no name is provided.
  20. Args:
  21. name: Name of the logger. If no name provided, the name will
  22. be derived from the call stack.
  23. """
  24. # Derive the name of the caller, if none provided
  25. # Use depth=2 since this function takes up one level in the call stack
  26. return _setup_logger(name or _derive_module_name(depth=2))
  27. def _setup_logger(name: Optional[str] = None):
  28. logger = logging.getLogger(name)
  29. logger.setLevel(os.environ.get("LOGLEVEL", get_log_level()))
  30. return logger
  31. def _derive_module_name(depth: int = 1) -> Optional[str]:
  32. """
  33. Derives the name of the caller module from the stack frames.
  34. Args:
  35. depth: The position of the frame in the stack.
  36. """
  37. try:
  38. stack = inspect.stack()
  39. assert depth < len(stack)
  40. # FrameInfo is just a named tuple: (frame, filename, lineno, function, code_context, index)
  41. frame_info = stack[depth]
  42. module = inspect.getmodule(frame_info[0])
  43. if module:
  44. module_name = module.__name__
  45. else:
  46. # inspect.getmodule(frame_info[0]) does NOT work (returns None) in
  47. # binaries built with @mode/opt
  48. # return the filename (minus the .py extension) as modulename
  49. filename = frame_info[1]
  50. module_name = os.path.splitext(os.path.basename(filename))[0]
  51. return module_name
  52. except Exception as e:
  53. warnings.warn(
  54. f"Error deriving logger module name, using <None>. Exception: {e}",
  55. RuntimeWarning,
  56. )
  57. return None