Pontonkid commited on
Commit
c0a8df3
·
verified ·
1 Parent(s): 1ae0de7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -204
app.py CHANGED
@@ -1,15 +1,11 @@
1
  # app.py
2
  import os
3
- import threading
4
  import datetime
5
  import json
6
  from pathlib import Path
7
- import requests
8
  from reportlab.lib.pagesizes import letter
9
  from reportlab.pdfgen import canvas
10
  import gradio as gr
11
- from fastapi import FastAPI, UploadFile, File
12
- import uvicorn
13
 
14
  # -----------------------
15
  # CONFIG
@@ -19,121 +15,8 @@ FILE_STORAGE.mkdir(exist_ok=True)
19
  REPORT_DIR = Path("reports")
20
  REPORT_DIR.mkdir(exist_ok=True)
21
 
22
- FILE_SERVER_PORT = 8001
23
- EXECUTOR_PORT = 8002
24
- MEMORY_PORT = 8003
25
-
26
- # -----------------------
27
- # MCP SERVERS
28
- # -----------------------
29
- file_app = FastAPI()
30
- executor_app = FastAPI()
31
- memory_app = FastAPI()
32
-
33
- # --- File Server ---
34
- @file_app.post("/upload")
35
- async def upload_file(file: UploadFile = File(...)):
36
- dest = FILE_STORAGE / file.filename
37
- content = await file.read()
38
- if isinstance(content, bytes):
39
- content = content.decode("utf-8", errors="ignore")
40
- with open(dest, "w", encoding="utf-8") as f:
41
- f.write(content)
42
- return {"status": "ok", "filename": file.filename}
43
-
44
- @file_app.get("/list")
45
- def list_files():
46
- return {"files": [p.name for p in FILE_STORAGE.iterdir() if p.is_file()]}
47
-
48
- @file_app.get("/read/{name}")
49
- def read_file(name: str):
50
- fpath = FILE_STORAGE / name
51
- if not fpath.exists():
52
- return {"error": "not found"}
53
- return {"filename": name, "content": fpath.read_text(encoding="utf-8")}
54
-
55
- # --- Executor Server ---
56
- EXECUTOR_DB = Path("executor_db")
57
- EXECUTOR_DB.mkdir(exist_ok=True)
58
-
59
- @executor_app.post("/apply")
60
- def apply_patch(req: dict):
61
- rec = {
62
- "filename": req.get("filename"),
63
- "action": req.get("action"),
64
- "params": req.get("params", {}),
65
- "timestamp": datetime.datetime.utcnow().isoformat()
66
- }
67
- fname = EXECUTOR_DB / f"{rec['filename']}.patchlog.json"
68
- existing = []
69
- if fname.exists():
70
- existing = json.loads(fname.read_text())
71
- existing.append(rec)
72
- fname.write_text(json.dumps(existing, indent=2))
73
- return {"status": "applied", "record": rec}
74
-
75
- # --- Memory Server ---
76
- MEMORY_DB = Path("memory_db")
77
- MEMORY_DB.mkdir(exist_ok=True)
78
- MEMORY_FILE = MEMORY_DB / "memory.json"
79
- if not MEMORY_FILE.exists():
80
- MEMORY_FILE.write_text(json.dumps({}))
81
-
82
- @memory_app.post("/set")
83
- def set_memory(item: dict):
84
- m = json.loads(MEMORY_FILE.read_text())
85
- key = item.get("key")
86
- value = item.get("value")
87
- m[key] = value
88
- MEMORY_FILE.write_text(json.dumps(m, indent=2))
89
- return {"status": "ok", "key": key}
90
-
91
- @memory_app.get("/get/{key}")
92
- def get_memory(key: str):
93
- m = json.loads(MEMORY_FILE.read_text())
94
- return {"value": m.get(key)}
95
-
96
- # -----------------------
97
- # HELPER FUNCTIONS
98
- # -----------------------
99
- def list_mcp_files():
100
- try:
101
- r = requests.get(f"http://localhost:{FILE_SERVER_PORT}/list", timeout=5)
102
- return r.json()
103
- except:
104
- return {"files": [f.name for f in FILE_STORAGE.iterdir() if f.is_file()]}
105
-
106
- def read_mcp_file(name):
107
- try:
108
- r = requests.get(f"http://localhost:{FILE_SERVER_PORT}/read/{name}", timeout=5)
109
- return r.json()
110
- except:
111
- return {"error": "file read failed"}
112
-
113
- def apply_patch_mcp(filename, action, params=None):
114
- payload = {"filename": filename, "action": action, "params": params or {}}
115
- try:
116
- r = requests.post(f"http://localhost:{EXECUTOR_PORT}/apply", json=payload, timeout=5)
117
- return r.json()
118
- except:
119
- return {"error": "executor not reachable"}
120
-
121
- def memory_set(key, value):
122
- try:
123
- r = requests.post(f"http://localhost:{MEMORY_PORT}/set", json={"key": key, "value": value}, timeout=5)
124
- return r.json()
125
- except:
126
- return {"error": "memory not reachable"}
127
-
128
- def memory_get(key):
129
- try:
130
- r = requests.get(f"http://localhost:{MEMORY_PORT}/get/{key}", timeout=5)
131
- return r.json()
132
- except:
133
- return {"error": "memory not reachable"}
134
-
135
  # -----------------------
136
- # LOG ANALYSIS
137
  # -----------------------
138
  def parse_log_text(txt):
139
  lines = txt.splitlines()
@@ -141,125 +24,101 @@ def parse_log_text(txt):
141
  warnings = [l for l in lines if "WARNING" in l or "WARN" in l]
142
  return {"errors": errors, "warnings": warnings, "total_lines": len(lines)}
143
 
144
- def analyze_and_plan(filename):
145
- r = read_mcp_file(filename)
146
- if "error" in r:
147
- return {"summary": "File not found", "issues": [], "suggestions": [], "plan_text": ""}
148
- text = r.get("content","")
 
149
  parsed = parse_log_text(text)
 
150
  summary = f"Detected {len(parsed['errors'])} errors and {len(parsed['warnings'])} warnings in {parsed['total_lines']} lines."
151
- issues = parsed["errors"][:10] + parsed["warnings"][:10]
152
  suggestions = [
153
  "Investigate top errors",
154
  "Check system configuration",
155
  "Add proper exception handling"
156
  ]
157
- plan_text = "\n".join([
158
  "STEP 1: Review errors",
159
  "STEP 2: Apply suggested fixes",
160
  "STEP 3: Re-run analysis"
161
  ])
162
- return {"summary": summary, "issues": issues, "suggestions": suggestions, "plan_text": plan_text}
163
 
164
- def generate_incident_report(filename, summary, issues, suggestions):
165
- now = datetime.datetime.utcnow().isoformat().replace(":", "-")
166
  out = REPORT_DIR / f"incident_{filename}_{now}.pdf"
167
  c = canvas.Canvas(str(out), pagesize=letter)
168
- c.setFont("Helvetica-Bold", 16)
169
- c.drawString(40, 750, f"Incident Report - {filename}")
170
- c.setFont("Helvetica", 10)
171
- c.drawString(40, 730, f"Generated: {datetime.datetime.utcnow().isoformat()}")
172
- y = 700
173
- c.drawString(40, y, "Summary:")
174
- c.drawString(60, y-20, summary[:1000])
175
- y -= 60
176
- c.drawString(40, y, "Issues:")
177
  for it in issues:
178
- y -= 14
179
- c.drawString(60, y, it[:120])
180
- if y < 80:
181
- c.showPage(); y = 740
182
- y -= 20
183
- c.drawString(40, y, "Suggestions:")
 
184
  for s in suggestions:
185
- y -= 14
186
- c.drawString(60, y, f"- {s[:100]}")
187
- if y < 80:
188
- c.showPage(); y = 740
 
189
  c.save()
190
  return str(out)
191
 
192
  # -----------------------
193
  # GRADIO UI
194
  # -----------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  with gr.Blocks() as demo:
196
- gr.Markdown("## AgentOps MCP - Log Analysis & Agent Planning")
197
  with gr.Row():
198
  with gr.Column(scale=2):
199
  upload = gr.File(label="Upload log file", file_types=[".txt"])
200
  btn_upload = gr.Button("Upload File")
201
- files_list = gr.Dropdown(choices=[], label="Files on MCP Server", interactive=True)
202
  btn_refresh = gr.Button("Refresh files")
203
  btn_analyze = gr.Button("Analyze selected file")
204
- apply_dropdown = gr.Dropdown(choices=["increase_timeout","increase_retries","mark_fixed"], label="Select fix action")
205
- btn_apply = gr.Button("Apply fix")
206
  with gr.Column(scale=3):
207
- summary_box = gr.Textbox(label="Agent Summary", lines=6)
208
  issues_box = gr.Textbox(label="Detected Issues", lines=10)
209
- suggestions_box = gr.Textbox(label="Suggested Fixes", lines=6)
210
- plan_box = gr.Textbox(label="Agent Plan / Reasoning", lines=6)
211
- report_download = gr.File(label="Last Report (download)")
212
-
213
- # Initialize dropdown
214
- files_list.choices = [f for f in FILE_STORAGE.iterdir() if f.is_file()]
215
-
216
- def refresh_files():
217
- return list_mcp_files().get("files", [])
218
-
219
- btn_refresh.click(fn=refresh_files, outputs=[files_list])
220
 
221
- def on_upload(file_obj):
222
- if file_obj is None:
223
- return refresh_files()
224
- content = file_obj.read()
225
- if isinstance(content, bytes):
226
- content = content.decode("utf-8", errors="ignore")
227
- tmp = FILE_STORAGE / file_obj.name
228
- with open(tmp, "w", encoding="utf-8") as f:
229
- f.write(content)
230
- return refresh_files()
231
-
232
- btn_upload.click(fn=on_upload, inputs=[upload], outputs=[files_list])
233
-
234
- def analyze_selected(fname):
235
- if not fname:
236
- return "", "", "", "", None
237
- out = analyze_and_plan(fname)
238
- report_path = generate_incident_report(fname, out["summary"], out["issues"], out["suggestions"])
239
- return (out["summary"], "\n".join(out["issues"]), "\n".join(out["suggestions"]),
240
- out["plan_text"], gr.File.update(value=report_path))
241
-
242
- btn_analyze.click(fn=analyze_selected, inputs=[files_list],
243
  outputs=[summary_box, issues_box, suggestions_box, plan_box, report_download])
244
 
245
- def apply_action(fname, action_key):
246
- if not fname:
247
- return ""
248
- res = apply_patch_mcp(fname, action_key)
249
- return json.dumps(res, indent=2)
250
-
251
- btn_apply.click(fn=apply_action, inputs=[files_list, apply_dropdown], outputs=[plan_box])
252
-
253
- # -----------------------
254
- # START MCP SERVERS
255
- # -----------------------
256
- def start_file_server(): uvicorn.run(file_app, host="0.0.0.0", port=FILE_SERVER_PORT, log_level="error")
257
- def start_executor_server(): uvicorn.run(executor_app, host="0.0.0.0", port=EXECUTOR_PORT, log_level="error")
258
- def start_memory_server(): uvicorn.run(memory_app, host="0.0.0.0", port=MEMORY_PORT, log_level="error")
259
-
260
- threading.Thread(target=start_file_server, daemon=True).start()
261
- threading.Thread(target=start_executor_server, daemon=True).start()
262
- threading.Thread(target=start_memory_server, daemon=True).start()
263
-
264
  if __name__ == "__main__":
265
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  # app.py
2
  import os
 
3
  import datetime
4
  import json
5
  from pathlib import Path
 
6
  from reportlab.lib.pagesizes import letter
7
  from reportlab.pdfgen import canvas
8
  import gradio as gr
 
 
9
 
10
  # -----------------------
11
  # CONFIG
 
15
  REPORT_DIR = Path("reports")
16
  REPORT_DIR.mkdir(exist_ok=True)
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  # -----------------------
19
+ # LOG ANALYSIS FUNCTIONS
20
  # -----------------------
21
  def parse_log_text(txt):
22
  lines = txt.splitlines()
 
24
  warnings = [l for l in lines if "WARNING" in l or "WARN" in l]
25
  return {"errors": errors, "warnings": warnings, "total_lines": len(lines)}
26
 
27
+ def analyze_log(filename):
28
+ filepath = FILE_STORAGE / filename
29
+ if not filepath.exists():
30
+ return {"summary":"File not found","issues":[],"suggestions":[],"plan":""}
31
+
32
+ text = filepath.read_text(encoding="utf-8", errors="ignore")
33
  parsed = parse_log_text(text)
34
+
35
  summary = f"Detected {len(parsed['errors'])} errors and {len(parsed['warnings'])} warnings in {parsed['total_lines']} lines."
36
+ issues = parsed['errors'][:10] + parsed['warnings'][:10]
37
  suggestions = [
38
  "Investigate top errors",
39
  "Check system configuration",
40
  "Add proper exception handling"
41
  ]
42
+ plan = "\n".join([
43
  "STEP 1: Review errors",
44
  "STEP 2: Apply suggested fixes",
45
  "STEP 3: Re-run analysis"
46
  ])
47
+ return {"summary": summary, "issues": issues, "suggestions": suggestions, "plan": plan}
48
 
49
+ def generate_report(filename, summary, issues, suggestions):
50
+ now = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S")
51
  out = REPORT_DIR / f"incident_{filename}_{now}.pdf"
52
  c = canvas.Canvas(str(out), pagesize=letter)
53
+ c.setFont("Helvetica-Bold",16)
54
+ c.drawString(40,750,f"Incident Report - {filename}")
55
+ c.setFont("Helvetica",10)
56
+ c.drawString(40,730,f"Generated: {datetime.datetime.utcnow().isoformat()}")
57
+ y=700
58
+ c.drawString(40,y,"Summary:")
59
+ c.drawString(60,y-20,summary[:1000])
60
+ y-=60
61
+ c.drawString(40,y,"Issues:")
62
  for it in issues:
63
+ y-=14
64
+ c.drawString(60,y,it[:120])
65
+ if y<80:
66
+ c.showPage()
67
+ y=740
68
+ y-=20
69
+ c.drawString(40,y,"Suggestions:")
70
  for s in suggestions:
71
+ y-=14
72
+ c.drawString(60,y,f"- {s[:100]}")
73
+ if y<80:
74
+ c.showPage()
75
+ y=740
76
  c.save()
77
  return str(out)
78
 
79
  # -----------------------
80
  # GRADIO UI
81
  # -----------------------
82
+ def refresh_files():
83
+ return [f.name for f in FILE_STORAGE.iterdir() if f.is_file()]
84
+
85
+ def upload_file(file_obj):
86
+ if file_obj is None:
87
+ return refresh_files()
88
+ filepath = FILE_STORAGE / file_obj.name
89
+ content = file_obj.read()
90
+ if isinstance(content, bytes):
91
+ content = content.decode("utf-8", errors="ignore")
92
+ filepath.write_text(content, encoding="utf-8")
93
+ return refresh_files()
94
+
95
+ def analyze_selected(filename):
96
+ if not filename:
97
+ return "", "", "", "", None
98
+ out = analyze_log(filename)
99
+ report_path = generate_report(filename, out["summary"], out["issues"], out["suggestions"])
100
+ return (out["summary"], "\n".join(out["issues"]), "\n".join(out["suggestions"]), out["plan"], gr.File.update(value=report_path))
101
+
102
  with gr.Blocks() as demo:
103
+ gr.Markdown("## AgentOps MCP - Log Analysis")
104
  with gr.Row():
105
  with gr.Column(scale=2):
106
  upload = gr.File(label="Upload log file", file_types=[".txt"])
107
  btn_upload = gr.Button("Upload File")
108
+ files_dropdown = gr.Dropdown(choices=refresh_files(), label="Files available")
109
  btn_refresh = gr.Button("Refresh files")
110
  btn_analyze = gr.Button("Analyze selected file")
 
 
111
  with gr.Column(scale=3):
112
+ summary_box = gr.Textbox(label="Summary", lines=3)
113
  issues_box = gr.Textbox(label="Detected Issues", lines=10)
114
+ suggestions_box = gr.Textbox(label="Suggestions", lines=6)
115
+ plan_box = gr.Textbox(label="Agent Plan", lines=6)
116
+ report_download = gr.File(label="Download PDF Report")
 
 
 
 
 
 
 
 
117
 
118
+ btn_refresh.click(fn=refresh_files, outputs=files_dropdown)
119
+ btn_upload.click(fn=upload_file, inputs=upload, outputs=files_dropdown)
120
+ btn_analyze.click(fn=analyze_selected, inputs=files_dropdown,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  outputs=[summary_box, issues_box, suggestions_box, plan_box, report_download])
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  if __name__ == "__main__":
124
  demo.launch(server_name="0.0.0.0", server_port=7860)