2222
2323logger = logging .getLogger (__name__ )
2424
25- _console_logging_enabled : bool = os .environ .get ("AZURE_AI_PROJECTS_CONSOLE_LOGGING" , "False" ).lower () in (
26- "true" ,
27- "1" ,
28- "yes" ,
29- )
30- if _console_logging_enabled :
31- import sys
32-
33- # Enable detailed console logs across Azure libraries
34- azure_logger = logging .getLogger ("azure" )
35- azure_logger .setLevel (logging .DEBUG )
36- azure_logger .addHandler (logging .StreamHandler (stream = sys .stdout ))
37- # Exclude detailed logs for network calls associated with getting Entra ID token.
38- identity_logger = logging .getLogger ("azure.identity" )
39- identity_logger .setLevel (logging .ERROR )
40- # Make sure regular (redacted) detailed azure.core logs are not shown, as we are about to
41- # turn on non-redacted logs by passing 'logging_enable=True' to the client constructor
42- # (which are implemented as a separate logging policy)
43- logger = logging .getLogger ("azure.core.pipeline.policies.http_logging_policy" )
44- logger .setLevel (logging .ERROR )
45-
4625
4726class AIProjectClient (AIProjectClientGenerated ): # pylint: disable=too-many-instance-attributes
4827 """AIProjectClient.
@@ -89,7 +68,27 @@ class AIProjectClient(AIProjectClientGenerated): # pylint: disable=too-many-ins
8968
9069 def __init__ (self , endpoint : str , credential : AsyncTokenCredential , ** kwargs : Any ) -> None :
9170
92- kwargs .setdefault ("logging_enable" , _console_logging_enabled )
71+ self ._console_logging_enabled : bool = (
72+ os .environ .get ("AZURE_AI_PROJECTS_CONSOLE_LOGGING" , "false" ).lower () == "true"
73+ )
74+
75+ if self ._console_logging_enabled :
76+ import sys
77+
78+ # Enable detailed console logs across Azure libraries
79+ azure_logger = logging .getLogger ("azure" )
80+ azure_logger .setLevel (logging .DEBUG )
81+ azure_logger .addHandler (logging .StreamHandler (stream = sys .stdout ))
82+ # Exclude detailed logs for network calls associated with getting Entra ID token.
83+ identity_logger = logging .getLogger ("azure.identity" )
84+ identity_logger .setLevel (logging .ERROR )
85+ # Make sure regular (redacted) detailed azure.core logs are not shown, as we are about to
86+ # turn on non-redacted logs by passing 'logging_enable=True' to the client constructor
87+ # (which are implemented as a separate logging policy)
88+ logger = logging .getLogger ("azure.core.pipeline.policies.http_logging_policy" )
89+ logger .setLevel (logging .ERROR )
90+
91+ kwargs .setdefault ("logging_enable" , self ._console_logging_enabled )
9392
9493 self ._kwargs = kwargs .copy ()
9594 self ._patched_user_agent = _patch_user_agent (self ._kwargs .pop ("user_agent" , None ))
@@ -134,7 +133,6 @@ async def get_openai_client(self, **kwargs) -> "AsyncOpenAI": # type: ignore[na
134133 "azure.identity package not installed. Please install it using 'pip install azure.identity'"
135134 ) from e
136135
137- # TODO: Test the case where input endpoint URL has "/" at the end
138136 base_url = self ._config .endpoint + "/openai" # pylint: disable=protected-access
139137
140138 if "default_query" not in kwargs :
@@ -147,7 +145,7 @@ async def get_openai_client(self, **kwargs) -> "AsyncOpenAI": # type: ignore[na
147145
148146 http_client = None
149147
150- if _console_logging_enabled :
148+ if self . _console_logging_enabled :
151149 try :
152150 import httpx
153151 except ModuleNotFoundError as e :
@@ -185,7 +183,7 @@ async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
185183 headers = dict (request .headers )
186184 self ._sanitize_auth_header (headers )
187185 print ("Headers:" )
188- for key , value in headers .items ():
186+ for key , value in sorted ( headers .items () ):
189187 print (f" { key } : { value } " )
190188
191189 self ._log_request_body (request )
@@ -194,13 +192,17 @@ async def handle_async_request(self, request: httpx.Request) -> httpx.Response:
194192
195193 print (f"\n <== Response:\n { response .status_code } { response .reason_phrase } " )
196194 print ("Headers:" )
197- for key , value in dict (response .headers ).items ():
195+ for key , value in sorted ( dict (response .headers ).items () ):
198196 print (f" { key } : { value } " )
199- try :
200- content = await response .aread ()
201- print (f"Body:\n { content .decode ('utf-8' )} " )
202- except Exception : # pylint: disable=broad-exception-caught
203- print ("Body:\n [non-text content]" )
197+
198+ content = await response .aread ()
199+ if content is None or content == b"" :
200+ print ("Body: [No content]" )
201+ else :
202+ try :
203+ print (f"Body:\n { content .decode ('utf-8' )} " )
204+ except Exception : # pylint: disable=broad-exception-caught
205+ print (f"Body (raw):\n { content !r} " )
204206 print ("\n " )
205207
206208 return response
@@ -230,8 +232,7 @@ def _log_request_body(self, request: httpx.Request) -> None:
230232 print (f"Body: [Cannot access content: { access_error } ]" )
231233 return
232234
233- # Check if content is None or empty
234- if content is None :
235+ if content is None or content == b"" :
235236 print ("Body: [No content]" )
236237 return
237238
0 commit comments