Merge pull request #1 from feature/design-draft

* feature/design-draft:
  Update swagger definition to use Explorations instead of Explorers
  Update design doc
  Use the chronograf name instead of enterprise
  Update swagger definition based on group discussion.
  Update design to reflect discussions.
  Update query response definition to simplify links.
  Reword swagger definition description of dashboard PUT
  Update swagger definition so users will have roles and ACLs are now Permissions.
  Update swagger definition to fix /dashboards/{id} response object typo.
  Update swagger definition to rename layout to dashboard.
  Fix invalid swagger definitions
  Update swagger interface to reflect our discussions.
  Spelling
  Update query proxy section
  Update design document organization; Add more specifics about releases and queries.
  Add a possible sequence flow for queries
  Add initial draft (sketch) of design
pull/36/head
Chris Goller 2016-09-12 14:08:02 -05:00
commit c0a3abe620
3 changed files with 1151 additions and 653 deletions

215
docs/design.md Normal file
View File

@ -0,0 +1,215 @@
## Chronograf
[TOC]
### Design Philosophy
1. Present uniform interface to front-end covering Plutonium and InfluxDB OSS offerings.
2. Simplify the front-end interaction with time-series database.
3. Ease of setup and use.
4. Extensible as base for future applications
5. There will be an open source version of this.
7. Stress Parallel Development across all teams.
8. First class support of on-prem.
9. Release to cloud first.
### Initial Goals
1. Produce pre-canned graphs for devops telegraf data for docker containers or system stats.
2. Up and running in 2 minutes
3. User administration for Influx Enterprise.
4. Leverage our existing enterprise front-end code.
5. Leverage lessons-learned for enterprise back-end code.
### Versions
Each version will contain more and more features around monitoring various devops components.
#### Features
1. v1
- Data explorer for both OSS and Enterprise
- Dashboards for telegraf system metrics
- User and Role adminstration
- Proxy queries over OSS and Enterprise
- Authenticate against OSS/Enterprise
2. v2
- Telegraf agent service
- Additional Dashboards for telegraf agent
### Supported Versions of TICK Stack
We will only support 1.0 of the TICK stack.
### Closed source vs Open Source
- Ideally, we would use the soon-to-be open source plutonium client to interact with Influx Enterprise. This would mean that this application could be entirely open source. (We should check with Todd and Nate.)
- However, if in the future we want to deliver a closed source version, we'll use the open source version as a library. The open source library will define certain routes (/users, /whatever); the closed source version will either override those routes, or add new ones. This implies that the closed source version is simply additional or manipulated routes on the server.
- Survey the experience of closed source with Jason and Nathaniel.
### Repository
#### Structure
Both the javascript and go source will be in the same repository.
#### Builds
Javascript build will be decoupled from Go build process.
Asset compilation will happen during build of backend-server.
This allows the front-end team to swap in mocked, auto-generated swagger backend for testing and development.
##### Javascript
Webpack
Static asset compilation during backend-server build.
##### Go
We'll use GDM as the vendoring solution to maintain consistency with other pieces of TICK stack.
*Future work*: we must switch to the community vendoring solution when it actually seems mature.
### API
#### REST
We'll use swagger interface definition to specify API and JSON validation. The goal is to emphasize designing to an interface facilitating parallel development.
#### Queries
Features would include:
1. Load balancing against all data nodes in cluster.
1. Formatting the output results to be simple to use in frontend.
1. Decimating the results to minimize network traffic.
1. Use parameters to move query time range.
1. Allow different types of response protocols (http GET, websocket, etc.).
- **`/proxy`:** used to send queries directly to the Influx backend. They should be most useful for the data explorer or other ad hoc query functionality.
##### `/proxy` Queries
Queries to the `/proxy` endpoint do not create new REST resources. Instead, it returns results of the query.
This endpoint uses POST with a JSON object to specify the query and the parameters. The endpoint's response will be the results of the query, or, the errors from the backend InfluxDB.
Errors in the 4xx range come from the Influxdb data source.
```sequence
App->/proxy: POST query
Note right of /proxy: Query Validation
Note right of /proxy: Load balance query
/proxy->Influx/Relay/Cluster: SELECT
Influx/Relay/Cluster-->/proxy: Time Series
Note right of /proxy: Format
/proxy-->App: Formatted results
```
Request:
```http
POST /enterprise/v1/sources/{id}/proxy HTTP/1.1
Accept: application/json
Content-Type: application/json
{
"query": "SELECT * from telegraf where time > $value",
"format": "dygraph",
}
```
Response:
```http
HTTP/1.1 200 OK
Content-Type: application/json
{
"results": "..."
}
```
Error Response:
```http
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"code": 400,
"message": "error parsing query: found..."
}
```
##### Load balancing
Use simple round robin load balancing requests to data nodes.
Discover active data nodes using Plutonium meta client.
#### Backend-server store
We will build a interface for storing API resources.
Some API resources could come from the influx data source (like users) most will be stored in a key/value or relational store.
Version 1.1 will use boltdb as the key/value store.
Future versions will support more HA data stores.
##### Objects
1. Data source
- Version 1.1 will have only one data source.
- InfluxDB
- InfluxDB Enterprise (this means clustering)
- InfluxDB relay possibly.
- Will provide meta data describing the data source (e.g. number of nodes)
1. User
- Version 1.1 will be a one-to-one mapping to influx.
1. Dashboards
- precanned dashboards for telegraf
- Includes location of query resources.
1. Queries
- Used to construct influxql.
1. Sessions
- We could simply use the JWT token as the session information
1. Server Configuration
- Any setting that would normally in TICK stack land be in a file, we'll expose through an updatable API.
- License/Organization info, modules(pre-canned dash, query builder, customer dash, config builder), usage and debug history/info, support contacts
#### Authentication
We want the backend data store (influx oss or influx meta) handle the authentication so that the web server has less responsibility.
We'll use JWT throughout.
### Testing
Talk with Mark and Michael and talk about larger efforts. This will impact the repository layout.
There is a potentially large testing matrix of components.
#### Integration Testing
Because we are pulling together so many TICK stack components we will need strong integration testing.
- Stress testing.
- Benchmark pathological queries
- End to end testing. Telegraf -> Plutonium -> Chronograf = expected graph.
- Would be nice to translate user stories to integration tests.
- If someone finds a bug in the integration we need a test so it will never happen again.
- Upgrade testing.
- Version support.
#### Usability and Experience Testing
1. Owned by design team.
1. We are trying to attract the devops crowd.
- Deployment experience
- Ease of use.
- Speed to accomplish task, e.g. find specific info, change setting.

30
docs/queries.md Normal file
View File

@ -0,0 +1,30 @@
##
Query proxy will be a façade over InfluxDB, InfluxDB Enterprise Cluster, and InfluxDB Relay.
It will provide a uniform interface to `SELECT` a time range of data.
```http
POST /enterprise/v1/sources/{id}/query HTTP/1.1
Accept: application/json
Content-Type: application/json
{
"query": "SELECT * from telegraf",
"format": "dygraph",
"max_points": 1000,
"type": "http"
}
```
Response:
```http
HTTP/1.1 202 OK
{
"link": {
"rel": "self",
"href": "/enterprise/v1/sources/{id}/query/{qid}",
"type": "http"
}
}
```

View File

@ -1,23 +1,24 @@
swagger: '2.0'
info:
title: Influxdata Enterprise Application
description: Monitor some stuff
title: Mr Fusion
description: Fuel for Chronograf
version: "1.1.0"
host: enterprise.influxdata.com
host: Chronograf.influxdata.com
schemes:
- https
basePath: /enterprise/v1
- http
basePath: /chronograf/v1
consumes:
- application/json
produces:
- application/json
paths:
'/':
get:
summary: Lists all the endpoints
description: |
List of the endpoints. This can be used to tell if this is OSS or not.
description: List of the endpoints.
responses:
200:
description: All dem links
description: Returns the links to the top level endpoints.
schema:
$ref: '#/definitions/Links'
default:
@ -27,8 +28,7 @@ paths:
/sources:
get:
summary: Configured data sources
description: |
These data sources store time series data.
description: These data sources store time series data.
responses:
200:
description: An array of data sources
@ -47,7 +47,7 @@ paths:
schema:
$ref: '#/definitions/Source'
responses:
'201':
201:
description: Successfully create data source
headers:
Location:
@ -69,11 +69,10 @@ paths:
description: ID of the data source
required: true
summary: Configured data sources
description: |
These data sources store time series data.
description: These data sources store time series data.
responses:
200:
description: Data source used to supply time series to layouts.
description: Data source used to supply time series to dashboards.
schema:
$ref: '#/definitions/Source'
404:
@ -99,9 +98,9 @@ paths:
$ref: '#/definitions/Source'
required: true
responses:
'204':
204:
description: Data source's configuration was changed
'404':
404:
description: Happens when trying to access a non-existent data source.
schema:
$ref: '#/definitions/Error'
@ -128,20 +127,56 @@ paths:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
/sources/{id}/permissions:
get:
/sources/{id}/proxy:
post:
description: Query the backend time series data source and return the response according to `format`
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
- name: query
in: body
description: Query Parameters
schema:
$ref: '#/definitions/Proxy'
required: true
responses:
200:
description: Result of the query from the backend time series data source.
schema:
$ref: '#/definitions/ProxyResponse'
400:
description: Any query that results in a data source error (syntax error, etc) will cause this response. The error message will be passed back in the body
schema:
$ref: '#/definitions/Error'
404:
description: Data source id does not exist.
schema:
$ref: '#/definitions/Error'
408:
description: Timeout trying to query data source.
schema:
$ref: '#/definitions/Error'
default:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
/sources/{id}/permissions:
get:
summary: Returns the list of possible permissions supported by the backend time series data source.
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
summary: List of possible valid permissions on this data source
responses:
200:
description: An array of permissions
schema:
$ref: '#/definitions/ACL'
$ref: '#/definitions/AllPermissions'
default:
description: Unexpected internal service error
schema:
@ -178,7 +213,7 @@ paths:
schema:
$ref: '#/definitions/User'
responses:
'201':
201:
description: Successfully created new user
headers:
Location:
@ -240,9 +275,9 @@ paths:
$ref: '#/definitions/User'
required: true
responses:
'204':
204:
description: Users's configuration was changed
'404':
404:
description: Happens when trying to access a non-existent user.
schema:
$ref: '#/definitions/Error'
@ -274,6 +309,166 @@ paths:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
/sources/{id}/users/{user_id}/explorations:
get:
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
- name: user_id
in: path
type: string
description: All Data Explorations returned only for this user.
required: true
responses:
200:
description: Data Explorations saved sessions for user are returned.
schema:
$ref: '#/definitions/Explorations'
404:
description: Data source id or user does not exist.
schema:
$ref: '#/definitions/Error'
default:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
post:
summary: Create new named exploration for this user
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
- name: user_id
in: path
type: string
description: ID of user to associate this exploration with.
required: true
- name: exploration
in: body
description: Exploration session to save
schema:
$ref: '#/definitions/Exploration'
responses:
201:
description: Successfully created new Exploration session
headers:
Location:
type: string
format: url
description: Location of the newly created exploration resource.
schema:
$ref: '#/definitions/Exploration'
404:
description: Data source id or user does not exist.
schema:
$ref: '#/definitions/Error'
default:
description: A processing or an unexpected error.
schema:
$ref: '#/definitions/Error'
/sources/{id}/user/{user_id}/explorations/{exploration_id}:
get:
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
- name: user_id
in: path
type: string
description: ID of user to associate this exploration with.
required: true
- name: exploration_id
in: path
type: string
description: ID of the specific exploration.
required: true
summary: Returns the specified data exploration session
description: |
A data exploration session specifies query information.
responses:
200:
description: Information relating to the exploration
schema:
$ref: '#/definitions/Exploration'
404:
description: Data source id, user, or exploration does not exist.
schema:
$ref: '#/definitions/Error'
default:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
patch:
summary: Update exploration configuration
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
- name: user_id
in: path
type: string
description: ID of user
required: true
- name: exploration_id
in: path
type: string
description: ID of the specific exploration.
required: true
- name: exploration
in: body
description: Update the exploration information to this.
required: true
schema:
$ref: "#/definitions/Exploration"
responses:
204:
description: Exploration's configuration was changed
404:
description: Data source id, user, or exploration does not exist.
schema:
$ref: '#/definitions/Error'
default:
description: A processing or an unexpected error.
schema:
$ref: '#/definitions/Error'
delete:
parameters:
- name: id
in: path
type: string
description: ID of the data source
required: true
- name: user_id
in: path
type: string
description: ID of user to associate this exploration with.
required: true
- name: exploration_id
in: path
type: string
description: ID of the specific exploration.
required: true
summary: This specific exporer session will be removed.
responses:
204:
description: Exploration session has been removed
404:
description: Data source id, user, or exploration does not exist.
schema:
$ref: '#/definitions/Error'
default:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
/sources/{id}/roles:
get:
parameters:
@ -306,7 +501,7 @@ paths:
schema:
$ref: '#/definitions/Role'
responses:
'201':
201:
description: Successfully created new role
headers:
Location:
@ -319,7 +514,7 @@ paths:
description: A processing or an unexpected error.
schema:
$ref: '#/definitions/Error'
/sources/{id}/role/{role_id}:
/sources/{id}/roles/{role_id}:
get:
parameters:
- name: id
@ -368,9 +563,9 @@ paths:
$ref: '#/definitions/Role'
required: true
responses:
'204':
204:
description: Role's configuration was changed
'404':
404:
description: Happens when trying to access a non-existent role.
schema:
$ref: '#/definitions/Error'
@ -402,62 +597,60 @@ paths:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
/layouts:
/dashboards:
get:
summary: Configured Layouts
summary: Pre-configured dashboards
description: |
Not sure what we are doing about this...
Dashboards are a collection of `Cells` that visualize time-series data.
responses:
200:
description: An array of layouts
description: An array of dashboards
schema:
$ref: '#/definitions/Layouts'
$ref: '#/definitions/Dashboards'
default:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
post:
summary: Create new layout
summary: Create new Dashboard
parameters:
- name: layout
- name: dashboard
in: body
description: Create new named layout
description: Defines the dashboard and queries of the cells within the dashboard.
schema:
$ref: '#/definitions/Layout'
$ref: '#/definitions/Dashboard'
responses:
'201':
description: Successfully create layout
201:
description: Successfully created new dashboard
headers:
Location:
type: string
format: url
description: Location of the newly created layout
description: Location of the newly created dashboard
schema:
$ref: '#/definitions/Layout'
$ref: '#/definitions/Dashboard'
default:
description: A processing or an unexpected error.
schema:
$ref: '#/definitions/Error'
/layouts/{id}:
/dashboards/{id}:
get:
parameters:
- name: id
in: path
type: string
description: ID of the layout
description: ID of the dashboard
required: true
summary: Unique named layout
summary: Specific pre-configured dashboard containing cells and queries.
description: |
Layouts will hold information about how to layout the page of graphs.
dashboards will hold information about how to layout the page of graphs.
responses:
200:
description: An array of layouts
description: Returns the specified dashboard containing `cells`.
schema:
type: array
items:
$ref: '#/definitions/Layouts'
$ref: '#/definitions/Dashboard'
404:
description: Unknown layout id
description: Unknown dashboard id
schema:
$ref: '#/definitions/Error'
default:
@ -469,39 +662,39 @@ paths:
- name: id
in: path
type: string
description: ID of the layout
description: ID of the dashboard
required: true
summary: This specific layout will be removed from the data store
summary: This specific dashboard will be removed from the data store
responses:
204:
description: An array of layouts
description: An array of dashboards
404:
description: Unknown layout id
description: Unknown dashboard id
schema:
$ref: '#/definitions/Error'
default:
description: Unexpected internal service error
schema:
$ref: '#/definitions/Error'
patch:
summary: Update layout configuration
put:
summary: Replace dashboard configuration.
parameters:
- name: id
in: path
type: string
description: ID of a layout
description: ID of a dashboard
required: true
- name: config
in: body
description: layout configuration update parameters
description: dashboard configuration update parameters
schema:
$ref: '#/definitions/Layout'
$ref: '#/definitions/Dashboard'
required: true
responses:
'204':
description: Layout's configuration was changed
'404':
description: Happens when trying to access a non-existent layout.
204:
description: Dashboard's configuration was changed
404:
description: Happens when trying to access a non-existent dashboard.
schema:
$ref: '#/definitions/Error'
default:
@ -518,6 +711,9 @@ definitions:
$ref: '#/definitions/Source'
Source:
type: object
required:
- type
- name
properties:
id:
type: string
@ -534,36 +730,71 @@ definitions:
- influx-enterprise
link:
$ref: "#/definitions/Link"
Proxy:
type: object
required:
- type
- name
- query
properties:
query:
type: string
format:
type: string
enum:
- raw
default: raw
ProxyResponse:
type: object
properties:
results:
description: results from influx
type: object
Explorations:
type: object
properties:
explorations:
type: array
items:
$ref: "#/definitions/Exploration"
Exploration:
type: object
properties:
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
description: Latest time the exploration was updated.
name:
type: string
description: Exploration name given by user.
data:
type: object
description: Serialization of the exploration query configuration.
link:
$ref: "#/definitions/Link"
Roles:
type: object
properties:
role:
roles:
type: array
items:
$ref: "#/definitions/Role"
Role:
type: object
required:
- permissions
- name
properties:
id:
type: string
name:
type: string
maxLength: 64
permissions:
type: array
items:
$ref: '#/definitions/Permission'
$ref: '#/definitions/Permissions'
users:
$ref: "#/definitions/Users"
link:
$ref: "#/definitions/Link"
users:
$ref: "#/definitions/Links"
required:
- id
- permissions
- name
Users:
type: object
properties:
@ -573,33 +804,30 @@ definitions:
$ref: "#/definitions/User"
User:
type: object
required:
- permissions
- username
properties:
id:
type: string
username:
type: string
maxLength: 64
permissions:
type: array
items:
$ref: '#/definitions/Permission'
$ref: '#/definitions/Permissions'
roles:
$ref: '#/definitions/Roles'
link:
$ref: "#/definitions/Link"
required:
- id
- permissions
Permission:
Permissions:
type: object
properties:
database:
description: permissions are scoped to a specific database
type: string
acls:
$ref: "/definitions/ACL"
ACL:
permissions:
type: array
items:
$ref: "#/definitions/AC"
AC:
$ref: "#/definitions/Permission"
Permission:
type: string
description: Specific access
enum:
@ -614,36 +842,53 @@ definitions:
- WriteData
- Rebalance
- ManageShard
Layouts:
type: object
properties:
layouts:
AllPermissions:
description: All Possible permission strings
type: array
items:
$ref: "#/definitions/Layout"
Layout:
$ref: "#/definitions/Permission"
Dashboards:
type: object
properties:
version:
type: string
data:
type: string
description: Information used to actually layout... I hate this name... not sure this is right.
data_source:
$ref: '#/definitions/Link'
dashboards:
type: array
items:
$ref: "#/definitions/Dashboard"
Dashboard:
type: object
required:
- cells
properties:
cells:
type: array
description: Cells are the individual visualization elements.
items:
$ref: "#/definitions/Cell"
link:
$ref: "#/definitions/Link"
required:
- version
- data
- data_source
Error:
Cell:
type: object
properties:
code:
x:
description: X-coordinate of Cell in the Dashboard
type: integer
format: int32
message:
'y':
description: Y-coordinate of Cell in the Dashboard
type: integer
format: int32
w:
description: Width of Cell in the Dashboard
type: integer
format: int32
h:
description: Height of Cell in the Dashboard
type: integer
format: int32
queries:
description: Time-series data queries for Cell.
type: array
items:
type: string
Links:
type: object
@ -654,6 +899,7 @@ definitions:
$ref: "#/definitions/Link"
Link:
type: object
required: [rel, href]
readOnly: true
description: URI of resource.
properties:
@ -662,4 +908,11 @@ definitions:
href:
type: string
format: url
required: [rel, href]
Error:
type: object
properties:
code:
type: integer
format: int32
message:
type: string