yashgori20 commited on
Commit
b02f039
Β·
1 Parent(s): 0ce5100
Files changed (1) hide show
  1. app.py +230 -19
app.py CHANGED
@@ -16,7 +16,10 @@ import requests
16
  from typing import List, Dict
17
  import time
18
  from functools import wraps
19
- # Import RAG utilities
 
 
 
20
  from rag_utils import get_comprehensive_context, format_context_for_prompt
21
 
22
  try:
@@ -1846,6 +1849,27 @@ def index():
1846
  <h3><span class="method">GET</span> <code>/history</code> - View Request History</h3>
1847
  <p>Browse all QC requests with preview and download options.</p>
1848
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1849
  </div>
1850
  </body>
1851
  </html>
@@ -2699,20 +2723,24 @@ INSTRUCTIONS:
2699
  traceback.print_exc()
2700
  return jsonify({"error": str(e)}), 500
2701
 
 
 
2702
  @app.route("/history", methods=["GET"])
2703
  def view_history():
2704
- """history view with additional metadata"""
2705
  if request.headers.get('Accept') == 'application/json' or request.args.get('format') == 'json':
2706
  try:
2707
  con = sql.connect("swift_check.db")
2708
  cur = con.cursor()
2709
 
2710
- # query with parameter counts
2711
  cur.execute("""
2712
  SELECT r.id, r.doc_type, r.product_name, r.supplier_name, r.created_at,
2713
- COUNT(p.id) as parameter_count
 
2714
  FROM qc_requests r
2715
  LEFT JOIN parameters p ON r.id = p.request_id
 
2716
  GROUP BY r.id
2717
  ORDER BY r.created_at DESC
2718
  """)
@@ -2726,7 +2754,10 @@ def view_history():
2726
  "product_name": row[2],
2727
  "supplier_name": row[3],
2728
  "created_at": row[4],
2729
- "parameter_count": row[5]
 
 
 
2730
  } for row in rows])
2731
 
2732
  except Exception as e:
@@ -2739,9 +2770,11 @@ def view_history():
2739
 
2740
  cur.execute("""
2741
  SELECT r.id, r.doc_type, r.product_name, r.supplier_name, r.created_at,
2742
- COUNT(p.id) as parameter_count
 
2743
  FROM qc_requests r
2744
  LEFT JOIN parameters p ON r.id = p.request_id
 
2745
  GROUP BY r.id
2746
  ORDER BY r.created_at DESC
2747
  """)
@@ -2755,22 +2788,42 @@ def view_history():
2755
  <title>QC Request History</title>
2756
  <style>
2757
  body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }
2758
- .container { max-width: 1400px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
2759
  table { border-collapse: collapse; width: 100%; margin-top: 20px; }
2760
  th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
2761
  th { background-color: #4CAF50; color: white; font-weight: bold; }
2762
  tr:nth-child(even) { background-color: #f2f2f2; }
2763
  tr:hover { background-color: #e8f5e8; }
2764
- a { color: #4CAF50; text-decoration: none; margin: 0 5px; padding: 4px 8px; border-radius: 3px; }
2765
  a:hover { background-color: #4CAF50; color: white; }
 
 
2766
  .badge { background: #28a745; color: white; padding: 2px 6px; border-radius: 10px; font-size: 11px; }
2767
  .param-count { font-weight: bold; color: #007bff; }
2768
  h1 { color: #333; text-align: center; margin-bottom: 30px; }
 
 
 
 
 
 
 
 
 
 
 
 
2769
  </style>
2770
  </head>
2771
  <body>
2772
  <div class="container">
2773
- <h1>QC Request History </h1>
 
 
 
 
 
 
2774
  <table>
2775
  <tr>
2776
  <th>ID</th>
@@ -2778,24 +2831,47 @@ def view_history():
2778
  <th>Doc Type</th>
2779
  <th>Supplier</th>
2780
  <th>Parameters</th>
 
 
2781
  <th>Created</th>
2782
  <th>Actions</th>
2783
  </tr>
2784
  """
2785
 
2786
  for row in rows:
2787
- param_badge = "🎯" if row[5] >= 15 else "⚠️" if row[5] >= 10 else "❌"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2788
  html += f"""
2789
  <tr>
2790
- <td>{row[0]}</td>
2791
- <td><strong>{row[2]}</strong></td>
2792
- <td>{row[1]}</td>
2793
- <td>{row[3]}</td>
2794
- <td class="param-count">{param_badge} {row[5]} params</td>
2795
- <td>{row[4]}</td>
 
 
2796
  <td>
2797
- <a href="/preview/{row[0]}">Preview</a>
2798
- <a href="/template/{row[0]}">JSON</a>
 
2799
  </td>
2800
  </tr>
2801
  """
@@ -2806,7 +2882,8 @@ def view_history():
2806
  <strong>Legend:</strong>
2807
  🎯 15+ params (Professional) |
2808
  ⚠️ 10-14 params (Good) |
2809
- ❌ <10 params (Basic)
 
2810
  </div>
2811
  </div>
2812
  </body>
@@ -3126,6 +3203,140 @@ def view_logs():
3126
 
3127
  except Exception as e:
3128
  return f"<h1>Error</h1><p>{str(e)}</p>", 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3129
  @app.route("/preview/<int:request_id>", methods=["GET"])
3130
  def preview_page(request_id):
3131
  """preview with better formatting and metadata"""
 
16
  from typing import List, Dict
17
  import time
18
  from functools import wraps
19
+ from flask import Flask, request, jsonify, redirect, url_for, render_template_string
20
+ from flask import Flask, request, jsonify, redirect, url_for, render_template_string
21
+ import time
22
+ from functools import wraps
23
  from rag_utils import get_comprehensive_context, format_context_for_prompt
24
 
25
  try:
 
1849
  <h3><span class="method">GET</span> <code>/history</code> - View Request History</h3>
1850
  <p>Browse all QC requests with preview and download options.</p>
1851
  </div>
1852
+ <div class="endpoint new">
1853
+ <h3><span class="method">GET</span> <code>/logs</code> - API Logs Dashboard<span class="badge">NEW</span></h3>
1854
+ <p>Comprehensive API activity monitoring with request details, processing times, file uploads, and error tracking.</p>
1855
+
1856
+ <h4>Features:</h4>
1857
+ <ul>
1858
+ <li><strong>Request Tracking:</strong> All API calls with endpoint, method, and status</li>
1859
+ <li><strong>File Information:</strong> Track uploaded files (OCR documents, reference files)</li>
1860
+ <li><strong>Performance Metrics:</strong> Processing times and success rates</li>
1861
+ <li><strong>Error Monitoring:</strong> Detailed error messages and troubleshooting</li>
1862
+ <li><strong>Filtering:</strong> Filter by endpoint, status, or request ID</li>
1863
+ </ul>
1864
+
1865
+ <h4>Query Parameters:</h4>
1866
+ <ul>
1867
+ <li><code>format=json</code> - Get logs in JSON format</li>
1868
+ <li><code>request_id=123</code> - Filter by specific request</li>
1869
+ <li><code>endpoint=refine</code> - Filter by endpoint</li>
1870
+ <li><code>limit=100</code> - Limit number of results</li>
1871
+ </ul>
1872
+ </div>
1873
  </div>
1874
  </body>
1875
  </html>
 
2723
  traceback.print_exc()
2724
  return jsonify({"error": str(e)}), 500
2725
 
2726
+ # REPLACE THE ENTIRE view_history() FUNCTION
2727
+
2728
  @app.route("/history", methods=["GET"])
2729
  def view_history():
2730
+ """history view with additional metadata and logs button"""
2731
  if request.headers.get('Accept') == 'application/json' or request.args.get('format') == 'json':
2732
  try:
2733
  con = sql.connect("swift_check.db")
2734
  cur = con.cursor()
2735
 
2736
+ # query with parameter counts and file info from logs
2737
  cur.execute("""
2738
  SELECT r.id, r.doc_type, r.product_name, r.supplier_name, r.created_at,
2739
+ COUNT(DISTINCT p.id) as parameter_count,
2740
+ l.file_info, l.endpoint, l.processing_time_ms
2741
  FROM qc_requests r
2742
  LEFT JOIN parameters p ON r.id = p.request_id
2743
+ LEFT JOIN api_logs l ON r.id = l.request_id
2744
  GROUP BY r.id
2745
  ORDER BY r.created_at DESC
2746
  """)
 
2754
  "product_name": row[2],
2755
  "supplier_name": row[3],
2756
  "created_at": row[4],
2757
+ "parameter_count": row[5],
2758
+ "file_info": row[6],
2759
+ "endpoint": row[7],
2760
+ "processing_time_ms": row[8]
2761
  } for row in rows])
2762
 
2763
  except Exception as e:
 
2770
 
2771
  cur.execute("""
2772
  SELECT r.id, r.doc_type, r.product_name, r.supplier_name, r.created_at,
2773
+ COUNT(DISTINCT p.id) as parameter_count,
2774
+ l.file_info, l.endpoint, l.processing_time_ms, l.status_code
2775
  FROM qc_requests r
2776
  LEFT JOIN parameters p ON r.id = p.request_id
2777
+ LEFT JOIN api_logs l ON r.id = l.request_id
2778
  GROUP BY r.id
2779
  ORDER BY r.created_at DESC
2780
  """)
 
2788
  <title>QC Request History</title>
2789
  <style>
2790
  body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }
2791
+ .container { max-width: 1600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
2792
  table { border-collapse: collapse; width: 100%; margin-top: 20px; }
2793
  th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
2794
  th { background-color: #4CAF50; color: white; font-weight: bold; }
2795
  tr:nth-child(even) { background-color: #f2f2f2; }
2796
  tr:hover { background-color: #e8f5e8; }
2797
+ a { color: #4CAF50; text-decoration: none; margin: 0 3px; padding: 4px 8px; border-radius: 3px; font-size: 11px; }
2798
  a:hover { background-color: #4CAF50; color: white; }
2799
+ .logs-btn { background-color: #007bff; color: white; }
2800
+ .logs-btn:hover { background-color: #0056b3; }
2801
  .badge { background: #28a745; color: white; padding: 2px 6px; border-radius: 10px; font-size: 11px; }
2802
  .param-count { font-weight: bold; color: #007bff; }
2803
  h1 { color: #333; text-align: center; margin-bottom: 30px; }
2804
+ .endpoint { padding: 2px 6px; border-radius: 8px; font-size: 10px; color: white; margin-left: 5px; }
2805
+ .refine { background: #28a745; }
2806
+ .edit { background: #ffc107; color: black; }
2807
+ .digitize { background: #17a2b8; }
2808
+ .validate { background: #6c757d; }
2809
+ .file-info { font-style: italic; color: #6c757d; font-size: 11px; }
2810
+ .processing-time { color: #007bff; font-size: 11px; }
2811
+ .nav-buttons { text-align: center; margin: 20px 0; }
2812
+ .nav-btn { background: linear-gradient(135deg, #007bff, #0056b3); color: white; padding: 12px 20px;
2813
+ border: none; border-radius: 6px; margin: 0 10px; text-decoration: none; display: inline-block;
2814
+ font-weight: bold; transition: all 0.3s ease; }
2815
+ .nav-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3); color: white; }
2816
  </style>
2817
  </head>
2818
  <body>
2819
  <div class="container">
2820
+ <h1>QC Request History πŸ“‹</h1>
2821
+
2822
+ <div class="nav-buttons">
2823
+ <a href="/logs" class="nav-btn">πŸ“Š View API Logs</a>
2824
+ <a href="/" class="nav-btn">🏠 Home</a>
2825
+ </div>
2826
+
2827
  <table>
2828
  <tr>
2829
  <th>ID</th>
 
2831
  <th>Doc Type</th>
2832
  <th>Supplier</th>
2833
  <th>Parameters</th>
2834
+ <th>Endpoint Used</th>
2835
+ <th>File/Processing Info</th>
2836
  <th>Created</th>
2837
  <th>Actions</th>
2838
  </tr>
2839
  """
2840
 
2841
  for row in rows:
2842
+ request_id, doc_type, product_name, supplier_name, created_at, param_count, file_info, endpoint, processing_time, status_code = row
2843
+
2844
+ param_badge = "🎯" if param_count >= 15 else "⚠️" if param_count >= 10 else "❌"
2845
+
2846
+ # Format endpoint
2847
+ endpoint_display = ""
2848
+ if endpoint:
2849
+ endpoint_clean = endpoint.replace('/', '').lower()
2850
+ endpoint_display = f'<span class="endpoint {endpoint_clean}">{endpoint}</span>'
2851
+
2852
+ # Format file and processing info
2853
+ info_display = ""
2854
+ if file_info:
2855
+ info_display += f'<div class="file-info">πŸ“ {file_info}</div>'
2856
+ if processing_time:
2857
+ info_display += f'<div class="processing-time">⏱️ {processing_time}ms</div>'
2858
+ if not info_display:
2859
+ info_display = "No file uploaded"
2860
+
2861
  html += f"""
2862
  <tr>
2863
+ <td>{request_id}</td>
2864
+ <td><strong>{product_name}</strong></td>
2865
+ <td>{doc_type}</td>
2866
+ <td>{supplier_name}</td>
2867
+ <td class="param-count">{param_badge} {param_count} params</td>
2868
+ <td>{endpoint_display}</td>
2869
+ <td>{info_display}</td>
2870
+ <td>{created_at}</td>
2871
  <td>
2872
+ <a href="/preview/{request_id}">Preview</a>
2873
+ <a href="/template/{request_id}">JSON</a>
2874
+ <a href="/logs?request_id={request_id}" class="logs-btn">Logs</a>
2875
  </td>
2876
  </tr>
2877
  """
 
2882
  <strong>Legend:</strong>
2883
  🎯 15+ params (Professional) |
2884
  ⚠️ 10-14 params (Good) |
2885
+ ❌ <10 params (Basic)<br>
2886
+ <strong>New:</strong> πŸ“Š Click "Logs" to see detailed API request information for each template
2887
  </div>
2888
  </div>
2889
  </body>
 
3203
 
3204
  except Exception as e:
3205
  return f"<h1>Error</h1><p>{str(e)}</p>", 500
3206
+
3207
+ # ADD this new endpoint after the /logs endpoint
3208
+
3209
+ @app.route("/logs/<int:log_id>", methods=["GET"])
3210
+ def view_detailed_log(log_id):
3211
+ """View detailed information for a specific log entry"""
3212
+ try:
3213
+ con = sql.connect("swift_check.db")
3214
+ cur = con.cursor()
3215
+
3216
+ # Get detailed log information
3217
+ cur.execute("""
3218
+ SELECT
3219
+ l.*,
3220
+ r.doc_type, r.product_name, r.supplier_name, r.user_message,
3221
+ lr.llm_response, lr.summary_text
3222
+ FROM api_logs l
3223
+ LEFT JOIN qc_requests r ON l.request_id = r.id
3224
+ LEFT JOIN llm_responses lr ON l.request_id = lr.request_id
3225
+ WHERE l.id = ?
3226
+ """, (log_id,))
3227
+
3228
+ log_data = cur.fetchone()
3229
+ con.close()
3230
+
3231
+ if not log_data:
3232
+ return jsonify({"error": f"Log ID {log_id} not found"}), 404
3233
+
3234
+ if request.headers.get('Accept') == 'application/json' or request.args.get('format') == 'json':
3235
+ # Return JSON format
3236
+ return jsonify({
3237
+ "log_id": log_data[0],
3238
+ "request_id": log_data[1],
3239
+ "endpoint": log_data[2],
3240
+ "method": log_data[3],
3241
+ "client_ip": log_data[4],
3242
+ "user_agent": log_data[5],
3243
+ "request_data": log_data[6],
3244
+ "response_data": log_data[7],
3245
+ "file_info": log_data[8],
3246
+ "processing_time_ms": log_data[9],
3247
+ "status_code": log_data[10],
3248
+ "error_message": log_data[11],
3249
+ "created_at": log_data[12],
3250
+ "doc_type": log_data[13],
3251
+ "product_name": log_data[14],
3252
+ "supplier_name": log_data[15],
3253
+ "user_message": log_data[16],
3254
+ "llm_response_summary": log_data[18]
3255
+ })
3256
+
3257
+ # HTML detailed view
3258
+ html = f"""
3259
+ <html>
3260
+ <head>
3261
+ <title>Log Details - #{log_id}</title>
3262
+ <style>
3263
+ body {{ font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }}
3264
+ .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
3265
+ .section {{ margin: 20px 0; padding: 15px; border-radius: 8px; }}
3266
+ .basic-info {{ background: #e8f4f8; border-left: 4px solid #007bff; }}
3267
+ .request-info {{ background: #f8f9fa; border-left: 4px solid #28a745; }}
3268
+ .response-info {{ background: #fff3cd; border-left: 4px solid #ffc107; }}
3269
+ .error-info {{ background: #f8d7da; border-left: 4px solid #dc3545; }}
3270
+ h1, h2 {{ color: #333; }}
3271
+ h1 {{ text-align: center; }}
3272
+ pre {{ background: #f8f9fa; padding: 15px; border-radius: 5px; overflow: auto; max-height: 300px; }}
3273
+ .status-success {{ color: #28a745; font-weight: bold; }}
3274
+ .status-error {{ color: #dc3545; font-weight: bold; }}
3275
+ .nav-btn {{ background: #007bff; color: white; padding: 10px 15px; text-decoration: none; border-radius: 5px; margin: 5px; display: inline-block; }}
3276
+ .nav-btn:hover {{ background: #0056b3; color: white; }}
3277
+ .metric {{ display: inline-block; margin: 10px 15px 10px 0; padding: 8px 12px; background: white; border-radius: 5px; border: 1px solid #ddd; }}
3278
+ </style>
3279
+ </head>
3280
+ <body>
3281
+ <div class="container">
3282
+ <h1>πŸ“‹ Log Details - #{log_id}</h1>
3283
+
3284
+ <div class="nav-buttons">
3285
+ <a href="/logs" class="nav-btn">⬅️ Back to Logs</a>
3286
+ <a href="/history" class="nav-btn">πŸ“‹ Request History</a>
3287
+ {f'<a href="/preview/{log_data[1]}" class="nav-btn">πŸ‘οΈ Preview Template</a>' if log_data[1] else ''}
3288
+ </div>
3289
+
3290
+ <div class="section basic-info">
3291
+ <h2>πŸ” Basic Information</h2>
3292
+ <div class="metric"><strong>Endpoint:</strong> {log_data[2]}</div>
3293
+ <div class="metric"><strong>Method:</strong> {log_data[3]}</div>
3294
+ <div class="metric"><strong>Status:</strong> <span class="{'status-success' if log_data[10] == 200 else 'status-error'}">{log_data[10]}</span></div>
3295
+ <div class="metric"><strong>Processing Time:</strong> {log_data[9] or 'N/A'}ms</div>
3296
+ <div class="metric"><strong>Created:</strong> {log_data[12]}</div>
3297
+ <div class="metric"><strong>Client IP:</strong> {log_data[4]}</div>
3298
+ </div>
3299
+
3300
+ {f'''
3301
+ <div class="section request-info">
3302
+ <h2>πŸ“‹ Request Information</h2>
3303
+ <p><strong>Product:</strong> {log_data[14]}</p>
3304
+ <p><strong>Document Type:</strong> {log_data[13]}</p>
3305
+ <p><strong>Supplier:</strong> {log_data[15]}</p>
3306
+ {f'<p><strong>File Info:</strong> {log_data[8]}</p>' if log_data[8] else ''}
3307
+ {f'<div><strong>User Message:</strong><pre>{log_data[16][:500]}{"..." if log_data[16] and len(log_data[16]) > 500 else ""}</pre></div>' if log_data[16] else ''}
3308
+ </div>
3309
+ ''' if log_data[1] else ''}
3310
+
3311
+ {f'''
3312
+ <div class="section response-info">
3313
+ <h2>πŸ“€ Response Information</h2>
3314
+ {f'<div><strong>Response Data:</strong><pre>{log_data[7]}</pre></div>' if log_data[7] else '<p>No response data available</p>'}
3315
+ </div>
3316
+ ''' if log_data[7] else ''}
3317
+
3318
+ {f'''
3319
+ <div class="section error-info">
3320
+ <h2>❌ Error Information</h2>
3321
+ <p><strong>Error Message:</strong></p>
3322
+ <pre>{log_data[11]}</pre>
3323
+ </div>
3324
+ ''' if log_data[11] else ''}
3325
+
3326
+ <div class="section">
3327
+ <h2>🌐 Technical Details</h2>
3328
+ <p><strong>User Agent:</strong> {log_data[5] or 'Not available'}</p>
3329
+ {f'<div><strong>Request Data:</strong><pre>{log_data[6]}</pre></div>' if log_data[6] else '<p>No request data captured</p>'}
3330
+ </div>
3331
+ </div>
3332
+ </body>
3333
+ </html>
3334
+ """
3335
+
3336
+ return html
3337
+
3338
+ except Exception as e:
3339
+ return f"<h1>Error</h1><p>{str(e)}</p>", 500
3340
  @app.route("/preview/<int:request_id>", methods=["GET"])
3341
  def preview_page(request_id):
3342
  """preview with better formatting and metadata"""