Commit 34cbf7a6 by Dave Syer

Make Hystrix dash embeddable

parent 4ca9d5f7
......@@ -6,7 +6,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.cloud.netflix.hystrix.HystrixDashboardConfiguration;
import org.springframework.cloud.netflix.hystrix.dashboard.HystrixDashboardConfiguration;
import org.springframework.context.annotation.Import;
/**
......
.dependencies .spacer {
width: 100%;
margin: 0 auto;
padding-top:4px;
clear:both;
}
.dependencies .last {
margin-right: 0px;
}
.dependencies span.loading {
display: block;
padding-top: 6%;
padding-bottom: 6%;
color: gray;
text-align: center;
}
.dependencies span.loading.failed {
color: red;
}
.dependencies div.monitor {
float: left;
margin-right:5px;
margin-top:5px;
}
.dependencies div.monitor p.name {
font-weight:bold;
font-size: 10pt;
text-align: right;
padding-bottom: 5px;
}
.dependencies div.monitor_data {
margin: 0 auto;
}
/* override the HREF when we have specified it as a tooltip to not act like a link */
.dependencies div.monitor_data a.tooltip {
text-decoration: none;
cursor: default;
}
.dependencies div.monitor_data div.counters {
text-align: right;
padding-bottom: 10px;
font-size: 10pt;
clear: both;
}
.dependencies div.monitor_data div.counters div.cell {
display: inline;
float: right;
}
.dependencies .borderRight {
border-right: 1px solid grey;
padding-right: 6px;
padding-left: 8px;
}
.dependencies div.cell .line {
display: block;
}
.dependencies div.monitor_data a,
.dependencies span.rate_value {
font-weight:bold;
}
.dependencies span.smaller {
font-size: 8pt;
color: grey;
}
.dependencies div.tableRow {
width:100%;
white-space: nowrap;
font-size: 8pt;
margin: 0 auto;
clear:both;
padding-left:26%;
}
.dependencies div.tableRow .cell {
float:left;
}
.dependencies div.tableRow .header {
width:18%;
text-align:right;
padding-right:2%;
}
.dependencies div.tableRow .data {
width:17%;
font-weight: bold;
text-align:right;
}
.dependencies div.monitor {
width: 245px; /* we want a fixed width instead of percentage as I want the boxes to be a set size and then fill in as many as can fit in each row ... this allows 3 columns on an iPad */
height: 150px;
}
.dependencies .success {
color: green;
}
.dependencies .shortCircuited {
color: blue;
}
.dependencies .timeout {
color: #FF9900; /* shade of orange */
}
.dependencies .failure {
color: red;
}
.dependencies .rejected {
color: purple;
}
.dependencies .exceptionsThrown {
color: brown;
}
.dependencies div.monitor_data a.rate {
color: black;
font-size: 11pt;
}
.dependencies div.rate {
padding-top: 1px;
clear:both;
text-align:right;
}
.dependencies .errorPercentage {
color: grey;
}
.dependencies div.cell .errorPercentage {
padding-left:5px;
font-size: 12pt !important;
}
.dependencies div.monitor div.chart {
}
.dependencies div.monitor div.chart svg {
}
.dependencies div.monitor div.chart svg text {
fill: white;
}
.dependencies div.circuitStatus {
width:100%;
white-space: nowrap;
font-size: 9pt;
margin: 0 auto;
clear:both;
text-align:right;
padding-top: 4px;
}
.dependencies #hidden {
width:1px;
height:1px;
background: lightgrey;
display: none;
}
/* sparkline */
.dependencies path {
stroke: steelblue;
stroke-width: 1;
fill: none;
}
}
<div class="counters">
<div class="cell line">
<a href="javascript://" title="Error Percentage [Timed-out + Threadpool Rejected + Failure / Total]" class="tooltip errorPercentage"><span class="value"><%= errorPercentage %></span> %</a>
</div>
<div class="cell borderRight">
<% if(propertyValue_executionIsolationStrategy == 'THREAD') { %>
<a href="javascript://" title="Timed-out Request Count" class="line tooltip timeout"><%= addCommas(rollingCountTimeout) %></a>
<a href="javascript://" title="Threadpool Rejected Request Count" class="line tooltip rejected"><%= addCommas(rollingCountThreadPoolRejected) %></a>
<% } %>
<a href="javascript://" title="Failure Request Count" class="line tooltip failure"><%= addCommas(rollingCountFailure) %></a>
</div>
<div class="cell borderRight">
<a href="javascript://" title="Successful Request Count" class="line tooltip success"><%= addCommas(rollingCountSuccess) %></a>
<a href="javascript://" title="Short-circuited Request Count" class="line tooltip shortCircuited"><%= addCommas(rollingCountShortCircuited) %></a>
<br>
</div>
</div>
<div class="rate">
<a href="javascript://" title="Total Request Rate per Second per Reporting Host" class="tooltip rate"><span class="smaller">Host: </span><span class="ratePerSecondPerHost"><%= addCommas(roundNumber(ratePerSecondPerHost)) %></span>/s</a>
</div>
<div class="rate">
<a href="javascript://" title="Total Request Rate per Second for Cluster" class="tooltip rate"><span class="smaller">Cluster: </span><span class="ratePerSecond"><%= addCommas(roundNumber(ratePerSecond)) %></span>/s</a>
</div>
<div class="circuitStatus">
<% if(propertyValue_circuitBreakerForceClosed) { %>
<span class="smaller">[ <font color="orange">Forced Closed</font> ]</span>
<% } %>
<% if(propertyValue_circuitBreakerForceOpen) { %>
Circuit <font color="red">Forced Open</font>
<% } else { %>
<% if(isCircuitBreakerOpen == reportingHosts) { %>
Circuit <font color="red">Open</font>
<% } else if(isCircuitBreakerOpen == 0) { %>
Circuit <font color="green">Closed</font>
<% } else {
/* We have some circuits that are open */
%>
Circuit <font color="orange"><%= isCircuitBreakerOpen.replace("true", "Open").replace("false", "Closed") %>)</font>
<% } %>
<% } %>
</div>
<div class="spacer"></div>
<div class="tableRow">
<% if(typeof reportingHosts != 'undefined') { %>
<div class="cell header">Hosts</div>
<div class="cell data"><%= reportingHosts %></div>
<% } else { %>
<div class="cell header">Host</div>
<div class="cell data">Single</div>
<% } %>
<div class="cell header">90th</div>
<div class="cell data latency90"><span class="value"><%= getInstanceAverage(latencyExecute['90'], reportingHosts, false) %></span>ms</div>
</div>
<div class="tableRow">
<div class="cell header">Median</div>
<div class="cell data latencyMedian"><span class="value"><%= getInstanceAverage(latencyExecute['50'], reportingHosts, false) %></span>ms</div>
<div class="cell header">99th</div>
<div class="cell data latency99"><span class="value"><%= getInstanceAverage(latencyExecute['99'], reportingHosts, false) %></span>ms</div>
</div>
<div class="tableRow">
<div class="cell header">Mean</div>
<div class="cell data latencyMean"><span class="value"><%= latencyExecute_mean %></span>ms</div>
<div class="cell header">99.5th</div>
<div class="cell data latency995"><span class="value"><%= getInstanceAverage(latencyExecute['99.5'], reportingHosts, false) %></span>ms</div>
</div>
<!-- <a href="">History</a> <a href="">EPIC</a> <a href="">Actions</a> -->
<div class="monitor" id="CIRCUIT_<%= name %>" style="position:relative;">
<%
var displayName = name;
var toolTip = "";
if(displayName.length > 32) {
displayName = displayName.substring(0,4) + "..." + displayName.substring(displayName.length-20, displayName.length);
toolTip = "title=\"" + name + "\"";
}
%>
<div id="chart_CIRCUIT_<%= name %>" class="chart" style="position:absolute;top:0px;left:0; float:left; width:100%; height:100%;"></div>
<div style="position:absolute;top:0x;width:100%;height:15px;opacity:0.8; background:white;">
<% if(includeDetailIcon) { %>
<p class="name" <%= toolTip %> style="padding-right:16px">
<%= displayName %>
<a href="../dependencies/command.jsp?name=<%= name %>"><img src="../components/hystrixCommand/magnifying-glass-icon-20.png" height="14px" width="14px" border="0" style="position: absolute; right:0px;"></a>
</p>
<% } else { %>
<p class="name" <%= toolTip %>><%= displayName %></p>
<% } %>
</div>
<div style="position:absolute;top:15px;; opacity:0.8; background:white; width:100%; height:95%;">
<div class="monitor_data"></div>
</div>
<div id="graph_CIRCUIT_<%= name %>" class="graph" style="position:absolute;top:25px;left:0; float:left; width:140px; height:62px;"></div>
<script>
var y = 200;
/* escape with two backslashes */
var vis = d3.select("#chart_CIRCUIT_<%= name.replace(/([ !"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g,'\\\\$1') %>").append("svg:svg").attr("width", "100%").attr("height", "100%");
/* add a circle -- we don't use the data point, we set it manually, so just passing in [1] */
var circle = vis.selectAll("circle").data([1]).enter().append("svg:circle");
/* setup the initial styling and sizing of the circle */
circle.style("fill", "green").attr("cx", "30%").attr("cy", "30%").attr("r", 5);
/* add the line graph - it will be populated by javascript, no default to show here */
/* escape with two backslashes */
var graph = d3.select("#graph_CIRCUIT_<%= name.replace(/([ !"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g,'\\\\$1') %>").append("svg:svg").attr("width", "100%").attr("height", "100%");
</script>
</div>
<div class="tableRow">
<div class="cell header">Median</div>
<div class="cell data"><span class="value"><%= sla_medianLastMinute %></span>ms</div>
<div class="cell header">99th</div>
<div class="cell data"><span class="value"><%= sla_percentile99LastMinute %></span>ms</div>
</div>
.dependencyThreadPools .spacer {
width: 100%;
margin: 0 auto;
padding-top:4px;
clear:both;
}
.dependencyThreadPools .last {
margin-right: 0px;
}
.dependencyThreadPools span.loading {
display: block;
padding-top: 6%;
padding-bottom: 6%;
color: gray;
text-align: center;
}
.dependencyThreadPools span.loading.failed {
color: red;
}
.dependencyThreadPools div.monitor {
float: left;
margin-right:5px; /* these are tweaked to look good on desktop and iPad portrait, and fit things densely */
margin-top:5px;
}
.dependencyThreadPools div.monitor p.name {
font-weight:bold;
font-size: 10pt;
text-align: right;
padding-bottom: 5px;
}
.dependencyThreadPools div.monitor_data {
margin: 0 auto;
}
.dependencyThreadPools span.smaller {
font-size: 8pt;
color: grey;
}
.dependencyThreadPools div.tableRow {
width:100%;
white-space: nowrap;
font-size: 8pt;
margin: 0 auto;
clear:both;
}
.dependencyThreadPools div.tableRow .cell {
float:left;
}
.dependencyThreadPools div.tableRow .header {
text-align:right;
padding-right:5px;
}
.dependencyThreadPools div.tableRow .header.left {
width:85px;
}
.dependencyThreadPools div.tableRow .header.right {
width:75px;
}
.dependencyThreadPools div.tableRow .data {
font-weight: bold;
text-align:right;
}
.dependencyThreadPools div.tableRow .data.left {
width:30px;
}
.dependencyThreadPools div.tableRow .data.right {
width:45px;
}
.dependencyThreadPools div.monitor {
width: 245px; /* we want a fixed width instead of percentage as I want the boxes to be a set size and then fill in as many as can fit in each row ... this allows 3 columns on an iPad */
height: 110px;
}
/* override the HREF when we have specified it as a tooltip to not act like a link */
.dependencyThreadPools div.monitor_data a.tooltip {
text-decoration: none;
cursor: default;
}
.dependencyThreadPools div.monitor_data a.rate {
font-weight:bold;
color: black;
font-size: 11pt;
}
.dependencyThreadPools div.rate {
padding-top: 1px;
clear:both;
text-align:right;
}
.dependencyThreadPools span.rate_value {
font-weight:bold;
}
.dependencyThreadPools div.monitor div.chart {
}
.dependencyThreadPools div.monitor div.chart svg {
}
.dependencyThreadPools div.monitor div.chart svg text {
fill: white;
}
.dependencyThreadPools #hidden {
width:1px;
height:1px;
background: lightgrey;
display: none;
}
<div class="spacer"></div>
<div class="rate">
<a href="javascript://" title="Total Execution Rate per Second per Reporting Host" class="tooltip rate"><span class="smaller">Host: </span><span class="ratePerSecondPerHost"><%= addCommas(ratePerSecondPerHost) %></span>/s</a>
</div>
<div class="rate">
<a href="javascript://" title="Total Execution Rate per Second for Cluster" class="tooltip rate"><span class="smaller">Cluster: </span><span class="ratePerSecond"><%= addCommas(ratePerSecond) %></span>/s</a>
</div>
<div class="spacer"></div>
<div class="tableRow">
<div class="cell header left">Active</div>
<div class="cell data left"><%= currentActiveCount%></div>
<div class="cell header right">Max Active</div>
<div class="cell data right"><%= addCommas(rollingMaxActiveThreads)%></div>
</div>
<div class="tableRow">
<div class="cell header left">Queued</div>
<div class="cell data left"><%= currentQueueSize %></div>
<div class="cell header right">Executions</div>
<div class="cell data right"><%= addCommas(rollingCountThreadsExecuted)%></div>
</div>
<div class="tableRow">
<div class="cell header left">Pool Size</div>
<div class="cell data left"><%= currentPoolSize %></div>
<div class="cell header right">Queue Size</div>
<div class="cell data right"><%= propertyValue_queueSizeRejectionThreshold %></div>
</div>
\ No newline at end of file
<div class="monitor" id="THREAD_POOL_<%= name %>" style="position:relative;">
<%
var displayName = name;
var toolTip = "";
if(displayName.length > 32) {
displayName = displayName.substring(0,4) + "..." + displayName.substring(displayName.length-20, displayName.length);
toolTip = "title=\"" + name + "\"";
}
%>
<div id="chart_THREAD_POOL_<%= name %>" class="chart" style="position:absolute;top:0px;left:0; float:left; width:100%; height:100%;"></div>
<div style="position:absolute;top:0x;width:100%;height:15px;opacity:0.8; background:white;"><p class="name" <%= toolTip %>><%= displayName %></p></div>
<div style="position:absolute;top:15px;; opacity:0.8; background:white; width:100%; height:95%;">
<div class="monitor_data"></div>
</div>
<script>
<% if(typeof errorPercentage != 'undefined') { %>
var errorPercentageData = [<%= errorPercentage %>];
<% } else { %>
var errorPercentageData = [99];
<% } %>
var y = 200;
/* escape with two backslashes */
var vis = d3.select("#chart_THREAD_POOL_<%= name.replace(/([ !"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g,'\\\\$1') %>").append("svg:svg").attr("width", "100%").attr("height", "100%");
/* add a circle -- we don't use the data point, we set it manually, so just passing in [1] */
var circle = vis.selectAll("circle").data([1]).enter().append("svg:circle");
/* setup the initial styling and sizing of the circle */
circle.style("fill", "green").attr("cx", "30%").attr("cy", "20%").attr("r", 5);
</script>
</div>
@IMPORT url("resets.css");
body {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
img, object, embed {
max-width: 100%;
}
img {
height: auto;
}
#header {
background: #FFFFFF url(http://raw.github.com/wiki/Netflix/Hystrix/images/hystrix-logo-tagline-tiny.png) no-repeat scroll 99% 0%;
height: 65px;
margin-bottom: 5px;
}
#header h2 {
float:left;
color: black;
position:relative;
padding-left: 20px;
top: 26px;
font-size: 20px;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
#header .header_nav {
position:absolute;
top:48px;
right:15px;
}
#header .header_links {
float:left;
color: lightgray;
font-size: 18px;
top: 3px;
padding-left: 10px;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
#header .header_links a {
color: white;
}
#header .header_clusters {
float:left;
position:relative;
padding-left: 10px;
top: -1px;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
@media screen and (min-width: 1500px) {
#header .header_nav {
top:13px;
right:130px;
}
#header {
background: #FFFFFF url(http://raw.github.com/wiki/Netflix/Hystrix/images/hystrix-logo-tagline-tiny.png) no-repeat scroll 99% 50%;
height: 65px;
}
}
/*
html5doctor.com Reset Stylesheet
v1.6.1
Last Updated: 2010-09-17
Author: Richard Clark - http://richclarkdesign.com
Twitter: @rich_clark
*/
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
body {
line-height:1;
}
article,aside,details,figcaption,figure,
footer,header,hgroup,menu,nav,section {
display:block;
}
nav ul {
list-style:none;
}
blockquote, q {
quotes:none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content:'';
content:none;
}
a {
margin:0;
padding:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
/* change colours to suit your needs */
ins {
background-color:#ff9;
color:#000;
text-decoration:none;
}
/* change colours to suit your needs */
mark {
background-color:#ff9;
color:#000;
font-style:italic;
font-weight:bold;
}
del {
text-decoration: line-through;
}
abbr[title], dfn[title] {
border-bottom:1px dotted;
cursor:help;
}
table {
border-collapse:collapse;
border-spacing:0;
}
/* change border colour to suit your needs */
hr {
display:block;
height:1px;
border:0;
border-top:1px solid #cccccc;
margin:1em 0;
padding:0;
}
input, select {
vertical-align:middle;
}
\ No newline at end of file
/* SimpleGrid - a fork of CSSGrid by Crowd Favorite (https://github.com/crowdfavorite/css-grid)
* http://simplegrid.info
* by Conor Muirhead (http://conor.cc) of Early LLC (http://earlymade.com)
* License: http://creativecommons.org/licenses/MIT/ */
/* Containers */
body { font-size: 1.125em; }
.grid{ width:1206px; }
/* 6-Col Grid Sizes */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5{ width:176px; } /* Sixths */
.slot-0-1,.slot-1-2,.slot-2-3,.slot-3-4,.slot-4-5{ width:382px; } /* Thirds */
.slot-0-1-2-3,.slot-1-2-3-4,.slot-2-3-4-5{ width:794px; } /* Two-Thirds */
.slot-0-1-2-3-4,.slot-1-2-3-4-5{ width:1000px; } /* Five-Sixths */
/* 4-Col Grid Sizes */
.slot-6,.slot-7,.slot-8,.slot-9{ width:279px; } /* Quarters */
.slot-6-7-8,.slot-7-8-9{ width:897px; } /* Three-Quarters */
/* 6-Col/4-Col Shared Grid Sizes */
.slot-0-1-2,.slot-1-2-3,.slot-2-3-4,.slot-3-4-5, .slot-6-7,.slot-7-8,.slot-8-9{ width:588px; } /* Halves */
\ No newline at end of file
/* SimpleGrid - a fork of CSSGrid by Crowd Favorite (https://github.com/crowdfavorite/css-grid)
* http://simplegrid.info
* by Conor Muirhead (http://conor.cc) of Early LLC (http://earlymade.com)
* License: http://creativecommons.org/licenses/MIT/ */
/* Containers */
body { font-size: 0.875em; padding: 0; }
.grid{ margin:0 auto; padding: 0 10px; width:700px; }
.row{ clear:left; }
/* Slots Setup */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5,.slot-0-1,.slot-0-1-2,.slot-0-1-2-3,.slot-0-1-2-3-4,.slot-0-1-2-3-4-5,.slot-1-2,.slot-1-2-3,.slot-1-2-3-4,.slot-1-2-3-4-5,.slot-2-3,.slot-2-3-4,.slot-2-3-4-5,.slot-3-4,.slot-3-4-5,.slot-4-5,.slot-6,.slot-7,.slot-8,.slot-9,.slot-6-7,.slot-6-7-8,.slot-6-7-8-9,.slot-7-8,.slot-7-8-9,.slot-8-9{ display:inline; float:left; margin-left:20px; }
/* 6-Col Grid Sizes */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5{ width:100px; } /* Sixths */
.slot-0-1,.slot-1-2,.slot-2-3,.slot-3-4,.slot-4-5{ width:220px; } /* Thirds */
.slot-0-1-2-3,.slot-1-2-3-4,.slot-2-3-4-5{ width:460px; } /* Two-Thirds */
.slot-0-1-2-3-4,.slot-1-2-3-4-5{ width:580px; } /* Five-Sixths */
/* 4-Col Grid Sizes */
.slot-6,.slot-7,.slot-8,.slot-9{ width:160px; } /* Quarters */
.slot-6-7-8,.slot-7-8-9{ width:520px; } /* Three-Quarters */
/* 6-Col/4-Col Shared Grid Sizes */
.slot-0-1-2,.slot-1-2-3,.slot-2-3-4,.slot-3-4-5, .slot-6-7,.slot-7-8,.slot-8-9{ width:340px; } /* Halves */
.slot-0-1-2-3-4-5, .slot-6-7-8-9{ width: 100%; } /* Full-Width */
/* Zeroing Out Leftmost Slot Margins */
.slot-0,.slot-0-1,.slot-0-1-2,.slot-0-1-2-3,.slot-0-1-2-3-4,.slot-0-1-2-3-4-5,.slot-6,.slot-6-7,.slot-6-7-8,.slot-6-7-8-9,.slot-1 .slot-1,.slot-1-2 .slot-1,.slot-1-2 .slot-1-2,.slot-1-2-3 .slot-1,.slot-1-2-3 .slot-1-2,.slot-1-2-3 .slot-1-2-3,.slot-1-2-3-4 .slot-1,.slot-1-2-3-4 .slot-1-2,.slot-1-2-3-4 .slot-1-2-3,.slot-1-2-3-4 .slot-1-2-3-4,.slot-1-2-3-4-5 .slot-1,.slot-1-2-3-4-5 .slot-1-2,.slot-1-2-3-4-5 .slot-1-2-3,.slot-1-2-3-4-5 .slot-1-2-3-4,.slot-1-2-3-4-5 .slot-1-2-3-4-5,.slot-2 .slot-2,.slot-2-3 .slot-2,.slot-2-3 .slot-2-3,.slot-2-3-4 .slot-2,.slot-2-3-4 .slot-2-3,.slot-2-3-4 .slot-2-3-4,.slot-2-3-4-5 .slot-2,.slot-2-3-4-5 .slot-2-3,.slot-2-3-4-5 .slot-2-3-4,.slot-2-3-4-5 .slot-2-3-4-5,.slot-3 .slot-3,.slot-3-4 .slot-3,.slot-3-4 .slot-3-4,.slot-3-4-5 .slot-3,.slot-3-4-5 .slot-3-4,.slot-3-4-5 .slot-3-4-5,.slot-4 .slot-4,.slot-4-5 .slot-4,.slot-4-5 .slot-4-5,.slot-5 .slot-5,.slot-7 .slot-7,.slot-7-8 .slot-7,.slot-7-8 .slot-7-8,.slot-7-8-9 .slot-7,.slot-7-8-9 .slot-7-8,.slot-7-8-9 .slot-7-8-9,.slot-8 .slot-8,.slot-8-9 .slot-8,.slot-8-9 .slot-8-9{ margin-left:0 !important; } /* Important is to avoid repeating this in larger screen css files */
/* Row Clearfix */
.row:after{ visibility:hidden; display:block; font-size:0; content:" "; clear:both; height:0; }
.row{ zoom:1; }
\ No newline at end of file
/* SimpleGrid - a fork of CSSGrid by Crowd Favorite (https://github.com/crowdfavorite/css-grid)
* http://simplegrid.info
* by Conor Muirhead (http://conor.cc) of Early LLC (http://earlymade.com)
* License: http://creativecommons.org/licenses/MIT/ */
/* Containers */
body { font-size: 100%; }
.grid{ width:966px; }
/* Slots Setup */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5,.slot-0-1,.slot-0-1-2,.slot-0-1-2-3,.slot-0-1-2-3-4,.slot-0-1-2-3-4-5,.slot-1-2,.slot-1-2-3,.slot-1-2-3-4,.slot-1-2-3-4-5,.slot-2-3,.slot-2-3-4,.slot-2-3-4-5,.slot-3-4,.slot-3-4-5,.slot-4-5,.slot-6,.slot-7,.slot-8,.slot-9,.slot-6-7,.slot-6-7-8,.slot-6-7-8-9,.slot-7-8,.slot-7-8-9,.slot-8-9{ display:inline; float:left; margin-left:30px; }
/* 6-Col Grid Sizes */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5{ width:136px; } /* Sixths */
.slot-0-1,.slot-1-2,.slot-2-3,.slot-3-4,.slot-4-5{ width:302px; } /* Thirds */
.slot-0-1-2-3,.slot-1-2-3-4,.slot-2-3-4-5{ width:634px; } /* Two-Thirds */
.slot-0-1-2-3-4,.slot-1-2-3-4-5{ width:800px; } /* Five-Sixths */
/* 4-Col Grid Sizes */
.slot-6,.slot-7,.slot-8,.slot-9{ width:219px; } /* Quarters */
.slot-6-7-8,.slot-7-8-9{ width:717px; } /* Three-Quarters */
/* 6-Col/4-Col Shared Grid Sizes */
.slot-0-1-2,.slot-1-2-3,.slot-2-3-4,.slot-3-4-5, .slot-6-7,.slot-7-8,.slot-8-9{ width:468px; } /* Halves */
\ No newline at end of file
Copyright (c) 2011 Crowd Favorite, Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
\ No newline at end of file
/* Extension of SimpleGrid by benjchristensen to allow percentage based sizing on very large displays
*
* SimpleGrid - a fork of CSSGrid by Crowd Favorite (https://github.com/crowdfavorite/css-grid)
* http://simplegrid.info
* by Conor Muirhead (http://conor.cc) of Early LLC (http://earlymade.com)
* License: http://creativecommons.org/licenses/MIT/ */
/* Containers */
body { font-size: 1.125em; }
.grid{ width:100%; }
/* Slots Setup */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5,.slot-0-1,.slot-0-1-2,.slot-0-1-2-3,.slot-0-1-2-3-4,.slot-0-1-2-3-4-5,.slot-1-2,.slot-1-2-3,.slot-1-2-3-4,.slot-1-2-3-4-5,.slot-2-3,.slot-2-3-4,.slot-2-3-4-5,.slot-3-4,.slot-3-4-5,.slot-4-5,.slot-6,.slot-7,.slot-8,.slot-9,.slot-6-7,.slot-6-7-8,.slot-6-7-8-9,.slot-7-8,.slot-7-8-9,.slot-8-9{ display:inline; float:left; margin-left:0px; }
/* 6-Col Grid Sizes */
.slot-0,.slot-1,.slot-2,.slot-3,.slot-4,.slot-5{ width:16.6%; } /* Sixths */
.slot-0-1,.slot-1-2,.slot-2-3,.slot-3-4,.slot-4-5{ width:33.3%; } /* Thirds */
.slot-0-1-2-3,.slot-1-2-3-4,.slot-2-3-4-5{ width:66.6%; } /* Two-Thirds */
.slot-0-1-2-3-4,.slot-1-2-3-4-5{ width:83.3%; } /* Five-Sixths */
/* 4-Col Grid Sizes */
.slot-6,.slot-7,.slot-8,.slot-9{ width:25%; } /* Quarters */
.slot-6-7-8,.slot-7-8-9{ width:75%; } /* Three-Quarters */
/* 6-Col/4-Col Shared Grid Sizes */
.slot-0-1-2,.slot-1-2-3,.slot-2-3-4,.slot-3-4-5, .slot-6-7,.slot-7-8,.slot-8-9{ width:50%; } /* Halves */
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hystrix Dashboard</title>
<!-- Javascript to monitor and display -->
<script src="/webjars/jquery/2.1.1/jquery.min.js" type="text/javascript"></script>
<script>
function sendToMonitor() {
if($('#stream').val().length > 0) {
var url = "/hystrix/monitor/monitor.html?stream=" + encodeURIComponent($('#stream').val()) + "";
if($('#delay').val().length > 0) {
url += "&delay=" + $('#delay').val();
}
if($('#title').val().length > 0) {
url += "&title=" + encodeURIComponent($('#title').val());
}
location.href= url;
} else {
$('#message').html("The 'stream' value is required.");
}
}
</script>
</head>
<body>
<div style="width:800px;margin:0 auto;">
<center>
<img width="264" height="233" src="https://raw.github.com/wiki/Netflix/Hystrix/images/hystrix-logo.png">
<br>
<br>
<h2>Hystrix Dashboard</h2>
<input id="stream" type="textfield" size="120" placeholder="http://hostname:port/turbine/turbine.stream"></input>
<br><br>
<i>Cluster via Turbine (default cluster):</i> http://turbine-hostname:port/turbine.stream
<br>
<i>Cluster via Turbine (custom cluster):</i> http://turbine-hostname:port/turbine.stream?cluster=[clusterName]
<br>
<i>Single Hystrix App:</i> http://hystrix-app:port/hystrix.stream
<br><br>
Delay: <input id="delay" type="textfield" size="10" placeholder="2000"></input>ms
&nbsp;&nbsp;&nbsp;&nbsp;
Title: <input id="title" type="textfield" size="60" placeholder="Example Hystrix App"></input><br>
<br>
<button onclick="sendToMonitor()">Monitor Stream</button>
<br><br>
<div id="message" style="color:red"></div>
</center>
</div>
</body>
</html>
\ No newline at end of file
/*
* jQuery TinySort - A plugin to sort child nodes by (sub) contents or attributes.
*
* Version: 1.0.5
*
* Copyright (c) 2008-2011 Ron Valstar http://www.sjeiti.com/
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function(b){b.tinysort={id:"TinySort",version:"1.0.5",copyright:"Copyright (c) 2008-2011 Ron Valstar",uri:"http://tinysort.sjeiti.com/",defaults:{order:"asc",attr:"",place:"start",returns:false,useVal:false}};b.fn.extend({tinysort:function(h,j){if(h&&typeof(h)!="string"){j=h;h=null}var e=b.extend({},b.tinysort.defaults,j);var p={};this.each(function(t){var v=(!h||h=="")?b(this):b(this).find(h);var u=e.order=="rand"?""+Math.random():(e.attr==""?(e.useVal?v.val():v.text()):v.attr(e.attr));var s=b(this).parent();if(!p[s]){p[s]={s:[],n:[]}}if(v.length>0){p[s].s.push({s:u,e:b(this),n:t})}else{p[s].n.push({e:b(this),n:t})}});for(var g in p){var d=p[g];d.s.sort(function k(t,s){var i=t.s.toLowerCase?t.s.toLowerCase():t.s;var u=s.s.toLowerCase?s.s.toLowerCase():s.s;if(c(t.s)&&c(s.s)){i=parseFloat(t.s);u=parseFloat(s.s)}return(e.order=="asc"?1:-1)*(i<u?-1:(i>u?1:0))})}var m=[];for(var g in p){var d=p[g];var n=[];var f=b(this).length;switch(e.place){case"first":b.each(d.s,function(s,t){f=Math.min(f,t.n)});break;case"org":b.each(d.s,function(s,t){n.push(t.n)});break;case"end":f=d.n.length;break;default:f=0}var q=[0,0];for(var l=0;l<b(this).length;l++){var o=l>=f&&l<f+d.s.length;if(a(n,l)){o=true}var r=(o?d.s:d.n)[q[o?0:1]].e;r.parent().append(r);if(o||!e.returns){m.push(r.get(0))}q[o?0:1]++}}return this.pushStack(m)}});function c(e){var d=/^\s*?[\+-]?(\d*\.?\d*?)\s*?$/.exec(e);return d&&d.length>0?d[1]:false}function a(e,f){var d=false;b.each(e,function(h,g){if(!d){d=g==f}});return d}b.fn.TinySort=b.fn.Tinysort=b.fn.tsort=b.fn.tinysort})(jQuery);
\ No newline at end of file
//Simple JavaScript Templating
//John Resig - http://ejohn.org/ - MIT Licensed
// http://ejohn.org/blog/javascript-micro-templating/
(function(window, undefined) {
var cache = {};
window.tmpl = function tmpl(str, data) {
try {
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
//console.log(fn);
// Provide some basic currying to the user
return data ? fn(data) : fn;
}catch(e) {
console.log(e);
}
};
})(window);
.container {
padding-left: 20px;
padding-right: 20px;
}
.row {
width: 100%;
margin: 0 auto;
overflow: hidden;
}
.spacer {
width: 100%;
margin: 0 auto;
padding-top:4px;
clear:both;
}
.last {
margin-right: 0px;
}
.menubar {
overflow: hidden;
border-bottom: 1px solid black;
}
.menubar div {
padding-bottom:5px;
margin: 0 auto;
overflow: hidden;
font-size: 80%;
font-family:'Bookman Old Style',Bookman,'URW Bookman L','Palatino Linotype',serif;
float:left;
}
.menubar .title {
float: left;
padding-right: 20px;
font-size: 110%;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: bold;
vertical-align: bottom;
}
.menubar .menu_actions {
float: left;
position:relative;
top: 4px;
}
.menubar .menu_legend {
float: right;
position:relative;
top: 4px;
}
h3.sectionHeader {
color: black;
font-size: 110%;
padding-top: 4px;
padding-bottom: 4px;
padding-left: 8px;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
background: lightgrey;
}
.success {
color: green;
}
.shortCircuited {
color: blue;
}
.timeout {
color: #FF9900; /* shade of orange */
}
.failure {
color: red;
}
.rejected {
color: purple;
}
.exceptionsThrown {
color: brown;
}
@media screen and (max-width: 1100px) {
.container {
padding-left: 5px;
padding-right: 5px;
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Hystrix Monitor</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Setup base for everything -->
<link rel="stylesheet" type="text/css" href="../css/global.css" />
<!-- Our custom CSS -->
<link rel="stylesheet" type="text/css" href="monitor.css" />
<!-- d3 -->
<script type="text/javascript" src="/webjars/d3js/3.4.11/d3.min.js" ></script>
<!-- Javascript to monitor and display -->
<script type="text/javascript" src="/webjars/jquery/2.1.1/jquery.min.js" ></script>
<script type="text/javascript" src="../js/jquery.tinysort.min.js"></script>
<script type="text/javascript" src="../js/tmpl.js"></script>
<!-- HystrixCommand -->
<script type="text/javascript" src="../components/hystrixCommand/hystrixCommand.js"></script>
<link rel="stylesheet" type="text/css" href="../components/hystrixCommand/hystrixCommand.css" />
<!-- HystrixThreadPool -->
<script type="text/javascript" src="../components/hystrixThreadPool/hystrixThreadPool.js"></script>
<link rel="stylesheet" type="text/css" href="../components/hystrixThreadPool/hystrixThreadPool.css" />
</head>
<body>
<div id="header">
<h2><span id="title_name"></span></h2>
</div>
<div class="container">
<div class="row">
<div class="menubar">
<div class="title">
Circuit
</div>
<div class="menu_actions">
Sort:
<a href="javascript://" onclick="hystrixMonitor.sortByErrorThenVolume();">Error then Volume</a> |
<a href="javascript://" onclick="hystrixMonitor.sortAlphabetically();">Alphabetical</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByVolume();">Volume</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByError();">Error</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByLatencyMean();">Mean</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByLatencyMedian();">Median</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByLatency90();">90</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByLatency99();">99</a> |
<a href="javascript://" onclick="hystrixMonitor.sortByLatency995();">99.5</a>
</div>
<div class="menu_legend">
<span class="success">Success</span> | <span class="shortCircuited">Short-Circuited</span> | <span class="timeout">Timeout</span> | <span class="rejected">Rejected</span> | <span class="failure">Failure</span> | <span class="errorPercentage">Error %</span>
</div>
</div>
</div>
<div id="dependencies" class="row dependencies"><span class="loading">Loading ...</span></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="row">
<div class="menubar">
<div class="title">
Thread Pools
</div>
<div class="menu_actions">
Sort: <a href="javascript://" onclick="dependencyThreadPoolMonitor.sortAlphabetically();">Alphabetical</a> |
<a href="javascript://" onclick="dependencyThreadPoolMonitor.sortByVolume();">Volume</a> |
</div>
</div>
</div>
<div id="dependencyThreadPools" class="row dependencyThreadPools"><span class="loading">Loading ...</span></div>
</div>
<script>
/**
* Queue up the monitor to start once the page has finished loading.
*
* This is an inline script and expects to execute once on page load.
*/
// commands
var hystrixMonitor = new HystrixCommandMonitor('dependencies', {includeDetailIcon:false});
var stream = getUrlVars()["stream"];
console.log("Stream: " + stream)
if(stream != undefined) {
if(getUrlVars()["delay"] != undefined) {
stream = stream + "&delay=" + getUrlVars()["delay"];
}
var commandStream = "/proxy.stream?origin=" + stream;
var poolStream = "/proxy.stream?origin=" + stream;
if(getUrlVars()["title"] != undefined) {
$('#title_name').html("Hystrix Stream: " + decodeURIComponent(getUrlVars()["title"]))
} else {
$('#title_name').html("Hystrix Stream: " + decodeURIComponent(stream))
}
}
console.log("Command Stream: " + commandStream)
$(window).load(function() { // within load with a setTimeout to prevent the infinite spinner
setTimeout(function() {
if(commandStream == undefined) {
console.log("commandStream is undefined")
$("#dependencies .loading").html("The 'stream' argument was not provided.");
$("#dependencies .loading").addClass("failed");
} else {
// sort by error+volume by default
hystrixMonitor.sortByErrorThenVolume();
// start the EventSource which will open a streaming connection to the server
var source = new EventSource(commandStream);
// add the listener that will process incoming events
source.addEventListener('message', hystrixMonitor.eventSourceMessageListener, false);
// source.addEventListener('open', function(e) {
// console.console.log(">>> opened connection, phase: " + e.eventPhase);
// // Connection was opened.
// }, false);
source.addEventListener('error', function(e) {
if (e.eventPhase == EventSource.CLOSED) {
// Connection was closed.
console.log("Connection was closed on error: " + JSON.stringify(e));
} else {
console.log("Error occurred while streaming: " + JSON.stringify(e));
}
}, false);
}
},0);
});
// thread pool
var dependencyThreadPoolMonitor = new HystrixThreadPoolMonitor('dependencyThreadPools');
$(window).load(function() { // within load with a setTimeout to prevent the infinite spinner
setTimeout(function() {
if(poolStream == undefined) {
console.log("poolStream is undefined")
$("#dependencyThreadPools .loading").html("The 'stream' argument was not provided.");
$("#dependencyThreadPools .loading").addClass("failed");
} else {
dependencyThreadPoolMonitor.sortByVolume();
// start the EventSource which will open a streaming connection to the server
var source = new EventSource(poolStream);
// add the listener that will process incoming events
source.addEventListener('message', dependencyThreadPoolMonitor.eventSourceMessageListener, false);
// source.addEventListener('open', function(e) {
// console.console.log(">>> opened connection, phase: " + e.eventPhase);
// // Connection was opened.
// }, false);
source.addEventListener('error', function(e) {
if (e.eventPhase == EventSource.CLOSED) {
// Connection was closed.
console.log("Connection was closed on error: " + e);
} else {
console.log("Error occurred while streaming: " + e);
}
}, false);
}
},0);
});
//Read a page's GET URL variables and return them as an associative array.
// from: http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
</script>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment