Source code for gigl.common.logger

import logging
import os
import pathlib
from datetime import datetime
from typing import Any, MutableMapping, Optional

from google.cloud import logging as google_cloud_logging

from gigl.env.constants import (
    GIGL_DEBUG,
    GIGL_DISABLE_CLOUD_LOGGING_ENV_KEY,
    is_env_flag_enabled,
)

_BASE_LOG_FILE_PATH = "/tmp/research/gbml/logs"


[docs] class Logger(logging.LoggerAdapter): """ GiGL's custom logger class used for local and cloud logging (VertexAI, Dataflow, etc.) On App Engine and Kubernetes, records are routed to Google Cloud Logging, which renders them as GCP JSON. Set ``GIGL_DISABLE_CLOUD_LOGGING`` to fall back to the console format. Args: logger (Optional[logging.Logger]): A custom logger to use. If not provided, the default logger will be created. name (Optional[str]): The name to be used for the logger. By default uses "root". log_to_file (bool): If True, logs will be written to a file. If False, logs will be written to the console. extra (Optional[dict[str, Any]]): Extra information to be added to the log message. """ _DID_ALERT_FOR_LOG_LEVEL: bool = False def __init__( self, logger: Optional[logging.Logger] = None, name: Optional[str] = None, log_to_file: bool = False, extra: Optional[dict[str, Any]] = None, ): gigl_debug = is_env_flag_enabled(GIGL_DEBUG) if gigl_debug: log_level = logging.DEBUG else: log_level = logging.INFO if logger is None: logger = logging.getLogger(name) self._setup_logger(logger, name, log_to_file, log_level) super().__init__(logger, extra or {}) if not Logger._DID_ALERT_FOR_LOG_LEVEL: Logger._DID_ALERT_FOR_LOG_LEVEL = True level_name = logging.getLevelName(log_level) self.info(f"{GIGL_DEBUG}={gigl_debug}, using log level {level_name}") def _setup_logger( self, logger: logging.Logger, name: Optional[str], log_to_file: bool, log_level: int, ) -> None: handler: logging.Handler if not logger.handlers: is_cloud_environment = bool( os.getenv("GAE_APPLICATION") or os.environ.get("KUBERNETES_SERVICE_HOST") ) if is_cloud_environment and not is_env_flag_enabled( GIGL_DISABLE_CLOUD_LOGGING_ENV_KEY ): # Google Cloud Logging client = google_cloud_logging.Client() client.setup_logging(log_level=log_level) else: # Logging locally. Set up logging to console or file if log_to_file: log_dir = _BASE_LOG_FILE_PATH datetime_str = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") log_file_name = f"{name}_{datetime_str}.log" log_file_path = os.path.join(log_dir, log_file_name) pathlib.Path(log_dir).mkdir(parents=True, exist_ok=True) handler = logging.FileHandler(log_file_path) else: handler = logging.StreamHandler() formatter = logging.Formatter( "%(asctime)s [%(levelname)s] : %(message)s (%(filename)s:%(funcName)s:%(lineno)d)", datefmt="%Y-%m-%d %H:%M", ) handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(log_level)
[docs] def process(self, msg: str, kwargs: MutableMapping[str, Any]) -> Any: if "extra" in kwargs: kwargs["extra"].update(self.extra) else: kwargs["extra"] = self.extra return msg, kwargs
def __getattr__(self, name: str): # Read ``logger`` straight from ``__dict__`` to avoid re-entering # ``__getattr__`` (which only runs on failed lookups) and recursing # forever before the wrapped logger is set. try: logger = self.__dict__["logger"] except KeyError: raise AttributeError(name) from None return getattr(logger, name)