我需要将应用程序 Flame Graph 嵌入 Azure Devops wiki 页面。
FlameGraph 是应用程序调用堆栈的可视化,形式非常简单易懂。物理上它是一个 SVG 图像,由浏览器呈现,如下所示(可点击):
但是,我想嵌入的不是通常的 FlameGraph,而是一个 HTML 图形,它是一个巨大的 70K+ HTML 和 JS 行。渲染后的这段代码看起来完全像 SVG,这里是示例
<g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')"
onclick="zoom(this, 'perf')" >
<title>consular_function</title>
<rect x="531.6" y="398" width="0.6" height="15.0" fill="rgb(220,220,220)" rx="2.2" ry="2.2" />
<text text-anchor="" x="534.61" y="408.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >
</text>
</g>
<g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')"
onclick="zoom(this, 'perf')" >
<title>db_function</title>
<rect x="1367.2" y="446" width="0.1" height="15.0" fill="rgb(130,202,250)" rx="2.2" ry="2.2" />
<text text-anchor="" x="1370.18" y="456.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >
</text>
</g>
<g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')" onclick="zoom(this, 'perf')" >
<title>db_function</title>
<rect x="1402.0" y="414" width="1.7" height="15.0" fill="rgb(130,202,250)" rx="2.2" ry="2.2" />
<text text-anchor="" x="1405.03" y="424.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >
</text>
</g>
<g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')"
onclick="zoom(this, 'perf')" >
<title>consular_function</title>
<rect x="1037.6" y="302" width="4.6" height="15.0" fill="rgb(220,220,220)" rx="2.2" ry="2.2" />
<text text-anchor="" x="1040.59" y="312.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >
</text>
</g>
<g id="" class="func_g" onmouseover="s(this, '', 'perf')" onmouseout="c('', 'perf')"
onclick="zoom(this, 'perf')" >
<title>moduled_function (3,218 us, 0,04%)</title>
<rect x="10.8" y="494" width="0.7" height="15.0" fill="rgb(237,110,36)" rx="2.2" ry="2.2" />
<text text-anchor="" x="13.78" y="504.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >
</text>
</g>
<defs >
<linearGradient id="background_mem" y1="0" y2="1" x1="0" x2="0" >
<stop stop-color="#eeeeef" offset="10%" />
<stop stop-color="#eeeee0" offset="90%" />
</linearGradient>
</defs>
<style type="text/css">
.func_g:hover { stroke:black; stroke-width:0.5; cursor:pointer; }
</style>
</svg>
<script type="text/ecmascript">
// Javascript for svg file
// Used to control flame graph operations, e.g. zoom in/out, search, etc
if(typeof window.flameGraph == "undefined") window.flameGraph={}; // global flame graph elements (contained width, it is a hashmap for each svgId)
if(typeof window.searchButton == "undefined") window.searchButton={}; // global searching button hashmap for each svgId
if(typeof window.detailedTextField == "undefined") window.detailedTextField={}; // global detailed text box (on the bottom of graph) hashmap for each svgId
if(typeof window.matchedTextField == "undefined") window.matchedTextField={}; // global matched text box (on the right of detailed text box) hashmap for each svgId
if(typeof window.isSearching == "undefined") window.isSearching={}; // global hashmap for each svg whether it is in searching mode or not
if(typeof window.revertGraph == "undefined") window.revertGraph={}; // global hashmap for each svg whether the flame graph is reverted or not
revertGraph['mem'] = 0;
function init(evt, hlString, svgId) { //init function used to initialize the variables
if(svgId == undefined) return;
flameGraph[svgId] = document.getElementById(svgId).getAttribute("svg_width"); // get flame graph width by internal svg label "svg_width"
searchButton[svgId] = document.getElementById(svgId + "_search"); // get search button
detailedTextField[svgId] = document.getElementById(svgId + "_details").firstChild; // get details text box
matchedTextField[svgId] = document.getElementById(svgId + "_matched"); // get matched text box
isSearching[svgId] = 0; // not searching
if(hlString.length != 0) search(hlString, svgId); // if needed -> highlight string with search function when creating flame graph
}
init(null, '', 'mem');
function jumpToPage(title) { // jump to formatted dev trace page
var reg = new RegExp('(?<=w)([0-9]+)(?=\\s\\()');
var pageNo = reg.exec(title);
if(pageNo == null) {alert('target not found.'); return;}
showDevTrace('' + pageNo[0] + '_html');
}
function s(node, id, svgId) { // mouse-over action
detailedTextField[svgId].nodeValue = "" + getTitleText(node); // show the text of current choosing node
if(id.length != 0) window.parent.highlightFrame(id);
}
function c(id, svgId) { // mouse-out action
detailedTextField[svgId].nodeValue = ' ';
if(id.length != 0) window.parent.unhighlightFrame(id);
}
function getTitleText(e) { //return the title string of the e node
var text = findChild(e, "title").firstChild.nodeValue;
return (text);
}
function findChild(e, name, attr) { // looking for the child (of e) whose name is equal to "name"
var children = e.childNodes;
for(var i=0; i<children.length;i++) {
if(children[i].tagName == name) {
if(attr == undefined) return children[i]; //return the child node
else children[i].attributes[attr].value; // if attr is inputed, return the attr value of this child node
}
}
return;
}
table, th, td {
background-color: #FFFFF1;
padding: 7px;
border: 1px solid black;
border-collapse: collapse;
overflow: visible;
font-size: 12px;
alig: left;
}
<style></body>
</html>
完整的代码太大了,所以我把完整的工作样本放入小提琴中。
我尝试将 HTML/JS 行直接放入 Azure 页面,但它不会像纯文本一样呈现此代码,但对于像表格和列表这样的简单 HTML,Azure 可以工作。
如何将此部分嵌入 Azure?我知道仍然不支持iframe但也许还有另一种方法?
PS 也许有办法将 html 渲染的图形转换为 SVG,Azure 是否正确渲染了这样的 SVG?