Anish-530 commited on
Commit
942a467
·
1 Parent(s): 5691a72

Fix: 404 page loader stuck, navbar loading spinners, bulletproof NR import

Browse files
backend/app/core/logger.py CHANGED
@@ -40,32 +40,39 @@ logger.add(
40
  enqueue=True
41
  )
42
 
43
- # 6. New Relic Cloud Sink
44
  # Set NEW_RELIC_LICENSE_KEY and NEW_RELIC_APP_NAME in your environment.
45
  _NR_KEY = os.environ.get("NEW_RELIC_LICENSE_KEY", "")
46
  if _NR_KEY:
47
- import newrelic.agent
48
  try:
49
- newrelic.agent.initialize()
50
- except Exception:
51
- pass
52
-
53
- def _newrelic_sink(message):
54
- record = message.record
55
  try:
56
- # Send to New Relic Logs APM
57
- newrelic.agent.record_log_event(
58
- message=record["message"],
59
- level=record["level"].name,
60
- timestamp=int(record["time"].timestamp() * 1000),
61
- attributes={
62
- "request_id": record["extra"].get("request_id", "SYSTEM"),
63
- "logger": record["name"],
64
- "function": record["function"],
65
- "line": record["line"],
66
- }
67
- )
68
  except Exception:
69
- pass # Never let cloud logging failure affect the app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
- logger.add(_newrelic_sink, level="INFO", enqueue=True)
 
 
 
 
 
 
 
40
  enqueue=True
41
  )
42
 
43
+ # 6. New Relic Cloud Sink (fully optional — never crashes the app)
44
  # Set NEW_RELIC_LICENSE_KEY and NEW_RELIC_APP_NAME in your environment.
45
  _NR_KEY = os.environ.get("NEW_RELIC_LICENSE_KEY", "")
46
  if _NR_KEY:
 
47
  try:
48
+ import newrelic.agent
 
 
 
 
 
49
  try:
50
+ newrelic.agent.initialize()
 
 
 
 
 
 
 
 
 
 
 
51
  except Exception:
52
+ pass
53
+
54
+ def _newrelic_sink(message):
55
+ record = message.record
56
+ try:
57
+ # Send to New Relic Logs APM
58
+ newrelic.agent.record_log_event(
59
+ message=record["message"],
60
+ level=record["level"].name,
61
+ timestamp=int(record["time"].timestamp() * 1000),
62
+ attributes={
63
+ "request_id": record["extra"].get("request_id", "SYSTEM"),
64
+ "logger": record["name"],
65
+ "function": record["function"],
66
+ "line": record["line"],
67
+ }
68
+ )
69
+ except Exception:
70
+ pass # Never let cloud logging failure affect the app
71
 
72
+ logger.add(_newrelic_sink, level="INFO", enqueue=True)
73
+ except ImportError:
74
+ # newrelic package not installed — skip silently
75
+ pass
76
+ except Exception:
77
+ # Any other error during setup — skip silently
78
+ pass
frontend/components/shared/Navbar.tsx CHANGED
@@ -17,6 +17,7 @@ export default function Navbar({ onAnalyzeClick }: NavbarProps) {
17
  const [dropdownOpen, setDropdownOpen] = useState(false);
18
  const [dropdownPinned, setDropdownPinned] = useState(false);
19
  const [soundEnabled, setSoundEnabled] = useState(true);
 
20
  const closeTimeoutRef = useRef<NodeJS.Timeout | null>(null);
21
 
22
  const handleMouseEnter = () => {
@@ -153,10 +154,30 @@ export default function Navbar({ onAnalyzeClick }: NavbarProps) {
153
  <div className="flex items-center gap-3">
154
  {!isAuthenticated ? (
155
  <>
156
- <button onClick={() => router.push('/login')} className="hidden sm:block bg-transparent text-[var(--theme-text)] border border-[var(--theme-text)]/30 px-6 py-2 rounded-full text-[11px] font-bold tracking-tight hover:bg-[var(--theme-text)]/5 hover-scale">
 
 
 
 
 
 
 
 
 
 
157
  Register
158
  </button>
159
- <button onClick={() => router.push('/login')} className="hidden sm:block bg-[var(--theme-text)] text-[var(--theme-bg)] px-6 py-2 rounded-full text-[11px] font-bold tracking-tight hover:shadow-[0_0_20px_rgba(253,232,214,0.3)] hover-scale">
 
 
 
 
 
 
 
 
 
 
160
  Login
161
  </button>
162
  </>
 
17
  const [dropdownOpen, setDropdownOpen] = useState(false);
18
  const [dropdownPinned, setDropdownPinned] = useState(false);
19
  const [soundEnabled, setSoundEnabled] = useState(true);
20
+ const [navLoading, setNavLoading] = useState(false);
21
  const closeTimeoutRef = useRef<NodeJS.Timeout | null>(null);
22
 
23
  const handleMouseEnter = () => {
 
154
  <div className="flex items-center gap-3">
155
  {!isAuthenticated ? (
156
  <>
157
+ <button
158
+ onClick={() => { setNavLoading(true); router.push('/login'); }}
159
+ disabled={navLoading}
160
+ className="hidden sm:flex items-center gap-2 bg-transparent text-[var(--theme-text)] border border-[var(--theme-text)]/30 px-6 py-2 rounded-full text-[11px] font-bold tracking-tight hover:bg-[var(--theme-text)]/5 hover-scale disabled:opacity-60 transition-opacity"
161
+ >
162
+ {navLoading ? (
163
+ <svg className="animate-spin w-3 h-3" viewBox="0 0 24 24" fill="none">
164
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
165
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"/>
166
+ </svg>
167
+ ) : null}
168
  Register
169
  </button>
170
+ <button
171
+ onClick={() => { setNavLoading(true); router.push('/login'); }}
172
+ disabled={navLoading}
173
+ className="hidden sm:flex items-center gap-2 bg-[var(--theme-text)] text-[var(--theme-bg)] px-6 py-2 rounded-full text-[11px] font-bold tracking-tight hover:shadow-[0_0_20px_rgba(253,232,214,0.3)] hover-scale disabled:opacity-60 transition-opacity"
174
+ >
175
+ {navLoading ? (
176
+ <svg className="animate-spin w-3 h-3" viewBox="0 0 24 24" fill="none">
177
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
178
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"/>
179
+ </svg>
180
+ ) : null}
181
  Login
182
  </button>
183
  </>
frontend/components/shared/PageLoader.tsx CHANGED
@@ -22,6 +22,12 @@ export default function PageLoader({ children }: { children: React.ReactNode })
22
 
23
  let progress = 0;
24
 
 
 
 
 
 
 
25
  const interval = setInterval(() => {
26
  if (progress < 90) {
27
  progress += Math.random() * 15 + 5;
@@ -40,6 +46,9 @@ export default function PageLoader({ children }: { children: React.ReactNode })
40
 
41
  return () => {
42
  clearInterval(interval);
 
 
 
43
  };
44
  }, [pathname]);
45
 
 
22
 
23
  let progress = 0;
24
 
25
+ // Safety net: force complete after 2500ms even if __PAGE_LOADED never fires
26
+ // (e.g. the 404 page, or any page that doesn't set the flag)
27
+ const safetyTimeout = setTimeout(() => {
28
+ (window as any).__PAGE_LOADED = true;
29
+ }, 2500);
30
+
31
  const interval = setInterval(() => {
32
  if (progress < 90) {
33
  progress += Math.random() * 15 + 5;
 
46
 
47
  return () => {
48
  clearInterval(interval);
49
+ clearTimeout(safetyTimeout);
50
+ // Always reset the flag on cleanup so next page starts fresh
51
+ (window as any).__PAGE_LOADED = false;
52
  };
53
  }, [pathname]);
54