Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
71b14e46
Commit
71b14e46
authored
Aug 26, 2013
by
Rashid Khan
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'zero'
parents
1222b498
49c596a8
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
175 additions
and
53 deletions
+175
-53
js/services.js
+4
-0
panels/dashcontrol/module.js
+41
-16
panels/histogram/module.js
+130
-37
No files found.
js/services.js
View file @
71b14e46
...
...
@@ -800,6 +800,10 @@ angular.module('kibana.services', [])
);
};
this
.
elasticsearch_create_index
=
function
()
{
return
ejs
.
client
.
post
(
'/'
+
config
.
kibana_index
);
};
this
.
elasticsearch_delete
=
function
(
id
)
{
return
ejs
.
Document
(
config
.
kibana_index
,
'dashboard'
,
id
).
doDelete
(
// Success
...
...
panels/dashcontrol/module.js
View file @
71b14e46
...
...
@@ -61,6 +61,10 @@ angular.module('kibana.dashcontrol', [])
services
:
{}
};
function
notice
(
type
,
title
,
message
)
{
alertSrv
.
set
(
title
,
message
,
type
,
5000
);
}
$scope
.
init
=
function
()
{
$scope
.
gist_pattern
=
/
(
^
\d{5,}
$
)
|
(
^
[
a-z0-9
]{10,}
$
)
|
(
gist.github.com
(\/
*.*
)\/[
a-z0-9
]{5,}\/
*$
)
/
;
$scope
.
gist
=
{};
...
...
@@ -69,17 +73,17 @@ angular.module('kibana.dashcontrol', [])
$scope
.
set_default
=
function
()
{
if
(
dashboard
.
set_default
())
{
alertSrv
.
set
(
'Local Default Set'
,
dashboard
.
current
.
title
+
' has been set as your local default'
,
'success'
,
5000
);
notice
(
'success'
,
'Local Default Set'
,
dashboard
.
current
.
title
+
' has been set as your local default'
);
}
else
{
alertSrv
.
set
(
'Incompatible Browser'
,
'Sorry, your browser is too old for this feature'
,
'error'
,
5000
);
notice
(
'error'
,
'Incompatible Browser'
,
'Sorry, your browser is too old for this feature'
);
}
};
$scope
.
purge_default
=
function
()
{
if
(
dashboard
.
purge_default
())
{
alertSrv
.
set
(
'Local Default Clear'
,
'Your local default dashboard has been cleared'
,
'success'
,
5000
);
notice
(
'success'
,
'Local Default Clear'
,
'Your local default dashboard has been cleared'
);
}
else
{
alertSrv
.
set
(
'Incompatible Browser'
,
'Sorry, your browser is too old for this feature'
,
'error'
,
5000
);
notice
(
'error'
,
'Incompatible Browser'
,
'Sorry, your browser is too old for this feature'
);
}
};
...
...
@@ -91,13 +95,30 @@ angular.module('kibana.dashcontrol', [])
).
then
(
function
(
result
)
{
if
(
!
_
.
isUndefined
(
result
.
_id
))
{
alertSrv
.
set
(
'Dashboard Saved'
,
'This dashboard has been saved to Elasticsearch as "'
+
result
.
_id
+
'"'
,
'success'
,
5000
);
notice
(
'success'
,
'Dashboard Saved'
,
'This dashboard has been saved to Elasticsearch as "'
+
result
.
_id
+
'"'
);
if
(
type
===
'temp'
)
{
$scope
.
share
=
dashboard
.
share_link
(
dashboard
.
current
.
title
,
'temp'
,
result
.
_id
);
$scope
.
share
=
dashboard
.
share_link
(
dashboard
.
current
.
title
,
'temp'
,
result
.
_id
);
}
}
else
{
alertSrv
.
set
(
'Save failed'
,
'Dashboard could not be saved to Elasticsearch'
,
'error'
,
5000
);
if
(
result
.
status
===
404
)
{
// auto create must be disabled and the index doesn't exist, create it!
return
dashboard
.
elasticsearch_create_index
().
then
(
function
()
{
return
$scope
.
elasticsearch_save
(
type
,
ttl
);
},
function
()
{
notice
(
'error'
,
'Save failed'
,
'Dashboard could not be saved because the "'
+
config
.
kibana_index
+
'" '
+
'index does not exist and could not be created.'
);
});
}
else
{
notice
(
'error'
,
'Save failed'
,
'Dashboard could not be saved to Elasticsearch'
);
}
}
});
};
...
...
@@ -107,15 +128,15 @@ angular.module('kibana.dashcontrol', [])
function
(
result
)
{
if
(
!
_
.
isUndefined
(
result
))
{
if
(
result
.
found
)
{
alertSrv
.
set
(
'Dashboard Deleted'
,
id
+
' has been deleted'
,
'success'
,
5000
);
notice
(
'success'
,
'Dashboard Deleted'
,
id
+
' has been deleted'
);
// Find the deleted dashboard in the cached list and remove it
var
toDelete
=
_
.
where
(
$scope
.
elasticsearch
.
dashboards
,{
_id
:
id
})[
0
];
$scope
.
elasticsearch
.
dashboards
=
_
.
without
(
$scope
.
elasticsearch
.
dashboards
,
toDelete
);
}
else
{
alertSrv
.
set
(
'Dashboard Not Found'
,
'Could not find '
+
id
+
' in Elasticsearch'
,
'warning'
,
5000
);
notice
(
'warning'
,
'Dashboard Not Found'
,
'Could not find '
+
id
+
' in Elasticsearch'
);
}
}
else
{
alertSrv
.
set
(
'Dashboard Not Deleted'
,
'An error occurred deleting the dashboard'
,
'error'
,
5000
);
notice
(
'error'
,
'Dashboard Not Deleted'
,
'An error occurred deleting the dashboard'
);
}
}
);
...
...
@@ -137,10 +158,14 @@ angular.module('kibana.dashcontrol', [])
function
(
link
)
{
if
(
!
_
.
isUndefined
(
link
))
{
$scope
.
gist
.
last
=
link
;
alertSrv
.
set
(
'Gist saved'
,
'You will be able to access your exported dashboard file at '
+
'<a href="'
+
link
+
'">'
+
link
+
'</a> in a moment'
,
'success'
);
notice
(
'success'
,
'Gist saved'
,
'You will be able to access your exported dashboard file at '
+
'<a href="'
+
link
+
'">'
+
link
+
'</a> in a moment'
);
}
else
{
alertSrv
.
set
(
'Save failed'
,
'Gist could not be saved'
,
'error'
,
5000
);
notice
(
'error'
,
'Save failed'
,
'Gist could not be saved'
);
}
});
};
...
...
@@ -151,7 +176,7 @@ angular.module('kibana.dashcontrol', [])
if
(
files
&&
files
.
length
>
0
)
{
$scope
.
gist
.
files
=
files
;
}
else
{
alertSrv
.
set
(
'Gist Failed'
,
'Could not retrieve dashboard list from gist'
,
'error
'
,
5000
);
notice
(
'error'
,
'Gist Failed'
,
'Could not retrieve dashboard list from gist
'
,
5000
);
}
});
};
...
...
@@ -183,7 +208,7 @@ angular.module('kibana.dashcontrol', [])
// Something
document
.
getElementById
(
'dashupload'
).
addEventListener
(
'change'
,
file_selected
,
false
);
}
else
{
alertSrv
.
set
(
'Oops'
,
'Sorry, the HTML5 File APIs are not fully supported in this browser.'
,
'error'
);
alertSrv
.
set
(
'Oops'
,
'Sorry, the HTML5 File APIs are not fully supported in this browser.'
,
'error'
,
5000
);
}
}
};
...
...
panels/histogram/module.js
View file @
71b14e46
...
...
@@ -108,11 +108,17 @@ angular.module('kibana.histogram', [])
$scope
.
panel
.
interval
=
interval
||
'10m'
;
return
$scope
.
panel
.
interval
;
};
/**
* Fetch the data for a chunk of a queries results. Multiple segments occur when several indicies
* need to be consulted (like timestamped logstash indicies)
* @param number segment The segment count, (0 based)
* @param number query_id The id of the query, generated on the first run and passed back when
*
* The results of this function are stored on the scope's data property. This property will be an
* array of objects with the properties info, time_series, and hits. These objects are used in the
* render_panel function to create the historgram.
*
* @param {number} segment The segment count, (0 based)
* @param {number} query_id The id of the query, generated on the first run and passed back when
* this call is made recursively for more segments
*/
$scope
.
get_data
=
function
(
segment
,
query_id
)
{
...
...
@@ -197,12 +203,12 @@ angular.module('kibana.histogram', [])
// we need to initialize the data variable on the first run,
// and when we are working on the first segment of the data.
if
(
_
.
isUndefined
(
$scope
.
data
[
i
])
||
segment
===
0
)
{
time_series
=
new
timeSeries
.
ZeroFilled
(
_interval
,
// range may be false
_range
&&
_range
.
from
,
_range
&&
_range
.
to
);
time_series
=
new
timeSeries
.
ZeroFilled
(
{
interval
:
_interval
,
start_date
:
_range
&&
_range
.
from
,
end_date
:
_range
&&
_range
.
to
,
fill_style
:
'minimal'
}
);
hits
=
0
;
}
else
{
time_series
=
$scope
.
data
[
i
].
time_series
;
...
...
@@ -216,9 +222,8 @@ angular.module('kibana.histogram', [])
$scope
.
hits
+=
entry
.
count
;
// Entire dataset level hits counter
});
$scope
.
data
[
i
]
=
{
time_series
:
time_series
,
info
:
querySrv
.
list
[
id
],
data
:
time_series
.
getFlotPairs
()
,
time_series
:
time_series
,
hits
:
hits
};
...
...
@@ -310,7 +315,7 @@ angular.module('kibana.histogram', [])
// Populate from the query service
try
{
_
.
each
(
scope
.
data
,
function
(
series
)
{
_
.
each
(
scope
.
data
,
function
(
series
)
{
series
.
label
=
series
.
info
.
alias
;
series
.
color
=
series
.
info
.
color
;
});
...
...
@@ -383,6 +388,19 @@ angular.module('kibana.histogram', [])
options
.
selection
=
{
mode
:
"x"
,
color
:
'#666'
};
}
// when rendering stacked bars, we need to ensure each point that has data is zero-filled
// so that the stacking happens in the proper order
var
required_times
=
[];
if
(
scope
.
panel
.
bars
&&
stack
)
{
required_times
=
Array
.
prototype
.
concat
.
apply
([],
_
.
map
(
scope
.
data
,
function
(
series
)
{
return
series
.
time_series
.
getOrderedTimes
();
}));
}
for
(
var
i
=
0
;
i
<
scope
.
data
.
length
;
i
++
)
{
scope
.
data
[
i
].
data
=
scope
.
data
[
i
].
time_series
.
getFlotPairs
(
required_times
);
}
scope
.
plot
=
$
.
plot
(
elem
,
scope
.
data
,
options
);
}
catch
(
e
)
{
...
...
@@ -448,36 +466,53 @@ angular.module('kibana.histogram', [])
};
})
.
service
(
'timeSeries'
,
function
()
{
// map compatable parseInt
function
base10Int
(
val
)
{
return
parseInt
(
val
,
10
);
}
/**
* Certain graphs require 0 entries to be specified for them to render
* properly (like the line graph). So with this we will caluclate all of
* the expected time measurements, and fill the missing ones in with 0
* @param date start The start time for the result set
* @param date end The end time for the result set
* @param integer interval The length between measurements, in es interval
* notation (1m, 30s, 1h, 15d)
* @param {object} opts An object specifying some/all of the options
*
* OPTIONS:
* @opt {string} interval The interval notion describing the expected spacing between
* each data point.
* @opt {date} start_date (optional) The start point for the time series, setting this and the
* end_date will ensure that the series streches to resemble the entire
* expected result
* @opt {date} end_date (optional) The end point for the time series, see start_date
* @opt {string} fill_style Either "minimal", or "all" describing the strategy used to zero-fill
* the series.
*/
var
undef
;
function
base10Int
(
val
)
{
return
parseInt
(
val
,
10
);
}
this
.
ZeroFilled
=
function
(
interval
,
start
,
end
)
{
this
.
ZeroFilled
=
function
(
opts
)
{
this
.
opts
=
_
.
defaults
(
opts
,
{
interval
:
'10m'
,
start_date
:
null
,
end_date
:
null
,
fill_style
:
'minimal'
});
// the expected differenece between readings.
this
.
interval_ms
=
base10Int
(
kbn
.
interval_to_seconds
(
interval
))
*
1000
;
this
.
interval_ms
=
base10Int
(
kbn
.
interval_to_seconds
(
opts
.
interval
))
*
1000
;
// will keep all values here, keyed by their time
this
.
_data
=
{};
if
(
start
)
{
this
.
addValue
(
start
,
null
);
if
(
opts
.
start_date
)
{
this
.
addValue
(
opts
.
start_date
,
null
);
}
if
(
end
)
{
this
.
addValue
(
end
,
null
);
if
(
opts
.
end_date
)
{
this
.
addValue
(
opts
.
end_date
,
null
);
}
};
/**
* Add a row
* @param
int
time The time for the value, in
* @param
any
value The value at this time
* @param
{int}
time The time for the value, in
* @param
{any}
value The value at this time
*/
this
.
ZeroFilled
.
prototype
.
addValue
=
function
(
time
,
value
)
{
if
(
time
instanceof
Date
)
{
...
...
@@ -486,19 +521,58 @@ angular.module('kibana.histogram', [])
time
=
base10Int
(
time
);
}
if
(
!
isNaN
(
time
))
{
this
.
_data
[
time
]
=
(
value
===
undef
?
0
:
value
);
this
.
_data
[
time
]
=
(
_
.
isUndefined
(
value
)
?
0
:
value
);
}
this
.
_cached_times
=
null
;
};
/**
* Get an array of the times that have been explicitly set in the series
* @param {array} include (optional) list of timestamps to include in the response
* @return {array} An array of integer times.
*/
this
.
ZeroFilled
.
prototype
.
getOrderedTimes
=
function
(
include
)
{
var
times
=
_
.
map
(
_
.
keys
(
this
.
_data
),
base10Int
).
sort
();
if
(
_
.
isArray
(
include
))
{
times
=
times
.
concat
(
include
);
}
return
times
;
};
/**
* return the rows in the format:
* [ [time, value], [time, value], ... ]
* @return array
*
* Heavy lifting is done by _get(Min|All)FlotPairs()
* @param {array} required_times An array of timestamps that must be in the resulting pairs
* @return {array}
*/
this
.
ZeroFilled
.
prototype
.
getFlotPairs
=
function
(
required_times
)
{
var
times
=
this
.
getOrderedTimes
(
required_times
),
strategy
,
pairs
;
if
(
this
.
opts
.
fill_style
===
'all'
)
{
strategy
=
this
.
_getAllFlotPairs
;
}
else
{
strategy
=
this
.
_getMinFlotPairs
;
}
return
_
.
reduce
(
times
,
// what
strategy
,
// how
[],
// where
this
// context
);
};
/**
* ** called as a reduce stragegy in getFlotPairs() **
* Fill zero's on either side of the current time, unless there is already a measurement there or
* we are looking at an edge.
* @return {array} An array of points to plot with flot
*/
this
.
ZeroFilled
.
prototype
.
getFlotPairs
=
function
()
{
// var startTime = performance.now();
var
times
=
_
.
map
(
_
.
keys
(
this
.
_data
),
base10Int
).
sort
(),
result
=
[];
_
.
each
(
times
,
function
(
time
,
i
,
times
)
{
this
.
ZeroFilled
.
prototype
.
_getMinFlotPairs
=
function
(
result
,
time
,
i
,
times
)
{
var
next
,
expected_next
,
prev
,
expected_prev
;
// check for previous measurement
...
...
@@ -511,7 +585,7 @@ angular.module('kibana.histogram', [])
}
// add the current time
result
.
push
([
time
,
this
.
_data
[
time
]
]);
result
.
push
([
time
,
this
.
_data
[
time
]
||
0
]);
// check for next measurement
if
(
times
.
length
>
i
)
{
...
...
@@ -522,8 +596,26 @@ angular.module('kibana.histogram', [])
}
}
},
this
);
// console.log(Math.round((performance.now() - startTime)*100)/100, 'ms to get', result.length, 'pairs');
return
result
;
};
/**
* ** called as a reduce stragegy in getFlotPairs() **
* Fill zero's to the right of each time, until the next measurement is reached or we are at the
* last measurement
* @return {array} An array of points to plot with flot
*/
this
.
ZeroFilled
.
prototype
.
_getAllFlotPairs
=
function
(
result
,
time
,
i
,
times
)
{
var
next
,
expected_next
;
result
.
push
([
times
[
i
],
this
.
_data
[
times
[
i
]]
||
0
]);
next
=
times
[
i
+
1
];
expected_next
=
times
[
i
]
+
this
.
interval_ms
;
for
(;
times
.
length
>
i
&&
next
>
expected_next
;
expected_next
+=
this
.
interval_ms
)
{
result
.
push
([
expected_next
,
0
]);
}
return
result
;
};
});
\ No newline at end of file
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