Skip to content

Commit

Permalink
feat(ui): python onboarding updating to influxdb3 python (#6770)
Browse files Browse the repository at this point in the history
* added python package changes

* Updated PythonWizard

* chore: refactor component and fix exports

---------

Co-authored-by: Jay Clifford <[email protected]>
  • Loading branch information
mavarius and Jay Clifford authored Jul 27, 2023
1 parent 4d0baef commit e195ae9
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 74 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react'
import CodeSnippet from 'src/shared/components/CodeSnippet'

import {SafeBlankLink} from 'src/utils/SafeBlankLink'
import {event} from 'src/cloud/utils/reporting'

const logCopyCodeSnippet = () => {
event('firstMile.pythonWizard.executeAggregateQuery.code.copied')
}

const logDocsOpened = () => {
event('firstMile.pythonWizard.executeAggregateQuery.docs.opened')
}

type OwnProps = {
bucket: string
}

export const ExecuteAggregateQuerySql = (props: OwnProps) => {
const {bucket} = props

const sqlSnippet = `SELECT mean(count)
FROM 'census'
WHERE time > now() - '10m'`

const querySnippet = `query = """SELECT mean(count)
FROM 'census'
WHERE time > now() - '10m'"""
# Execute the query
table = client.query(query=query, database="${bucket}", language='influxql') )
# Convert to dataframe
df = table.to_pandas().sort_values(by="time")
print(df)
`

return (
<>
<h1>Execute an Aggregate Query</h1>
<p>
<SafeBlankLink
href="https://docs.influxdata.com/flux/v0.x/function-types/#aggregates"
onClick={logDocsOpened}
>
Aggregate functions
</SafeBlankLink>{' '}
take the values of all rows in a table and use them to perform an
aggregate operation. The result is output as a new value in a single-row
table.
</p>
<CodeSnippet
text={sqlSnippet}
showCopyControl={false}
onCopy={logCopyCodeSnippet}
language="sql"
/>
<p>
In this example, we use the{' '}
<code className="homepage-wizard--code-highlight">mean()</code> function
to calculate the average value of data points in the last 10 minutes.
<br />
<br />
Run the following:
</p>
<CodeSnippet
text={querySnippet}
onCopy={logCopyCodeSnippet}
language="python"
/>
<p>
In this example we use{' '}
<code className="homepage-wizard--code-highlight">InfluxQL</code> to
perform our aggregation. SQL and InfluxQL can be used interchangeably in
the Python client.
</p>
</>
)
}
22 changes: 3 additions & 19 deletions src/homepageExperience/components/steps/python/ExecuteQuerySql.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import React from 'react'
import {useSelector} from 'react-redux'

import CodeSnippet from 'src/shared/components/CodeSnippet'
import {event} from 'src/cloud/utils/reporting'

import {selectCurrentIdentity} from 'src/identity/selectors'

const logCopyCodeSnippet = () => {
event('firstMile.pythonWizard.executeQuery.code.copied')
}
Expand All @@ -15,36 +12,23 @@ type OwnProps = {
}

export const ExecuteQuerySql = (props: OwnProps) => {
const {org: quartzOrg} = useSelector(selectCurrentIdentity)
const url = quartzOrg.clusterHost || window.location.origin

const {bucket} = props

const sqlSnippet = `SELECT *
FROM 'census'
WHERE time >= now() - interval '1 hour'
AND ('bees' IS NOT NULL OR 'ants' IS NOT NULL)`

const query = `from flightsql import FlightSQLClient
query = """SELECT *
const query = `query = """SELECT *
FROM 'census'
WHERE time >= now() - interval '24 hours'
AND ('bees' IS NOT NULL OR 'ants' IS NOT NULL)"""
# Define the query client
query_client = FlightSQLClient(
host = "${url.replace(/^https?:\/\//, '')}",
token = os.environ.get("INFLUXDB_TOKEN"),
metadata={"bucket-name": "${bucket}"})
# Execute the query
info = query_client.execute(query)
reader = query_client.do_get(info.endpoints[0].ticket)
table = client.query(query=query, database="${bucket}", language='sql') )
# Convert to dataframe
data = reader.read_all()
df = data.to_pandas().sort_values(by="time")
df = table.to_pandas().sort_values(by="time")
print(df)
`

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react'
import {useSelector} from 'react-redux'

import CodeSnippet from 'src/shared/components/CodeSnippet'
import {event} from 'src/cloud/utils/reporting'

import {getOrg} from 'src/organizations/selectors'
import {selectCurrentIdentity} from 'src/identity/selectors'

const logCopyCodeSnippet = () => {
event('firstMile.pythonWizard.initializeClient.code.copied')
}

export const InitializeClientSql = () => {
const org = useSelector(getOrg)
const {org: quartzOrg} = useSelector(selectCurrentIdentity)

const url = quartzOrg.clusterHost || window.location.origin

const pythonCode = `import os, time
from influxdb_client_3 import InfluxDBClient3, Point
token = os.environ.get("INFLUXDB_TOKEN")
org = "${org.name}"
host = "${url}"
client = InfluxDBClient3(host=host, token=token, org=org)`

return (
<>
<h1>Initialize Client</h1>
<p>
Run this command in your terminal to open the interactive Python shell:
</p>
<CodeSnippet language="properties" text="python3" />
<p>
Paste the following code after the prompt (&gt;&gt;&gt;) and press
Enter.
</p>
<CodeSnippet
language="python"
onCopy={logCopyCodeSnippet}
text={pythonCode}
/>
<p>
Here, we initialize the token, organization info, and server url host
that are needed to set up the initial connection to InfluxDB. The client
connection is then established with the{' '}
<code className="homepage-wizard--code-highlight">InfluxDBClient</code>{' '}
initialization.
</p>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,16 @@ export class InstallDependenciesSql extends PureComponent {
</p>
<p>
Install the{' '}
<SafeBlankLink href="https://github.com/influxdata/influxdb-client-python">
influxdb-client
<SafeBlankLink href="https://github.com/InfluxCommunity/influxdb3-python">
influxdb3-python
</SafeBlankLink>{' '}
module. You'll use this to write to InfluxDB. Run the command below in
your terminal:
module. You'll use this to write and query InfluxDB. Run the command
below in your terminal:
</p>
<CodeSnippet
language="properties"
onCopy={this.logCopyCodeSnippet}
text="pip install influxdb-client"
/>
<p>
Next, install the{' '}
<SafeBlankLink href="https://github.com/influxdata/flightsql-dbapi">
flightsql-dbapi
</SafeBlankLink>
. This is used to Query InfluxDB with SQL.
</p>
<CodeSnippet
language="properties"
onCopy={this.logCopyCodeSnippet}
text="pip install flightsql-dbapi"
text="pip install influxdb3-python"
/>
<p>
Lastly, let's install{' '}
Expand Down
10 changes: 3 additions & 7 deletions src/homepageExperience/components/steps/python/WriteDataSql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ export const WriteDataSqlComponent = (props: OwnProps) => {
onSelectBucket(bucket.name)
}, [bucket, onSelectBucket])

const codeSnippet = `bucket="${bucket.name}"
# Define the write api
write_api = write_client.write_api(write_options=SYNCHRONOUS)
const codeSnippet = `database="${bucket.name}"
data = {
"point1": {
Expand Down Expand Up @@ -93,7 +90,7 @@ for key in data:
.tag("location", data[key]["location"])
.field(data[key]["species"], data[key]["count"])
)
write_api.write(bucket=bucket, org=org, record=point)
client.write(database=database, record=point)
time.sleep(1) # separate points by 1 second
print("Complete. Return to the InfluxDB UI.")
Expand Down Expand Up @@ -227,8 +224,7 @@ print("Complete. Return to the InfluxDB UI.")
</Table.Cell>
<Table.Cell>
We are storing the "location" of where each census is taken. Tags
are indexed and should generally be bounded (i.e. only a few
cities).
form part of your primary key.
</Table.Cell>
</Table.Row>
<Table.Row>
Expand Down
88 changes: 57 additions & 31 deletions src/homepageExperience/containers/PythonWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import {InstallDependenciesSql} from 'src/homepageExperience/components/steps/py
import {Overview} from 'src/homepageExperience/components/steps/Overview'
import {Tokens} from 'src/homepageExperience/components/steps/Tokens'
import {InitializeClient} from 'src/homepageExperience/components/steps/python/InitializeClient'
import {InitializeClientSql} from 'src/homepageExperience/components/steps/python/InitializeClientSql'
import {WriteData} from 'src/homepageExperience/components/steps/python/WriteData'
import {WriteDataSql} from 'src/homepageExperience/components/steps/python/WriteDataSql'
import {ExecuteQuery} from 'src/homepageExperience/components/steps/python/ExecuteQuery'
import {ExecuteQuerySql} from 'src/homepageExperience/components/steps/python/ExecuteQuerySql'
import {Finish} from 'src/homepageExperience/components/steps/Finish'
import {ExecuteAggregateQuery} from 'src/homepageExperience/components/steps/python/ExecuteAggregateQuery'
import {ExecuteAggregateQuerySql} from 'src/homepageExperience/components/steps/python/ExecuteAggregateQuerySql'

import {normalizeEventName} from 'src/cloud/utils/reporting'

import {PythonIcon} from 'src/homepageExperience/components/HomepageIcons'
Expand All @@ -34,7 +37,6 @@ import {isFlagEnabled} from 'src/shared/utils/featureFlag'
import {
scrollNextPageIntoView,
HOMEPAGE_NAVIGATION_STEPS,
HOMEPAGE_NAVIGATION_STEPS_SQL,
} from 'src/homepageExperience/utils'

interface State {
Expand All @@ -54,19 +56,7 @@ export class PythonWizard extends PureComponent<null, State> {
finalFeedback: null,
}

subwayNavSteps = isFlagEnabled('ioxOnboarding')
? HOMEPAGE_NAVIGATION_STEPS_SQL
: HOMEPAGE_NAVIGATION_STEPS

installDependenciesStep = isFlagEnabled('ioxOnboarding')
? InstallDependenciesSql
: InstallDependencies

writeDataStep = isFlagEnabled('ioxOnboarding') ? WriteDataSql : WriteData

executeQueryStep = isFlagEnabled('ioxOnboarding')
? ExecuteQuerySql
: ExecuteQuery
subwayNavSteps = HOMEPAGE_NAVIGATION_STEPS

private handleSelectBucket = (bucketName: string) => {
this.setState({selectedBucket: bucketName})
Expand Down Expand Up @@ -151,7 +141,7 @@ export class PythonWizard extends PureComponent<null, State> {
return <Overview wizard="pythonWizard" />
}
case 2: {
return <this.installDependenciesStep />
return <InstallDependencies />
}
case 3: {
return (
Expand All @@ -166,25 +156,13 @@ export class PythonWizard extends PureComponent<null, State> {
return <InitializeClient />
}
case 5: {
return <this.writeDataStep onSelectBucket={this.handleSelectBucket} />
return <WriteData onSelectBucket={this.handleSelectBucket} />
}
case 6: {
return <this.executeQueryStep bucket={this.state.selectedBucket} />
return <ExecuteQuery bucket={this.state.selectedBucket} />
}
case 7: {
if (!isFlagEnabled('ioxOnboarding')) {
return <ExecuteAggregateQuery bucket={this.state.selectedBucket} />
} else {
return (
<Finish
wizardEventName="pythonSqlWizard"
markStepAsCompleted={this.handleMarkStepAsCompleted}
finishStepCompleted={this.state.finishStepCompleted}
finalFeedback={this.state.finalFeedback}
setFinalFeedback={this.setFinalFeedback}
/>
)
}
return <ExecuteAggregateQuery bucket={this.state.selectedBucket} />
}
case 8: {
return (
Expand All @@ -203,6 +181,52 @@ export class PythonWizard extends PureComponent<null, State> {
}
}

renderSqlStep = () => {
switch (this.state.currentStep) {
case 1: {
return <Overview wizard="pythonWizard" />
}
case 2: {
return <InstallDependenciesSql />
}
case 3: {
return (
<Tokens
wizardEventName="pythonWizard"
setTokenValue={this.setTokenValue}
tokenValue={this.state.tokenValue}
/>
)
}
case 4: {
return <InitializeClientSql />
}
case 5: {
return <WriteDataSql onSelectBucket={this.handleSelectBucket} />
}
case 6: {
return <ExecuteQuerySql bucket={this.state.selectedBucket} />
}
case 7: {
return <ExecuteAggregateQuerySql bucket={this.state.selectedBucket} />
}
case 8: {
return (
<Finish
wizardEventName="pythonSqlWizard"
markStepAsCompleted={this.handleMarkStepAsCompleted}
finishStepCompleted={this.state.finishStepCompleted}
finalFeedback={this.state.finalFeedback}
setFinalFeedback={this.setFinalFeedback}
/>
)
}
default: {
return <Overview wizard="pythonWizard" />
}
}
}

render() {
const {currentStep} = this.state

Expand Down Expand Up @@ -238,7 +262,9 @@ export class PythonWizard extends PureComponent<null, State> {
)}
>
<WriteDataDetailsContextProvider>
{this.renderStep()}
{isFlagEnabled('ioxOnboarding')
? this.renderSqlStep()
: this.renderStep()}
</WriteDataDetailsContextProvider>
</div>

Expand Down

0 comments on commit e195ae9

Please sign in to comment.