Skip to content

Commit 5837094

Browse files
committed
chore: add pre-commit hook to enforce llama_stack.log logger
Signed-off-by: Mustafa Elbehery <[email protected]>
1 parent 5220161 commit 5837094

File tree

25 files changed

+124
-115
lines changed

25 files changed

+124
-115
lines changed

.pre-commit-config.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,26 @@ repos:
145145
echo;
146146
exit 1;
147147
} || true
148+
- id: check-logger-usage
149+
name: Check for proper logger usage (use llama_stack.log instead)
150+
entry: bash
151+
language: system
152+
types: [python]
153+
pass_filenames: true
154+
args:
155+
- -c
156+
- |
157+
grep -EnH '^[^#]*\b(import logging|from logging\b)' "$@" | grep -v '# allow-direct-logging' && {
158+
echo;
159+
echo "❌ Do not use 'import logging' or 'from logging import'.";
160+
echo " Use the custom logger instead:";
161+
echo " from llama_stack.log import get_logger";
162+
echo " logger = get_logger(name=__name__, category=\"core\")";
163+
echo;
164+
echo " If direct logging is truly needed, add: # allow-direct-logging";
165+
echo;
166+
exit 1;
167+
} || true
148168
149169
ci:
150170
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

llama_stack/distribution/build.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# the root directory of this source tree.
66

77
import importlib.resources
8-
import logging
98
import sys
109
from pathlib import Path
1110

@@ -17,11 +16,12 @@
1716
from llama_stack.distribution.external import load_external_apis
1817
from llama_stack.distribution.utils.exec import run_command
1918
from llama_stack.distribution.utils.image_types import LlamaStackImageType
19+
from llama_stack.log import get_logger
20+
21+
logger = get_logger(name=__name__, category="core")
2022
from llama_stack.providers.datatypes import Api
2123
from llama_stack.templates.template import DistributionTemplate
2224

23-
log = logging.getLogger(__name__)
24-
2525
# These are the dependencies needed by the distribution server.
2626
# `llama-stack` is automatically installed by the installation script.
2727
SERVER_DEPENDENCIES = [
@@ -170,7 +170,7 @@ def build_image(
170170
return_code = run_command(args)
171171

172172
if return_code != 0:
173-
log.error(
173+
logger.error(
174174
f"Failed to build target {image_name} with return code {return_code}",
175175
)
176176

llama_stack/distribution/request_headers.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
import contextvars
88
import json
9-
import logging
109
from contextlib import AbstractContextManager
1110
from typing import Any
1211

1312
from llama_stack.distribution.datatypes import User
13+
from llama_stack.log import get_logger
1414

15-
from .utils.dynamic import instantiate_class_type
15+
logger = get_logger(name=__name__, category="core")
1616

17-
log = logging.getLogger(__name__)
17+
from .utils.dynamic import instantiate_class_type
1818

1919
# Context variable for request provider data and auth attributes
2020
PROVIDER_DATA_VAR = contextvars.ContextVar("provider_data", default=None)
@@ -61,7 +61,7 @@ def get_request_provider_data(self) -> Any:
6161
provider_data = validator(**val)
6262
return provider_data
6363
except Exception as e:
64-
log.error(f"Error parsing provider data: {e}")
64+
logger.error(f"Error parsing provider data: {e}")
6565
return None
6666

6767

@@ -83,7 +83,7 @@ def parse_request_provider_data(headers: dict[str, str]) -> dict[str, Any] | Non
8383
try:
8484
return json.loads(val)
8585
except json.JSONDecodeError:
86-
log.error("Provider data not encoded as a JSON object!")
86+
logger.error("Provider data not encoded as a JSON object!")
8787
return None
8888

8989

llama_stack/distribution/utils/exec.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@
44
# This source code is licensed under the terms described in the LICENSE file in
55
# the root directory of this source tree.
66

7-
import logging
7+
import importlib
8+
import json
89
import os
910
import signal
1011
import subprocess
1112
import sys
13+
from pathlib import Path
1214

1315
from termcolor import cprint
1416

15-
log = logging.getLogger(__name__)
16-
17-
import importlib
18-
import json
19-
from pathlib import Path
20-
2117
from llama_stack.distribution.utils.image_types import LlamaStackImageType
18+
from llama_stack.log import get_logger
19+
20+
logger = get_logger(name=__name__, category="core")
2221

2322

2423
def formulate_run_args(image_type: str, image_name: str) -> list[str]:
@@ -119,7 +118,7 @@ def run_command(command: list[str]) -> int:
119118
def sigint_handler(signum, frame):
120119
nonlocal ctrl_c_pressed
121120
ctrl_c_pressed = True
122-
log.info("\nCtrl-C detected. Aborting...")
121+
logger.info("\nCtrl-C detected. Aborting...")
123122

124123
try:
125124
# Set up the signal handler
@@ -133,10 +132,10 @@ def sigint_handler(signum, frame):
133132
)
134133
return result.returncode
135134
except subprocess.SubprocessError as e:
136-
log.error(f"Subprocess error: {e}")
135+
logger.error(f"Subprocess error: {e}")
137136
return 1
138137
except Exception as e:
139-
log.exception(f"Unexpected error: {e}")
138+
logger.exception(f"Unexpected error: {e}")
140139
return 1
141140
finally:
142141
# Restore the original signal handler

llama_stack/distribution/utils/prompt_for_config.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66

77
import inspect
88
import json
9-
import logging
109
from enum import Enum
1110
from typing import Annotated, Any, Literal, Union, get_args, get_origin
1211

1312
from pydantic import BaseModel
1413
from pydantic.fields import FieldInfo
1514
from pydantic_core import PydanticUndefinedType
1615

17-
log = logging.getLogger(__name__)
16+
from llama_stack.log import get_logger
17+
18+
logger = get_logger(name=__name__, category="core")
1819

1920

2021
def is_list_of_primitives(field_type):
@@ -107,7 +108,7 @@ def prompt_for_discriminated_union(
107108

108109
if discriminator_value in type_map:
109110
chosen_type = type_map[discriminator_value]
110-
log.info(f"\nConfiguring {chosen_type.__name__}:")
111+
logger.info(f"\nConfiguring {chosen_type.__name__}:")
111112

112113
if existing_value and (getattr(existing_value, discriminator) != discriminator_value):
113114
existing_value = None
@@ -117,7 +118,7 @@ def prompt_for_discriminated_union(
117118
setattr(sub_config, discriminator, discriminator_value)
118119
return sub_config
119120
else:
120-
log.error(f"Invalid {discriminator}. Please try again.")
121+
logger.error(f"Invalid {discriminator}. Please try again.")
121122

122123

123124
# This is somewhat elaborate, but does not purport to be comprehensive in any way.
@@ -166,7 +167,7 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
166167
config_data[field_name] = validated_value
167168
break
168169
except KeyError:
169-
log.error(f"Invalid choice. Please choose from: {', '.join(e.name for e in field_type)}")
170+
logger.error(f"Invalid choice. Please choose from: {', '.join(e.name for e in field_type)}")
170171
continue
171172

172173
if is_discriminated_union(field):
@@ -179,7 +180,7 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
179180
config_data[field_name] = None
180181
continue
181182
nested_type = get_non_none_type(field_type)
182-
log.info(f"Entering sub-configuration for {field_name}:")
183+
logger.info(f"Entering sub-configuration for {field_name}:")
183184
config_data[field_name] = prompt_for_config(nested_type, existing_value)
184185
elif is_optional(field_type) and is_discriminated_union(get_non_none_type(field_type)):
185186
prompt = f"Do you want to configure {field_name}? (y/n): "
@@ -193,7 +194,7 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
193194
existing_value,
194195
)
195196
elif can_recurse(field_type):
196-
log.info(f"\nEntering sub-configuration for {field_name}:")
197+
logger.info(f"\nEntering sub-configuration for {field_name}:")
197198
config_data[field_name] = prompt_for_config(
198199
field_type,
199200
existing_value,
@@ -220,7 +221,7 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
220221
config_data[field_name] = None
221222
break
222223
else:
223-
log.error("This field is required. Please provide a value.")
224+
logger.error("This field is required. Please provide a value.")
224225
continue
225226
else:
226227
try:
@@ -242,10 +243,10 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
242243
value = [element_type(item) for item in value]
243244

244245
except json.JSONDecodeError:
245-
log.error('Invalid JSON. Please enter a valid JSON-encoded list e.g., ["foo","bar"]')
246+
logger.error('Invalid JSON. Please enter a valid JSON-encoded list e.g., ["foo","bar"]')
246247
continue
247248
except ValueError as e:
248-
log.error(f"{str(e)}")
249+
logger.error(f"{str(e)}")
249250
continue
250251

251252
elif get_origin(field_type) is dict:
@@ -255,7 +256,7 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
255256
raise ValueError("Input must be a JSON-encoded dictionary")
256257

257258
except json.JSONDecodeError:
258-
log.error("Invalid JSON. Please enter a valid JSON-encoded dict.")
259+
logger.error("Invalid JSON. Please enter a valid JSON-encoded dict.")
259260
continue
260261

261262
# Convert the input to the correct type
@@ -268,7 +269,9 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
268269
value = field_type(user_input)
269270

270271
except ValueError:
271-
log.error(f"Invalid input. Expected type: {getattr(field_type, '__name__', str(field_type))}")
272+
logger.error(
273+
f"Invalid input. Expected type: {getattr(field_type, '__name__', str(field_type))}"
274+
)
272275
continue
273276

274277
try:
@@ -277,6 +280,6 @@ def prompt_for_config(config_type: type[BaseModel], existing_config: BaseModel |
277280
config_data[field_name] = validated_value
278281
break
279282
except ValueError as e:
280-
log.error(f"Validation error: {str(e)}")
283+
logger.error(f"Validation error: {str(e)}")
281284

282285
return config_type(**config_data)

llama_stack/log.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
# This source code is licensed under the terms described in the LICENSE file in
55
# the root directory of this source tree.
66

7-
import logging
7+
import logging # allow-direct-logging
88
import os
99
import re
1010
import sys
11-
from logging.config import dictConfig
11+
from logging.config import dictConfig # allow-direct-logging
1212

1313
from rich.console import Console
1414
from rich.errors import MarkupError

llama_stack/models/llama/llama4/quantization/loader.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
# This source code is licensed under the terms described in the LICENSE file in
55
# the root directory of this source tree.
66

7-
import logging
87
import os
98
from collections.abc import Callable
109

@@ -13,12 +12,12 @@
1312
from torch import Tensor, nn
1413
from torch.nn import functional as F
1514

15+
from llama_stack.log import log
16+
1617
from ...datatypes import QuantizationMode
1718
from ..model import Transformer, TransformerBlock
1819
from ..moe import MoE
1920

20-
log = logging.getLogger(__name__)
21-
2221

2322
def swiglu_wrapper_no_reduce(
2423
self,

llama_stack/models/llama/quantize_impls.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66

77
# type: ignore
88
import collections
9-
import logging
109

11-
log = logging.getLogger(__name__)
10+
from llama_stack.log import log
1211

1312
try:
1413
import fbgemm_gpu.experimental.gen_ai # noqa: F401

llama_stack/providers/inline/agents/meta_reference/persistence.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# the root directory of this source tree.
66

77
import json
8-
import logging
98
import uuid
109
from datetime import UTC, datetime
1110

@@ -14,9 +13,10 @@
1413
from llama_stack.distribution.access_control.datatypes import AccessRule
1514
from llama_stack.distribution.datatypes import User
1615
from llama_stack.distribution.request_headers import get_authenticated_user
17-
from llama_stack.providers.utils.kvstore import KVStore
16+
from llama_stack.log import get_logger
1817

19-
log = logging.getLogger(__name__)
18+
logger = get_logger(name=__name__, category="agents")
19+
from llama_stack.providers.utils.kvstore import KVStore
2020

2121

2222
class AgentSessionInfo(Session):
@@ -126,7 +126,7 @@ async def get_session_turns(self, session_id: str) -> list[Turn]:
126126
turn = Turn(**json.loads(value))
127127
turns.append(turn)
128128
except Exception as e:
129-
log.error(f"Error parsing turn: {e}")
129+
logger.error(f"Error parsing turn: {e}")
130130
continue
131131

132132
# The kvstore does not guarantee order, so we sort by started_at
@@ -193,7 +193,7 @@ async def list_sessions(self) -> list[Session]:
193193
session_info = Session(**json.loads(value))
194194
sessions.append(session_info)
195195
except Exception as e:
196-
log.error(f"Error parsing session info: {e}")
196+
logger.error(f"Error parsing session info: {e}")
197197
continue
198198
return sessions
199199

llama_stack/providers/inline/agents/meta_reference/safety.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
# the root directory of this source tree.
66

77
import asyncio
8-
import logging
98

109
from llama_stack.apis.inference import Message
1110
from llama_stack.apis.safety import Safety, SafetyViolation, ViolationLevel
12-
from llama_stack.providers.utils.telemetry import tracing
11+
from llama_stack.log import get_logger
1312

14-
log = logging.getLogger(__name__)
13+
logger = get_logger(name=__name__, category="agents")
14+
from llama_stack.providers.utils.telemetry import tracing
1515

1616

1717
class SafetyException(Exception): # noqa: N818
@@ -49,4 +49,4 @@ async def run_shield_with_span(identifier: str):
4949
if violation.violation_level == ViolationLevel.ERROR:
5050
raise SafetyException(violation)
5151
elif violation.violation_level == ViolationLevel.WARN:
52-
log.warning(f"[Warn]{identifier} raised a warning")
52+
logger.warning(f"[Warn]{identifier} raised a warning")

0 commit comments

Comments
 (0)