Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): python onboarding updating to influxdb3 python #6770

Merged
merged 3 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
</>
)
}
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
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>
Comment on lines 264 to 268
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! This flow is cleaner than before 👍

</div>

Expand Down