0

我需要将应用程序 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?

4

0 回答 0