Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spring-cloud-netflix
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
openSource
spring-cloud-netflix
Commits
a2270dc2
Commit
a2270dc2
authored
Jul 27, 2015
by
Spencer Gibb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upgrade to Hystrix 1.4.13
Also brings in patches to the hystrix dashboard. fixes gh-465
parent
e5e677c0
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
75 additions
and
66 deletions
+75
-66
pom.xml
pom.xml
+1
-1
hystrixCommand.css
...atic/hystrix/components/hystrixCommand/hystrixCommand.css
+1
-1
hystrixCommand.js
...tatic/hystrix/components/hystrixCommand/hystrixCommand.js
+70
-60
hystrixCircuitContainer.html
...nts/hystrixCommand/templates/hystrixCircuitContainer.html
+1
-1
hystrixThreadPoolContainer.html
...strixThreadPool/templates/hystrixThreadPoolContainer.html
+1
-1
monitor.ftl
...ashboard/src/main/resources/templates/hystrix/monitor.ftl
+1
-2
No files found.
pom.xml
View file @
a2270dc2
...
...
@@ -27,7 +27,7 @@
<archaius.version>
0.6.5
</archaius.version>
<eureka.version>
1.1.147
</eureka.version>
<feign.version>
8.6.0
</feign.version>
<hystrix.version>
1.4.1
0
</hystrix.version>
<hystrix.version>
1.4.1
3
</hystrix.version>
<ribbon.version>
2.0.0
</ribbon.version>
<zuul.version>
1.0.28
</zuul.version>
<rxjava.version>
1.0.11
</rxjava.version>
...
...
spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/hystrixCommand.css
View file @
a2270dc2
...
...
@@ -110,7 +110,7 @@
.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
:
15
0
px
;
height
:
15
5
px
;
}
.dependencies
.success
{
...
...
spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/hystrixCommand.js
View file @
a2270dc2
...
...
@@ -16,19 +16,19 @@
/**
* Object containing functions for displaying and updating the UI with streaming data.
*
*
* Publish this externally as "HystrixCommandMonitor"
*/
window
.
HystrixCommandMonitor
=
function
(
containerId
,
args
)
{
var
self
=
this
;
// keep scope under control
self
.
args
=
args
;
if
(
self
.
args
==
undefined
)
{
self
.
args
=
{};
}
this
.
containerId
=
containerId
;
/**
* Initialization on construction
*/
...
...
@@ -36,7 +36,7 @@
var
maxXaxisForCircle
=
"40%"
;
var
maxYaxisForCircle
=
"40%"
;
var
maxRadiusForCircle
=
"125"
;
// CIRCUIT_BREAKER circle visualization settings
self
.
circuitCircleRadius
=
d3
.
scale
.
pow
().
exponent
(
0.5
).
domain
([
0
,
400
]).
range
([
"5"
,
maxRadiusForCircle
]);
// requests per second per host
self
.
circuitCircleYaxis
=
d3
.
scale
.
linear
().
domain
([
0
,
400
]).
range
([
"30%"
,
maxXaxisForCircle
]);
...
...
@@ -47,7 +47,7 @@
/**
* We want to keep sorting in the background since data values are always changing, so this will re-sort every X milliseconds
* to maintain whatever sort the user (or default) has chosen.
*
*
* In other words, sorting only for adds/deletes is not sufficient as all but alphabetical sort are dynamically changing.
*/
setInterval
(
function
()
{
...
...
@@ -55,11 +55,11 @@
self
.
sortSameAsLast
();
},
10000
);
/**
* END of Initialization on construction
*/
/**
* Event listener to handle new messages from EventSource as streamed from the server.
*/
...
...
@@ -70,7 +70,7 @@
if
(
!
data
.
reportingHosts
)
{
data
.
reportingHosts
=
1
;
}
if
(
data
&&
data
.
type
==
'HystrixCommand'
)
{
if
(
data
.
deleteData
==
'true'
)
{
deleteCircuit
(
data
.
escapedName
);
...
...
@@ -82,34 +82,43 @@
};
/**
* Pre process the data before displying in the UI.
* e.g Get Averages from sums, do rate calculation etc.
* Pre process the data before displying in the UI.
* e.g Get Averages from sums, do rate calculation etc.
*/
function
preProcessData
(
data
)
{
// set defaults for values that may be missing from older streams
setIfMissing
(
data
,
"rollingCountBadRequests"
,
0
);
// assert all the values we need
validateData
(
data
);
// escape string used in jQuery & d3 selectors
data
.
escapedName
=
data
.
name
.
replace
(
/
([
!"#$%&'()*+,.
/
:;<=>?@[
\]
^`{|}~
])
/g
,
'
\\
$1'
);
// do math
converAllAvg
(
data
);
conver
t
AllAvg
(
data
);
calcRatePerSecond
(
data
);
}
function
setIfMissing
(
data
,
key
,
defaultValue
)
{
if
(
data
[
key
]
==
undefined
)
{
data
[
key
]
=
defaultValue
;
}
}
/**
* Since the stream of data can be aggregated from multiple hosts in a tiered manner
* the aggregation just sums everything together and provides us the denominator (reportingHosts)
* so we must divide by it to get an average per instance value.
*
* so we must divide by it to get an average per instance value.
*
* We want to do this on any numerical values where we want per instance rather than cluster-wide sum.
*/
function
converAllAvg
(
data
)
{
function
conver
t
AllAvg
(
data
)
{
convertAvg
(
data
,
"errorPercentage"
,
true
);
convertAvg
(
data
,
"latencyExecute_mean"
,
false
);
convertAvg
(
data
,
"latencyTotal_mean"
,
false
);
// the following will break when it becomes a compound string if the property is dynamically changed
convertAvg
(
data
,
"propertyValue_metricsRollingStatisticalWindowInMilliseconds"
,
false
);
}
function
convertAvg
(
data
,
key
,
decimal
)
{
if
(
decimal
)
{
data
[
key
]
=
getInstanceAverage
(
data
[
key
],
data
[
"reportingHosts"
],
decimal
);
...
...
@@ -117,7 +126,7 @@
data
[
key
]
=
getInstanceAverage
(
data
[
key
],
data
[
"reportingHosts"
],
decimal
);
}
}
function
getInstanceAverage
(
value
,
reportingHosts
,
decimal
)
{
if
(
decimal
)
{
return
roundNumber
(
value
/
reportingHosts
);
...
...
@@ -125,7 +134,7 @@
return
Math
.
floor
(
value
/
reportingHosts
);
}
}
function
calcRatePerSecond
(
data
)
{
var
numberSeconds
=
data
[
"propertyValue_metricsRollingStatisticalWindowInMilliseconds"
]
/
1000
;
...
...
@@ -159,6 +168,7 @@
assertNotNull
(
data
,
"rollingCountSuccess"
);
assertNotNull
(
data
,
"rollingCountThreadPoolRejected"
);
assertNotNull
(
data
,
"rollingCountTimeout"
);
assertNotNull
(
data
,
"rollingCountBadRequests"
);
assertNotNull
(
data
,
"currentConcurrentExecutionCount"
);
assertNotNull
(
data
,
"latencyExecute_mean"
);
assertNotNull
(
data
,
"latencyExecute"
);
...
...
@@ -178,7 +188,7 @@
assertNotNull
(
data
,
"propertyValue_requestLogEnabled"
);
assertNotNull
(
data
,
"propertyValue_metricsRollingStatisticalWindowInMilliseconds"
);
}
function
assertNotNull
(
data
,
key
)
{
if
(
data
[
key
]
==
undefined
)
{
throw
new
Error
(
"Key Missing: "
+
key
+
" for "
+
data
.
name
);
...
...
@@ -187,25 +197,25 @@
/**
* Method to display the CIRCUIT data
*
*
* @param data
*/
/* private */
function
displayCircuit
(
data
)
{
try
{
preProcessData
(
data
);
}
catch
(
err
)
{
log
(
"Failed preProcessData: "
+
err
.
message
);
return
;
}
// add the 'addCommas' function to the 'data' object so the HTML templates can use it
data
.
addCommas
=
addCommas
;
// add the 'roundNumber' function to the 'data' object so the HTML templates can use it
data
.
roundNumber
=
roundNumber
;
// add the 'getInstanceAverage' function to the 'data' object so the HTML templates can use it
data
.
getInstanceAverage
=
getInstanceAverage
;
var
addNew
=
false
;
// check if we need to create the container
if
(
!
$
(
'#CIRCUIT_'
+
data
.
escapedName
).
length
)
{
...
...
@@ -215,39 +225,39 @@
}
else
{
data
.
includeDetailIcon
=
false
;
}
// it doesn't exist so add it
var
html
=
tmpl
(
hystrixTemplateCircuitContainer
,
data
);
// remove the loading thing first
$
(
'#'
+
containerId
+
' span.loading'
).
remove
();
// now create the new data and add it
$
(
'#'
+
containerId
+
''
).
append
(
html
);
// add the default sparkline graph
d3
.
selectAll
(
'#graph_CIRCUIT_'
+
data
.
escapedName
+
' svg'
).
append
(
"svg:path"
);
// remember this is new so we can trigger a sort after setting data
addNew
=
true
;
}
// now update/insert the data
$
(
'#CIRCUIT_'
+
data
.
escapedName
+
' div.monitor_data'
).
html
(
tmpl
(
hystrixTemplateCircuit
,
data
));
var
ratePerSecond
=
data
.
ratePerSecond
;
var
ratePerSecondPerHost
=
data
.
ratePerSecondPerHost
;
var
ratePerSecondPerHostDisplay
=
ratePerSecondPerHost
;
var
errorThenVolume
=
(
data
.
errorPercentage
*
100000000
)
+
ratePerSecond
;
// set the rates on the div element so it's available for sorting
$
(
'#CIRCUIT_'
+
data
.
escapedName
).
attr
(
'rate_value'
,
ratePerSecond
);
$
(
'#CIRCUIT_'
+
data
.
escapedName
).
attr
(
'error_then_volume'
,
errorThenVolume
);
// update errorPercentage color on page
$
(
'#CIRCUIT_'
+
data
.
escapedName
+
' a.errorPercentage'
).
css
(
'color'
,
self
.
circuitErrorPercentageColorRange
(
data
.
errorPercentage
));
updateCircle
(
'circuit'
,
'#CIRCUIT_'
+
data
.
escapedName
+
' circle'
,
ratePerSecondPerHostDisplay
,
data
.
errorPercentage
);
if
(
data
.
graphValues
)
{
// we have a set of values to initialize with
updateSparkline
(
'circuit'
,
'#CIRCUIT_'
+
data
.
escapedName
+
' path'
,
data
.
graphValues
);
...
...
@@ -260,7 +270,7 @@
self
.
sortSameAsLast
();
}
}
/* round a number to X digits: num => the number to round, dec => the number of decimals */
/* private */
function
roundNumber
(
num
)
{
var
dec
=
1
;
...
...
@@ -271,10 +281,10 @@
}
return
resultAsString
;
};
/* private */
function
updateCircle
(
variablePrefix
,
cssTarget
,
rate
,
errorPercentage
)
{
var
newXaxisForCircle
=
self
[
variablePrefix
+
'CircleXaxis'
](
rate
);
if
(
parseInt
(
newXaxisForCircle
)
>
parseInt
(
maxXaxisForCircle
))
{
...
...
@@ -288,7 +298,7 @@
if
(
parseInt
(
newRadiusForCircle
)
>
parseInt
(
maxRadiusForCircle
))
{
newRadiusForCircle
=
maxRadiusForCircle
;
}
d3
.
selectAll
(
cssTarget
)
.
transition
()
.
duration
(
400
)
...
...
@@ -297,7 +307,7 @@
.
attr
(
"r"
,
newRadiusForCircle
)
.
style
(
"fill"
,
self
[
variablePrefix
+
'ColorRange'
](
errorPercentage
));
}
/* private */
function
updateSparkline
(
variablePrefix
,
cssTarget
,
newDataPoint
)
{
var
currentTimeMilliseconds
=
new
Date
().
getTime
();
var
data
=
self
[
variablePrefix
+
cssTarget
+
'_data'
];
...
...
@@ -313,40 +323,40 @@
self
[
variablePrefix
+
cssTarget
+
'_data'
]
=
data
;
}
else
{
if
(
typeof
newDataPoint
==
'object'
)
{
/* if an array is passed in we'll replace the cached one */
/* if an array is passed in we'll replace the cached one */
data
=
newDataPoint
;
}
else
{
// else we just add to the existing one
data
.
push
({
"v"
:
parseFloat
(
newDataPoint
),
"t"
:
currentTimeMilliseconds
});
}
}
while
(
data
.
length
>
200
)
{
// 400 should be plenty for the 2 minutes we have the scale set to below even with a very low update latency
// remove data so we don't keep increasing forever
// remove data so we don't keep increasing forever
data
.
shift
();
}
}
if
(
data
.
length
==
1
&&
data
[
0
].
v
==
0
)
{
//console.log("we have a single 0 so skipping");
// don't show if we have a single 0
return
;
}
if
(
data
.
length
>
1
&&
data
[
0
].
v
==
0
&&
data
[
1
].
v
!=
0
)
{
//console.log("we have a leading 0 so removing it");
// get rid of a leading 0 if the following number is not a 0
data
.
shift
();
}
}
var
xScale
=
d3
.
time
.
scale
().
domain
([
new
Date
(
currentTimeMilliseconds
-
(
60
*
1000
*
2
)),
new
Date
(
currentTimeMilliseconds
)]).
range
([
0
,
140
]);
var
yMin
=
d3
.
min
(
data
,
function
(
d
)
{
return
d
.
v
;
});
var
yMax
=
d3
.
max
(
data
,
function
(
d
)
{
return
d
.
v
;
});
var
yScale
=
d3
.
scale
.
linear
().
domain
([
yMin
,
yMax
]).
nice
().
range
([
60
,
0
]);
// y goes DOWN, so 60 is the "lowest"
sparkline
=
d3
.
svg
.
line
()
// assign the X function to plot our line as we wish
.
x
(
function
(
d
,
i
)
{
.
x
(
function
(
d
,
i
)
{
// return the X coordinate where we want to plot this datapoint based on the time
return
xScale
(
new
Date
(
d
.
t
));
})
...
...
@@ -354,14 +364,14 @@
return
yScale
(
d
.
v
);
})
.
interpolate
(
"basis"
);
d3
.
selectAll
(
cssTarget
).
attr
(
"d"
,
sparkline
(
data
));
}
/* private */
function
deleteCircuit
(
circuitName
)
{
$
(
'#CIRCUIT_'
+
circuitName
).
remove
();
}
};
// public methods for sorting
...
...
@@ -391,7 +401,7 @@
$
(
'#'
+
this
.
containerId
+
' div.monitor'
).
tsort
(
"p.name"
,
{
order
:
direction
});
};
HystrixCommandMonitor
.
prototype
.
sortByError
=
function
()
{
var
direction
=
"desc"
;
if
(
this
.
sortedBy
==
'error_desc'
)
{
...
...
@@ -404,7 +414,7 @@
this
.
sortedBy
=
'error_'
+
direction
;
$
(
'#'
+
this
.
containerId
+
' div.monitor'
).
tsort
(
".errorPercentage .value"
,
{
order
:
direction
});
};
HystrixCommandMonitor
.
prototype
.
sortByErrorThenVolume
=
function
()
{
var
direction
=
"desc"
;
if
(
this
.
sortedBy
==
'error_then_volume_desc'
)
{
...
...
@@ -412,7 +422,7 @@
}
this
.
sortByErrorThenVolumeInDirection
(
direction
);
};
HystrixCommandMonitor
.
prototype
.
sortByErrorThenVolumeInDirection
=
function
(
direction
)
{
this
.
sortedBy
=
'error_then_volume_'
+
direction
;
$
(
'#'
+
this
.
containerId
+
' div.monitor'
).
tsort
({
order
:
direction
,
attr
:
'error_then_volume'
});
...
...
@@ -484,7 +494,7 @@
}
else
if
(
this
.
sortedBy
==
'error_then_volume_asc'
)
{
this
.
sortByErrorThenVolumeInDirection
(
'asc'
);
}
else
if
(
this
.
sortedBy
==
'error_then_volume_desc'
)
{
this
.
sortByErrorThenVolumeInDirection
(
'desc'
);
this
.
sortByErrorThenVolumeInDirection
(
'desc'
);
}
else
if
(
this
.
sortedBy
==
'lat90_asc'
)
{
this
.
sortByMetricInDirection
(
'asc'
,
'.latency90 .value'
);
}
else
if
(
this
.
sortedBy
==
'lat90_desc'
)
{
...
...
@@ -505,7 +515,7 @@
this
.
sortByMetricInDirection
(
'asc'
,
'.latencyMedian .value'
);
}
else
if
(
this
.
sortedBy
==
'latMedian_desc'
)
{
this
.
sortByMetricInDirection
(
'desc'
,
'.latencyMedian .value'
);
}
}
};
// default sort type and direction
...
...
spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/templates/hystrixCircuitContainer.html
View file @
a2270dc2
...
...
@@ -9,7 +9,7 @@
%>
<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:0
x
;width:100%;height:15px;opacity:0.8; background:white;"
>
<div
style=
"position:absolute;top:0;width:100%;height:15px;opacity:0.8; background:white;"
>
<
%
if
(
includeDetailIcon
)
{
%
>
<p
class=
"name"
<%=
toolTip
%
>
style="padding-right:16px">
<
%=
displayName
%
>
...
...
spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixThreadPool/templates/hystrixThreadPoolContainer.html
View file @
a2270dc2
...
...
@@ -10,7 +10,7 @@
%>
<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:0
x
;width:100%;height:15px;opacity:0.8; background:white;"
><p
class=
"name"
<%=
toolTip
%
>
>
<
%=
displayName
%
></p></div>
<div
style=
"position:absolute;top:0;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>
...
...
spring-cloud-netflix-hystrix-dashboard/src/main/resources/templates/hystrix/monitor.ftl
View file @
a2270dc2
...
...
@@ -61,8 +61,7 @@
<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"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment