class_docstr: The base monitor class. All monitors should inherit from this class.
  Subclasses should implement the following methods:
  - export_schema
  - export_data
  to export the schema and data to the desired format.
docstr: log a data with column name, role and type to the current record
docstr_tok: ["log","a","data","with","column","name",",","role","and","type","to","the","current","record"]
code: def log(
      self,
      data: DT,
      name: str,
      role: str,
      data_type: str,
  ) -> None:
      """
      log a data with column name, role and type to the current record
      """
      if name in self.PRESERVED_COLUMNS:
          logger.warning(
              "Column name %s is reserved, will be renamed to %s",
              name,
              name + "_",
          )
          name = name + "_"
  
      if role not in BENTOML_MONITOR_ROLES:
          logger.warning(
              "Role {role} is not officially supported, but will be logged anyway."
          )
      if data_type not in BENTOML_MONITOR_TYPES:
          logger.warning(
              "Data type {data_type} is not officially supported, but will be logged anyway."
          )
  
      if self.columns_schema is None:
          columns = MON_COLUMN_VAR.get()
          assert columns is not None
          if name in columns:
              logger.warning(
                  "Column name %s is duplicated, will be ignored.",
                  name,
              )
          else:
              columns[name] = {
                  "name": name,
                  "role": role,
                  "type": data_type,
              }
      datas = MON_DATAS_VAR.get()
      assert datas is not None
      datas[name].append(data)
  
imports: from __future__ import annotations
  import collections
  import contextvars
  import logging
  import typing
label_desc: Use image node_id 6 for calling the MonitorBase obj's underlying member method code with example usage: obj.log(data, name, role, data_type) without return types