class_docstr: Base class for log writers, triggered at every reset and step by finite env.
  
  What to do with a specific log depends on the implementation of subclassing :class:`LogWriter`.
  The general principle is that, it should handle logs above its loglevel (inclusive),
  and discard logs that are not acceptable. For instance, console loggers obviously can't handle an image.
class_docstr_tok: ["Base","class","for","log","writers",",","triggered","at","every","reset","and","step","by","finite","env",".","What","to","do","with","a","specific","log","depends","on","the","implementation","of","subclassing",":","class",":","`","LogWriter","`",".","The","general","principle","is","that",",","it","should","handle","logs","above","its","loglevel","(","inclusive",")",",","and","discard","logs","that","are","not","acceptable",".","For","instance",",","console","loggers","obviously","ca","n't","handle","an","image","."]
code: def __init__(
      self, loglevel: int | LogLevel = LogLevel.PERIODIC
  ) -> None:
      self.loglevel = loglevel
  
      self.global_step = 0
      self.global_episode = 0
  
      # Information, logs of one episode is stored here.
      # This assumes that episode is not too long to fit into the memory.
      self.episode_lengths = dict()
      self.episode_rewards = dict()
      self.episode_logs = dict()
  
      self.clear()
  
imports: from __future__ import annotations
  import logging
  from collections import defaultdict
  from enum import IntEnum
  from pathlib import Path
  from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, List, Sequence, Set, Tuple, TypeVar
  import numpy
  import pandas
  from qlib.log import get_module_logger
label_desc: Use image node_id 1 to create a new LogWriter object from inherited base classes: Generic with example: obj = LogWriter(loglevel)