def index_json(request): jsonp = request.REQUEST.get('jsonp', False) matches = [] for root, dirs, files in os.walk(settings.WHISPER_DIR): root = root.replace(settings.WHISPER_DIR, '') for basename in files: if fnmatch.fnmatch(basename, '*.wsp'): matches.append(os.path.join(root, basename)) for match in do_walk_rrd_dirs(settings.RRD_DIR): matches.append(match) matches = [ m .replace('.wsp', '') .replace('.rrd', '') .replace('/', '.') .lstrip('.') for m in sorted(matches) ] if jsonp: return HttpResponse("%s(%s)" % (jsonp, json.dumps(matches)), mimetype='text/javascript') else: return HttpResponse(json.dumps(matches), mimetype='application/json')
def get_data(request): if 'jsonp' in request.REQUEST: response = HttpResponse( "%s(%s)" % (request.REQUEST.get('jsonp'), json.dumps(fetch(request), cls=EventEncoder)), mimetype='text/javascript') else: response = HttpResponse( json.dumps(fetch(request), cls=EventEncoder), mimetype="application/json") return response
def context_view(request): if request.method == 'GET': contexts = [] if not 'metric' not in request.GET: return HttpResponse('{ "error" : "missing required parameter \"metric\"" }', mimetype='application/json') for metric in request.GET.getlist('metric'): try: context = STORE.get(metric).context except: contexts.append({ 'metric' : metric, 'error' : 'failed to retrieve context', 'traceback' : traceback.format_exc() }) else: contexts.append({ 'metric' : metric, 'context' : context }) content = json.dumps( { 'contexts' : contexts } ) return HttpResponse(content, mimetype='application/json') elif request.method == 'POST': if 'metric' not in request.POST: return HttpResponse('{ "error" : "missing required parameter \"metric\"" }', mimetype='application/json') newContext = dict( item for item in request.POST.items() if item[0] != 'metric' ) for metric in request.POST.getlist('metric'): STORE.get(metric).updateContext(newContext) return HttpResponse('{ "success" : true }', mimetype='application/json') else: return HttpResponseBadRequest("invalid method, must be GET or POST")
def set_metadata_view(request): results = {} if request.method == 'GET': metric = request.GET['metric'] key = request.GET['key'] value = request.GET['value'] try: results[metric] = CarbonLink.set_metadata(metric, key, value) except: log.exception() results[metric] = dict(error="Unexpected error occurred in CarbonLink.set_metadata(%s, %s)" % (metric, key)) elif request.method == 'POST': if request.META.get('CONTENT_TYPE') == 'application/json': operations = json.loads( request.raw_post_data ) else: operations = json.loads( request.POST['operations'] ) for op in operations: metric = None try: metric, key, value = op['metric'], op['key'], op['value'] results[metric] = CarbonLink.set_metadata(metric, key, value) except: log.exception() if metric: results[metric] = dict(error="Unexpected error occurred in bulk CarbonLink.set_metadata(%s)" % metric) else: results = dict(error="Invalid request method") return HttpResponse(json.dumps(results), mimetype='application/json')
def expand_view(request): "View for expanding a pattern into matching metric paths" local_only = int( request.REQUEST.get('local', 0) ) group_by_expr = int( request.REQUEST.get('groupByExpr', 0) ) leaves_only = int( request.REQUEST.get('leavesOnly', 0) ) if local_only: store = LOCAL_STORE else: store = STORE results = {} for query in request.REQUEST.getlist('query'): results[query] = set() for node in store.find(query): if node.isLeaf() or not leaves_only: results[query].add( node.metric_path ) # Convert our results to sorted lists because sets aren't json-friendly if group_by_expr: for query, matches in results.items(): results[query] = sorted(matches) else: results = sorted( reduce(set.union, results.values(), set()) ) result = { 'results' : results } response = HttpResponse(json.dumps(result), mimetype='application/json') response['Pragma'] = 'no-cache' response['Cache-Control'] = 'no-cache' return response
def tree_json(nodes, base_path, wildcards=False, contexts=False): results = [] branchNode = { 'allowChildren': 1, 'expandable': 1, 'leaf': 0, } leafNode = { 'allowChildren': 0, 'expandable': 0, 'leaf': 1, } #Add a wildcard node if appropriate if len(nodes) > 1 and wildcards: wildcardNode = {'text' : '*', 'id' : base_path + '*'} if any(not n.isLeaf() for n in nodes): wildcardNode.update(branchNode) else: wildcardNode.update(leafNode) results.append(wildcardNode) found = set() results_leaf = [] results_branch = [] for node in nodes: #Now let's add the matching children if node.name in found: continue found.add(node.name) resultNode = { 'text' : str(node.name), 'id' : base_path + str(node.name), } if contexts: resultNode['context'] = node.context else: resultNode['context'] = {} if node.isLeaf(): resultNode.update(leafNode) results_leaf.append(resultNode) else: resultNode.update(branchNode) results_branch.append(resultNode) results.extend(results_branch) results.extend(results_leaf) return json.dumps(results)
def get_metadata_view(request): key = request.REQUEST['key'] metrics = request.REQUEST.getlist('metric') results = {} for metric in metrics: try: results[metric] = CarbonLink.get_metadata(metric, key) except: log.exception() results[metric] = dict(error="Unexpected error occurred in CarbonLink.get_metadata(%s, %s)" % (metric, key)) return HttpResponse(json.dumps(results), mimetype='application/json')
def json_response(nodes, request=None): if request: jsonp = request.REQUEST.get('jsonp', False) else: jsonp = False json_data = json.dumps(nodes) if jsonp: response = HttpResponse("%s(%s)" % (jsonp, json_data),mimetype="text/javascript") else: response = HttpResponse(json_data,mimetype="application/json") response['Pragma'] = 'no-cache' response['Cache-Control'] = 'no-cache' return response
def search_view(request): try: query = str( request.REQUEST['query'] ) except: return HttpResponseBadRequest(content="Missing required parameter 'query'", mimetype="text/plain") search_request = { 'query' : query, 'max_results' : int( request.REQUEST.get('max_results', 25) ), 'keep_query_pattern' : int(request.REQUEST.get('keep_query_pattern', 0)), } #if not search_request['query'].endswith('*'): # search_request['query'] += '*' results = sorted(searcher.search(**search_request)) result_data = json.dumps( dict(metrics=results) ) return HttpResponse(result_data, mimetype='application/json')
def get_data(request): """Get the data for one series.""" (graphOptions, requestOptions) = parseOptions(request) requestContext = { 'startTime' : requestOptions['startTime'], 'endTime' : requestOptions['endTime'], 'localOnly' : False, 'data' : [] } target = requestOptions['targets'][0] seriesList = evaluateTarget(requestContext, target) result = [ dict( name=timeseries.name, data=[ x for x in timeseries ], start=timeseries.start, end=timeseries.end, step=timeseries.step, ) for timeseries in seriesList ] if not result: raise Http404 return HttpResponse(json.dumps(result), mimetype="application/json")
def renderView(request): start = time() (graphOptions, requestOptions) = parseOptions(request) useCache = 'noCache' not in requestOptions cacheTimeout = requestOptions['cacheTimeout'] requestContext = { 'startTime' : requestOptions['startTime'], 'endTime' : requestOptions['endTime'], 'localOnly' : requestOptions['localOnly'], 'data' : [] } data = requestContext['data'] # First we check the request cache if useCache: requestKey = hashRequest(request) cachedResponse = cache.get(requestKey) if cachedResponse: log.cache('Request-Cache hit [%s]' % requestKey) log.rendering('Returned cached response in %.6f' % (time() - start)) return cachedResponse else: log.cache('Request-Cache miss [%s]' % requestKey) # Now we prepare the requested data if requestOptions['graphType'] == 'pie': for target in requestOptions['targets']: if target.find(':') >= 0: try: name,value = target.split(':',1) value = float(value) except: raise ValueError, "Invalid target '%s'" % target data.append( (name,value) ) else: seriesList = evaluateTarget(requestContext, target) for series in seriesList: func = PieFunctions[requestOptions['pieMode']] data.append( (series.name, func(requestContext, series) or 0 )) elif requestOptions['graphType'] == 'line': # Let's see if at least our data is cached if useCache: targets = requestOptions['targets'] startTime = requestOptions['startTime'] endTime = requestOptions['endTime'] dataKey = hashData(targets, startTime, endTime) cachedData = cache.get(dataKey) if cachedData: log.cache("Data-Cache hit [%s]" % dataKey) else: log.cache("Data-Cache miss [%s]" % dataKey) else: cachedData = None if cachedData is not None: requestContext['data'] = data = cachedData else: # Have to actually retrieve the data now for target in requestOptions['targets']: t = time() seriesList = evaluateTarget(requestContext, target) log.rendering("Retrieval of %s took %.6f" % (target, time() - t)) data.extend(seriesList) if useCache: cache.set(dataKey, data, cacheTimeout) format = requestOptions.get('format') if format == 'csv': response = HttpResponse(mimetype='text/csv') writer = csv.writer(response, dialect='excel') for series in data: for i, value in enumerate(series): timestamp = datetime.fromtimestamp(series.start + (i * series.step), requestOptions['tzinfo']) writer.writerow((series.name, timestamp.strftime("%Y-%m-%d %H:%M:%S"), value)) return response if format == 'json': series_data = [] for series in data: timestamps = range(series.start, series.end, series.step) datapoints = zip(series, timestamps) series_data.append( dict(target=series.name, datapoints=datapoints) ) if 'jsonp' in requestOptions: response = HttpResponse( content="%s(%s)" % (requestOptions['jsonp'], json.dumps(series_data)), mimetype='text/javascript') else: response = HttpResponse(content=json.dumps(series_data), mimetype='application/json') response['Pragma'] = 'no-cache' response['Cache-Control'] = 'no-cache' return response if format == 'raw': response = HttpResponse(mimetype='text/plain') for series in data: response.write( "%s,%d,%d,%d|" % (series.name, series.start, series.end, series.step) ) response.write( ','.join(map(str,series)) ) response.write('\n') log.rendering('Total rawData rendering time %.6f' % (time() - start)) return response if format == 'svg': graphOptions['outputFormat'] = 'svg' if format == 'pickle': response = HttpResponse(mimetype='application/pickle') seriesInfo = [series.getInfo() for series in data] pickle.dump(seriesInfo, response, protocol=-1) log.rendering('Total pickle rendering time %.6f' % (time() - start)) return response # We've got the data, now to render it graphOptions['data'] = data if settings.REMOTE_RENDERING: # Rendering on other machines is faster in some situations image = delegateRendering(requestOptions['graphType'], graphOptions) else: image = doImageRender(requestOptions['graphClass'], graphOptions) useSVG = graphOptions.get('outputFormat') == 'svg' if useSVG and 'jsonp' in requestOptions: response = HttpResponse( content="%s(%s)" % (requestOptions['jsonp'], json.dumps(image)), mimetype='text/javascript') else: response = buildResponse(image, useSVG and 'image/svg+xml' or 'image/png') if useCache: cache.set(requestKey, response, cacheTimeout) log.rendering('Total rendering time %.6f seconds' % (time() - start)) return response
def find_view(request): "View for finding metrics matching a given pattern" profile = getProfile(request) format = request.REQUEST.get('format', 'treejson') local_only = int( request.REQUEST.get('local', 0) ) contexts = int( request.REQUEST.get('contexts', 0) ) wildcards = int( request.REQUEST.get('wildcards', 0) ) automatic_variants = int( request.REQUEST.get('automatic_variants', 0) ) try: query = str( request.REQUEST['query'] ) except: return HttpResponseBadRequest(content="Missing required parameter 'query'", mimetype="text/plain") if '.' in query: base_path = query.rsplit('.', 1)[0] + '.' else: base_path = '' if local_only: store = LOCAL_STORE else: store = STORE if format == 'completer': query = query.replace('..', '*.') if not query.endswith('*'): query += '*' if automatic_variants: query_parts = query.split('.') for i,part in enumerate(query_parts): if ',' in part and '{' not in part: query_parts[i] = '{%s}' % part query = '.'.join(query_parts) try: matches = list( store.find(query) ) except: log.exception() raise log.info('find_view query=%s local_only=%s matches=%d' % (query, local_only, len(matches))) matches.sort(key=lambda node: node.name) if format == 'treejson': content = tree_json(matches, base_path, wildcards=profile.advancedUI or wildcards, contexts=contexts) response = HttpResponse(content, mimetype='application/json') elif format == 'pickle': content = pickle_nodes(matches, contexts=contexts) response = HttpResponse(content, mimetype='application/pickle') elif format == 'completer': #if len(matches) == 1 and (not matches[0].isLeaf()) and query == matches[0].metric_path + '*': # auto-complete children # matches = list( store.find(query + '.*') ) results = [] for node in matches: node_info = dict(path=node.metric_path, name=node.name, is_leaf=str(int(node.isLeaf()))) if not node.isLeaf(): node_info['path'] += '.' results.append(node_info) if len(results) > 1 and wildcards: wildcardNode = {'name' : '*'} results.append(wildcardNode) content = json.dumps({ 'metrics' : results }) response = HttpResponse(content, mimetype='application/json') else: return HttpResponseBadRequest(content="Invalid value for 'format' parameter", mimetype="text/plain") response['Pragma'] = 'no-cache' response['Cache-Control'] = 'no-cache' return response