blob: 76bfb784d4e2961922cb8ecfb0338218f1b7704b [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
from flask import Flask, request, jsonify
from distill.models.brew import Brew
from distill.models.userale import UserAle
# from distill.models.stout import Stout
from distill.algorithms.stats.hist import Hist
from distill.version import __version__
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
Show Distill version information, connection status,
and all registered applications.
.. code-block:: bash
$ curl -XGET http://localhost:8090
"name": "Distill",
"version" : "0.1.0",
"status" : true,
"applications" : {
"xdata_v3" : {
testing: 205,
parsed: 500,
"test_app" : {
logs: 500,
parsed: 100,
:return: Distill's status information
return jsonify(name="Distill",
@app.route('/create/<app_id>', methods=['POST', 'PUT'])
def create(app_id):
Register an application.
@todo Need to include UserALE.js mapping information in a general sense.
.. code-block:: bash
$ curl -XPOST http://localhost:8090/create/xdata_v3
:param app_id: Application name
:return: Newly created application's status
return jsonify(Brew.create(app_id))
@app.route('/sankey/<app_id>', methods=['GET'])
def sankey(app_id):
Generate a node-link diagram
from distill.algorithms.graphs.graph import GraphAnalytics
# Time range using date math
from_range = 'now-15m'
to_range = 'now'
if 'from' in request.args and request.args.get('from') != '':
from_range = request.args.get('from')
if 'to' in request.args and request.args.get('to') != '':
to_range = request.args.get('to')
ts_range = [from_range, to_range]
# Size
size = 20
if 'size' in request.args and request.args.get('size') != '':
size = request.args.get('size')
# events (event_in)
events = []
if 'event' in request.args and request.args.get('event') != '':
events = request.args.get('event').split(',')
# filter in/out targets
target_in = []
if 'target_in' in request.args and request.args.get('target_in') != '':
target_in = request.args.get('target_in').split(',')
target_out = []
if 'target_out' in request.args and request.args.get('target_out') != '':
target_out = request.args.get('target_out').split(',')
return jsonify(GraphAnalytics.generate_graph(app_id,
targets=[target_in, target_out],
@app.route('/status/<app_id>', defaults={"app_type": None}, methods=['GET'])
@app.route('/status/<app_id>/<app_type>', methods=['GET'])
def status(app_id, app_type):
Presents meta information about an registered application,
including field names and document types.
.. code-block:: bash
$ curl -XGET http://localhost:8090/status/xdata_v3
"application": "xdata_v3",
"health": "green",
"num_docs": "433",
"status": "open"
:param app_id: Application name
:param app_type: Application type
:return: Registered applications meta data
res =, app_type=app_type)
return jsonify(res)
@app.route('/update/<app_id>', methods=['POST', 'PUT'])
def update(app_id):
Renames a specific application
.. code-block:: bash
$ curl -XPOST http://localhost:8090/update/xdata_v3?name="xdata_v4"
:param app_id: Application name
:return: Boolean response message
return jsonify(Brew.update(app_id))
@app.route('/delete/<app_id>', methods=['DELETE'])
def delete(app_id):
Deletes an application permentantly from Distill
.. code-block:: bash
$ curl -XDELETE http://localhost:8090/xdata_v3
:param app_id: Application name
:return: Boolean response message
res = Brew.delete(app_id)
jsonify(status="Deleted index %s" % app_id)
@app.route('/search/<app_id>', defaults={"app_type": None}, methods=['GET'])
@app.route('/search/<app_id>/<app_type>', methods=['GET'])
def segment(app_id, app_type):
Search against an application on various fields.
.. code-block:: bash
$ curl -XGET http://localhost:8090/search/xdata_v3?q=session_id:A1234&size=100&scroll=false&fl=param1,param2
:param app_id: Application name
:param app_type: Optional document type to filter against
:param q: Main search query. To return all documents, pass in q=*:*
:param size: Maximum number of documents to return in request
:param scroll: Scroll id if the number of documents exceeds 10,000
:param fl: List of fields to restrict the result set
:return: JSON blob of result set
q = request.args
return UserAle.segment(app_id, app_type=app_type, params=q)
@app.route('/stat/<app_id>', defaults={"app_type": None}, methods=['GET'])
@app.route('/stat/<app_id>/<app_type>', methods=['GET'])
def stat(app_id, app_type):
Generic histogram counts for a single registered
application filtered optionally by document type.
View the Statistics document page for method definitions and arguments
.. code-block:: bash
$ curl -XGET http://localhost:8090/stat/xdata_v3/testing/?stat=terms&elem=signup&event=click
:param app_id: Application name
:param app_type: Application type
:return: JSON blob of result set
stat = request.args.get('stat')
q = request.args
hist_cls = Hist()
method = None
method = getattr(hist_cls, stat)
return method(app_id, app_type, q=q)
except AttributeError:
msg = "Class `{}` does not implement `{}`".format(
hist_cls.__class__.__name__, stat)
return jsonify(error=msg)
# @app.route('/denoise/<app_id>', methods=['GET'])
# def denoise(app_id):
# """
# Bootstrap script to cleanup the raw logs. A document type called "parsed"
# will be stored with new log created unless specified in the request.
# Have option to save parsed results back to data store.
# These parsed logs can be integrated with STOUT results
# by running the stout bootstrap script.
# .. code-block:: bash
# $ curl -XGET http://localhost:8090/denoise/xdata_v3?save=true&type=parsed
# :param app_id: Application name
# :return: [dict]
# """
# doc_type = 'parsed'
# save = False
# # q = request.args
# # if 'save' in q:
# # save = str2bool(q.get('save'))
# # if 'type' in q:
# # # @TODO: Proper cleanup script needs to happen
# # doc_type = q.get('type')
# return UserAle.denoise(app_id, doc_type=doc_type, save=save)
def page_not_found(error):
Generic Error Message
return "Unable to find Distill."