From c1b9f703b0f35d66a48d3c6f47214c359ee8e82c Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 06:43:59 +0200 Subject: [PATCH 1/9] fix(ui): provide better error message --- ui/src/data_explorer/actions/view/write.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/src/data_explorer/actions/view/write.ts b/ui/src/data_explorer/actions/view/write.ts index dffafe8dc..eb2010663 100644 --- a/ui/src/data_explorer/actions/view/write.ts +++ b/ui/src/data_explorer/actions/view/write.ts @@ -18,7 +18,11 @@ export const writeLineProtocolAsync = ( await writeLineProtocolAJAX(source, db, data, precision) dispatch(notify(notifyDataWritten())) } catch (response) { - dispatch(notify(notifyDataWriteFailed(response.data.error))) + dispatch( + notify( + notifyDataWriteFailed(response.data?.error || response.data?.message) + ) + ) throw response } } From 5f66f6fb693193fcaf8ee7a46885896d7f57761d Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 06:45:27 +0200 Subject: [PATCH 2/9] feat(ui): allow to specify API version for InfluxDB write --- ui/src/data_explorer/actions/view/write.ts | 5 +++-- ui/src/data_explorer/apis/index.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ui/src/data_explorer/actions/view/write.ts b/ui/src/data_explorer/actions/view/write.ts index eb2010663..f2113e4a8 100644 --- a/ui/src/data_explorer/actions/view/write.ts +++ b/ui/src/data_explorer/actions/view/write.ts @@ -12,10 +12,11 @@ export const writeLineProtocolAsync = ( source: Source, db: string, data: string, - precision?: string + precision?: string, + v2?: boolean ) => async (dispatch): Promise => { try { - await writeLineProtocolAJAX(source, db, data, precision) + await writeLineProtocolAJAX(source, db, data, precision, v2) dispatch(notify(notifyDataWritten())) } catch (response) { dispatch( diff --git a/ui/src/data_explorer/apis/index.ts b/ui/src/data_explorer/apis/index.ts index 2819cde9c..2c657444f 100644 --- a/ui/src/data_explorer/apis/index.ts +++ b/ui/src/data_explorer/apis/index.ts @@ -5,10 +5,11 @@ export const writeLineProtocol = async ( source: Source, db: string, data: string, - precision?: string + precision?: string, + v2?: boolean ): Promise => { const url = `${source.links.write}?db=${db}&precision=${ precision ? precision : 'ns' - }` + }${v2 ? '&v=2' : ''}` await AJAX({url, method: 'POST', data}) } From b89cd9d21dfc23b09c1f8b3dbeae54085279c6fd Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 06:47:29 +0200 Subject: [PATCH 3/9] feat(ui): show databases or buckets depending on props --- ui/src/shared/components/DatabaseDropdown.tsx | 77 +++++++++++++------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/ui/src/shared/components/DatabaseDropdown.tsx b/ui/src/shared/components/DatabaseDropdown.tsx index 931b2acd0..6acd9513a 100644 --- a/ui/src/shared/components/DatabaseDropdown.tsx +++ b/ui/src/shared/components/DatabaseDropdown.tsx @@ -5,6 +5,7 @@ import {showDatabases} from 'src/shared/apis/metaQuery' import parsers from 'src/shared/parsing' import {Source} from 'src/types/sources' import {ErrorHandling} from 'src/shared/decorators/errors' +import {getBuckets} from 'src/flux/components/DatabaseList' const {databases: showDatabasesParser} = parsers interface Database { @@ -17,10 +18,12 @@ interface Props { onStartEdit?: () => void onErrorThrown: (error: string) => void source: Source + // true loads buckets in place of databases + useBuckets?: boolean } interface State { - databases: Database[] + databases: string[] } @ErrorHandling @@ -58,30 +61,58 @@ class DatabaseDropdown extends Component { } private getDatabasesAsync = async (): Promise => { - const {source, database, onSelectDatabase, onErrorThrown} = this.props - const proxy = source.links.proxy - try { - const {data} = await showDatabases(proxy) - const {databases, errors} = showDatabasesParser(data) - if (errors.length > 0) { - throw errors[0] // only one error can come back from this, but it's returned as an array + const { + source, + database, + onSelectDatabase, + onErrorThrown, + useBuckets, + } = this.props + let databases: string[] + if (useBuckets) { + try { + databases = await getBuckets(source) + databases.sort((a, b) => { + // databases starting with '_' are the last + if (b.startsWith('_')) { + if (a.startsWith('_')) { + return a.localeCompare(b) + } + return -1 + } + return a.localeCompare(b) + }) + } catch (e) { + console.error(e) + onErrorThrown(e) + return + } + } else { + try { + const proxy = source.links.proxy + const {data} = await showDatabases(proxy) + const parserResult = showDatabasesParser(data) + if (parserResult.errors.length > 0) { + throw parserResult.errors[0] // only one error can come back from this, but it's returned as an array + } + databases = parserResult.databases + } catch (error) { + console.error(error) + onErrorThrown(error) + return } - - const nonSystemDatabases = databases.filter(name => name !== '_internal') - - this.setState({ - databases: nonSystemDatabases, - }) - const selectedDatabaseText = nonSystemDatabases.includes(database) - ? database - : nonSystemDatabases[0] || 'No databases' - onSelectDatabase({ - text: selectedDatabaseText, - }) - } catch (error) { - console.error(error) - onErrorThrown(error) } + const nonSystemDatabases = databases.filter(name => name !== '_internal') + + this.setState({ + databases: nonSystemDatabases, + }) + const selectedDatabaseText = nonSystemDatabases.includes(database) + ? database + : nonSystemDatabases[0] || 'No databases' + onSelectDatabase({ + text: selectedDatabaseText, + }) } } From de1cb4c4fbf0c2c8032fd1a8215857c41659b495 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 06:49:35 +0200 Subject: [PATCH 4/9] feat(ui): switch write to v2 API when Flux query is used --- .../data_explorer/components/WriteDataForm.tsx | 17 +++++++++++++---- .../components/WriteDataHeader.tsx | 3 +++ .../data_explorer/containers/DataExplorer.tsx | 3 ++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ui/src/data_explorer/components/WriteDataForm.tsx b/ui/src/data_explorer/components/WriteDataForm.tsx index 322452840..cb816fed5 100644 --- a/ui/src/data_explorer/components/WriteDataForm.tsx +++ b/ui/src/data_explorer/components/WriteDataForm.tsx @@ -22,11 +22,13 @@ interface Props { selectedDatabase: string onClose: () => void errorThrown: () => void + useV2: boolean writeLineProtocol: ( source: Source, database: string, content: string, - precision?: string + precision?: string, + useV2?: boolean ) => void } @@ -62,7 +64,7 @@ class WriteDataForm extends PureComponent { } public render() { - const {onClose, errorThrown, source} = this.props + const {onClose, errorThrown, source, useV2} = this.props const {dragClass} = this.state return ( @@ -81,6 +83,7 @@ class WriteDataForm extends PureComponent { onClose={onClose} errorThrown={errorThrown} onToggleMode={this.handleToggleMode} + useBuckets={useV2} handlePrecisionChange={this.handlePrecisionChange} handleSelectDatabase={this.handleSelectDatabase} /> @@ -119,7 +122,7 @@ class WriteDataForm extends PureComponent { } private handleSubmit = async () => { - const {onClose, source, writeLineProtocol} = this.props + const {onClose, source, writeLineProtocol, useV2} = this.props const { inputContent, uploadContent, @@ -135,7 +138,13 @@ class WriteDataForm extends PureComponent { this.setState({isUploading: true}) try { - await writeLineProtocol(source, selectedDatabase, content, precision) + await writeLineProtocol( + source, + selectedDatabase, + content, + precision, + useV2 + ) this.setState({isUploading: false}) onClose() window.location.reload() diff --git a/ui/src/data_explorer/components/WriteDataHeader.tsx b/ui/src/data_explorer/components/WriteDataHeader.tsx index bc9293344..89374a886 100644 --- a/ui/src/data_explorer/components/WriteDataHeader.tsx +++ b/ui/src/data_explorer/components/WriteDataHeader.tsx @@ -15,6 +15,7 @@ interface Props { onClose: () => void mode: string source: Source + useBuckets: boolean } class WriteDataHeader extends PureComponent { @@ -26,6 +27,7 @@ class WriteDataHeader extends PureComponent { onClose, source, precision, + useBuckets, } = this.props return ( @@ -36,6 +38,7 @@ class WriteDataHeader extends PureComponent { source={source} onSelectDatabase={handleSelectDatabase} database={selectedDatabase} + useBuckets={useBuckets} onErrorThrown={errorThrown} /> {this.modeSelector} diff --git a/ui/src/data_explorer/containers/DataExplorer.tsx b/ui/src/data_explorer/containers/DataExplorer.tsx index 103b5242d..c606d36f8 100644 --- a/ui/src/data_explorer/containers/DataExplorer.tsx +++ b/ui/src/data_explorer/containers/DataExplorer.tsx @@ -297,7 +297,7 @@ export class DataExplorer extends PureComponent { } private get writeDataForm(): JSX.Element { - const {source, errorThrownAction, writeLineProtocol} = this.props + const {source, errorThrownAction, writeLineProtocol, queryType} = this.props const {isWriteFormVisible} = this.state return ( @@ -308,6 +308,7 @@ export class DataExplorer extends PureComponent { selectedDatabase={this.selectedDatabase} onClose={this.handleCloseWriteData} writeLineProtocol={writeLineProtocol} + useV2={queryType === 'flux'} /> ) From afa462196411510d1e87126a10522bf601f5cc59 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 07:13:37 +0200 Subject: [PATCH 5/9] chore: comment out unused code --- server/mux.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/server/mux.go b/server/mux.go index 9f12eadb6..8973010d6 100644 --- a/server/mux.go +++ b/server/mux.go @@ -495,15 +495,15 @@ func paramID(key string, r *http.Request) (int, error) { return id, nil } -func paramInt64(key string, r *http.Request) (int64, error) { - ctx := r.Context() - param := httprouter.GetParamFromContext(ctx, key) - v, err := strconv.ParseInt(param, 10, 64) - if err != nil { - return -1, fmt.Errorf("Error converting parameter %s", param) - } - return v, nil -} +// func paramInt64(key string, r *http.Request) (int64, error) { +// ctx := r.Context() +// param := httprouter.GetParamFromContext(ctx, key) +// v, err := strconv.ParseInt(param, 10, 64) +// if err != nil { +// return -1, fmt.Errorf("Error converting parameter %s", param) +// } +// return v, nil +// } func paramStr(key string, r *http.Request) (string, error) { ctx := r.Context() From a0a265120ceba625fb64a57f971e9b66907d100f Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 07:25:31 +0200 Subject: [PATCH 6/9] chore: improve log message --- ui/src/data_explorer/components/WriteDataForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/data_explorer/components/WriteDataForm.tsx b/ui/src/data_explorer/components/WriteDataForm.tsx index cb816fed5..539522115 100644 --- a/ui/src/data_explorer/components/WriteDataForm.tsx +++ b/ui/src/data_explorer/components/WriteDataForm.tsx @@ -150,7 +150,7 @@ class WriteDataForm extends PureComponent { window.location.reload() } catch (error) { this.setState({isUploading: false}) - console.error(error.data.error) + console.error(error.data) } } From 50d69494f36c8b3fffdf81973491c65d2cbb06c1 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 07:42:19 +0200 Subject: [PATCH 7/9] feat(ui): exclude _internal bucket from write --- ui/src/shared/components/DatabaseDropdown.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/shared/components/DatabaseDropdown.tsx b/ui/src/shared/components/DatabaseDropdown.tsx index 6acd9513a..cc205e6b7 100644 --- a/ui/src/shared/components/DatabaseDropdown.tsx +++ b/ui/src/shared/components/DatabaseDropdown.tsx @@ -102,7 +102,9 @@ class DatabaseDropdown extends Component { return } } - const nonSystemDatabases = databases.filter(name => name !== '_internal') + const nonSystemDatabases = databases.filter( + name => !name.startsWith('_internal') + ) this.setState({ databases: nonSystemDatabases, From 8ea76c76bbfaa5a05a0db901459e376273a93d7d Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Mon, 3 May 2021 08:40:01 +0200 Subject: [PATCH 8/9] feat(server): implement v2 write proxy --- server/influx.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/server/influx.go b/server/influx.go index a1507a140..090458640 100644 --- a/server/influx.go +++ b/server/influx.go @@ -120,8 +120,19 @@ func (s *Service) Write(w http.ResponseWriter, r *http.Request) { Error(w, http.StatusUnprocessableEntity, msg, s.Logger) return } - u.Path = "/write" - u.RawQuery = r.URL.RawQuery + query := r.URL.Query() + version := query.Get("v") + query.Del("v") + if strings.HasPrefix(version, "2") { + u.Path = "/api/v2/write" + // v2 organization name is stored in username (org does not matter against v1) + query.Set("org", src.Username) + query.Set("bucket", query.Get("db")) + query.Del("db") + } else { + u.Path = "/write" + } + u.RawQuery = query.Encode() director := func(req *http.Request) { // Set the Host header of the original source URL From 78e4e13b43e0d87251bfc9a50d9bb06a43ee7ae7 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Tue, 4 May 2021 07:18:00 +0200 Subject: [PATCH 9/9] chore: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f67e0005..307d5a280 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ 1. [#5726](https://github.com/influxdata/chronograf/pull/5726): Allow to setup InfluxDB v2 connection from chronograf command-line. 1. [#5735](https://github.com/influxdata/chronograf/pull/5735): Allow to add custom auto-refresh intervals. 1. [#5737](https://github.com/influxdata/chronograf/pull/5737): Allow to send multiple queries to dashboard. +1. [#5746](https://github.com/influxdata/chronograf/pull/5746): Write to buckets when Flux tab is selected. ### Bug Fixes