docstr: Creates the logger if not already created. Called in init
docstr_tok: ["Creates","the","logger","if","not","already","created",".","Called","in","init"]
code: def _define_logger(self, capture_warnings=True):
      """Creates the logger if not already created. Called in init"""
  
      # Use double-checked locking to avoid taking lock unnecessarily.
      if self._logger is not None:
          return self._logger
  
      with self._logger_lock:
          try:
              self._logger = _logging.getLogger("nemo_logger")
              # By default, silence all loggers except the logger for rank 0
              self.remove_stream_handlers()
              # If NEMO_TESTING is set, add a streamhandler to all ranks
              if get_envbool(NEMO_ENV_VARNAME_TESTING, False):
                  old_factory = _logging.getLogRecordFactory()
  
                  def record_factory(*args, **kwargs):
                      record = old_factory(*args, **kwargs)
                      record.rank = self.rank
                      return record
  
                  _logging.setLogRecordFactory(record_factory)
                  self.add_stream_handlers(formatter=DebugNeMoFormatter)
              elif is_global_rank_zero():
                  self.add_stream_handlers()
  
              # Add memoryhandlers, essentially buffers. They are used to save messages that we will flush to file
              # once the appropriate file handlers are added.
              if is_global_rank_zero():
                  # Add a memoryhandler for error messages. Only logged on rank 0
                  self._handlers["memory_err"] = MemoryHandler(-1)
                  self._handlers["memory_err"].addFilter(
                      lambda record: record.levelno > _logging.INFO
                  )
                  formatter = BaseNeMoFormatter
                  self._handlers["memory_err"].setFormatter(formatter())
                  self._logger.addHandler(self._handlers["memory_err"])
              # Add a memoryhandler for all messages on all ranks
              self._handlers["memory_all"] = MemoryHandler(-1)
              formatter = BaseNeMoFormatter
              self._handlers["memory_all"].setFormatter(formatter())
              self._logger.addHandler(self._handlers["memory_all"])
  
          finally:
              level = Logger.INFO
              if get_envbool(NEMO_ENV_VARNAME_TESTING, False):
                  level = Logger.DEBUG
              self.set_verbosity(verbosity_level=level)
              self.captureWarnings(capture_warnings)
  
      self._logger.propagate = False
  
imports: import enum
  import logging
  import sys
  import threading
  import warnings
  from contextlib import contextmanager
  from logging.handlers import MemoryHandler
  from nemo.constants import NEMO_ENV_VARNAME_REDIRECT_LOGS_TO_STDERR, NEMO_ENV_VARNAME_TESTING
  from nemo.utils.env_var_parsing import get_envbool
  from nemo.utils.formatters.base import BaseNeMoFormatter, DebugNeMoFormatter
  from nemo.utils.get_rank import is_global_rank_zero
  from nemo.utils.metaclasses import Singleton
label_desc: Use image node_id 2 for calling the Logger obj's underlying member method code with example usage: obj._define_logger(capture_warnings) and returns: self, record