Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
O
opentrafficshaper
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
eezysol
opentrafficshaper
Commits
b9f01f00
Commit
b9f01f00
authored
11 years ago
by
Nigel Kukard
Browse files
Options
Downloads
Patches
Plain Diff
Refactored statistics page
parent
0c64381a
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
opentrafficshaper/plugins/webserver/pages/statistics.pm
+205
-106
205 additions, 106 deletions
opentrafficshaper/plugins/webserver/pages/statistics.pm
with
205 additions
and
106 deletions
opentrafficshaper/plugins/webserver/pages/statistics.pm
+
205
−
106
View file @
b9f01f00
# OpenTrafficShaper webserver module: users page
# Copyright (C) 2007-2013, AllWorldIT
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
...
...
@@ -33,37 +33,68 @@ our (@ISA,@EXPORT,@EXPORT_OK);
use
DateTime
;
use
HTML::
Entities
;
use
HTTP::
Status
qw( :constants )
;
use
JSON
;
use
opentrafficshaper::
logger
;
use
opentrafficshaper::
utils
;
use
opentrafficshaper::
utils
qw( parseURIQuery )
;
use
opentrafficshaper::plugins::
configmanager
qw( getLimit )
;
use
opentrafficshaper::plugins::statistics::
statistics
;
#
Default page/action
sub
defaul
t
#
Graphs by limit
sub
bylimi
t
{
my
(
$kernel
,
$globals
,
$client_session_id
,
$request
)
=
@_
;
# Build content
my
$content
=
<<EOF;
<div id="header"
>
<
h2>Traffic Shaper Stats</h2
>
</div>
<div id="header">
<h2>Limit Stats View</h2
>
<
/div
>
EOF
<div id="content" style="float:left">
my
$limit
;
# Maybe we were given an override key as a parameter? this would be an edit form
if
(
$request
->
method
eq
"
GET
")
{
# Parse GET data
my
$queryParams
=
parseURIQuery
(
$request
);
# We need a key first of all...
if
(
!
defined
(
$queryParams
->
{'
lid
'}))
{
$content
.=
<<EOF;
<tr class="info">
<td colspan="8"><p class="text-center">No LID in Query String</p></td>
</tr>
EOF
}
# Check if we get some data back when pulling the limit from the backend
if
(
!
defined
(
$limit
=
getLimit
(
$queryParams
->
{'
lid
'})))
{
$content
.=
<<EOF;
<tr class="info">
<td colspan="8"><p class="text-center">No Results</p></td>
</tr>
EOF
goto
END
;
}
}
my
$name
=
(
defined
(
$limit
->
{'
FriendlyName
'})
&&
$limit
->
{'
FriendlyName
'}
ne
"")
?
$limit
->
{'
FriendlyName
'}
:
$limit
->
{'
Username
'};
my
$usernameEncoded
=
encode_entities
(
$name
);
<div style="position: relative; top:50px;">
<h4 style="color:#8f8f8f;">Json Data (loads from /static/stats.json.js)</h4>
<br/>
# Build content
$content
=
<<EOF;
<div id="content" style="float:left">
<div id="ajaxData" class="ajaxData" style="float:left; width:1024px; height: 560px"></div>
</div>
<div style="position: relative; top: 50px;">
<h4 style="color:#8f8f8f;">Latest Data For: $usernameEncoded</h4>
<br/>
</div>
<div id="ajaxData" class="ajaxData" style="float:left; width:1024px; height: 560px"></div>
</div>
</div>
EOF
# FIXME - Dynamic script inclusion required
...
...
@@ -78,13 +109,18 @@ EOF
# '/static/awit-flot/jquery.flot.websockets.js'
);
# Build our data path using the URI module to make sure its nice and clean
my
$dataPath
=
URI
->
new
('
/statistics/data-by-limit
');
# Pass it the original query, just incase we had extra params we can use
$dataPath
->
query_form
(
$request
->
uri
->
query_form
()
);
my
$dataPathStr
=
$dataPath
->
as_string
();
# String put in <script> </script> tags after the above files are loaded
my
$javascript
=
<<EOF;
//
// Tooltip - Displays detailed information regarding the data point
//
function showTooltip(x, y, contents) {
jQuery('<div id="tooltip">' + contents + '</div>').css( {
// Tooltip - Displays detailed information regarding the data point
function showTooltip(x, y, contents) {
jQuery('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y - 30,
...
...
@@ -94,107 +130,170 @@ EOF
'border-radius': '6px',
'background-color': '#000',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
jQuery("#ajaxData").bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
jQuery("#tooltip").remove();
var x = item.datapoint[0].toFixed(0),
y = item.datapoint[1].toFixed(0);
showTooltip(item.pageX, item.pageY,
item.series.label + ' date: ' + month);
}
}
else {
jQuery("#tooltip").remove();
previousPoint = null;
}
});
// Setting up the graph here
options = {
series: {
lines: { show: true,
lineWidth: 1,
fill: true,
fillColor: { colors: [ { opacity: 0.1 }, { opacity: 0.13 } ] }
},
points: { show: true,
lineWidth: 2,
radius: 3
},
shadowSize: 0,
stack: true
},
grid: {
hoverable: true,
clickable: false,
tickColor: "#f9f9f9",
borderWidth: 0
var previousPoint = null;
jQuery("#ajaxData").bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
jQuery("#tooltip").remove();
showTooltip(item.pageX, item.pageY, item.series.label);
}
} else {
jQuery("#tooltip").remove();
previousPoint = null;
}
});
// Setting up the graph here
options = {
series: {
lines: {
show: true,
lineWidth: 1,
fill: true,
fillColor: {
colors: [
{ opacity: 0.1 },
{ opacity: 0.13 }
]
}
},
legend: {
// show: false
labelBoxBorderColor: "#fff"
//,container: '#legend-container'
points: {
show: false,
lineWidth: 2,
radius: 3
},
xaxis: {
mode: "time",
tickSize: [2, "second"],
tickFormatter: function (v, axis) {
var date = new Date(v);
if (date.getSeconds() % 1 == 0) {
var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return hours + ":" + minutes + ":" + seconds;
} else {
return "";
}
},
shadowSize: 0,
stack: true
},
grid: {
hoverable: true,
clickable: false,
tickColor: "#f9f9f9",
borderWidth: 0
},
legend: {
labelBoxBorderColor: "#fff"
},
xaxis: {
mode: "time",
tickSize: [60, "second"],
tickFormatter: function (v, axis) {
var date = new Date(v);
if (date.getSeconds() % 5 == 0) {
var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return hours + ":" + minutes + ":" + seconds;
} else {
return "";
}
},
},
yaxis: {
min: 0,
// max: 4000,
tickFormatter: function (v, axis) {
if (v % 10 == 0) {
res = v.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ",");
console.log(res);
return res + ' Kbps';
} else {
return "";
}
},
yaxis: {
min: 0,
max: 4000,
tickFormatter: function (v, axis) {
if (v % 10 == 0) {
return v;
} else {
return "";
}
},
}
}
//*/
}
// Load data from ajax
jQuery.ajax({
url: '$dataPathStr',
dataType: 'json',
// loading the stats.json.js file as data and drawing the graph on successful response.
jQuery.ajax({
url: '/static/stats.json.js',
dataType: "json",
success: function(statsData){
success: function(statsData) {
plot = null;
// formatting time to match javascript's epoch in milliseconds
for (i = 0; (i < statsData.length); i++) {
//console.log(statsData[i].data);
for (y = 0; (y < statsData[i].data.length); y++) {
d = new Date(statsData[i].data[y][0] * 1000);
statsData[i].data[y][0] = statsData[i].data[y][0] * 1000;
}
}
if (statsData.length > 0) {
plot = jQuery.plot(jQuery("#ajaxData"), statsData, options);
}
}
});
}
});
EOF
END
:
return
(
HTTP_OK
,
$content
,{
'
javascripts
'
=>
\
@javascripts
,
'
javascript
'
=>
$javascript
});
}
sub
databylimit
{
my
(
$kernel
,
$globals
,
$client_session_id
,
$request
)
=
@_
;
# Pull in query string
my
%query
=
$request
->
uri
->
query_form
();
# Check if the username was passed to us
if
(
!
defined
(
$query
{'
lid
'}))
{
return
(
HTTP_OK
,
undef
,{
'
type
'
=>
'
json
'
});
}
# Pull in stats data
my
$statsData
=
opentrafficshaper::plugins::statistics::
getStats
(
$query
{'
lid
'});
# First stage refinement
my
$rawData
;
foreach
my
$timestamp
(
sort
keys
%
{
$statsData
})
{
foreach
my
$direction
(
keys
%
{
$statsData
->
{
$timestamp
}})
{
foreach
my
$stat
('
rate
','
pps
','
cir
','
limit
')
{
push
(
@
{
$rawData
->
{"
$direction
.
$stat
"}
->
{'
data
'}}
,
[
$timestamp
,
$statsData
->
{
$timestamp
}
->
{
$direction
}
->
{
$stat
}
]
);
}
}
}
# Second stage - add labels
foreach
my
$direction
('
tx
','
rx
')
{
foreach
my
$stat
('
rate
','
pps
','
cir
','
limit
')
{
# Make it looks nice: Tx Rate
my
$label
=
uc
(
$direction
)
.
"
"
.
ucfirst
(
$stat
);
# And set it as the label
$rawData
->
{"
$direction
.
$stat
"}
->
{'
label
'}
=
$label
;
}
}
# Final stage, chop it out how we need it
my
$jsonData
=
[
$rawData
->
{'
tx.limit
'},
$rawData
->
{'
rx.limit
'},
$rawData
->
{'
tx.rate
'}
,
$rawData
->
{'
rx.rate
'}
];
return
(
HTTP_OK
,
$jsonData
,{
'
type
'
=>
'
json
'
});
}
1
;
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment