@ -1,16 +1,18 @@
var Prometheus = Prometheus || { } ;
var graphs = [ ] ;
var graphTemplate ;
var SECOND = 1000 ;
Handlebars . registerHelper ( 'pathPrefix' , function ( ) { return PATH _PREFIX ; } ) ;
Prometheus . Graph = function ( element , options ) {
Prometheus . Graph = function ( element , options , handleChange , handleRemove ) {
this . el = element ;
this . graphHTML = null ;
this . options = options ;
this . changeHandler = null ;
this . handleChange = handleChange ;
this . handleRemove = function ( ) {
handleRemove ( this ) ;
} ;
this . rickshawGraph = null ;
this . data = [ ] ;
@ -69,7 +71,7 @@ Prometheus.Graph.prototype.initialize = function() {
} ;
$ ( this ) . on ( 'keyup input' , function ( ) { resizeTextarea ( this ) ; } ) ;
} ) ;
self . expr . change ( storeGraphOptionsInURL ) ;
self . expr . change ( self . handleChange ) ;
self . rangeInput = self . queryForm . find ( "input[name=range_input]" ) ;
self . stackedBtn = self . queryForm . find ( ".stacked_btn" ) ;
@ -85,7 +87,7 @@ Prometheus.Graph.prototype.initialize = function() {
self . tabs . on ( "shown.bs.tab" , function ( e ) {
var target = $ ( e . target ) ;
self . options . tab = target . parent ( ) . index ( ) ;
storeGraphOptionsInURL ( ) ;
self . handleChange ( ) ;
if ( $ ( "#" + target . attr ( "aria-controls" ) ) . hasClass ( "reload" ) ) {
self . submitQuery ( ) ;
}
@ -208,10 +210,6 @@ Prometheus.Graph.prototype.populateInsertableMetrics = function() {
} ) ;
} ;
Prometheus . Graph . prototype . onChange = function ( handler ) {
this . changeHandler = handler ;
} ;
Prometheus . Graph . prototype . getOptions = function ( ) {
var self = this ;
var options = { } ;
@ -544,7 +542,7 @@ Prometheus.Graph.prototype.updateGraph = function() {
legend : legend
} ) ;
self . changeHandler ( ) ;
self . handleChange ( ) ;
} ;
Prometheus . Graph . prototype . resizeGraph = function ( ) {
@ -622,41 +620,10 @@ Prometheus.Graph.prototype.handleConsoleResponse = function(data, textStatus) {
Prometheus . Graph . prototype . remove = function ( ) {
var self = this ;
$ ( self . graphHTML ) . remove ( ) ;
graphs = graphs . filter ( function ( e ) { return e !== self } ) ;
storeGraphOptionsInURL ( ) ;
self . handleRemove ( ) ;
self . handleChange ( ) ;
} ;
function parseGraphOptionsFromURL ( ) {
var hashOptions = window . location . hash . slice ( 1 ) ;
if ( ! hashOptions ) {
return [ ] ;
}
var optionsJSON = decodeURIComponent ( window . location . hash . slice ( 1 ) ) ;
options = JSON . parse ( optionsJSON ) ;
return options ;
}
// NOTE: This needs to be kept in sync with rules/helpers.go:GraphLinkForExpression!
function storeGraphOptionsInURL ( ) {
var allGraphsOptions = [ ] ;
for ( var i = 0 ; i < graphs . length ; i ++ ) {
allGraphsOptions . push ( graphs [ i ] . getOptions ( ) ) ;
}
var optionsJSON = JSON . stringify ( allGraphsOptions ) ;
window . location . hash = encodeURIComponent ( optionsJSON ) ;
}
function addGraph ( options ) {
var graph = new Prometheus . Graph ( $ ( "#graph_container" ) , options ) ;
graphs . push ( graph ) ;
graph . onChange ( function ( ) {
storeGraphOptionsInURL ( ) ;
} ) ;
$ ( window ) . resize ( function ( ) {
graph . resizeGraph ( ) ;
} ) ;
}
function escapeHTML ( string ) {
var entityMap = {
"&" : "&" ,
@ -672,6 +639,135 @@ function escapeHTML(string) {
} ) ;
}
Prometheus . Page = function ( ) {
this . graphs = [ ] ;
} ;
Prometheus . Page . prototype . init = function ( ) {
var graphOptions = this . parseURL ( ) ;
if ( graphOptions . length === 0 ) {
graphOptions . push ( { } ) ;
}
graphOptions . forEach ( this . addGraph , this ) ;
$ ( "#add_graph" ) . click ( this . addGraph . bind ( this , { } ) ) ;
} ;
Prometheus . Page . prototype . parseURL = function ( ) {
if ( window . location . search == "" ) {
return [ ] ;
}
var queryParams = window . location . search . substring ( 1 ) . split ( '&' ) ;
var queryParamHelper = new Prometheus . Page . QueryParamHelper ( ) ;
return queryParamHelper . parseQueryParams ( queryParams ) ;
} ;
Prometheus . Page . prototype . addGraph = function ( options ) {
var graph = new Prometheus . Graph (
$ ( "#graph_container" ) ,
options ,
this . updateURL . bind ( this ) ,
this . removeGraph . bind ( this )
) ;
this . graphs . push ( graph ) ;
$ ( window ) . resize ( function ( ) {
graph . resizeGraph ( ) ;
} ) ;
} ;
// NOTE: This needs to be kept in sync with /util/strutil/strconv.go:GraphLinkForExpression
Prometheus . Page . prototype . updateURL = function ( ) {
var queryString = this . graphs . map ( function ( graph , index ) {
var graphOptions = graph . getOptions ( ) ;
var queryParamHelper = new Prometheus . Page . QueryParamHelper ( ) ;
var queryObject = queryParamHelper . generateQueryObject ( graphOptions , index ) ;
return $ . param ( queryObject ) ;
} , this ) . join ( "&" ) ;
history . pushState ( { } , "" , "graph?" + queryString ) ;
} ;
Prometheus . Page . prototype . removeGraph = function ( graph ) {
this . graphs = this . graphs . filter ( function ( g ) { return g !== graph } ) ;
} ;
Prometheus . Page . QueryParamHelper = function ( ) { } ;
Prometheus . Page . QueryParamHelper . prototype . parseQueryParams = function ( queryParams ) {
var orderedQueryParams = this . filterInvalidParams ( queryParams ) . sort ( ) ;
return this . fetchOptionsFromOrderedParams ( orderedQueryParams , 0 ) ;
} ;
Prometheus . Page . QueryParamHelper . queryParamFormat = /^g\d+\..+=.+$/ ;
Prometheus . Page . QueryParamHelper . prototype . filterInvalidParams = function ( paramTuples ) {
return paramTuples . filter ( function ( paramTuple ) {
return Prometheus . Page . QueryParamHelper . queryParamFormat . test ( paramTuple ) ;
} ) ;
} ;
Prometheus . Page . QueryParamHelper . prototype . fetchOptionsFromOrderedParams = function ( queryParams , graphIndex ) {
if ( queryParams . length == 0 ) {
return [ ] ;
}
var prefixOfThisIndex = this . queryParamPrefix ( graphIndex ) ;
var numberOfParamsForThisGraph = queryParams . filter ( function ( paramTuple ) {
return paramTuple . startsWith ( prefixOfThisIndex ) ;
} ) . length ;
if ( numberOfParamsForThisGraph == 0 ) {
return [ ] ;
}
var paramsForThisGraph = queryParams . splice ( 0 , numberOfParamsForThisGraph ) ;
paramsForThisGraph = paramsForThisGraph . map ( function ( paramTuple ) {
return paramTuple . substring ( prefixOfThisIndex . length ) ;
} ) ;
var options = this . parseQueryParamsOfOneGraph ( paramsForThisGraph ) ;
var optionAccumulator = this . fetchOptionsFromOrderedParams ( queryParams , graphIndex + 1 ) ;
optionAccumulator . unshift ( options ) ;
return optionAccumulator ;
} ;
Prometheus . Page . QueryParamHelper . prototype . parseQueryParamsOfOneGraph = function ( queryParams ) {
var options = { } ;
queryParams . forEach ( function ( tuple ) {
var optionNameAndValue = tuple . split ( '=' ) ;
var optionName = optionNameAndValue [ 0 ] ;
var optionValue = decodeURIComponent ( optionNameAndValue [ 1 ] ) ;
optionValue = optionValue . replace ( /\+/g , " " ) ; // $.param turns spaces into pluses
if ( optionName == "tab" ) {
optionValue = parseInt ( optionValue ) ; // tab is integer
}
options [ optionName ] = optionValue ;
} ) ;
return options ;
} ;
Prometheus . Page . QueryParamHelper . prototype . queryParamPrefix = function ( index ) {
return "g" + index + "." ;
} ;
Prometheus . Page . QueryParamHelper . prototype . generateQueryObject = function ( graphOptions , index ) {
var prefix = this . queryParamPrefix ( index ) ;
var queryObject = { } ;
Object . keys ( graphOptions ) . forEach ( function ( key ) {
queryObject [ prefix + key ] = graphOptions [ key ] ;
} ) ;
return queryObject ;
} ;
function init ( ) {
$ . ajaxSetup ( {
cache : false
@ -681,14 +777,8 @@ function init() {
url : PATH _PREFIX + "/static/js/graph_template.handlebar" ,
success : function ( data ) {
graphTemplate = Handlebars . compile ( data ) ;
var options = parseGraphOptionsFromURL ( ) ;
if ( options . length === 0 ) {
options . push ( { } ) ;
}
for ( var i = 0 ; i < options . length ; i ++ ) {
addGraph ( options [ i ] ) ;
}
$ ( "#add_graph" ) . click ( function ( ) { addGraph ( { } ) ; } ) ;
var Page = new Prometheus . Page ( ) ;
Page . init ( ) ;
}
} ) ;
}