Skip to content

Commit 033a231

Browse files
authored
Merge pull request #59 from qiniu/xgopilot/claude/issue-58-1764151462
优化 query_live_traffic_stats 实现
2 parents 17930be + efa670a commit 033a231

File tree

2 files changed

+103
-11
lines changed

2 files changed

+103
-11
lines changed

src/mcp_server/core/live_streaming/live_streaming.py

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -336,16 +336,18 @@ def get_play_urls(self, play_domain: str, bucket: str, stream_name: str) -> Dict
336336
"message": "Playback URLs generated successfully"
337337
}
338338

339-
async def query_live_traffic_stats(self, begin: str, end: str) -> Dict[str, Any]:
339+
async def query_live_traffic_stats(self, begin: str, end: str, include_raw_data: bool = False) -> Dict[str, Any]:
340340
"""
341341
Query live streaming traffic statistics
342342
343343
Args:
344344
begin: Start time in format YYYYMMDDHHMMSS (e.g., 20240101000000)
345345
end: End time in format YYYYMMDDHHMMSS (e.g., 20240129105148)
346+
include_raw_data: If True, includes raw JSON data for download (default: False)
346347
347348
Returns:
348-
Dict containing traffic statistics
349+
Dict containing traffic statistics with total traffic (bytes), average bandwidth (bps),
350+
peak bandwidth (bps), and optionally raw data
349351
"""
350352
if not self.live_endpoint:
351353
self.live_endpoint = "mls.cn-east-1.qiniumiku.com"
@@ -375,14 +377,99 @@ async def query_live_traffic_stats(self, begin: str, end: str) -> Dict[str, Any]
375377

376378
if status == 200:
377379
logger.info("Successfully queried live traffic stats")
378-
return {
379-
"status": "success",
380-
"begin": begin,
381-
"end": end,
382-
"data": text,
383-
"message": "Traffic statistics retrieved successfully",
384-
"status_code": status
385-
}
380+
381+
try:
382+
# Parse JSON response
383+
data = json.loads(text)
384+
385+
# Calculate total traffic and bandwidth metrics
386+
total_traffic_bytes = 0
387+
bandwidth_values = []
388+
data_points = []
389+
390+
# Data format: [{"time":"2025-11-26T00:00:00+08:00","values":{"flow":0}}, ...]
391+
for item in data:
392+
if isinstance(item, dict) and "values" in item and "flow" in item["values"]:
393+
flow_bytes = item["values"]["flow"]
394+
total_traffic_bytes += flow_bytes
395+
396+
# Convert to bandwidth: flow is accumulated over 5 minutes (300 seconds)
397+
# Bandwidth (bps) = bytes / 300 seconds * 8 bits/byte
398+
bandwidth_bps = (flow_bytes / 300) * 8
399+
bandwidth_values.append(bandwidth_bps)
400+
401+
# Store data point with timestamp
402+
data_points.append({
403+
"time": item.get("time", ""),
404+
"traffic_bytes": flow_bytes,
405+
"bandwidth_bps": bandwidth_bps
406+
})
407+
408+
# Calculate average and peak bandwidth
409+
avg_bandwidth_bps = sum(bandwidth_values) / len(bandwidth_values) if bandwidth_values else 0
410+
peak_bandwidth_bps = max(bandwidth_values) if bandwidth_values else 0
411+
412+
# Convert to human-readable units
413+
def format_bytes(bytes_val):
414+
"""Convert bytes to human-readable format"""
415+
for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
416+
if bytes_val < 1024.0:
417+
return f"{bytes_val:.2f} {unit}"
418+
bytes_val /= 1024.0
419+
return f"{bytes_val:.2f} PB"
420+
421+
def format_bandwidth(bps):
422+
"""Convert bits per second to human-readable format"""
423+
for unit in ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps']:
424+
if bps < 1000.0:
425+
return f"{bps:.2f} {unit}"
426+
bps /= 1000.0
427+
return f"{bps:.2f} Pbps"
428+
429+
result = {
430+
"status": "success",
431+
"begin": begin,
432+
"end": end,
433+
"summary": {
434+
"total_traffic_bytes": total_traffic_bytes,
435+
"total_traffic_formatted": format_bytes(total_traffic_bytes),
436+
"data_points_count": len(data_points),
437+
"average_bandwidth_bps": avg_bandwidth_bps,
438+
"average_bandwidth_formatted": format_bandwidth(avg_bandwidth_bps),
439+
"peak_bandwidth_bps": peak_bandwidth_bps,
440+
"peak_bandwidth_formatted": format_bandwidth(peak_bandwidth_bps),
441+
"granularity": "5 minutes"
442+
},
443+
"message": "Traffic statistics calculated successfully",
444+
"status_code": status
445+
}
446+
447+
# Include raw data only if requested
448+
if include_raw_data:
449+
result["raw_data"] = data
450+
result["data_points"] = data_points
451+
452+
return result
453+
454+
except json.JSONDecodeError as e:
455+
logger.error(f"Failed to parse JSON response: {e}")
456+
return {
457+
"status": "error",
458+
"begin": begin,
459+
"end": end,
460+
"message": f"Failed to parse traffic stats response: {str(e)}",
461+
"raw_response": text,
462+
"status_code": status
463+
}
464+
except Exception as e:
465+
logger.error(f"Error processing traffic stats: {e}")
466+
return {
467+
"status": "error",
468+
"begin": begin,
469+
"end": end,
470+
"message": f"Error processing traffic stats: {str(e)}",
471+
"status_code": status
472+
}
386473
else:
387474
logger.error(f"Failed to query traffic stats, status: {status}, response: {text}")
388475
return {

src/mcp_server/core/live_streaming/tools.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ async def get_play_urls(self, **kwargs) -> list[types.TextContent]:
177177
@tools.tool_meta(
178178
types.Tool(
179179
name="live_streaming_query_live_traffic_stats",
180-
description="Query live streaming traffic statistics for a time range. Returns bandwidth and traffic usage data.",
180+
description="Query live streaming traffic statistics for a time range. Returns total traffic (bytes), average bandwidth (bps), peak bandwidth (bps), and optionally raw data for download.",
181181
inputSchema={
182182
"type": "object",
183183
"properties": {
@@ -189,6 +189,11 @@ async def get_play_urls(self, **kwargs) -> list[types.TextContent]:
189189
"type": "string",
190190
"description": "End time in format YYYYMMDDHHMMSS (e.g., 20240129105148)",
191191
},
192+
"include_raw_data": {
193+
"type": "boolean",
194+
"description": "If true, includes raw JSON data and detailed data points for download. Default is false.",
195+
"default": False,
196+
},
192197
},
193198
"required": ["begin", "end"],
194199
},

0 commit comments

Comments
 (0)