[← Back to Reviews Index](../Stewards%20Reviews%20Index.md)

# React UX Observability Review — Azure-AI-RAG-CSharp-Semantic-Kernel-Functions

| Field | Value |
|---|---|
| Project | Azure-AI-RAG-CSharp-Semantic-Kernel-Functions |
| Review Date | 2026-03-21 |
| Steward | React UX Observability Steward (UOTL) |
| Scope | React frontend at `src/web/` |
| Critical | 3 |
| Notable | 3 |
| Minor | 2 |
| Info | 2 |
| Total Findings | 10 |

---

## 1. Frontend Observability Overview

The React frontend is a Create React App (CRA) project bootstrapped with `react-scripts 5.0.1`. It provides a single-page chat interface that sends user messages to a backend API and displays AI responses. The application has one route and consists of six components: `App`, `Main`, `SupportAgent`, `ChatLayout`, `AzureFreeAccount`, and `AzureServiceCards`.

**Overall observability posture: Very Poor.**

The application has no error boundaries, no global error handlers, no Application Insights integration, no structured logging, and no active performance monitoring. Errors that occur in any component — including during API calls — are either silently swallowed or cause full application crashes with no visibility to the development team. The application is effectively a black box in production.

The `web-vitals` package is present in `dependencies` and `reportWebVitals.js` exists, but the function is called with no callback (`reportWebVitals()`), making performance data collection completely inert.

---

## 2. Error Boundary Assessment

**Result: No error boundaries exist anywhere in the application.**

None of the six components — `App`, `Main`, `SupportAgent`, `ChatLayout`, `AzureFreeAccount`, or `AzureServiceCards` — implement or are wrapped in a React Error Boundary. There is no `ErrorBoundary` class component, no `componentDidCatch` lifecycle method, and no usage of any third-party error boundary library.

The `App` component uses `React.StrictMode` and `BrowserRouter` to wrap the application, but neither provides error boundary protection.

**Impact:** A runtime render error in any single component — including the main `SupportAgent` chat component — will crash the entire application and render a blank white screen with no feedback to the user and no notification to the team.

The `ChatLayout` component renders unsanitized HTML via `html-react-parser` (`parse(obj.message)`). If the API returns malformed or unexpected HTML, a parse error will propagate up the component tree uncaught, taking down the entire app.

---

## 3. Global Error Handler Assessment

**Result: No global error handlers are registered.**

No file in the frontend codebase contains:
- `window.onerror`
- `window.addEventListener('unhandledrejection', ...)`
- Any equivalent global error capturing mechanism

**Impact of missing `window.onerror`:** JavaScript runtime errors that occur outside of React's render cycle — such as event handler failures or third-party script errors — are invisible to the team.

**Impact of missing `unhandledrejection`:** The `handlePrompt` and `handleSession` functions in `Agent.js` use `.then()` promise chains with no `.catch()` handlers. If the API call to `/chat` or `/session` fails (network error, CORS error, server error), the promise rejection is silently unhandled. The user sees no feedback and the error is lost entirely. This is a production-quality gap.

```js
// Agent.js — no .catch() on either fetch chain
fetch(process.env.REACT_APP_API_HOST + '/chat', { ... })
  .then((response) => response.json())
  .then((res) => { ... })
// No .catch() — rejection is silently dropped
```

---

## 4. Performance Monitoring Assessment

**Result: Performance monitoring infrastructure exists but is completely inert.**

The `web-vitals` package (v2.1.4) is installed and `reportWebVitals.js` is properly implemented to collect CLS, FID, FCP, LCP, and TTFB metrics. However, in `index.js` the function is called with no argument:

```js
reportWebVitals(); // no callback — metrics are collected and discarded
```

For `reportWebVitals` to do anything, it must receive a callback function. The CRA documentation shows either `reportWebVitals(console.log)` for development logging or a custom function that sends metrics to an analytics endpoint. As-is, no performance data is reported anywhere.

There is no long-task monitoring, no slow API call detection, and no Largest Contentful Paint or Cumulative Layout Shift data reaching any backend or monitoring system.

---

## 5. Application Insights / Azure Monitor Assessment

**Result: No Application Insights SDK installed or configured.**

The `@microsoft/applicationinsights-web` package is not present in `package.json`. No Application Insights connection string, instrumentation key, or SDK initialization exists anywhere in the frontend codebase. No `.env` files were found in the project.

Given the project is an Azure-hosted application (using Azure AI, Azure Functions, Azure CosmosDB based on the overall solution), the absence of the Azure Monitor frontend SDK is a significant gap. Frontend exceptions, page views, and custom events are not tracked in Azure Monitor.

This means:
- No end-to-end correlation between frontend user actions and backend API calls
- No exception tracking in Azure Application Insights
- No page view tracking
- No availability telemetry from the client perspective

---

## 6. Structured Logging Assessment

**Result: No logging abstraction. Raw `console.log` used directly in production code.**

The codebase contains one `console.log` call in a production code path:

```js
// Agent.js, line 38 — logs the full API response to the browser console
console.log(res);
```

This call logs the complete API response object — which may include sensitive information from the AI model or internal backend data — to the browser console. It will be visible in production to any user who opens browser developer tools. There is no logging abstraction, no log level management, and no mechanism to suppress debug output in production builds.

No `console.error` or `console.warn` calls were found, which means errors are not even minimally surfaced — they are entirely silent.

---

## 7. Findings

| Severity | ID | Title | File |
|---|---|---|---|
| 🔴 Critical | UOTL-ERROR-001 | No React Error Boundaries — one render crash takes down the entire app | `src/index.js`, `src/App.js` |
| 🔴 Critical | UOTL-ERROR-002 | No global unhandledrejection handler — API call failures are silently dropped | `src/SupportAgent/Agent.js` |
| 🔴 Critical | UOTL-ERROR-003 | No window.onerror handler — runtime JS errors outside React cycle are invisible | `src/index.js` |
| 🟡 Notable | UOTL-APPINS-001 | No Application Insights SDK — no frontend exceptions, page views, or traces in Azure Monitor | `package.json` |
| 🟡 Notable | UOTL-PERF-001 | reportWebVitals called with no callback — Core Web Vitals are collected and silently discarded | `src/index.js` |
| 🟡 Notable | UOTL-ERROR-004 | fetch() calls have no .catch() — API errors produce no user feedback and no error capture | `src/SupportAgent/Agent.js` |
| 🟢 Minor | UOTL-LOG-001 | console.log(res) in production code path — full API response exposed in browser console | `src/SupportAgent/Agent.js:38` |
| 🟢 Minor | UOTL-LOG-002 | No structured logging abstraction — raw console calls scattered through components | `src/SupportAgent/Agent.js` |
| ℹ️ Info | UOTL-PERF-002 | web-vitals package is installed and reportWebVitals.js is correctly implemented — infrastructure is ready, only the callback is missing | `src/reportWebVitals.js` |
| ℹ️ Info | UOTL-ARCH-001 | Application is a single-route CRA SPA — error boundary placement strategy should cover root App and the SupportAgent subtree | `src/App.js` |

---

## 8. Recommended Improvements

| Finding | Recommended Action | Priority |
|---|---|---|
| UOTL-ERROR-001 | Create a class-based `ErrorBoundary` component with `componentDidCatch`. Wrap `<App>` at root level and wrap `<SupportAgent>` as a critical subtree boundary. `componentDidCatch` should call Application Insights `trackException`. | Immediate |
| UOTL-ERROR-002 | Add `window.addEventListener('unhandledrejection', handler)` in `index.js`. The handler should log the reason and (once App Insights is added) call `trackException`. | Immediate |
| UOTL-ERROR-003 | Add `window.onerror = (message, source, lineno, colno, error) => { ... }` in `index.js` to capture uncaught runtime errors and report them to Application Insights. | Immediate |
| UOTL-APPINS-001 | Install `@microsoft/applicationinsights-web`. Create an `appInsights.js` module that initializes the SDK with a connection string from `REACT_APP_APPINSIGHTS_CONNECTION_STRING`. Call `trackPageView()` on route changes and `trackException()` in error boundaries and global handlers. | High |
| UOTL-PERF-001 | Pass a reporting callback to `reportWebVitals()`. Until App Insights is integrated, use `reportWebVitals(console.log)` for development visibility. Once integrated, send metrics via `appInsights.trackMetric()`. | High |
| UOTL-ERROR-004 | Add `.catch(error => { ... })` to both fetch chains in `Agent.js`. At minimum, display an error message in the chat UI and log the error. Once App Insights is available, call `trackException`. | High |
| UOTL-LOG-001 | Remove `console.log(res)` from the `handlePrompt` response handler. If the response needs inspection during development, gate it behind `process.env.NODE_ENV === 'development'`. | Moderate |
| UOTL-LOG-002 | Create a thin `logger.js` module that wraps `console` methods and conditionally suppresses output in production (`process.env.NODE_ENV !== 'development'`). Use this module instead of direct `console` calls. | Moderate |

---

## 9. Observability Maturity Checklist

| Area | Check | Status |
|---|---|---|
| Error Boundaries | Root-level error boundary exists | ❌ Missing |
| Error Boundaries | Critical subtree boundaries exist (e.g., chat widget) | ❌ Missing |
| Error Boundaries | Error boundary calls monitoring service on catch | ❌ Missing |
| Global Handlers | `window.onerror` registered | ❌ Missing |
| Global Handlers | `window.addEventListener('unhandledrejection', ...)` registered | ❌ Missing |
| API Error Handling | All fetch/promise chains have `.catch()` handlers | ❌ Missing |
| Performance | `reportWebVitals` configured with a reporting callback | ❌ Not active (called with no argument) |
| Performance | Core Web Vitals sent to a monitoring endpoint | ❌ Missing |
| Application Insights | `@microsoft/applicationinsights-web` installed | ❌ Missing |
| Application Insights | SDK initialized with connection string from environment variable | ❌ Missing |
| Application Insights | `trackException()` called in error handlers | ❌ Missing |
| Application Insights | `trackPageView()` called on route changes | ❌ Missing |
| Structured Logging | Logging abstraction module exists | ❌ Missing |
| Structured Logging | No `console.log` in production code paths | ❌ `console.log(res)` in Agent.js:38 |
| Structured Logging | Sensitive data not logged to console | ⚠️ API response logged (content unknown) |
| Package | `web-vitals` installed | ✅ Present (v2.1.4) |

**Maturity score: 1 / 16 checks passing.**

---

## Footer

> This review is the output of static analysis of the source files at `src/web/` in the `Azure-AI-RAG-CSharp-Semantic-Kernel-Functions` workspace. It reflects the code as read on 2026-03-21 and does not represent runtime behavior, deployed configuration, or any environment-specific overrides. No build or execution was performed.
>
> Steward: React UX Observability Steward (`react-ux-otl-steward`) — PREFIX `UOTL`
