class_docstr: Tracks object tree depth and calculates pickled object size.
  
  A single instance of this wraps the module's logger, as the logging API
  doesn't allow setting it directly with a custom Logger subclass.  The added
  'trace()' method receives a pickle instance as the first argument and
  creates extra values to be added in the LogRecord from it, then calls
  'info()'.
  
  Usage of logger with 'trace()' method:
  
  >>> from dill.logger import adapter as logger  #NOTE: not dill.logger.logger
  >>> ...
  >>> def save_atype(pickler, obj):
  >>>     logger.trace(pickler, "Message with %s and %r etc. placeholders", 'text', obj)
  >>>     ...
class_docstr_tok: ["Tracks","object","tree","depth","and","calculates","pickled","object","size",".","A","single","instance","of","this","wraps","the","module","'s","logger",",","as","the","logging","API","does","n't","allow","setting","it","directly","with","a","custom","Logger","subclass",".","The","added","'trace","(",")","'","method","receives","a","pickle","instance","as","the","first","argument","and","creates","extra","values","to","be","added","in","the","LogRecord","from","it",",","then","calls","'info","(",")","'",".","Usage","of","logger","with","'trace","(",")","'","method",":",">",">",">","from","dill.logger","import","adapter","as","logger","#","NOTE",":","not","dill.logger.logger",">",">",">","...",">",">",">","def","save_atype","(","pickler",",","obj",")",":",">",">",">","logger.trace","(","pickler",",","``","Message","with","%","s","and","%","r","etc",".","placeholders","''",",","'text","'",",","obj",")",">",">",">","..."]
code: def trace(self, pickler, msg, *args, **kwargs):
      if not hasattr(pickler, "_trace_depth"):
          logger.info(msg, *args, **kwargs)
          return
      if pickler._trace_depth is None:
          return
      extra = kwargs.get("extra", {})
      pushed_obj = msg.startswith("#")
      size = None
      try:
          # Streams are not required to be tellable.
          size = pickler._file.tell()
          frame = pickler.framer.current_frame
          try:
              size += frame.tell()
          except AttributeError:
              # PyPy may use a BytesBuilder as frame
              size += len(frame)
      except (AttributeError, TypeError):
          pass
      if size is not None:
          if not pushed_obj:
              pickler._size_stack.append(size)
          else:
              size -= pickler._size_stack.pop()
              extra["size"] = size
      if pushed_obj:
          pickler._trace_depth -= 1
      extra["depth"] = pickler._trace_depth
      kwargs["extra"] = extra
      self.info(msg, *args, **kwargs)
      if not pushed_obj:
          pickler._trace_depth += 1
  
imports: import codecs
  import contextlib
  import locale
  import logging
  import math
  import os
  from functools import partial
  from typing import TextIO, Union
  import dill
label_desc: Use image node_id 6 for calling the TraceAdapter obj's underlying member method code with example usage: obj.trace(pickler, msg) without return types