Skip to content

Commit 7fa34b4

Browse files
committed
[Logging] Switch from Standard Logging to Loguru
As loguru is used in some places, we update other logging instances for consistency with its behavior * metrics/logger.py: Change `level: Optional[int]` to `level: Optional[Union[int, str]]` to better support loguru's logging level behavior * Update `PythonLogger._create_default_logger` to use loguru.logger * PythonLogger: Add class-level variable `_global_file_sink_id` to prevent duplicate file sink creations and remove manual stream handler setup since loguru adds a default `sys.stderr` sink * Simplify `PythonLogger` by no longer accepting an external logger instance, because the main concept of loguru is that there is one and only one `logger` * Simplify `SparsificationGroupLogger` by replacing the `python` union type with `bool`, aligning it with `log_python` in `LoggerManager` and removing ambiguity
1 parent 4bde0fe commit 7fa34b4

File tree

1 file changed

+42
-87
lines changed

1 file changed

+42
-87
lines changed

src/llmcompressor/metrics/logger.py

Lines changed: 42 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
Contains code for loggers that help visualize the information from each modifier
33
"""
44

5-
import logging
65
import os
76
import time
87
import warnings
98
from abc import ABC
9+
from loguru import logger
1010
from contextlib import contextmanager
1111
from datetime import datetime
12-
from logging import CRITICAL, DEBUG, ERROR, INFO, WARN, Logger
1312
from pathlib import Path
1413
from types import ModuleType
1514
from typing import Any, Callable, Dict, List, Optional, Union
@@ -52,16 +51,8 @@
5251
"WANDBLogger",
5352
"SparsificationGroupLogger",
5453
"LoggerManager",
55-
"LOGGING_LEVELS",
5654
]
5755
ALL_TOKEN = "__ALL__"
58-
LOGGING_LEVELS = {
59-
"debug": DEBUG,
60-
"info": INFO,
61-
"warn": WARN,
62-
"error": ERROR,
63-
"critical": CRITICAL,
64-
}
6556
DEFAULT_TAG = "defaul_tag"
6657

6758

@@ -231,7 +222,7 @@ def lambda_func(
231222
def log_hyperparams(
232223
self,
233224
params: Dict,
234-
level: Optional[int] = None,
225+
level: Optional[Union[int, str]] = None,
235226
) -> bool:
236227
"""
237228
:param params: Each key-value pair in the dictionary is the name of the
@@ -256,7 +247,7 @@ def log_scalar(
256247
value: float,
257248
step: Optional[int] = None,
258249
wall_time: Optional[float] = None,
259-
level: Optional[int] = None,
250+
level: Optional[Union[int, str]] = None,
260251
) -> bool:
261252
"""
262253
:param tag: identifying tag to log the value with
@@ -285,7 +276,7 @@ def log_scalars(
285276
values: Dict[str, float],
286277
step: Optional[int] = None,
287278
wall_time: Optional[float] = None,
288-
level: Optional[int] = None,
279+
level: Optional[Union[int, str]] = None,
289280
) -> bool:
290281
"""
291282
:param tag: identifying tag to log the values with
@@ -313,40 +304,28 @@ class PythonLogger(LambdaLogger):
313304
"""
314305
Modifier metrics that handles printing values into a python metrics instance.
315306
316-
:param logger: a metrics instance to log to, if None then will create it's own
317-
:param log_level: default level to log any incoming data at on the logging.Logger
318-
instance when an explicit log level isn't provided
319307
:param name: name given to the metrics, used for identification;
320308
defaults to python
321309
:param enabled: True to log, False otherwise
322310
"""
323311

312+
# Class-level variable to track if file sink is created
313+
_global_file_sink_id = None
314+
324315
def __init__(
325316
self,
326-
logger: Logger = None,
327-
log_level: int = None,
328317
name: str = "python",
329318
enabled: bool = True,
330319
):
331-
self._logger = logger or self._create_default_logger(log_level=log_level)
320+
self._create_default_logger()
332321

333322
super().__init__(
334323
lambda_func=self._log_lambda,
335324
name=name,
336325
enabled=enabled,
337326
)
338327

339-
def __getattr__(self, item):
340-
return getattr(self._logger, item)
341-
342-
@property
343-
def logger(self) -> Logger:
344-
"""
345-
:return: a metrics instance to log to, if None then will create it's own
346-
"""
347-
return self._logger
348-
349-
def _create_default_logger(self, log_level: Optional[int] = None) -> logging.Logger:
328+
def _create_default_logger(self) -> None:
350329
"""
351330
Create a default modifier metrics,
352331
with a file handler logging at the debug level
@@ -355,24 +334,9 @@ def _create_default_logger(self, log_level: Optional[int] = None) -> logging.Log
355334
:param log_level: logging level for the console metrics
356335
:return: metrics
357336
"""
358-
logger = logging.getLogger(__name__)
359-
360-
# Console handler, for logging high level modifier logs
361-
# must be created before the file handler
362-
# as file handler is also a stream handler
363-
if not any(
364-
isinstance(handler, logging.StreamHandler) for handler in logger.handlers
365-
):
366-
stream_handler = logging.StreamHandler()
367-
stream_handler.setLevel(
368-
log_level or logging.getLogger("llmcompressor").level
369-
)
370-
logger.addHandler(stream_handler)
371337

372338
# File handler setup, for logging modifier debug statements
373-
if not any(
374-
isinstance(handler, logging.FileHandler) for handler in logger.handlers
375-
):
339+
if PythonLogger._global_file_sink_id is None:
376340
base_log_path = (
377341
os.environ.get("NM_TEST_LOG_DIR")
378342
if os.environ.get("NM_TEST_MODE")
@@ -382,27 +346,19 @@ def _create_default_logger(self, log_level: Optional[int] = None) -> logging.Log
382346
dt_string = now.strftime("%d-%m-%Y_%H.%M.%S")
383347
log_path = os.path.join(base_log_path, f"{dt_string}.log")
384348
os.makedirs(base_log_path, exist_ok=True)
385-
file_handler = logging.FileHandler(
386-
log_path,
387-
delay=True,
349+
PythonLogger._global_file_sink_id = logger.add(
350+
log_path, level="DEBUG", delay=True
388351
)
389-
file_handler.setLevel(LOGGING_LEVELS["debug"])
390-
logger.addHandler(file_handler)
391352
logger.info(f"Logging all LLM Compressor modifier-level logs to {log_path}")
392353

393-
logger.setLevel(LOGGING_LEVELS["debug"])
394-
logger.propagate = False
395-
396-
return logger
397-
398354
def _log_lambda(
399355
self,
400356
tag: Optional[str],
401357
value: Optional[Union[float, str]],
402358
values: Optional[Dict[str, float]],
403359
step: Optional[int],
404360
wall_time: Optional[float],
405-
level: Optional[int] = None,
361+
level: Optional[Union[int, str]] = None,
406362
) -> bool:
407363
"""
408364
:param tag: identifying tag to log the values with
@@ -415,9 +371,11 @@ def _log_lambda(
415371
:return: True if logged, False otherwise.
416372
"""
417373
if not level:
418-
level = LOGGING_LEVELS["debug"]
374+
level = "DEBUG"
419375

420-
if level > LOGGING_LEVELS["debug"]:
376+
if (isinstance(level, int) and level > logger.level("DEBUG").no) or (
377+
isinstance(level, str) and logger.level(level).no > logger.level("DEBUG").no
378+
):
421379
if step is not None:
422380
format = "%s %s step %s: %s"
423381
log_args = [
@@ -433,7 +391,7 @@ def _log_lambda(
433391
format = "%s %s [%s - %s]: %s"
434392
log_args = [self.name, tag, step, wall_time, values or value]
435393

436-
self._logger.log(level, format, *log_args)
394+
logger.log(level, format, *log_args)
437395

438396
return True
439397

@@ -443,7 +401,7 @@ def log_string(
443401
string: Optional[str],
444402
step: Optional[int],
445403
wall_time: Optional[float] = None,
446-
level: Optional[int] = None,
404+
level: Optional[Union[int, str]] = None,
447405
) -> bool:
448406
"""
449407
:param tag: identifying tag to log the values with
@@ -540,7 +498,7 @@ def _log_lambda(
540498
values: Optional[Dict[str, float]],
541499
step: Optional[int],
542500
wall_time: Optional[float],
543-
level: Optional[int] = None,
501+
level: Optional[Union[int, str]] = None,
544502
) -> bool:
545503
if value is not None:
546504
self._writer.add_scalar(tag, value, step, wall_time)
@@ -614,7 +572,7 @@ def _log_lambda(
614572
values: Optional[Dict[str, float]],
615573
step: Optional[int],
616574
wall_time: Optional[float],
617-
level: Optional[int] = None,
575+
level: Optional[Union[int, str]] = None,
618576
) -> bool:
619577
params = {}
620578

@@ -656,11 +614,10 @@ class SparsificationGroupLogger(BaseLogger):
656614
:param lambda_func: an optional lambda function to call back into with any logs.
657615
The expected call sequence is (tag, value, values, step, wall_time) -> bool
658616
The return type is True if logged and False otherwise.
659-
:param python: an optional argument for logging to a python metrics.
660-
May be a logging.Logger instance to log to, True to create a metrics instance,
661-
or non truthy to not log anything (False, None)
617+
:param python: an bool argument for logging to a python metrics.
618+
True to create a metrics instance, or False to not log anything
662619
:param python_log_level: if python,
663-
the level to log any incoming data at on the logging.Logger instance
620+
the level to log any incoming data at on the loguru.logger instance
664621
:param tensorboard: an optional argument for logging to a tensorboard writer.
665622
May be a SummaryWriter instance to log to, a string representing the directory
666623
to create a new SummaryWriter to log to, True to create a new SummaryWriter,
@@ -688,8 +645,8 @@ def __init__(
688645
bool,
689646
]
690647
] = None,
691-
python: Optional[Union[bool, Logger]] = None,
692-
python_log_level: int = logging.INFO,
648+
python: bool = False,
649+
python_log_level: Optional[Union[int, str]] = "INFO",
693650
tensorboard: Optional[Union[bool, str, SummaryWriter]] = None,
694651
wandb_: Optional[Union[bool, Dict]] = None,
695652
name: str = "sparsification",
@@ -706,8 +663,6 @@ def __init__(
706663
if python:
707664
self._loggers.append(
708665
PythonLogger(
709-
logger=python if isinstance(python, Logger) else None,
710-
log_level=python_log_level,
711666
name=name,
712667
enabled=enabled,
713668
)
@@ -751,7 +706,7 @@ def loggers(self) -> List[BaseLogger]:
751706
"""
752707
return self._loggers
753708

754-
def log_hyperparams(self, params: Dict, level: Optional[int] = None):
709+
def log_hyperparams(self, params: Dict, level: Optional[Union[int, str]] = None):
755710
"""
756711
:param params: Each key-value pair in the dictionary is the name of the
757712
hyper parameter and it's corresponding value.
@@ -765,7 +720,7 @@ def log_scalar(
765720
value: float,
766721
step: Optional[int] = None,
767722
wall_time: Optional[float] = None,
768-
level: Optional[int] = None,
723+
level: Optional[Union[int, str]] = None,
769724
):
770725
"""
771726
:param tag: identifying tag to log the value with
@@ -783,7 +738,7 @@ def log_scalars(
783738
values: Dict[str, float],
784739
step: Optional[int] = None,
785740
wall_time: Optional[float] = None,
786-
level: Optional[int] = None,
741+
level: Optional[Union[int, str]] = None,
787742
):
788743
"""
789744
:param tag: identifying tag to log the values with
@@ -956,7 +911,7 @@ def log_scalar(
956911
step: Optional[int] = None,
957912
wall_time: Optional[float] = None,
958913
log_types: Union[str, List[str]] = ALL_TOKEN,
959-
level: Optional[int] = None,
914+
level: Optional[Union[int, str]] = None,
960915
):
961916
"""
962917
(Note: this method is deprecated and will be removed in a future version,
@@ -986,7 +941,7 @@ def log_scalars(
986941
step: Optional[int] = None,
987942
wall_time: Optional[float] = None,
988943
log_types: Union[str, List[str]] = ALL_TOKEN,
989-
level: Optional[int] = None,
944+
level: Optional[Union[int, str]] = None,
990945
):
991946
"""
992947
(Note: this method is deprecated and will be removed in a future version,
@@ -1013,7 +968,7 @@ def log_hyperparams(
1013968
self,
1014969
params: Dict,
1015970
log_types: Union[str, List[str]] = ALL_TOKEN,
1016-
level: Optional[int] = None,
971+
level: Optional[Union[int, str]] = None,
1017972
):
1018973
"""
1019974
(Note: this method is deprecated and will be removed in a future version,
@@ -1036,7 +991,7 @@ def log_string(
1036991
step: Optional[int] = None,
1037992
wall_time: Optional[float] = None,
1038993
log_types: Union[str, List[str]] = ALL_TOKEN,
1039-
level: Optional[int] = None,
994+
level: Optional[Union[int, str]] = None,
1040995
):
1041996
"""
1042997
(Note: this method is deprecated and will be removed in a future version,
@@ -1119,7 +1074,7 @@ def log_string(
11191074
step: Optional[int] = None,
11201075
wall_time: Optional[float] = None,
11211076
log_types: Union[str, List[str]] = ALL_TOKEN,
1122-
level: Optional[int] = None,
1077+
level: Optional[Union[int, str]] = None,
11231078
):
11241079
"""
11251080
:param tag: identifying tag to log the values with
@@ -1151,7 +1106,7 @@ def debug(self, tag, string, *args, **kwargs):
11511106
:param kwargs: additional arguments to pass to the metrics,
11521107
see `log_string` for more details
11531108
"""
1154-
kwargs["level"] = logging.DEBUG
1109+
kwargs["level"] = "DEBUG"
11551110
self.log_string(tag=tag, string=string, *args, **kwargs)
11561111

11571112
def info(self, tag, string, *args, **kwargs):
@@ -1166,7 +1121,7 @@ def info(self, tag, string, *args, **kwargs):
11661121
:param kwargs: additional arguments to pass to the metrics,
11671122
see `log_string` for more details
11681123
"""
1169-
kwargs["level"] = logging.INFO
1124+
kwargs["level"] = "INFO"
11701125
self.log_string(tag=tag, string=string, *args, **kwargs)
11711126

11721127
def warning(self, tag, string, *args, **kwargs):
@@ -1181,7 +1136,7 @@ def warning(self, tag, string, *args, **kwargs):
11811136
:param kwargs: additional arguments to pass to the metrics,
11821137
see `log_string` for more details
11831138
"""
1184-
kwargs["level"] = logging.WARNING
1139+
kwargs["level"] = "WARNING"
11851140
self.log_string(tag=tag, string=string, *args, **kwargs)
11861141

11871142
def warn(self, tag, string, *args, **kwargs):
@@ -1204,7 +1159,7 @@ def error(self, tag, string, *args, **kwargs):
12041159
:param kwargs: additional arguments to pass to the metrics,
12051160
see `log_string` for more details
12061161
"""
1207-
kwargs["level"] = logging.ERROR
1162+
kwargs["level"] = "ERROR"
12081163
self.log_string(tag=tag, string=string, *args, **kwargs)
12091164

12101165
def critical(self, tag, string, *args, **kwargs):
@@ -1219,7 +1174,7 @@ def critical(self, tag, string, *args, **kwargs):
12191174
:param kwargs: additional arguments to pass to the metrics,
12201175
see `log_string` for more details
12211176
"""
1222-
kwargs["level"] = logging.CRITICAL
1177+
kwargs["level"] = "CRITICAL"
12231178
self.log_string(tag=tag, string=string, *args, **kwargs)
12241179

12251180

@@ -1232,7 +1187,7 @@ def log_hyperparams(
12321187
self,
12331188
params: Dict,
12341189
log_types: Union[str, List[str]] = ALL_TOKEN,
1235-
level: Optional[int] = None,
1190+
level: Optional[Union[int, str]] = None,
12361191
):
12371192
"""
12381193
:param params: Each key-value pair in the dictionary is the name of the
@@ -1249,7 +1204,7 @@ def log_scalar(
12491204
step: Optional[int] = None,
12501205
wall_time: Optional[float] = None,
12511206
log_types: Union[str, List[str]] = ALL_TOKEN,
1252-
level: Optional[int] = None,
1207+
level: Optional[Union[int, str]] = None,
12531208
):
12541209
"""
12551210
:param tag: identifying tag to log the value with
@@ -1276,7 +1231,7 @@ def log_scalars(
12761231
step: Optional[int] = None,
12771232
wall_time: Optional[float] = None,
12781233
log_types: Union[str, List[str]] = ALL_TOKEN,
1279-
level: Optional[int] = None,
1234+
level: Optional[Union[int, str]] = None,
12801235
):
12811236
"""
12821237
:param tag: identifying tag to log the values with

0 commit comments

Comments
 (0)