UNPKG

memory-monitor-sdk

Version:

A powerful JavaScript memory monitoring SDK for Web and mobile applications. Features real-time monitoring, data visualization, automatic reporting, and memory leak detection.

1 lines 10.2 kB
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>内存监控数据可视化</title><script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script><style>*{margin:0;padding:0;box-sizing:border-box}body{font-family:'Segoe UI',Tahoma,Geneva,Verdana,sans-serif;background:linear-gradient(135deg,#667eea 0,#764ba2 100%);min-height:100vh;padding:20px}.container{max-width:1400px;margin:0 auto;background:#fff;border-radius:15px;box-shadow:0 20px 40px rgba(0,0,0,.1);overflow:hidden}.header{background:linear-gradient(135deg,#667eea 0,#764ba2 100%);color:#fff;padding:30px;text-align:center}.header h1{font-size:2.5em;margin-bottom:10px;font-weight:300}.header p{font-size:1.1em;opacity:.9}.controls{padding:20px 30px;background:#f8f9fa;border-bottom:1px solid #e9ecef;display:flex;gap:15px;align-items:center;flex-wrap:wrap}.file-input-wrapper{position:relative;display:inline-block}.file-input{display:none}.file-input-label{background:#007bff;color:#fff;padding:10px 20px;border-radius:8px;cursor:pointer;transition:all .3s ease;display:inline-block;font-weight:500}.file-input-label:hover{background:#0056b3;transform:translateY(-2px)}.btn{background:#28a745;color:#fff;border:none;padding:10px 20px;border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;transition:all .3s ease}.btn:hover{background:#218838;transform:translateY(-2px)}.btn-secondary{background:#6c757d}.btn-secondary:hover{background:#5a6268}.info-panel{background:#e3f2fd;padding:15px;border-radius:8px;margin-left:auto;min-width:200px}.info-item{display:flex;justify-content:space-between;margin-bottom:5px}.info-label{font-weight:600;color:#1976d2}.info-value{color:#333}.chart-container{padding:30px}.chart-title{font-size:1.5em;margin-bottom:20px;color:#333;text-align:center}.chart-wrapper{width:100%;height:500px;border:1px solid #e9ecef;border-radius:8px;padding:20px;background:#fafafa}.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px;margin-bottom:30px}.stat-card{background:#fff;padding:20px;border-radius:10px;box-shadow:0 4px 6px rgba(0,0,0,.1);border-left:4px solid #007bff}.stat-title{font-size:.9em;color:#666;margin-bottom:10px;text-transform:uppercase;letter-spacing:1px}.stat-value{font-size:2em;font-weight:700;color:#333;margin-bottom:5px}.stat-subtitle{font-size:.8em;color:#999}.no-data{text-align:center;padding:60px 20px;color:#666}.no-data-icon{font-size:4em;margin-bottom:20px}.loading{text-align:center;padding:40px;color:#666}.spinner{border:4px solid #f3f3f3;border-top:4px solid #007bff;border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite;margin:0 auto 20px}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.error{background:#f8d7da;color:#721c24;padding:15px;border-radius:8px;margin:20px 0;border:1px solid #f5c6cb}.success{background:#d4edda;color:#155724;padding:15px;border-radius:8px;margin:20px 0;border:1px solid #c3e6cb}@media (max-width:768px){.controls{flex-direction:column;align-items:stretch}.info-panel{margin-left:0;margin-top:15px}.chart-wrapper{height:400px}.stats-grid{grid-template-columns:1fr}}</style></head><body><div class="container"><div class="header"><h1>🔍 内存监控数据可视化</h1><p>实时内存使用情况分析和趋势展示</p></div><div class="controls"><div class="file-input-wrapper"><input type="file" id="fileInput" class="file-input" accept=".json" multiple="multiple"> <label for="fileInput" class="file-input-label">📁 选择JSON数据文件</label></div><button class="btn" onclick="loadSampleData()">📊 加载示例数据</button> <button class="btn btn-secondary" onclick="clearData()">🗑️ 清空数据</button> <button class="btn btn-secondary" onclick="exportData()">💾 导出数据</button><div class="info-panel" id="infoPanel" style="display:none"><div class="info-item"><span class="info-label">会话ID:</span> <span class="info-value" id="sessionId">-</span></div><div class="info-item"><span class="info-label">运行时长:</span> <span class="info-value" id="duration">-</span></div><div class="info-item"><span class="info-label">采样点数:</span> <span class="info-value" id="sampleCount">-</span></div><div class="info-item"><span class="info-label">峰值变化:</span> <span class="info-value" id="peakChanges">-</span></div></div></div><div class="chart-container"><div id="messageArea"></div><div class="stats-grid" id="statsGrid" style="display:none"><div class="stat-card"><div class="stat-title">当前内存使用</div><div class="stat-value" id="currentMemory">-</div><div class="stat-subtitle">MB</div></div><div class="stat-card"><div class="stat-title">最大内存使用</div><div class="stat-value" id="maxMemory">-</div><div class="stat-subtitle">MB</div></div><div class="stat-title">平均内存使用</div><div class="stat-value" id="avgMemory">-</div><div class="stat-subtitle">MB</div></div><div class="stat-card"><div class="stat-title">内存使用率</div><div class="stat-value" id="usagePercent">-</div><div class="stat-subtitle">%</div></div></div><div class="chart-title">内存使用趋势图</div><div class="chart-wrapper"><div id="memoryChart" style="width:100%;height:100%"></div></div></div><script>let currentData=null,chart=null;function initChart(){const e=document.getElementById("memoryChart");chart=echarts.init(e);chart.setOption({title:{text:"内存使用趋势",left:"center",textStyle:{fontSize:18,fontWeight:"normal"}},tooltip:{trigger:"axis",backgroundColor:"rgba(0,0,0,0.8)",borderColor:"#333",textStyle:{color:"#fff"},formatter:function(e){const t=e[0].data;return`\n <div style="padding: 10px;">\n <div><strong>时间:</strong> ${t.time}</div>\n <div><strong>运行时长:</strong> ${t.runtime}</div>\n <div><strong>页面:</strong> ${t.page}</div>\n <div><strong>内存使用:</strong> ${t.used}MB</div>\n <div><strong>使用率:</strong> ${t.usage}%</div>\n </div>\n `}},legend:{data:["内存使用","内存限制"],top:30},grid:{left:"3%",right:"4%",bottom:"3%",top:"15%",containLabel:!0},xAxis:{type:"category",boundaryGap:!1,data:[],axisLabel:{rotate:45,fontSize:12}},yAxis:{type:"value",name:"内存使用 (MB)",axisLabel:{formatter:"{value} MB"}},series:[{name:"内存使用",type:"line",data:[],smooth:!0,lineStyle:{color:"#007bff",width:3},itemStyle:{color:"#007bff"},areaStyle:{color:{type:"linear",x:0,y:0,x2:0,y2:1,colorStops:[{offset:0,color:"rgba(0, 123, 255, 0.3)"},{offset:1,color:"rgba(0, 123, 255, 0.1)"}]}}}]})}function loadData(e){currentData=e,document.getElementById("sessionId").textContent=e.sessionId||"-",document.getElementById("duration").textContent=e.duration||"-",document.getElementById("sampleCount").textContent=e.totalSamples||"-",document.getElementById("peakChanges").textContent=e.peakChanges?e.peakChanges.length:"-",document.getElementById("infoPanel").style.display="block",document.getElementById("statsGrid").style.display="grid";const t=e.data||[],n=t.map(e=>e.used),a=n[n.length-1]||0,o=Math.max(...n),r=Math.round(n.reduce((e,t)=>e+t,0)/n.length),s=Math.round(a/e.config.simulatedLimitMB*100);if(document.getElementById("currentMemory").textContent=a,document.getElementById("maxMemory").textContent=o,document.getElementById("avgMemory").textContent=r,document.getElementById("usagePercent").textContent=s,chart){const e=t.map(e=>e.runtime),n=t.map(e=>({value:e.used,time:e.time,runtime:e.runtime,page:e.page,used:e.used,usage:e.usage}));chart.setOption({xAxis:{data:e},series:[{data:n}]})}showMessage("数据加载成功!","success")}function loadSampleData(){loadData({sessionId:"sample_20241219_001",startTime:Date.now()-3e5,endTime:Date.now(),duration:"5分0秒",totalSamples:30,peakChanges:[{timestamp:Date.now()-2e5,change:25,memory:150,runtimeFromStart:"2分30秒",page:"/pages/index/index",timeFromStart:"14:30:15"}],trend:{trend:"increasing",message:"内存使用增长 15.5%,可能存在内存泄漏",growth:"20MB"},data:generateSampleMemoryData(),config:{simulatedLimitMB:300,peakThresholdMB:20}})}function generateSampleMemoryData(){const e=[],t=Date.now()-3e5;for(let n=0;n<30;n++){const a=t+1e4*n,o=a-t,r=`${Math.floor(o/1e3/60)}:${Math.floor(o%6e4/1e3).toString().padStart(2,"0")}`,s=20*Math.sin(.2*n)+2*n,i=Math.round(100+s+10*Math.random());e.push({timestamp:a,time:new Date(a).toLocaleTimeString(),runtime:r,page:n<10?"/pages/index/index":n<20?"/pages/call/call":"/pages/chat/chat",used:i,total:i+Math.round(50*Math.random()),usage:Math.round(i/300*100)})}return e}function clearData(){currentData=null,document.getElementById("infoPanel").style.display="none",document.getElementById("statsGrid").style.display="none",chart&&chart.setOption({xAxis:{data:[]},series:[{data:[]}]}),showMessage("数据已清空","success")}function exportData(){if(!currentData)return void showMessage("没有数据可导出","error");const e=JSON.stringify(currentData,null,2),t=new Blob([e],{type:"application/json"}),n=URL.createObjectURL(t),a=document.createElement("a");a.href=n,a.download=`memory-data-${currentData.sessionId}.json`,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n),showMessage("数据已导出","success")}function showMessage(e,t){const n=document.getElementById("messageArea");n.innerHTML=`<div class="${t}">${e}</div>`,setTimeout(()=>{n.innerHTML=""},3e3)}document.getElementById("fileInput").addEventListener("change",function(e){const t=e.target.files;if(t.length>0){const e=t[0],n=new FileReader;n.onload=function(e){try{loadData(JSON.parse(e.target.result))}catch(e){showMessage("文件格式错误,请选择有效的JSON文件","error")}},n.readAsText(e)}}),window.addEventListener("load",function(){initChart(),showMessage("欢迎使用内存监控数据可视化工具!请选择JSON数据文件或加载示例数据。","success")}),window.addEventListener("resize",function(){chart&&chart.resize()})</script></body></html>