From a6300f25f069bc8f7da431d0d86450a778f4b68d Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Thu, 13 Oct 2016 18:10:54 -0400 Subject: [PATCH 1/5] Wire up /mappings API to LayoutsStore This makes the /mappings endpoint return real data based off of the layouts seen within the LayoutsStore. --- ui/package.json | 1 + ui/src/hosts/apis/index.js | 7 ++ ui/src/hosts/components/LayoutRenderer.js | 69 +++++++++++++++++++ ui/src/hosts/containers/HostPage.js | 84 +++++++++++------------ ui/src/shared/components/AutoRefresh.js | 8 +-- 5 files changed, 122 insertions(+), 47 deletions(-) create mode 100644 ui/src/hosts/components/LayoutRenderer.js diff --git a/ui/package.json b/ui/package.json index d9922b558..e208e5fe7 100644 --- a/ui/package.json +++ b/ui/package.json @@ -96,6 +96,7 @@ "react-addons-update": "^15.1.0", "react-dimensions": "^1.2.0", "react-dom": "^15.0.2", + "react-grid-layout": "^0.13.9", "react-onclickoutside": "^5.2.0", "react-redux": "^4.4.0", "react-router": "^2.4.1", diff --git a/ui/src/hosts/apis/index.js b/ui/src/hosts/apis/index.js index 3efb9d202..60010dc59 100644 --- a/ui/src/hosts/apis/index.js +++ b/ui/src/hosts/apis/index.js @@ -65,3 +65,10 @@ export function getAppsForHosts(proxyLink, hosts, supportedApps) { return newHosts; }); } + +export function fetchLayout() { + return AJAX({ + url: `/chronograf/v1/layouts`, + method: 'GET', + }); +} diff --git a/ui/src/hosts/components/LayoutRenderer.js b/ui/src/hosts/components/LayoutRenderer.js new file mode 100644 index 000000000..3d8ec8029 --- /dev/null +++ b/ui/src/hosts/components/LayoutRenderer.js @@ -0,0 +1,69 @@ +import React, {PropTypes} from 'react'; +import AutoRefresh from 'shared/components/AutoRefresh'; +import LineGraph from 'shared/components/LineGraph'; +import ReactGridLayout from 'react-grid-layout'; +import _ from 'lodash'; + +const RefreshingLineGraph = AutoRefresh(LineGraph); + +export const LayoutRenderer = React.createClass({ + propTypes: { + cells: PropTypes.arrayOf( + PropTypes.shape({ + queries: PropTypes.arrayOf( + PropTypes.shape({ + rp: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + database: PropTypes.string.isRequired, + }).isRequired + ).isRequired, + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired, + w: PropTypes.number.isRequired, + h: PropTypes.number.isRequired, + i: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + }).isRequired + ), + autoRefreshMs: PropTypes.number.isRequired, + host: PropTypes.string.isRequired, + source: PropTypes.string, + }, + + getInitialState() { + return ({ + layout: _.without(this.props.cells, ['queries']), + }); + }, + + generateGraphs() { + return this.props.cells.map((cell) => { + const qs = cell.queries.map((q) => { + _.merge(q, {host: this.props.source, text: q.query, i: "used_percent", name: "Disk Used Percent"}); + q.text += ` where host = '${this.props.host}' and time > now() - 15m`; + return q; + }); + return ( +
+

{cell.name}

+
+ +
+
+ ); + }); + }, + + render() { + return ( + + {this.generateGraphs()} + + ); + }, +}); + +export default LayoutRenderer; diff --git a/ui/src/hosts/containers/HostPage.js b/ui/src/hosts/containers/HostPage.js index 95e072d95..46f7d4bc4 100644 --- a/ui/src/hosts/containers/HostPage.js +++ b/ui/src/hosts/containers/HostPage.js @@ -1,9 +1,8 @@ import React, {PropTypes} from 'react'; // TODO: move this to a higher level package than chronograf? -import AutoRefresh from 'shared/components/AutoRefresh'; -import LineGraph from 'shared/components/LineGraph'; - -const RefreshingLineGraph = AutoRefresh(LineGraph); +import FlashMessages from 'shared/components/FlashMessages'; +import LayoutRenderer from '../components/LayoutRenderer'; +import {fetchLayout} from '../apis'; export const HostPage = React.createClass({ propTypes: { @@ -17,34 +16,43 @@ export const HostPage = React.createClass({ }).isRequired, }, + componentDidMount() { + fetchLayout().then((layout) => { + this.setState({layout}); + }); + }, + render() { const autoRefreshMs = 15000; const source = this.props.source.links.proxy; const hostID = this.props.params.hostID; - const queries = [ + + const cells = [ { - text: `SELECT "usage_user" FROM "telegraf".."cpu" WHERE host = '${this.props.params.hostID}' AND time > now() - 15m`, - name: 'CPU', - }, - { - text: `SELECT "used_percent" FROM "telegraf".."mem" WHERE host = '${this.props.params.hostID}' AND time > now() - 15m`, - name: "Memory", - }, - { - text: `SELECT "load1" FROM "telegraf".."system" WHERE host = '${this.props.params.hostID}' AND time > now() - 15m`, - name: "Load", - }, - { - text: `SELECT "bytes_recv", "bytes_sent" FROM "telegraf".."net" WHERE host = '${this.props.params.hostID}' AND time > now() - 15m`, - name: "Network", - }, - { - text: `SELECT "io_time" FROM "telegraf".."diskio" WHERE host = '${this.props.params.hostID}' AND time > now() - 15m`, - name: "Disk IO", - }, - { - text: `SELECT "used_percent" FROM "telegraf".."disk" WHERE host = '${this.props.params.hostID}' AND time > now() - 15m`, - name: "Disk Usage", + id: "18aed9a7-dc83-406e-a4dc-40d53049541a", + cells: [ + { + queries: [ + { + rp: "autogen", + text: "select usage_user from cpu", + database: "telegraf", + }, + ], + x: 0, + h: 100, + y: 0, + w: 50, + i: "used_percent", + name: "Disk Used Percent", + }, + ], + measurement: "disk", + link: { + rel: "self", + href: "/chronograf/v1/layouts/18aed9a7-dc83-406e-a4dc-40d53049541a", + }, + app: "User Facing Application Name", }, ]; @@ -62,22 +70,12 @@ export const HostPage = React.createClass({
- { - queries.map((query) => { - const q = Object.assign({}, query, {host: source}); - return ( -
-

{q.name}

-
- -
-
- ); - }) - } +
diff --git a/ui/src/shared/components/AutoRefresh.js b/ui/src/shared/components/AutoRefresh.js index 71f3ce4d8..954e42a5a 100644 --- a/ui/src/shared/components/AutoRefresh.js +++ b/ui/src/shared/components/AutoRefresh.js @@ -2,8 +2,8 @@ import React, {PropTypes} from 'react'; import _ from 'lodash'; import {proxy} from 'utils/queryUrlGenerator'; -function _fetchTimeSeries(source, db, query) { - return proxy({source, db, query}); +function _fetchTimeSeries(source, db, rp, query) { + return proxy({source, db, rp, query}); } export default function AutoRefresh(ComposedComponent) { @@ -58,8 +58,8 @@ export default function AutoRefresh(ComposedComponent) { this.setState({isFetching: true}); let count = 0; const newSeries = []; - queries.forEach(({host, database, text}) => { - _fetchTimeSeries(host, database, text).then((resp) => { + queries.forEach(({host, database, rp, text}) => { + _fetchTimeSeries(host, database, rp, text).then((resp) => { newSeries.push({identifier: host, response: resp.data}); count += 1; if (count === queries.length) { From 1f4e813768cef6492298b671a26114e1565890aa Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Wed, 26 Oct 2016 16:29:25 -0400 Subject: [PATCH 2/5] Add "I" and "Name" to cells on backend React-grid-layout uses an "i" parameter in the JSON describing a layout as an identifier. This is used to bind DOM elements' keys to Cells from the API. Also, we need a "Name" to describe what each graph is to a user. Also, react-grid-layout specified widths and heights in terms of units of the grid that it establishes. In order to have this properly configured, the extents of this grid need to be spelled out when creating a ReactGridLayout, hence the addition of "cols" and "rowHeight" props to that component. Finally, react-grid-layout incorporates some of its own styles. To support this, some modifications needed to be made to the webpack config to allow us to pull in includes from node_modules. --- ..._18aed9a7-dc83-406e-a4dc-40d53049541a.json | 47 ++++++++----- chronograf.go | 2 + ui/src/hosts/apis/index.js | 2 +- ui/src/hosts/components/LayoutRenderer.js | 4 +- ui/src/hosts/containers/HostPage.js | 68 +++++++++---------- ui/src/style/chronograf/main.scss | 1 + ui/src/style/external/react-grid-layout.scss | 1 + ui/webpack/devConfig.js | 3 + 8 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 ui/src/style/external/react-grid-layout.scss diff --git a/canned/disk_18aed9a7-dc83-406e-a4dc-40d53049541a.json b/canned/disk_18aed9a7-dc83-406e-a4dc-40d53049541a.json index f82e4d900..7515a386f 100644 --- a/canned/disk_18aed9a7-dc83-406e-a4dc-40d53049541a.json +++ b/canned/disk_18aed9a7-dc83-406e-a4dc-40d53049541a.json @@ -1,16 +1,31 @@ - { - "id": "18aed9a7-dc83-406e-a4dc-40d53049541a", - "measurement": "disk", - "app": "User Facing Application Name", - "cells": [{ - "x": 0, - "y": 0, - "w": 10, - "h": 10, - "queries": [{ - "query": "select used_percent from disk", - "db": "telegraf", - "rp": "autogen" - }] - }] - } +{ + "id": "18aed9a7-dc83-406e-a4dc-40d53049541a", + "measurement": "disk", + "app": "User Facing Application Name", + "cells": [{ + "x": 0, + "y": 0, + "w": 5, + "h": 5, + "i": "used_percent", + "name": "Used Percent", + "queries": [{ + "query": "select used_percent from disk", + "db": "telegraf", + "rp": "autogen" + }] + }, + { + "x": 5, + "y": 1, + "w": 5, + "h": 5, + "i": "cpu_usage", + "name": "CPU Usage", + "queries": [{ + "query": "select 100 - usage_idle from cpu", + "db": "telegraf", + "rp": "autogen" + }] + }] +} diff --git a/chronograf.go b/chronograf.go index dfec8b8fc..3638033df 100644 --- a/chronograf.go +++ b/chronograf.go @@ -174,6 +174,8 @@ type Cell struct { Y int32 `json:"y"` W int32 `json:"w"` H int32 `json:"h"` + I string `json:"i"` + Name string `json:"name"` Queries []Query `json:"queries"` } diff --git a/ui/src/hosts/apis/index.js b/ui/src/hosts/apis/index.js index 60010dc59..172f64d0a 100644 --- a/ui/src/hosts/apis/index.js +++ b/ui/src/hosts/apis/index.js @@ -66,7 +66,7 @@ export function getAppsForHosts(proxyLink, hosts, supportedApps) { }); } -export function fetchLayout() { +export function fetchLayouts() { return AJAX({ url: `/chronograf/v1/layouts`, method: 'GET', diff --git a/ui/src/hosts/components/LayoutRenderer.js b/ui/src/hosts/components/LayoutRenderer.js index 3d8ec8029..fc0ac1afe 100644 --- a/ui/src/hosts/components/LayoutRenderer.js +++ b/ui/src/hosts/components/LayoutRenderer.js @@ -39,7 +39,7 @@ export const LayoutRenderer = React.createClass({ generateGraphs() { return this.props.cells.map((cell) => { const qs = cell.queries.map((q) => { - _.merge(q, {host: this.props.source, text: q.query, i: "used_percent", name: "Disk Used Percent"}); + _.merge(q, {host: this.props.source}); q.text += ` where host = '${this.props.host}' and time > now() - 15m`; return q; }); @@ -59,7 +59,7 @@ export const LayoutRenderer = React.createClass({ render() { return ( - + {this.generateGraphs()} ); diff --git a/ui/src/hosts/containers/HostPage.js b/ui/src/hosts/containers/HostPage.js index 46f7d4bc4..f690b4bdd 100644 --- a/ui/src/hosts/containers/HostPage.js +++ b/ui/src/hosts/containers/HostPage.js @@ -2,7 +2,8 @@ import React, {PropTypes} from 'react'; // TODO: move this to a higher level package than chronograf? import FlashMessages from 'shared/components/FlashMessages'; import LayoutRenderer from '../components/LayoutRenderer'; -import {fetchLayout} from '../apis'; +import {fetchLayouts} from '../apis'; +import _ from 'lodash'; export const HostPage = React.createClass({ propTypes: { @@ -16,9 +17,13 @@ export const HostPage = React.createClass({ }).isRequired, }, + getInitialState() { + return {layouts: []}; + }, + componentDidMount() { - fetchLayout().then((layout) => { - this.setState({layout}); + fetchLayouts().then((ls) => { + this.setState({layouts: ls.data.layouts}); }); }, @@ -27,34 +32,28 @@ export const HostPage = React.createClass({ const source = this.props.source.links.proxy; const hostID = this.props.params.hostID; - const cells = [ - { - id: "18aed9a7-dc83-406e-a4dc-40d53049541a", - cells: [ - { - queries: [ - { - rp: "autogen", - text: "select usage_user from cpu", - database: "telegraf", - }, - ], - x: 0, - h: 100, - y: 0, - w: 50, - i: "used_percent", - name: "Disk Used Percent", - }, - ], - measurement: "disk", - link: { - rel: "self", - href: "/chronograf/v1/layouts/18aed9a7-dc83-406e-a4dc-40d53049541a", - }, - app: "User Facing Application Name", - }, - ]; + const layout = _.head(this.state.layouts); + + let layoutComponent; + if (layout) { + layout.cells.forEach((cell) => { + cell.queries.forEach((q) => { + q.text = q.query; + q.database = q.db; + }); + }); + + layoutComponent = ( + + ); + } else { + layoutComponent =
; + } return (
@@ -70,12 +69,7 @@ export const HostPage = React.createClass({
- + {layoutComponent}
diff --git a/ui/src/style/chronograf/main.scss b/ui/src/style/chronograf/main.scss index 7c2792df8..e2af9b10c 100644 --- a/ui/src/style/chronograf/main.scss +++ b/ui/src/style/chronograf/main.scss @@ -17,3 +17,4 @@ @import '../external/fixed-data-table'; @import '../external/fixed-data-table-base'; @import '../external/fixed-data-table-style'; +@import '../external/react-grid-layout'; diff --git a/ui/src/style/external/react-grid-layout.scss b/ui/src/style/external/react-grid-layout.scss new file mode 100644 index 000000000..1773421f1 --- /dev/null +++ b/ui/src/style/external/react-grid-layout.scss @@ -0,0 +1 @@ +@import '~react-grid-layout/css/styles.css'; diff --git a/ui/webpack/devConfig.js b/ui/webpack/devConfig.js index 5d20f9f9b..278032e3b 100644 --- a/ui/webpack/devConfig.js +++ b/ui/webpack/devConfig.js @@ -60,6 +60,9 @@ module.exports = { }, ], }, + sassLoader: { + includePaths: [path.resolve(__dirname, "node_modules")], + }, eslint: { failOnWarning: false, failOnError: false, From 9622eafff0113e7604e51c034bfa48c8b59dec23 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Thu, 27 Oct 2016 12:10:16 -0400 Subject: [PATCH 3/5] Satisfy build errors Somehow an unused FlashMessages snuck in during the rebase. Also there were places where Mappings was expecting a *string, but we were passing a string. I believe this is because the autogenerated code creates *string, and I modified it to use strings at one point. Everywhere should use *string now. --- ui/src/hosts/containers/HostPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/src/hosts/containers/HostPage.js b/ui/src/hosts/containers/HostPage.js index f690b4bdd..2b4dd753c 100644 --- a/ui/src/hosts/containers/HostPage.js +++ b/ui/src/hosts/containers/HostPage.js @@ -1,6 +1,5 @@ import React, {PropTypes} from 'react'; // TODO: move this to a higher level package than chronograf? -import FlashMessages from 'shared/components/FlashMessages'; import LayoutRenderer from '../components/LayoutRenderer'; import {fetchLayouts} from '../apis'; import _ from 'lodash'; From faf2ac7685321a44d57e2b4b81aaf49611c86ba6 Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Fri, 28 Oct 2016 16:43:06 -0400 Subject: [PATCH 4/5] Add I and Name to protobufs I and Name were added to support react-grid-layout. They were added to the chronograf types, but not to the protobuf definitions, so the only layouts that could make use of them were the canned variety. This allows layouts' I and Name to be persisted as well. --- bolt/internal/internal.go | 4 ++ bolt/internal/internal.pb.go | 114 ++++++++++++++++++----------------- bolt/internal/internal.proto | 2 + 3 files changed, 64 insertions(+), 56 deletions(-) diff --git a/bolt/internal/internal.go b/bolt/internal/internal.go index f4bd07d33..c48e37392 100644 --- a/bolt/internal/internal.go +++ b/bolt/internal/internal.go @@ -115,6 +115,8 @@ func MarshalLayout(l chronograf.Layout) ([]byte, error) { Y: c.Y, W: c.W, H: c.H, + I: c.I, + Name: c.Name, Queries: queries, } } @@ -151,6 +153,8 @@ func UnmarshalLayout(data []byte, l *chronograf.Layout) error { Y: c.Y, W: c.W, H: c.H, + I: c.I, + Name: c.Name, Queries: queries, } } diff --git a/bolt/internal/internal.pb.go b/bolt/internal/internal.pb.go index af8673da4..a71075cc4 100644 --- a/bolt/internal/internal.pb.go +++ b/bolt/internal/internal.pb.go @@ -34,13 +34,13 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type Exploration struct { - ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"` - UserID int64 `protobuf:"varint,3,opt,name=UserID,json=userID,proto3" json:"UserID,omitempty"` - Data string `protobuf:"bytes,4,opt,name=Data,json=data,proto3" json:"Data,omitempty"` - CreatedAt int64 `protobuf:"varint,5,opt,name=CreatedAt,json=createdAt,proto3" json:"CreatedAt,omitempty"` - UpdatedAt int64 `protobuf:"varint,6,opt,name=UpdatedAt,json=updatedAt,proto3" json:"UpdatedAt,omitempty"` - Default bool `protobuf:"varint,7,opt,name=Default,json=default,proto3" json:"Default,omitempty"` + ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + UserID int64 `protobuf:"varint,3,opt,name=UserID,proto3" json:"UserID,omitempty"` + Data string `protobuf:"bytes,4,opt,name=Data,proto3" json:"Data,omitempty"` + CreatedAt int64 `protobuf:"varint,5,opt,name=CreatedAt,proto3" json:"CreatedAt,omitempty"` + UpdatedAt int64 `protobuf:"varint,6,opt,name=UpdatedAt,proto3" json:"UpdatedAt,omitempty"` + Default bool `protobuf:"varint,7,opt,name=Default,proto3" json:"Default,omitempty"` } func (m *Exploration) Reset() { *m = Exploration{} } @@ -49,13 +49,13 @@ func (*Exploration) ProtoMessage() {} func (*Exploration) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{0} } type Source struct { - ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"` - Type string `protobuf:"bytes,3,opt,name=Type,json=type,proto3" json:"Type,omitempty"` - Username string `protobuf:"bytes,4,opt,name=Username,json=username,proto3" json:"Username,omitempty"` - Password string `protobuf:"bytes,5,opt,name=Password,json=password,proto3" json:"Password,omitempty"` - URL string `protobuf:"bytes,6,opt,name=URL,json=uRL,proto3" json:"URL,omitempty"` - Default bool `protobuf:"varint,7,opt,name=Default,json=default,proto3" json:"Default,omitempty"` + ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + Type string `protobuf:"bytes,3,opt,name=Type,proto3" json:"Type,omitempty"` + Username string `protobuf:"bytes,4,opt,name=Username,proto3" json:"Username,omitempty"` + Password string `protobuf:"bytes,5,opt,name=Password,proto3" json:"Password,omitempty"` + URL string `protobuf:"bytes,6,opt,name=URL,proto3" json:"URL,omitempty"` + Default bool `protobuf:"varint,7,opt,name=Default,proto3" json:"Default,omitempty"` } func (m *Source) Reset() { *m = Source{} } @@ -64,12 +64,12 @@ func (*Source) ProtoMessage() {} func (*Source) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{1} } type Server struct { - ID int64 `protobuf:"varint,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,json=name,proto3" json:"Name,omitempty"` - Username string `protobuf:"bytes,3,opt,name=Username,json=username,proto3" json:"Username,omitempty"` - Password string `protobuf:"bytes,4,opt,name=Password,json=password,proto3" json:"Password,omitempty"` - URL string `protobuf:"bytes,5,opt,name=URL,json=uRL,proto3" json:"URL,omitempty"` - SrcID int64 `protobuf:"varint,6,opt,name=SrcID,json=srcID,proto3" json:"SrcID,omitempty"` + ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + Username string `protobuf:"bytes,3,opt,name=Username,proto3" json:"Username,omitempty"` + Password string `protobuf:"bytes,4,opt,name=Password,proto3" json:"Password,omitempty"` + URL string `protobuf:"bytes,5,opt,name=URL,proto3" json:"URL,omitempty"` + SrcID int64 `protobuf:"varint,6,opt,name=SrcID,proto3" json:"SrcID,omitempty"` } func (m *Server) Reset() { *m = Server{} } @@ -78,10 +78,10 @@ func (*Server) ProtoMessage() {} func (*Server) Descriptor() ([]byte, []int) { return fileDescriptorInternal, []int{2} } type Layout struct { - ID string `protobuf:"bytes,1,opt,name=ID,json=iD,proto3" json:"ID,omitempty"` - Application string `protobuf:"bytes,2,opt,name=Application,json=application,proto3" json:"Application,omitempty"` - Measurement string `protobuf:"bytes,3,opt,name=Measurement,json=measurement,proto3" json:"Measurement,omitempty"` - Cells []*Cell `protobuf:"bytes,4,rep,name=Cells,json=cells" json:"Cells,omitempty"` + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + Application string `protobuf:"bytes,2,opt,name=Application,proto3" json:"Application,omitempty"` + Measurement string `protobuf:"bytes,3,opt,name=Measurement,proto3" json:"Measurement,omitempty"` + Cells []*Cell `protobuf:"bytes,4,rep,name=Cells" json:"Cells,omitempty"` } func (m *Layout) Reset() { *m = Layout{} } @@ -102,6 +102,8 @@ type Cell struct { W int32 `protobuf:"varint,3,opt,name=w,proto3" json:"w,omitempty"` H int32 `protobuf:"varint,4,opt,name=h,proto3" json:"h,omitempty"` Queries []*Query `protobuf:"bytes,5,rep,name=queries" json:"queries,omitempty"` + I string `protobuf:"bytes,6,opt,name=i,proto3" json:"i,omitempty"` + Name string `protobuf:"bytes,7,opt,name=name,proto3" json:"name,omitempty"` } func (m *Cell) Reset() { *m = Cell{} } @@ -117,9 +119,9 @@ func (m *Cell) GetQueries() []*Query { } type Query struct { - Command string `protobuf:"bytes,1,opt,name=Command,json=command,proto3" json:"Command,omitempty"` - DB string `protobuf:"bytes,2,opt,name=DB,json=dB,proto3" json:"DB,omitempty"` - RP string `protobuf:"bytes,3,opt,name=RP,json=rP,proto3" json:"RP,omitempty"` + Command string `protobuf:"bytes,1,opt,name=Command,proto3" json:"Command,omitempty"` + DB string `protobuf:"bytes,2,opt,name=DB,proto3" json:"DB,omitempty"` + RP string `protobuf:"bytes,3,opt,name=RP,proto3" json:"RP,omitempty"` } func (m *Query) Reset() { *m = Query{} } @@ -139,33 +141,33 @@ func init() { func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) } var fileDescriptorInternal = []byte{ - // 444 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x93, 0xcb, 0x8e, 0xd3, 0x30, - 0x14, 0x86, 0xe5, 0x24, 0xce, 0xe5, 0x04, 0x15, 0x64, 0x21, 0x14, 0x21, 0x16, 0x51, 0xc4, 0xa2, - 0x6c, 0x66, 0x01, 0x4f, 0xd0, 0x69, 0x58, 0x54, 0x2a, 0xa8, 0x78, 0xe8, 0x03, 0x98, 0xe4, 0xa0, - 0x89, 0x94, 0x1b, 0x8e, 0x4d, 0x9b, 0x2d, 0x6b, 0x1e, 0x83, 0x37, 0xe0, 0x05, 0x91, 0x5d, 0x97, - 0xce, 0x62, 0x34, 0xea, 0xf2, 0xfb, 0xff, 0x23, 0x9d, 0xef, 0xa4, 0x2e, 0x2c, 0x9a, 0x5e, 0xa1, - 0xec, 0x45, 0x7b, 0x33, 0xca, 0x41, 0x0d, 0x2c, 0x3e, 0x73, 0xf1, 0x97, 0x40, 0xfa, 0xf1, 0x38, - 0xb6, 0x83, 0x14, 0xaa, 0x19, 0x7a, 0xb6, 0x00, 0x6f, 0x53, 0x66, 0x24, 0x27, 0x4b, 0x9f, 0x7b, - 0x4d, 0xc9, 0x18, 0x04, 0x9f, 0x45, 0x87, 0x99, 0x97, 0x93, 0x65, 0xc2, 0x83, 0x5e, 0x74, 0xc8, - 0x5e, 0x41, 0xb8, 0x9f, 0x50, 0x6e, 0xca, 0xcc, 0xb7, 0x73, 0xa1, 0xb6, 0x64, 0x66, 0x4b, 0xa1, - 0x44, 0x16, 0x9c, 0x66, 0x6b, 0xa1, 0x04, 0x7b, 0x03, 0xc9, 0x5a, 0xa2, 0x50, 0x58, 0xaf, 0x54, - 0x46, 0xed, 0x78, 0x52, 0x9d, 0x03, 0xd3, 0xee, 0xc7, 0xda, 0xb5, 0xe1, 0xa9, 0xd5, 0xe7, 0x80, - 0x65, 0x10, 0x95, 0xf8, 0x5d, 0xe8, 0x56, 0x65, 0x51, 0x4e, 0x96, 0x31, 0x8f, 0xea, 0x13, 0x16, - 0x7f, 0x08, 0x84, 0x77, 0x83, 0x96, 0x15, 0x5e, 0x25, 0xcc, 0x20, 0xf8, 0x3a, 0x8f, 0x68, 0x75, - 0x13, 0x1e, 0xa8, 0x79, 0x44, 0xf6, 0x1a, 0x62, 0x73, 0x84, 0xe9, 0x9d, 0x70, 0xac, 0x1d, 0x9b, - 0x6e, 0x27, 0xa6, 0xe9, 0x30, 0xc8, 0xda, 0x3a, 0x27, 0x3c, 0x1e, 0x1d, 0xb3, 0x17, 0xe0, 0xef, - 0xf9, 0xd6, 0xca, 0x26, 0xdc, 0xd7, 0x7c, 0xfb, 0x84, 0xe6, 0x6f, 0xa3, 0x89, 0xf2, 0x27, 0xca, - 0xab, 0x34, 0x1f, 0x2a, 0xf9, 0x4f, 0x28, 0x05, 0x8f, 0x2b, 0xd1, 0x8b, 0xd2, 0x4b, 0xa0, 0x77, - 0xb2, 0xda, 0x94, 0xee, 0x9b, 0xd2, 0xc9, 0x40, 0xf1, 0x8b, 0x40, 0xb8, 0x15, 0xf3, 0xa0, 0xd5, - 0x03, 0x9d, 0xc4, 0xea, 0xe4, 0x90, 0xae, 0xc6, 0xb1, 0x6d, 0x2a, 0xfb, 0x0a, 0x9c, 0x55, 0x2a, - 0x2e, 0x91, 0x99, 0xf8, 0x84, 0x62, 0xd2, 0x12, 0x3b, 0xec, 0x95, 0xf3, 0x4b, 0xbb, 0x4b, 0xc4, - 0xde, 0x02, 0x5d, 0x63, 0xdb, 0x4e, 0x59, 0x90, 0xfb, 0xcb, 0xf4, 0xfd, 0xe2, 0xe6, 0xff, 0xa3, - 0x33, 0x31, 0xa7, 0x95, 0x29, 0x8b, 0x06, 0x02, 0x83, 0xec, 0x19, 0x90, 0xa3, 0x15, 0xa0, 0x9c, - 0x1c, 0x0d, 0xcd, 0x76, 0x2b, 0xe5, 0x64, 0x36, 0x74, 0xb0, 0x1b, 0x28, 0x27, 0x07, 0x43, 0xf7, - 0xf6, 0x66, 0xca, 0xc9, 0x3d, 0x7b, 0x07, 0xd1, 0x0f, 0x8d, 0xb2, 0xc1, 0x29, 0xa3, 0x76, 0xcf, - 0xf3, 0xcb, 0x9e, 0x2f, 0x1a, 0xe5, 0xcc, 0xcf, 0x7d, 0xb1, 0x02, 0x6a, 0x13, 0xf3, 0x0b, 0xad, - 0x87, 0xae, 0x13, 0x7d, 0xed, 0x4e, 0x8e, 0xaa, 0x13, 0x9a, 0xef, 0x50, 0xde, 0xba, 0x73, 0xbd, - 0xfa, 0xd6, 0x30, 0xdf, 0xb9, 0xe3, 0x3c, 0xb9, 0xfb, 0x16, 0xda, 0xff, 0xcb, 0x87, 0x7f, 0x01, - 0x00, 0x00, 0xff, 0xff, 0x0d, 0xab, 0x03, 0x3b, 0x41, 0x03, 0x00, 0x00, + // 442 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x93, 0xcf, 0x8e, 0xd3, 0x30, + 0x10, 0xc6, 0xe5, 0x24, 0x4e, 0x9b, 0x29, 0x2a, 0xc8, 0x42, 0xc8, 0x42, 0x1c, 0xa2, 0x88, 0x43, + 0xb9, 0xec, 0x01, 0x9e, 0xa0, 0xdb, 0x70, 0xa8, 0xb4, 0xa0, 0xe2, 0xa5, 0x0f, 0x60, 0x5a, 0xa3, + 0x8d, 0x94, 0x26, 0xc1, 0x71, 0x68, 0x73, 0xe5, 0x0a, 0x8f, 0xc1, 0x1b, 0xf0, 0x82, 0x68, 0x26, + 0xee, 0x9f, 0xc3, 0x6a, 0xd5, 0xdb, 0x7c, 0x33, 0x5f, 0x34, 0x3f, 0x7f, 0x76, 0x60, 0x5a, 0x54, + 0xce, 0xd8, 0x4a, 0x97, 0x37, 0x8d, 0xad, 0x5d, 0x2d, 0xc6, 0x47, 0x9d, 0xfd, 0x63, 0x30, 0xf9, + 0x78, 0x68, 0xca, 0xda, 0x6a, 0x57, 0xd4, 0x95, 0x98, 0x42, 0xb0, 0xcc, 0x25, 0x4b, 0xd9, 0x2c, + 0x54, 0xc1, 0x32, 0x17, 0x02, 0xa2, 0xcf, 0x7a, 0x67, 0x64, 0x90, 0xb2, 0x59, 0xa2, 0xa8, 0x16, + 0xaf, 0x20, 0x5e, 0xb7, 0xc6, 0x2e, 0x73, 0x19, 0x92, 0xcf, 0x2b, 0xf4, 0xe6, 0xda, 0x69, 0x19, + 0x0d, 0x5e, 0xac, 0xc5, 0x1b, 0x48, 0x16, 0xd6, 0x68, 0x67, 0xb6, 0x73, 0x27, 0x39, 0xd9, 0xcf, + 0x0d, 0x9c, 0xae, 0x9b, 0xad, 0x9f, 0xc6, 0xc3, 0xf4, 0xd4, 0x10, 0x12, 0x46, 0xb9, 0xf9, 0xae, + 0xbb, 0xd2, 0xc9, 0x51, 0xca, 0x66, 0x63, 0x75, 0x94, 0xd9, 0x5f, 0x06, 0xf1, 0x7d, 0xdd, 0xd9, + 0x8d, 0xb9, 0x0a, 0x58, 0x40, 0xf4, 0xb5, 0x6f, 0x0c, 0xe1, 0x26, 0x8a, 0x6a, 0xf1, 0x1a, 0xc6, + 0x88, 0x5d, 0xa1, 0x77, 0x00, 0x3e, 0x69, 0x9c, 0xad, 0x74, 0xdb, 0xee, 0x6b, 0xbb, 0x25, 0xe6, + 0x44, 0x9d, 0xb4, 0x78, 0x01, 0xe1, 0x5a, 0xdd, 0x11, 0x6c, 0xa2, 0xb0, 0x7c, 0x02, 0xf3, 0x0f, + 0x62, 0x1a, 0xfb, 0xd3, 0xd8, 0xab, 0x30, 0x2f, 0x91, 0xc2, 0x27, 0x90, 0xa2, 0xc7, 0x91, 0xf8, + 0x19, 0xe9, 0x25, 0xf0, 0x7b, 0xbb, 0x59, 0xe6, 0x3e, 0xd3, 0x41, 0x64, 0xbf, 0x18, 0xc4, 0x77, + 0xba, 0xaf, 0x3b, 0x77, 0x81, 0x93, 0x10, 0x4e, 0x0a, 0x93, 0x79, 0xd3, 0x94, 0xc5, 0x86, 0x5e, + 0x81, 0xa7, 0xba, 0x6c, 0xa1, 0xe3, 0x93, 0xd1, 0x6d, 0x67, 0xcd, 0xce, 0x54, 0xce, 0xf3, 0x5d, + 0xb6, 0xc4, 0x5b, 0xe0, 0x0b, 0x53, 0x96, 0xad, 0x8c, 0xd2, 0x70, 0x36, 0x79, 0x3f, 0xbd, 0x39, + 0x3d, 0x3a, 0x6c, 0xab, 0x61, 0x98, 0xfd, 0x66, 0x10, 0x61, 0x25, 0x9e, 0x01, 0x3b, 0x10, 0x01, + 0x57, 0xec, 0x80, 0xaa, 0xa7, 0xb5, 0x5c, 0xb1, 0x1e, 0xd5, 0x9e, 0x56, 0x70, 0xc5, 0xf6, 0xa8, + 0x1e, 0xe8, 0xd0, 0x5c, 0xb1, 0x07, 0xf1, 0x0e, 0x46, 0x3f, 0x3a, 0x63, 0x0b, 0xd3, 0x4a, 0x4e, + 0x8b, 0x9e, 0x9f, 0x17, 0x7d, 0xe9, 0x8c, 0xed, 0xd5, 0x71, 0x8e, 0x1f, 0x16, 0xfe, 0xa6, 0x58, + 0x81, 0x91, 0x53, 0xb4, 0xa3, 0x21, 0x72, 0xac, 0xb3, 0x39, 0x70, 0xfa, 0x06, 0x2f, 0x71, 0x51, + 0xef, 0x76, 0xba, 0xda, 0xfa, 0x54, 0x8e, 0x12, 0xa3, 0xca, 0x6f, 0x7d, 0x22, 0x41, 0x7e, 0x8b, + 0x5a, 0xad, 0xfc, 0xf9, 0x03, 0xb5, 0xfa, 0x16, 0xd3, 0x2f, 0xf5, 0xe1, 0x7f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x85, 0xa7, 0xa7, 0xb1, 0x64, 0x03, 0x00, 0x00, } diff --git a/bolt/internal/internal.proto b/bolt/internal/internal.proto index 0005785b7..b482fe86c 100644 --- a/bolt/internal/internal.proto +++ b/bolt/internal/internal.proto @@ -43,6 +43,8 @@ message Cell { int32 w = 3; // Width of Cell in the Layout int32 h = 4; // Height of Cell in the Layout repeated Query queries = 5; // Time-series data queries for Cell. + string i = 6; // Unique identifier for the cell + string name = 7; // User-facing name for this cell } message Query { From 88f7815b65654ab648e6b8c41533c4b9c1bbab7e Mon Sep 17 00:00:00 2001 From: Tim Raymond Date: Fri, 28 Oct 2016 19:08:05 -0400 Subject: [PATCH 5/5] Remove erroneous ,string struct tag The JSON encoder was very upset with the ,string struct tag option. It spat out the error: json: invalid use of ,string struct tag, trying to unmarshal "18aed9a7-dc83-406e-a4dc-40d53049541a" into string The documentation appears to be incomplete on this struct tag option, and removing it fixes this error. --- chronograf.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chronograf.go b/chronograf.go index 3638033df..563fb6d2f 100644 --- a/chronograf.go +++ b/chronograf.go @@ -181,7 +181,7 @@ type Cell struct { // Layout is a collection of Cells for visualization type Layout struct { - ID string `json:"id,string"` + ID string `json:"id"` Application string `json:"app"` Measurement string `json:"measurement"` Cells []Cell `json:"cells"`