#NEWLINE# @ app . route ( '/render' , methods = methods ) #NEWLINE# def render( ) : #NEWLINE# #INDENT# errors = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# graph_options = { #NEWLINE# #INDENT# 'width' : 600 , #NEWLINE# 'height' : 300 , #NEWLINE# #UNINDENT# } #NEWLINE# request_options = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# graph_type = RequestParams . get ( 'graphType' , 'line' ) #NEWLINE# try : #NEWLINE# #INDENT# graph_class = GraphTypes [ graph_type ] #NEWLINE# request_options [ 'graphType' ] = graph_type #NEWLINE# request_options [ 'graphClass' ] = graph_class #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# errors [ 'graphType' ] = "Invalid graphType '{0}', must be one of '{1}'." . format ( graph_type , "', '" . join ( sorted ( GraphTypes . keys ( ) ) ) ) #NEWLINE# #UNINDENT# request_options [ 'pieMode' ] = RequestParams . get ( 'pieMode' , 'average' ) #NEWLINE# targets = RequestParams . getlist ( 'target' ) #NEWLINE# if ( not len ( targets ) ) : #NEWLINE# #INDENT# errors [ 'target' ] = 'This parameter is required.' #NEWLINE# #UNINDENT# request_options [ 'targets' ] = targets #NEWLINE# if ( 'rawData' in RequestParams ) : #NEWLINE# #INDENT# request_options [ 'format' ] = 'raw' #NEWLINE# #UNINDENT# if ( 'format' in RequestParams ) : #NEWLINE# #INDENT# request_options [ 'format' ] = RequestParams [ 'format' ] #NEWLINE# if ( 'jsonp' in RequestParams ) : #NEWLINE# #INDENT# request_options [ 'jsonp' ] = RequestParams [ 'jsonp' ] #NEWLINE# #UNINDENT# #UNINDENT# if ( 'maxDataPoints' in RequestParams ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# request_options [ 'maxDataPoints' ] = int ( float ( RequestParams [ 'maxDataPoints' ] ) ) #NEWLINE# #UNINDENT# except ValueError : #NEWLINE# #INDENT# errors [ 'maxDataPoints' ] = 'Must be an integer.' #NEWLINE# #UNINDENT# #UNINDENT# if errors : #NEWLINE# #INDENT# return jsonify ( { #NEWLINE# #INDENT# 'errors' : errors , #NEWLINE# #UNINDENT# } , status = 400 ) #NEWLINE# #UNINDENT# for opt in graph_class . customizable : #NEWLINE# #INDENT# if ( opt in RequestParams ) : #NEWLINE# #INDENT# value = RequestParams [ opt ] #NEWLINE# try : #NEWLINE# #INDENT# value = int ( value ) #NEWLINE# #UNINDENT# except ValueError : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# value = float ( value ) #NEWLINE# #UNINDENT# except ValueError : #NEWLINE# #INDENT# if ( value . lower ( ) in ( 'true' , 'false' ) ) : #NEWLINE# #INDENT# value = ( value . lower ( ) == 'true' ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( value . lower ( ) == 'default' ) or ( not opt ) ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# graph_options [ opt ] = value #NEWLINE# #UNINDENT# #UNINDENT# tzinfo = pytz . timezone ( app . config [ 'TIME_ZONE' ] ) #NEWLINE# tz = RequestParams . get ( 'tz' ) #NEWLINE# if tz : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# tzinfo = pytz . timezone ( tz ) #NEWLINE# #UNINDENT# except pytz . UnknownTimeZoneError : #NEWLINE# #INDENT# errors [ 'tz' ] = "Unknown timezone: '{0}'." . format ( tz ) #NEWLINE# #UNINDENT# #UNINDENT# request_options [ 'tzinfo' ] = tzinfo #NEWLINE# until_time = parseATTime ( RequestParams . get ( 'until' , 'now' ) , tzinfo ) #NEWLINE# from_time = parseATTime ( RequestParams . get ( 'from' , '-1d' ) , tzinfo ) #NEWLINE# start_time = min ( from_time , until_time ) #NEWLINE# end_time = max ( from_time , until_time ) #NEWLINE# if ( start_time == end_time ) : #NEWLINE# #INDENT# errors [ 'from' ] = errors [ 'until' ] = 'Invalid empty time range' #NEWLINE# #UNINDENT# request_options [ 'startTime' ] = start_time #NEWLINE# request_options [ 'endTime' ] = end_time #NEWLINE# use_cache = ( ( app . cache is not None ) and ( 'noCache' not in RequestParams ) ) #NEWLINE# cache_timeout = RequestParams . get ( 'cacheTimeout' ) #NEWLINE# if ( cache_timeout is not None ) : #NEWLINE# #INDENT# cache_timeout = int ( cache_timeout ) #NEWLINE# #UNINDENT# if errors : #NEWLINE# #INDENT# return jsonify ( { #NEWLINE# #INDENT# 'errors' : errors , #NEWLINE# #UNINDENT# } , status = 400 ) #NEWLINE# #UNINDENT# if use_cache : #NEWLINE# #INDENT# request_key = hash_request ( ) #NEWLINE# response = app . cache . get ( request_key ) #NEWLINE# if ( response is not None ) : #NEWLINE# #INDENT# return response #NEWLINE# #UNINDENT# #UNINDENT# headers = ( { #NEWLINE# #INDENT# 'Last-Modified' : http_date ( time . time ( ) ) , #NEWLINE# 'Expires' : http_date ( ( time . time ( ) + ( cache_timeout or 60 ) ) ) , #NEWLINE# 'Cache-Control' : 'max-age={0}' . format ( ( cache_timeout or 60 ) ) , #NEWLINE# #UNINDENT# } if use_cache else { #NEWLINE# #INDENT# 'Pragma' : 'no-cache' , #NEWLINE# 'Cache-Control' : 'no-cache' , #NEWLINE# #UNINDENT# } ) #NEWLINE# context = { #NEWLINE# #INDENT# 'startTime' : request_options [ 'startTime' ] , #NEWLINE# 'endTime' : request_options [ 'endTime' ] , #NEWLINE# 'tzinfo' : request_options [ 'tzinfo' ] , #NEWLINE# 'data' : [ ] , #NEWLINE# #UNINDENT# } #NEWLINE# paths = [ ] #NEWLINE# for target in request_options [ 'targets' ] : #NEWLINE# #INDENT# if ( request_options [ 'graphType' ] == 'pie' ) : #NEWLINE# #INDENT# if ( ':' in target ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# #UNINDENT# if target . strip ( ) : #NEWLINE# #INDENT# paths += pathsFromTarget ( target ) #NEWLINE# #UNINDENT# #UNINDENT# data_store = fetchData ( context , paths ) #NEWLINE# if ( request_options [ 'graphType' ] == 'pie' ) : #NEWLINE# #INDENT# for target in request_options [ 'targets' ] : #NEWLINE# #INDENT# if ( ':' in target ) : #NEWLINE# #INDENT# ( name , value ) = target . split ( ':' , 1 ) #NEWLINE# try : #NEWLINE# #INDENT# value = float ( value ) #NEWLINE# #UNINDENT# except ValueError : #NEWLINE# #INDENT# errors [ 'target' ] = "Invalid target: '{0}'." . format ( target ) #NEWLINE# #UNINDENT# context [ 'data' ] . append ( ( name , value ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# series_list = evaluateTarget ( context , target , data_store ) #NEWLINE# for series in series_list : #NEWLINE# #INDENT# func = app . functions [ request_options [ 'pieMode' ] ] #NEWLINE# context [ 'data' ] . append ( ( series . name , ( func ( context , series ) or 0 ) ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# if errors : #NEWLINE# #INDENT# return jsonify ( { #NEWLINE# #INDENT# 'errors' : errors , #NEWLINE# #UNINDENT# } , status = 400 ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# for target in request_options [ 'targets' ] : #NEWLINE# #INDENT# if ( not target . strip ( ) ) : #NEWLINE# #INDENT# continue #NEWLINE# #UNINDENT# series_list = evaluateTarget ( context , target , data_store ) #NEWLINE# context [ 'data' ] . extend ( series_list ) #NEWLINE# #UNINDENT# request_options [ 'format' ] = request_options . get ( 'format' ) #NEWLINE# if ( request_options [ 'format' ] == 'csv' ) : #NEWLINE# #INDENT# response = ( BytesIO ( ) if six . PY2 else StringIO ( ) ) #NEWLINE# writer = csv . writer ( response , dialect = 'excel' ) #NEWLINE# for series in context [ 'data' ] : #NEWLINE# #INDENT# for ( index , value ) in enumerate ( series ) : #NEWLINE# #INDENT# ts = datetime . fromtimestamp ( ( series . start + ( index * series . step ) ) , request_options [ 'tzinfo' ] ) #NEWLINE# writer . writerow ( ( series . name , ts . strftime ( '%Y-%m-%d %H:%M:%S' ) , value ) ) #NEWLINE# #UNINDENT# #UNINDENT# response . seek ( 0 ) #NEWLINE# headers [ 'Content-Type' ] = 'text/csv' #NEWLINE# return ( response . read ( ) , 200 , headers ) #NEWLINE# #UNINDENT# if ( request_options [ 'format' ] == 'json' ) : #NEWLINE# #INDENT# series_data = [ ] #NEWLINE# if ( ( 'maxDataPoints' in request_options ) and any ( context [ 'data' ] ) ) : #NEWLINE# #INDENT# start_time = min ( [ s . start for s in context [ 'data' ] ] ) #NEWLINE# end_time = max ( [ s . end for s in context [ 'data' ] ] ) #NEWLINE# for series in context [ 'data' ] : #NEWLINE# #INDENT# series_data . append ( prune_datapoints ( series , request_options [ 'maxDataPoints' ] , start_time , end_time ) ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# for series in context [ 'data' ] : #NEWLINE# #INDENT# timestamps = range ( series . start , ( series . end + series . step ) , series . step ) #NEWLINE# datapoints = zip ( series , timestamps ) #NEWLINE# series_data . append ( { #NEWLINE# #INDENT# 'target' : series . name , #NEWLINE# 'datapoints' : datapoints , #NEWLINE# #UNINDENT# } ) #NEWLINE# #UNINDENT# #UNINDENT# return jsonify ( series_data , headers = headers ) #NEWLINE# #UNINDENT# if ( request_options [ 'format' ] == 'raw' ) : #NEWLINE# #INDENT# response = StringIO ( ) #NEWLINE# for series in context [ 'data' ] : #NEWLINE# #INDENT# response . write ( ( '%s,%d,%d,%d|' % ( series . name , series . start , series . end , series . step ) ) ) #NEWLINE# response . write ( ',' . join ( map ( repr , series ) ) ) #NEWLINE# response . write ( '\n' ) #NEWLINE# #UNINDENT# response . seek ( 0 ) #NEWLINE# headers [ 'Content-Type' ] = 'text/plain' #NEWLINE# return ( response . read ( ) , 200 , headers ) #NEWLINE# #UNINDENT# if ( request_options [ 'format' ] == 'svg' ) : #NEWLINE# #INDENT# graph_options [ 'outputFormat' ] = 'svg' #NEWLINE# #UNINDENT# #UNINDENT# graph_options [ 'data' ] = context [ 'data' ] #NEWLINE# image = doImageRender ( request_options [ 'graphClass' ] , graph_options ) #NEWLINE# use_svg = ( graph_options . get ( 'outputFormat' ) == 'svg' ) #NEWLINE# if ( use_svg and ( 'jsonp' in request_options ) ) : #NEWLINE# #INDENT# headers [ 'Content-Type' ] = 'text/javascript' #NEWLINE# response = ( '{0}({1})' . format ( request_options [ 'jsonp' ] , json . dumps ( image . decode ( 'utf-8' ) ) ) , 200 , headers ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# ctype = ( 'image/svg+xml' if use_svg else 'image/png' ) #NEWLINE# headers [ 'Content-Type' ] = ctype #NEWLINE# response = ( image , 200 , headers ) #NEWLINE# #UNINDENT# if use_cache : #NEWLINE# #INDENT# app . cache . add ( request_key , response , cache_timeout ) #NEWLINE# #UNINDENT# return response