Skip to content

Commit 0bd12c6

Browse files
Merge pull request #811 from microsoft/psl-logging-improvements
feat: improve Application Insights logging and telemetry handling
2 parents cce4cb9 + cfdfd47 commit 0bd12c6

File tree

10 files changed

+385
-76
lines changed

10 files changed

+385
-76
lines changed

infra/main.bicep

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,6 @@ module applicationInsights 'br/public:avm/res/insights/component:0.7.1' = if (en
331331
flowType: 'Bluefield'
332332
// WAF aligned configuration for Monitoring
333333
workspaceResourceId: enableMonitoring ? logAnalyticsWorkspaceResourceId : ''
334-
diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null
335334
}
336335
}
337336
// ========== Virtual Network and Networking Components ========== //

src/api/api/api_routes.py

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,19 @@
1212
from services.chart_service import ChartService
1313
from common.logging.event_utils import track_event_if_configured
1414
from helpers.azure_credential_utils import get_azure_credential
15-
from azure.monitor.opentelemetry import configure_azure_monitor
15+
from auth.auth_utils import get_authenticated_user_details
1616
from opentelemetry import trace
1717
from opentelemetry.trace import Status, StatusCode
1818

1919
router = APIRouter()
2020

2121
logger = logging.getLogger(__name__)
2222

23-
# Check if the Application Insights Instrumentation Key is set in the environment variables
24-
instrumentation_key = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING")
25-
if instrumentation_key:
26-
# Configure Application Insights if the Instrumentation Key is found
27-
configure_azure_monitor(connection_string=instrumentation_key)
28-
logging.info("Application Insights configured with the provided Instrumentation Key")
29-
else:
30-
# Log a warning if the Instrumentation Key is not found
31-
logging.warning("No Application Insights Instrumentation Key found. Skipping configuration")
32-
3323

3424
@router.get("/fetchChartData")
3525
async def fetch_chart_data():
3626
try:
27+
logger.info("GET /fetchChartData called")
3728
chart_service = ChartService()
3829
response = await chart_service.fetch_chart_data()
3930
track_event_if_configured(
@@ -43,6 +34,10 @@ async def fetch_chart_data():
4334
return JSONResponse(content=response)
4435
except Exception as e:
4536
logger.exception("Error in fetch_chart_data: %s", str(e))
37+
track_event_if_configured("FetchChartDataError", {
38+
"error": str(e),
39+
"error_type": type(e).__name__
40+
})
4641
span = trace.get_current_span()
4742
if span is not None:
4843
span.record_exception(e)
@@ -53,7 +48,7 @@ async def fetch_chart_data():
5348
@router.post("/fetchChartDataWithFilters")
5449
async def fetch_chart_data_with_filters(chart_filters: ChartFilters):
5550
try:
56-
logger.info(f"Received filters: {chart_filters}")
51+
logger.info("Received filters: %s", chart_filters)
5752
chart_service = ChartService()
5853
response = await chart_service.fetch_chart_data_with_filters(chart_filters)
5954
track_event_if_configured(
@@ -69,6 +64,10 @@ async def fetch_chart_data_with_filters(chart_filters: ChartFilters):
6964
return JSONResponse(content=response)
7065
except Exception as e:
7166
logger.exception("Error in fetch_chart_data_with_filters: %s", str(e))
67+
track_event_if_configured("FetchChartDataWithFiltersError", {
68+
"error": str(e),
69+
"error_type": type(e).__name__
70+
})
7271
span = trace.get_current_span()
7372
if span is not None:
7473
span.record_exception(e)
@@ -79,6 +78,7 @@ async def fetch_chart_data_with_filters(chart_filters: ChartFilters):
7978
@router.get("/fetchFilterData")
8079
async def fetch_filter_data():
8180
try:
81+
logger.info("GET /fetchFilterData called")
8282
chart_service = ChartService()
8383
response = await chart_service.fetch_filter_data()
8484
track_event_if_configured(
@@ -88,6 +88,10 @@ async def fetch_filter_data():
8888
return JSONResponse(content=response)
8989
except Exception as e:
9090
logger.exception("Error in fetch_filter_data: %s", str(e))
91+
track_event_if_configured("FetchFilterDataError", {
92+
"error": str(e),
93+
"error_type": type(e).__name__
94+
})
9195
span = trace.get_current_span()
9296
if span is not None:
9397
span.record_exception(e)
@@ -102,16 +106,42 @@ async def conversation(request: Request):
102106
request_json = await request.json()
103107
conversation_id = request_json.get("conversation_id")
104108
query = request_json.get("query")
109+
authenticated_user = get_authenticated_user_details(request_headers=request.headers)
110+
user_id = authenticated_user.get("user_principal_id", "")
111+
logger.info("POST /chat called: conversation_id=%s, query_length=%d",
112+
conversation_id, len(query) if query else 0)
113+
114+
# Track chat request initiation
115+
track_event_if_configured("ChatRequestReceived", {
116+
"conversation_id": conversation_id,
117+
"user_id": user_id
118+
})
119+
120+
# Attach conversation_id to current span for Application Insights correlation
121+
span = trace.get_current_span()
122+
if span and conversation_id:
123+
span.set_attribute("conversation_id", conversation_id)
124+
105125
chat_service = ChatService()
106-
result = await chat_service.stream_chat_request(conversation_id, query)
126+
result = await chat_service.stream_chat_request(conversation_id, query, user_id=user_id)
127+
logger.info("Chat stream initiated successfully for conversation_id=%s", conversation_id)
107128
track_event_if_configured(
108129
"ChatStreamSuccess",
109-
{"conversation_id": conversation_id, "query": query}
130+
{"conversation_id": conversation_id, "user_id": user_id, "query": query}
110131
)
111132
return StreamingResponse(result, media_type="application/json-lines")
112133

113134
except Exception as ex:
114135
logger.exception("Error in conversation endpoint: %s", str(ex))
136+
137+
# Track specific error type
138+
track_event_if_configured("ChatRequestError", {
139+
"conversation_id": request_json.get("conversation_id") if 'request_json' in locals() else "",
140+
"user_id": locals().get("user_id", ""),
141+
"error": str(ex),
142+
"error_type": type(ex).__name__
143+
})
144+
115145
span = trace.get_current_span()
116146
if span is not None:
117147
span.record_exception(ex)
@@ -121,6 +151,7 @@ async def conversation(request: Request):
121151

122152
@router.get("/layout-config")
123153
async def get_layout_config():
154+
logger.info("GET /layout-config called")
124155
layout_config_str = os.getenv("REACT_APP_LAYOUT_CONFIG", "")
125156
if layout_config_str:
126157
try:
@@ -129,6 +160,10 @@ async def get_layout_config():
129160
return JSONResponse(content=layout_config_json) # Return the parsed JSON
130161
except json.JSONDecodeError as e:
131162
logger.exception("Failed to parse layout config JSON: %s", str(e))
163+
track_event_if_configured("LayoutConfigParseError", {
164+
"error": str(e),
165+
"error_type": "JSONDecodeError"
166+
})
132167
span = trace.get_current_span()
133168
if span is not None:
134169
span.record_exception(e)
@@ -140,6 +175,7 @@ async def get_layout_config():
140175

141176
@router.get("/display-chart-default")
142177
async def get_chart_config():
178+
logger.info("GET /display-chart-default called")
143179
chart_config = os.getenv("DISPLAY_CHART_DEFAULT", "")
144180
if chart_config:
145181
track_event_if_configured("ChartDisplayDefaultFetched", {"value": chart_config})
@@ -158,6 +194,7 @@ async def fetch_azure_search_content_endpoint(request: Request):
158194
# Parse the request JSON
159195
request_json = await request.json()
160196
url = request_json.get("url")
197+
logger.info("POST /fetch-azure-search-content called: url=%s", url)
161198

162199
if not url:
163200
return JSONResponse(content={"error": "URL is required"}, status_code=400)
@@ -183,8 +220,10 @@ def fetch_content():
183220
data = response.json()
184221
content = data.get("content", "")
185222
title = data.get("sourceurl", "")
223+
logger.info("Azure Search content fetched successfully: url=%s", url)
186224
return {"content": content, "title": title}
187225
else:
226+
logger.warning("Azure Search content fetch failed: url=%s, status=%d", url, response.status_code)
188227
return {"error": f"HTTP {response.status_code}"}
189228
except Exception:
190229
logger.exception("Exception occurred while making the HTTP request")

0 commit comments

Comments
 (0)