Skip to content

Commit b093848

Browse files
committed
support loguru
Signed-off-by: Kyle Sayers <[email protected]>
1 parent 4370618 commit b093848

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

src/compressed_tensors/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
# flake8: noqa
16+
# isort: off
17+
from .logger import LoggerConfig, configure_logger, logger
1518
from .base import *
1619

17-
# flake8: noqa
1820
from .compressors import *
1921
from .config import *
2022
from .quantization import QuantizationConfig, QuantizationStatus

src/compressed_tensors/logger.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing,
10+
# software distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""
16+
Logger configuration for Compressed Tensors.
17+
"""
18+
19+
import os
20+
import sys
21+
from dataclasses import dataclass
22+
from typing import Any, Dict, Optional
23+
24+
from loguru import logger
25+
26+
27+
__all__ = ["LoggerConfig", "configure_logger", "logger"]
28+
29+
30+
# used by `support_log_once``
31+
_logged_once = set()
32+
33+
34+
@dataclass
35+
class LoggerConfig:
36+
disabled: bool = False
37+
clear_loggers: bool = True
38+
console_log_level: Optional[str] = "INFO"
39+
log_file: Optional[str] = None
40+
log_file_level: Optional[str] = None
41+
42+
43+
def configure_logger(config: Optional[LoggerConfig] = None) -> None:
44+
"""
45+
Configure the logger for Compressed Tensors.
46+
This function sets up the console and file logging
47+
as per the specified or default parameters.
48+
49+
Note: Environment variables take precedence over the function parameters.
50+
51+
:param config: The configuration for the logger to use.
52+
:type config: LoggerConfig
53+
"""
54+
logger_config = config or LoggerConfig()
55+
56+
# env vars get priority
57+
if (disabled := os.getenv("COMPRESSED_TENSORS_LOG_DISABLED")) is not None:
58+
logger_config.disabled = disabled.lower() == "true"
59+
if (clear_loggers := os.getenv("COMPRESSED_TENSORS_CLEAR_LOGGERS")) is not None:
60+
logger_config.clear_loggers = clear_loggers.lower() == "true"
61+
if (console_log_level := os.getenv("COMPRESSED_TENSORS_LOG_LEVEL")) is not None:
62+
logger_config.console_log_level = console_log_level.upper()
63+
if (log_file := os.getenv("COMPRESSED_TENSORS_LOG_FILE")) is not None:
64+
logger_config.log_file = log_file
65+
if (log_file_level := os.getenv("COMPRESSED_TENSORS_LOG_FILE_LEVEL")) is not None:
66+
logger_config.log_file_level = log_file_level.upper()
67+
68+
if logger_config.disabled:
69+
logger.disable("compressed_tensors")
70+
return
71+
72+
logger.enable("compressed_tensors")
73+
74+
if logger_config.clear_loggers:
75+
logger.remove()
76+
77+
if logger_config.console_log_level:
78+
# log as a human readable string with the time, function, level, and message
79+
logger.add(
80+
sys.stdout,
81+
level=logger_config.console_log_level.upper(),
82+
format="{time} | {function} | {level} - {message}",
83+
filter=support_log_once,
84+
)
85+
86+
if logger_config.log_file or logger_config.log_file_level:
87+
log_file = logger_config.log_file or "compressed_tensors.log"
88+
log_file_level = logger_config.log_file_level or "INFO"
89+
# log as json to the file for easier parsing
90+
logger.add(
91+
log_file,
92+
level=log_file_level.upper(),
93+
serialize=True,
94+
filter=support_log_once,
95+
)
96+
97+
98+
def support_log_once(record: Dict[str, Any]) -> bool:
99+
"""
100+
Support logging only once using `.bind(log_once=True)`
101+
102+
```
103+
logger.bind(log_once=False).info("This will log multiple times")
104+
logger.bind(log_once=False).info("This will log multiple times")
105+
logger.bind(log_once=True).info("This will only log once")
106+
logger.bind(log_once=True).info("This will only log once") # skipped
107+
```
108+
"""
109+
log_once = record["extra"].get("log_once", False)
110+
level = getattr(record["level"], "name", "none")
111+
message = str(level) + record["message"]
112+
113+
if log_once and message in _logged_once:
114+
return False
115+
116+
if log_once:
117+
_logged_once.add(message)
118+
119+
return True
120+
121+
122+
# invoke logger setup on import with default values enabling console logging with INFO
123+
# and disabling file logging
124+
configure_logger(
125+
config=LoggerConfig(
126+
disabled=False,
127+
clear_loggers=True,
128+
console_log_level="INFO",
129+
log_file=None,
130+
log_file_level=None,
131+
)
132+
)

0 commit comments

Comments
 (0)