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
49c596a8
Commit
49c596a8
authored
Aug 26, 2013
by
Rashid Khan
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'spencer/zero-filled-ts' into zero
parents
e7626d2b
252b2fd6
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
130 additions
and
37 deletions
+130
-37
panels/histogram/module.js
+130
-37
No files found.
panels/histogram/module.js
View file @
49c596a8
...
...
@@ -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