Skip to content

Commit 848a0aa

Browse files
Merge pull request #609 from microsoft/PSL-US-26408
feat: Implementation of Configurable Logging Control via Flag
2 parents 71604db + 3e9392e commit 848a0aa

File tree

7 files changed

+113
-67
lines changed

7 files changed

+113
-67
lines changed

infra/main.bicep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,9 @@ module webSite 'modules/web-sites.bicep' = {
12091209
UWSGI_THREADS: '2'
12101210
APP_ENV: appEnvironment
12111211
AZURE_CLIENT_ID: userAssignedIdentity.outputs.clientId
1212+
AZURE_BASIC_LOGGING_LEVEL: 'INFO'
1213+
AZURE_PACKAGE_LOGGING_LEVEL: 'WARNING'
1214+
AZURE_LOGGING_PACKAGES: ''
12121215
}
12131216
// WAF aligned configuration for Monitoring
12141217
applicationInsightResourceId: enableMonitoring ? applicationInsights!.outputs.resourceId : null

infra/main.json

Lines changed: 47 additions & 42 deletions
Large diffs are not rendered by default.

infra/main_custom.bicep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,9 @@ module webSite 'modules/web-sites.bicep' = {
12011201
UWSGI_THREADS: '2'
12021202
APP_ENV: appEnvironment
12031203
AZURE_CLIENT_ID: userAssignedIdentity.outputs.clientId
1204+
AZURE_BASIC_LOGGING_LEVEL: 'INFO'
1205+
AZURE_PACKAGE_LOGGING_LEVEL: 'WARNING'
1206+
AZURE_LOGGING_PACKAGES: ''
12041207
}
12051208
// WAF aligned configuration for Monitoring
12061209
applicationInsightResourceId: enableMonitoring ? applicationInsights!.outputs.resourceId : null

src/.env.sample

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
# Chat
2-
DEBUG=True
1+
# Basic application logging (default: INFO level)
2+
AZURE_BASIC_LOGGING_LEVEL=INFO
3+
# Azure package logging (default: WARNING level to suppress INFO)
4+
AZURE_PACKAGE_LOGGING_LEVEL=WARNING
5+
# Comma-separated list of specific logger names to configure (default: empty - no custom loggers)
6+
# Example: AZURE_LOGGING_PACKAGES=azure.identity.aio._internal,azure.monitor.opentelemetry.exporter.export._base
7+
AZURE_LOGGING_PACKAGES=
8+
39
AZURE_AI_AGENT_API_VERSION=
410
AZURE_AI_AGENT_ENDPOINT=
511
AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=

src/app.py

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
MINIMUM_SUPPORTED_AZURE_OPENAI_PREVIEW_API_VERSION, app_settings)
2121
from backend.utils import (ChatType, format_as_ndjson,
2222
format_non_streaming_response,
23-
format_stream_response)
23+
format_stream_response, configure_logging)
2424
from event_utils import track_event_if_configured
2525
from azure.monitor.opentelemetry import configure_azure_monitor
2626
from opentelemetry import trace
@@ -40,6 +40,9 @@
4040

4141
bp = Blueprint("routes", __name__, static_folder="static", template_folder="static")
4242

43+
# Configure logging based on environment variables
44+
configure_logging(app_settings.logging)
45+
4346
# Check if the Application Insights Instrumentation Key is set in the environment variables
4447
instrumentation_key = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING")
4548
if instrumentation_key:
@@ -50,20 +53,6 @@
5053
# Log a warning if the Instrumentation Key is not found
5154
logging.warning("No Application Insights Instrumentation Key found. Skipping configuration")
5255

53-
# Configure logging
54-
logging.basicConfig(level=logging.INFO)
55-
56-
# Suppress INFO logs from 'azure.core.pipeline.policies.http_logging_policy'
57-
logging.getLogger("azure.core.pipeline.policies.http_logging_policy").setLevel(
58-
logging.WARNING
59-
)
60-
logging.getLogger("azure.identity.aio._internal").setLevel(logging.WARNING)
61-
62-
# Suppress info logs from OpenTelemetry exporter
63-
logging.getLogger("azure.monitor.opentelemetry.exporter.export._base").setLevel(
64-
logging.WARNING
65-
)
66-
6756

6857
def create_app():
6958
app = Quart(__name__)
@@ -115,10 +104,7 @@ async def assets(path):
115104
return await send_from_directory("static/assets", path)
116105

117106

118-
# Debug settings
119-
DEBUG = os.environ.get("DEBUG", "false")
120-
if DEBUG.lower() == "true":
121-
logging.basicConfig(level=logging.DEBUG)
107+
# Debug settings are now handled by the logging configuration above
122108

123109
USER_AGENT = "GitHubSampleWebApp/AsyncAzureOpenAI/1.0.0"
124110

src/backend/settings.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,31 @@ class _UiSettings(BaseSettings):
3434
show_share_button: bool = False
3535

3636

37+
class _LoggingSettings(BaseSettings):
38+
model_config = SettingsConfigDict(
39+
env_prefix="AZURE_", env_file=DOTENV_PATH, extra="ignore", env_ignore_empty=True
40+
)
41+
42+
basic_logging_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "INFO"
43+
package_logging_level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "WARNING"
44+
logging_packages: Optional[List[str]] = []
45+
46+
@field_validator("logging_packages", mode="before")
47+
@classmethod
48+
def split_logging_packages(cls, packages) -> Optional[List[str]]:
49+
if isinstance(packages, str) and len(packages.strip()) > 0:
50+
return [pkg.strip() for pkg in packages.split(",") if pkg.strip()]
51+
return None
52+
53+
def get_basic_log_level(self) -> int:
54+
"""Convert string log level to logging constant"""
55+
return getattr(logging, self.basic_logging_level.upper())
56+
57+
def get_package_log_level(self) -> int:
58+
"""Convert string package log level to logging constant"""
59+
return getattr(logging, self.package_logging_level.upper())
60+
61+
3762
class _ChatHistorySettings(BaseSettings):
3863
model_config = SettingsConfigDict(
3964
env_prefix="AZURE_COSMOSDB_",
@@ -367,6 +392,7 @@ class _AppSettings(BaseModel):
367392
azure_ai: _AzureAISettings = _AzureAISettings()
368393
search: _SearchCommonSettings = _SearchCommonSettings()
369394
ui: Optional[_UiSettings] = _UiSettings()
395+
logging: _LoggingSettings = _LoggingSettings()
370396

371397
# Constructed properties
372398
chat_history: Optional[_ChatHistorySettings] = None

src/backend/utils.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
import uuid
99
import time
1010

11-
DEBUG = os.environ.get("DEBUG", "false")
12-
if DEBUG.lower() == "true":
13-
logging.basicConfig(level=logging.DEBUG)
14-
1511
AZURE_SEARCH_PERMITTED_GROUPS_COLUMN = os.environ.get(
1612
"AZURE_SEARCH_PERMITTED_GROUPS_COLUMN"
1713
)
@@ -153,3 +149,24 @@ def comma_separated_string_to_list(s: str) -> List[str]:
153149
Split comma-separated values into a list.
154150
"""
155151
return s.strip().replace(" ", "").split(",")
152+
153+
154+
def configure_logging(logging_settings):
155+
"""
156+
Configure logging based on the provided logging settings.
157+
158+
Args:
159+
logging_settings: Instance of _LoggingSettings containing logging configuration
160+
"""
161+
# Configure basic logging
162+
logging.basicConfig(
163+
level=logging_settings.get_basic_log_level(),
164+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
165+
force=True # Override any existing configuration
166+
)
167+
168+
azure_log_level = logging_settings.get_package_log_level()
169+
for logger_name in logging_settings.logging_packages or []:
170+
logging.getLogger(logger_name).setLevel(azure_log_level)
171+
172+
logging.info(f"Logging configured - Basic: {logging_settings.basic_logging_level}, Azure packages: {logging_settings.package_logging_level}, Packages: {logging_settings.logging_packages}")

0 commit comments

Comments
 (0)