Skip to content

Commit 74bb552

Browse files
authored
Merge pull request #45 from Azure-Samples/m-hietala/tracing_and_file_logging_related_updates
tracing and file logging related updates
2 parents bf2bb5f + 607b59d commit 74bb552

File tree

3 files changed

+70
-58
lines changed

3 files changed

+70
-58
lines changed

src/api/main.py

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,52 +18,16 @@
1818
from fastapi.responses import JSONResponse
1919
from dotenv import load_dotenv
2020

21-
# Create a central logger for the application
22-
logger = logging.getLogger("azureaiapp")
23-
logger.setLevel(logging.INFO)
24-
25-
# Configure the stream handler (stdout)
26-
stream_handler = logging.StreamHandler(sys.stdout)
27-
stream_handler.setLevel(logging.INFO)
28-
stream_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
29-
stream_handler.setFormatter(stream_formatter)
30-
logger.addHandler(stream_handler)
31-
32-
# Configure logging to file, if log file name is provided
33-
log_file_name = os.getenv("APP_LOG_FILE", "")
34-
if log_file_name != "":
35-
file_handler = logging.FileHandler(log_file_name)
36-
file_handler.setLevel(logging.INFO)
37-
file_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
38-
file_handler.setFormatter(file_formatter)
39-
logger.addHandler(file_handler)
40-
41-
enable_trace_string = os.getenv("ENABLE_AZURE_MONITOR_TRACING", "")
21+
from logging_config import configure_logging
22+
4223
enable_trace = False
43-
if enable_trace_string != "":
44-
enable_trace = False
45-
else:
46-
enable_trace = str(enable_trace_string).lower() == "true"
47-
if enable_trace:
48-
logger.info("Tracing is enabled.")
49-
try:
50-
from azure.monitor.opentelemetry import configure_azure_monitor
51-
except ModuleNotFoundError:
52-
logger.error("Required libraries for tracing not installed.")
53-
logger.error("Please make sure azure-monitor-opentelemetry is installed.")
54-
exit()
55-
else:
56-
logger.info("Tracing is not enabled")
24+
logger = None
5725

5826
@contextlib.asynccontextmanager
5927
async def lifespan(app: fastapi.FastAPI):
6028
agent = None
6129

6230
try:
63-
if not os.getenv("RUNNING_IN_PRODUCTION"):
64-
logger.info("Loading .env file")
65-
load_dotenv(override=True)
66-
6731
ai_client = AIProjectClient.from_connection_string(
6832
credential=DefaultAzureCredential(exclude_shared_token_cache_credential=True),
6933
conn_str=os.environ["AZURE_AIPROJECT_CONNECTION_STRING"],
@@ -82,7 +46,10 @@ async def lifespan(app: fastapi.FastAPI):
8246
logger.error("Enable it via the 'Tracing' tab in your AI Foundry project page.")
8347
exit()
8448
else:
49+
from azure.monitor.opentelemetry import configure_azure_monitor
8550
configure_azure_monitor(connection_string=application_insights_connection_string)
51+
# Do not instrument the code yet, before trace fix is available.
52+
#ai_client.telemetry.enable()
8653

8754
if os.environ.get("AZURE_AI_AGENT_ID"):
8855
try:
@@ -125,6 +92,30 @@ async def lifespan(app: fastapi.FastAPI):
12592

12693

12794
def create_app():
95+
if not os.getenv("RUNNING_IN_PRODUCTION"):
96+
load_dotenv(override=True)
97+
98+
global logger
99+
logger = configure_logging(os.getenv("APP_LOG_FILE", ""))
100+
101+
enable_trace_string = os.getenv("ENABLE_AZURE_MONITOR_TRACING", "")
102+
global enable_trace
103+
enable_trace = False
104+
if enable_trace_string == "":
105+
enable_trace = False
106+
else:
107+
enable_trace = str(enable_trace_string).lower() == "true"
108+
if enable_trace:
109+
logger.info("Tracing is enabled.")
110+
try:
111+
from azure.monitor.opentelemetry import configure_azure_monitor
112+
except ModuleNotFoundError:
113+
logger.error("Required libraries for tracing not installed.")
114+
logger.error("Please make sure azure-monitor-opentelemetry is installed.")
115+
exit()
116+
else:
117+
logger.info("Tracing is not enabled")
118+
128119
directory = os.path.join(os.path.dirname(__file__), "static")
129120
app = fastapi.FastAPI(lifespan=lifespan)
130121
app.mount("/static", StaticFiles(directory=directory), name="static")

src/gunicorn.conf.py

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,11 @@
1111

1212
from dotenv import load_dotenv
1313

14+
from logging_config import configure_logging
15+
1416
load_dotenv()
1517

16-
# Create a central logger for the application
17-
logger = logging.getLogger("azureaiapp")
18-
logger.setLevel(logging.INFO)
19-
20-
# Configure the stream handler (stdout)
21-
stream_handler = logging.StreamHandler(sys.stdout)
22-
stream_handler.setLevel(logging.INFO)
23-
stream_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
24-
stream_handler.setFormatter(stream_formatter)
25-
logger.addHandler(stream_handler)
26-
27-
# Configure logging to file, if log file name is provided
28-
log_file_name = os.getenv("APP_LOG_FILE", "")
29-
if log_file_name != "":
30-
file_handler = logging.FileHandler(log_file_name)
31-
file_handler.setLevel(logging.INFO)
32-
file_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
33-
file_handler.setFormatter(file_formatter)
34-
logger.addHandler(file_handler)
18+
logger = configure_logging(os.getenv("APP_LOG_FILE", ""))
3519

3620
FILES_NAMES = ["product_info_1.md", "product_info_2.md"]
3721

src/logging_config.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
# Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
3+
4+
import logging
5+
import sys
6+
from typing import Optional
7+
8+
def configure_logging(log_file_name: Optional[str] = None, logger_name: str = "azureaiapp") -> logging.Logger:
9+
"""
10+
Configure and return a logger with both stream (stdout) and optional file handlers.
11+
12+
:param log_file_name: The path to the log file. If provided, logs will also be written to this file.
13+
:type log_file_name: Optional[str]
14+
:param logger_name: The name of the logger to configure.
15+
:type logger_name: str
16+
:return: The configured logger instance.
17+
:rtype: logging.Logger
18+
"""
19+
logger = logging.getLogger(logger_name)
20+
logger.setLevel(logging.INFO)
21+
22+
# Stream handler (stdout)
23+
stream_handler = logging.StreamHandler(sys.stdout)
24+
stream_handler.setLevel(logging.INFO)
25+
stream_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
26+
stream_handler.setFormatter(stream_formatter)
27+
logger.addHandler(stream_handler)
28+
29+
# File handler if a log file is specified
30+
if log_file_name:
31+
file_handler = logging.FileHandler(log_file_name)
32+
file_handler.setLevel(logging.INFO)
33+
file_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
34+
file_handler.setFormatter(file_formatter)
35+
logger.addHandler(file_handler)
36+
37+
return logger

0 commit comments

Comments
 (0)