Googolplexic commited on
Commit
c912400
·
1 Parent(s): 1891daa

Spewed some formatting code for database data retrieval; will have to wait for actual database entries to further test

Browse files
Files changed (2) hide show
  1. api_monitor.py +247 -30
  2. main.py +39 -3
api_monitor.py CHANGED
@@ -391,7 +391,7 @@ def activate_monitoring(config_id, mcp_api_key):
391
  }
392
 
393
 
394
- def retrieve_monitored_data(config_id, mcp_api_key):
395
  """
396
  TOOL: Retrieve monitored data for a specific API configuration.
397
 
@@ -400,11 +400,10 @@ def retrieve_monitored_data(config_id, mcp_api_key):
400
 
401
  PREREQUISITE: Must call validate_api_configuration() first and obtain a config_id from successful validation, then activate_monitoring() to start monitoring.
402
 
403
- This function can be called at any time after monitoring activation to retrieve the latest data collected by the monitoring system.
404
-
405
- Parameters:
406
  - config_id: The ID of the API configuration to retrieve data for (required)
407
  - mcp_api_key: User's MCP API key for verification (must match validation step)
 
408
 
409
  Input Examples:
410
  1. Retrieve data for stock monitoring:
@@ -413,28 +412,71 @@ def retrieve_monitored_data(config_id, mcp_api_key):
413
 
414
  2. Retrieve data for weather alerts:
415
  config_id: 987654321
416
- mcp_api_key: "your_mcp_key_here"
 
417
 
418
- Returns:
419
- - Dictionary with success status, data, and message
420
- - If no data found, returns success=False with appropriate message
421
- Example return:
422
  {
423
  "success": True,
424
- "data": [
425
- {"timestamp": "2025-06-04T12:00:00Z", "response": {...}},
426
- {"timestamp": "2025-06-04T12:20:00Z", "response": {...}},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  ],
428
- "message": "Data retrieved successfully for config_id 123456789"
 
 
 
 
429
  }
430
- - If config_id not found or invalid, returns success=False with error message
431
- - If mcp_api_key does not match, returns success=False with error message
432
 
433
- Example error return:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  {
435
  "success": False,
436
- "message": "Invalid config_id or mcp_api_key",
437
- "data": []
438
  }
439
  ERROR HANDLING: If config_id not found or invalid, returns success=False with error message
440
  """
@@ -444,25 +486,200 @@ def retrieve_monitored_data(config_id, mcp_api_key):
444
  cur.execute(
445
  "SELECT * FROM api_configurations WHERE config_id = %s", (config_id,)
446
  )
447
- config = cur.fetchone()
448
 
449
- if not config:
450
  conn.close()
451
  return {
452
  "success": False,
453
  "message": "Invalid config_id",
454
  "data": [],
455
  }
456
- print(config)
457
- # 2. Query the api_configurations table for the given config_id
458
- # 3. If found, retrieve the associated monitored data
459
- # 4. Return the data in the specified format
460
- conn.close()
461
- return {
462
- "success": False,
463
- "message": "Function not implemented yet; this is a placeholder.",
464
- "data": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  except Exception as e:
467
  return {
468
  "success": False,
@@ -503,4 +720,4 @@ if __name__ == "__main__":
503
  config_id=activate_monitoring_response.get("config_id"),
504
  mcp_api_key="your_api_key",
505
  )
506
- print(response)
 
391
  }
392
 
393
 
394
+ def retrieve_monitored_data(config_id, mcp_api_key, mode="summary"):
395
  """
396
  TOOL: Retrieve monitored data for a specific API configuration.
397
 
 
400
 
401
  PREREQUISITE: Must call validate_api_configuration() first and obtain a config_id from successful validation, then activate_monitoring() to start monitoring.
402
 
403
+ This function can be called at any time after monitoring activation to retrieve the latest data collected by the monitoring system. Parameters:
 
 
404
  - config_id: The ID of the API configuration to retrieve data for (required)
405
  - mcp_api_key: User's MCP API key for verification (must match validation step)
406
+ - mode: Data return mode - "summary" (LLM-optimized), "details" (full responses, minimal metadata), "full" (everything)
407
 
408
  Input Examples:
409
  1. Retrieve data for stock monitoring:
 
412
 
413
  2. Retrieve data for weather alerts:
414
  config_id: 987654321
415
+ mcp_api_key: "your_mcp_key_here" Returns:
416
+ - Dictionary with monitoring status in one of three formats based on mode parameter
417
 
418
+ SUMMARY mode (LLM-optimized, default):
 
 
 
419
  {
420
  "success": True,
421
+ "config_name": "Weather Alert Monitor",
422
+ "summary": {
423
+ "status": "active", // "active", "inactive"
424
+ "health": "good", // "good", "degraded", "no_data"
425
+ "calls_made": 15,
426
+ "success_rate": 93.3,
427
+ "last_call": "2025-06-05T15:20:00",
428
+ "last_success": "2025-06-05T15:20:00"
429
+ },
430
+ "recent_calls": [
431
+ {
432
+ "timestamp": "2025-06-05T15:20:00",
433
+ "success": true,
434
+ "error": null,
435
+ "response_preview": "{'alerts': [{'type': 'tornado'}]}..." // truncated
436
+ }
437
+ // ... up to 5 most recent calls
438
  ],
439
+ "full_data_available": 15,
440
+ "monitoring_details": {
441
+ "interval_minutes": 20,
442
+ "is_finished": false
443
+ }
444
  }
 
 
445
 
446
+ DETAILS mode (full responses, minimal metadata):
447
+ {
448
+ "success": True,
449
+ "config_name": "Weather Alert Monitor",
450
+ "status": "active",
451
+ "calls_made": 15,
452
+ "success_rate": 93.3,
453
+ "recent_responses": [
454
+ {
455
+ "timestamp": "2025-06-05T15:20:00",
456
+ "success": true,
457
+ "response_data": {...}, // full response data
458
+ "error": null
459
+ }
460
+ // ... up to 10 most recent calls with full responses
461
+ ]
462
+ }
463
+
464
+ FULL mode (everything):
465
+ {
466
+ "success": True,
467
+ "config_name": "Weather Alert Monitor",
468
+ "config_description": "Monitor severe weather alerts",
469
+ "is_active": True,
470
+ "is_finished": False,
471
+ "progress": {...},
472
+ "schedule_info": {...},
473
+ "data": [...] // all historical data
474
+ }
475
+
476
+ Error return format:
477
  {
478
  "success": False,
479
+ "message": "Invalid config_id or mcp_api_key"
 
480
  }
481
  ERROR HANDLING: If config_id not found or invalid, returns success=False with error message
482
  """
 
486
  cur.execute(
487
  "SELECT * FROM api_configurations WHERE config_id = %s", (config_id,)
488
  )
489
+ config_row = cur.fetchone()
490
 
491
+ if not config_row:
492
  conn.close()
493
  return {
494
  "success": False,
495
  "message": "Invalid config_id",
496
  "data": [],
497
  }
498
+
499
+ config = dict(config_row)
500
+ print(f"Retrieved config: {config}")
501
+
502
+ if config["mcp_api_key"] != mcp_api_key:
503
+ conn.close()
504
+ return {
505
+ "success": False,
506
+ "message": "Invalid mcp_api_key. You are not authorized to access this configuration.",
507
+ "data": [],
508
+ }
509
+
510
+ # Query the api_call_results table for monitored data
511
+ cur.execute(
512
+ "SELECT * FROM api_call_results WHERE config_id = %s ORDER BY called_at DESC",
513
+ (config_id,),
514
+ )
515
+ monitored_data_rows = cur.fetchall()
516
+
517
+ # Convert rows to dictionaries and format timestamps
518
+ monitored_data = []
519
+ for row in monitored_data_rows:
520
+ row_dict = dict(row)
521
+ # Format the timestamp for better readability
522
+ if row_dict.get("called_at"):
523
+ row_dict["called_at"] = row_dict["called_at"].isoformat()
524
+ monitored_data.append(row_dict)
525
+
526
+ # Check if monitoring is finished
527
+ now = datetime.now()
528
+ stop_time = config.get("time_to_start")
529
+ if stop_time and config.get("schedule_interval_minutes"):
530
+ # Calculate when monitoring should stop
531
+ stop_after_hours = (
532
+ config.get("schedule_interval_minutes", 24) / 60 * 24
533
+ ) # Default fallback
534
+ if hasattr(stop_time, "replace"):
535
+ stop_at = stop_time + timedelta(hours=stop_after_hours)
536
+ else:
537
+ stop_at = datetime.fromisoformat(str(stop_time)) + timedelta(
538
+ hours=stop_after_hours
539
+ )
540
+ is_finished = now > stop_at or config.get("stop", False)
541
+ else:
542
+ is_finished = config.get("stop", False)
543
+
544
+ # Calculate progress statistics
545
+ total_expected_calls = 0
546
+ if config.get("time_to_start") and config.get("schedule_interval_minutes"):
547
+ start_time = config["time_to_start"]
548
+ if hasattr(start_time, "replace"):
549
+ start_dt = start_time
550
+ else:
551
+ start_dt = datetime.fromisoformat(str(start_time))
552
+
553
+ elapsed_minutes = (now - start_dt).total_seconds() / 60
554
+ if elapsed_minutes > 0:
555
+ total_expected_calls = max(
556
+ 1, int(elapsed_minutes / config["schedule_interval_minutes"])
557
+ )
558
+
559
+ # Get success/failure counts
560
+ successful_calls = len(
561
+ [d for d in monitored_data if d.get("is_successful", False)]
562
+ )
563
+ failed_calls = len(
564
+ [d for d in monitored_data if not d.get("is_successful", True)]
565
+ )
566
+ total_calls = len(
567
+ monitored_data
568
+ ) # Create simplified summary for LLM consumption
569
+ summary = {
570
+ "status": (
571
+ "active"
572
+ if config.get("is_active", False) and not is_finished
573
+ else "inactive"
574
+ ),
575
+ "health": (
576
+ "good"
577
+ if total_calls > 0 and (successful_calls / total_calls) > 0.8
578
+ else "degraded" if total_calls > 0 else "no_data"
579
+ ),
580
+ "calls_made": total_calls,
581
+ "success_rate": (
582
+ round(successful_calls / total_calls * 100, 1) if total_calls > 0 else 0
583
+ ),
584
+ "last_call": monitored_data[0]["called_at"] if monitored_data else None,
585
+ "last_success": next(
586
+ (d["called_at"] for d in monitored_data if d.get("is_successful")), None
587
+ ),
588
  }
589
+
590
+ # Handle different return modes
591
+ if mode == "full":
592
+ # Return complete detailed data (original detailed format)
593
+ return {
594
+ "success": True,
595
+ "message": f"Full data retrieved for config_id {config_id}",
596
+ "config_name": config.get("name", "Unknown"),
597
+ "config_description": config.get("description", ""),
598
+ "is_active": config.get("is_active", False),
599
+ "is_finished": is_finished,
600
+ "progress": {
601
+ "total_calls": total_calls,
602
+ "successful_calls": successful_calls,
603
+ "failed_calls": failed_calls,
604
+ "expected_calls": total_expected_calls,
605
+ "success_rate": (
606
+ round(successful_calls / total_calls * 100, 2)
607
+ if total_calls > 0
608
+ else 0
609
+ ),
610
+ },
611
+ "schedule_info": {
612
+ "interval_minutes": config.get("schedule_interval_minutes"),
613
+ "started_at": (
614
+ config.get("time_to_start").isoformat()
615
+ if config.get("time_to_start")
616
+ else None
617
+ ),
618
+ "is_stopped": config.get("stop", False),
619
+ },
620
+ "data": monitored_data,
621
+ }
622
+
623
+ elif mode == "details":
624
+ # Return full response data but minimal metadata (up to 10 recent calls)
625
+ recent_responses = []
626
+ for item in monitored_data[:10]: # Last 10 calls with full responses
627
+ recent_responses.append(
628
+ {
629
+ "timestamp": item["called_at"],
630
+ "success": item.get("is_successful", False),
631
+ "response_data": item.get(
632
+ "response_data"
633
+ ), # Full response data
634
+ "error": (
635
+ item.get("error_message")
636
+ if not item.get("is_successful")
637
+ else None
638
+ ),
639
+ }
640
+ )
641
+
642
+ return {
643
+ "success": True,
644
+ "config_name": config.get("name", "Unknown"),
645
+ "status": summary["status"],
646
+ "calls_made": total_calls,
647
+ "success_rate": summary["success_rate"],
648
+ "recent_responses": recent_responses,
649
+ }
650
+
651
+ else: # mode == "summary" (default)
652
+ # Get recent data (last 5 calls) with essential info only
653
+ recent_data = []
654
+ for item in monitored_data[:5]: # Only last 5 calls
655
+ recent_data.append(
656
+ {
657
+ "timestamp": item["called_at"],
658
+ "success": item.get("is_successful", False),
659
+ "error": (
660
+ item.get("error_message")
661
+ if not item.get("is_successful")
662
+ else None
663
+ ),
664
+ "response_preview": (
665
+ str(item.get("response_data", ""))[:100] + "..."
666
+ if item.get("response_data")
667
+ else None
668
+ ),
669
+ }
670
+ )
671
+
672
+ return {
673
+ "success": True,
674
+ "config_name": config.get("name", "Unknown"),
675
+ "summary": summary,
676
+ "recent_calls": recent_data,
677
+ "full_data_available": len(monitored_data),
678
+ "monitoring_details": {
679
+ "interval_minutes": config.get("schedule_interval_minutes"),
680
+ "is_finished": is_finished,
681
+ },
682
+ }
683
  except Exception as e:
684
  return {
685
  "success": False,
 
720
  config_id=activate_monitoring_response.get("config_id"),
721
  mcp_api_key="your_api_key",
722
  )
723
+ print(json.dumps(response, indent=2, default=str))
main.py CHANGED
@@ -1,6 +1,10 @@
1
  import gradio as gr
2
  from api_client import call_api
3
- from api_monitor import validate_api_configuration, activate_monitoring
 
 
 
 
4
  import json
5
 
6
 
@@ -125,10 +129,42 @@ scheduler_tab = gr.Interface(
125
  ],
126
  )
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  # Create tabbed interface
129
  demo = gr.TabbedInterface(
130
- [validation_tab, scheduler_tab],
131
- ["Validate & Store", "Activate Scheduler"],
132
  title="MCP API Monitoring System",
133
  )
134
 
 
1
  import gradio as gr
2
  from api_client import call_api
3
+ from api_monitor import (
4
+ validate_api_configuration,
5
+ activate_monitoring,
6
+ retrieve_monitored_data,
7
+ )
8
  import json
9
 
10
 
 
129
  ],
130
  )
131
 
132
+ # Retrieve Data Tab
133
+ retrieve_tab = gr.Interface(
134
+ fn=retrieve_monitored_data,
135
+ inputs=[
136
+ gr.Number(label="Config ID", value=None),
137
+ gr.Textbox(
138
+ label="MCP API Key", placeholder="Enter your MCP API key", type="password"
139
+ ),
140
+ gr.Dropdown(
141
+ choices=["summary", "details", "full"],
142
+ label="Data Mode",
143
+ value="summary",
144
+ info="summary: LLM-optimized | details: full responses, minimal metadata | full: everything",
145
+ ),
146
+ ],
147
+ outputs=gr.JSON(label="Monitoring Progress & Data"),
148
+ title="Retrieve Monitoring Data",
149
+ description="STEP 3: Check the progress and retrieve data from your active monitoring configurations. Use the Config ID from the validation step. Three modes: 'summary' (LLM-optimized), 'details' (full responses), 'full' (complete debug info).",
150
+ flagging_mode="manual",
151
+ flagging_options=[
152
+ "Config Not Found",
153
+ "Invalid API Key",
154
+ "No Data Available",
155
+ "Other",
156
+ ],
157
+ examples=[
158
+ [123456789, "test_mcp_key_123", "summary"],
159
+ [987654321, "test_mcp_key_456", "details"],
160
+ [456789123, "test_mcp_key_789", "full"],
161
+ ],
162
+ )
163
+
164
  # Create tabbed interface
165
  demo = gr.TabbedInterface(
166
+ [validation_tab, scheduler_tab, retrieve_tab],
167
+ ["Validate & Store", "Activate Scheduler", "Retrieve Data"],
168
  title="MCP API Monitoring System",
169
  )
170