Skip to content

Commit

Permalink
feat: query variables from datav datasource #290
Browse files Browse the repository at this point in the history
  • Loading branch information
sunface committed Nov 3, 2023
1 parent aa2b1d6 commit 0314809
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 88 deletions.
4 changes: 2 additions & 2 deletions ui/src/types/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ export interface PanelDatasource {
export interface PanelQuery {
id: number
metrics: string
legend: string
visible: boolean
legend?: string
visible?: boolean
interval?: number
data?: {[key:string]:any}
}
Expand Down
3 changes: 3 additions & 0 deletions ui/src/utils/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ export const queryPluginDataToTable = (data: QueryPluginData, query: PanelQuery)
return [series]
}

export const queryPluginDataToValueList= (data: QueryPluginData, query: PanelQuery) => {
return data.data.flat()
}

export const queryPluginDataToLogs = (data: {
logs: QueryPluginData;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ const domainParams = [
["gropu", "group name, logical group of services","default",""],
]

const apiList = [{
export const apiList = [{
name: "getServiceInfoList",
desc: "get service infos, such as p99 latency, errors, qps, render as a table",
params: `{
Expand All @@ -150,15 +150,15 @@ const apiList = [{
params: `{
}`,
paramsDesc: [],
format: DataFormat.Table
format: DataFormat.ValueList
},
{
name: "getServiceNames",
desc: "get service names, can be used in variable values",
params: `{
}`,
paramsDesc: [...domainParams],
format: DataFormat.Table
format: DataFormat.ValueList
},
{
name: "getServiceOperations",
Expand All @@ -170,7 +170,7 @@ const apiList = [{
...domainParams,
["service", "service name"]
],
format: DataFormat.Table
format: DataFormat.ValueList
},
{
name: "getLogs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,95 +10,72 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { CodeEditorModal } from "src/components/CodeEditor/CodeEditorModal"
import Label from "src/components/form/Item"
import { isEmpty } from "lodash"
import { DatasourceVariableEditorProps } from "types/datasource"
import { isJSON } from "utils/is"
import { useEffect } from "react"
import { queryHttpVariableValues } from "./query_runner"
import FormItem from "src/components/form/Item"
import { EditorInputItem } from "src/components/editor/EditorItem"
import React from "react";
import { useStore } from "@nanostores/react"
import { httpDsMsg } from "src/i18n/locales/en"
import { Select } from "antd"
import { apiList } from "./QueryEditor"
import { Box } from "@chakra-ui/react"
import CodeEditor from "components/CodeEditor/CodeEditor"
import { DataFormat } from "types/format"

const HttpVariableEditor = ({ variable, onChange, onQueryResult }: DatasourceVariableEditorProps) => {
const VariableEditor = ({ variable, onChange, onQueryResult }: DatasourceVariableEditorProps) => {
const t1 = useStore(httpDsMsg)
const data = isJSON(variable.value) ? JSON.parse(variable.value) : {}

let update;
if (isEmpty(data.transformResult)) {
data.transformResult = initTransformResult
if (isEmpty(data.params)) {
data.params = "{}"
update = true
}
if (isEmpty(data.transformRequest)) {
data.transformRequest = initTransformRequest
update = true
}
if (update) onChange(variable => {
if (update) onChange(variable => {
variable.value = JSON.stringify(data)
})

useEffect(() => {
loadVariables(variable)
}, [variable])

const loadVariables = async (v) => {
const result = await queryHttpVariableValues(variable)
onQueryResult(result)
}

return (<>
<FormItem title="URL">
<EditorInputItem
value={data.url}
onChange={(v) => {
data.url = v
onChange(variable => {
variable.value = JSON.stringify(data)
})
}}
placeholder="support variable"
/>
</FormItem>
<FormItem title={t1.reqTransform}>
{/* <Label width="200px" desc="If you want insert some imformation before request is sent to remote, e.g current time, just edit this function">Request transform</Label> */}
<CodeEditorModal value={data.transformRequest} onChange={v => {
data.transformRequest = v
<FormItem title="API" labelWidth="100px" size="sm">
<Select style={{minWidth: "150px"}} popupMatchSelectWidth={false} value={data.url} options={apiList.filter(api => api.format == DataFormat.ValueList).map(api => ({ label: api.name, value: api.name }))} onChange={(v) => {
data.url = v
onChange(variable => {
variable.value = JSON.stringify(data)
})
}} />
</FormItem>


<FormItem title={t1.respTransform}>
{/* <Label width="200px" desc="The http request result is probably not compatible with your visualization panels, here you can define a function to transform the result">Result transform</Label> */}
<CodeEditorModal value={data.transformResult} onChange={v => {
data.transformResult = v
onChange(variable => {
variable.value = JSON.stringify(data)
})
}} />
<FormItem title="Params" labelWidth="100px" size="sm">
<Box width="300px">
<CodeEditor
language="json"
value={data.params}
height="200px"
onChange={(v) => {
data.params = v
}}
onBlur={() => {
onChange(variable => {
variable.value = JSON.stringify(data)
})
}}
isSingleLine
/>
</Box>
</FormItem>
</>)
}

export default HttpVariableEditor



const initTransformRequest =
`
// support variables
function transformRequest(url,headers,startTime, endTime, variables) {
let newUrl = url + \`?&start=$\{startTime}&end=$\{endTime}\`
return newUrl
}`
export default VariableEditor

const initTransformResult =
`function transformResult(httpResult) {
console.log("here333 transformResult:", httpResult)
return httpResult
}`
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ import { isEmpty } from "utils/validate"
import { roundDsTime } from "utils/datasource"
import { $variables } from "src/views/variables/store"
import { QueryPluginResult } from "types/plugin"
import { queryPluginDataToLogs, queryPluginDataToNodeGraph, queryPluginDataToTable, queryPluginDataToTimeSeries } from "utils/plugins"
import { queryPluginDataToLogs, queryPluginDataToNodeGraph, queryPluginDataToTable, queryPluginDataToTimeSeries, queryPluginDataToValueList } from "utils/plugins"
import { DataFormat } from "types/format"
import { $datavQueryParams } from "./store"
import { parseVariableFormat } from "utils/format"
import { VariableSplitChar } from "src/data/variable"
import { queryPluginDataToTrace, queryPluginDataToTraceChart } from "./utils"
import { $datasources } from "src/views/datasource/store"

export const runQuery = async (panel: Panel, q: PanelQuery, range: TimeRange, ds: Datasource, extraParams?: Record<string,any>) => {
if (isEmpty(q.metrics)) {
Expand Down Expand Up @@ -115,6 +116,9 @@ export const runQuery = async (panel: Panel, q: PanelQuery, range: TimeRange, ds
case DataFormat.Trace:
data = queryPluginDataToTrace(res.data.data as any, q)
break
case DataFormat.ValueList:
data = queryPluginDataToValueList(res.data.data as any, q)
break
default:
data = res.data.data
}
Expand All @@ -141,46 +145,40 @@ export const queryHttpVariableValues = async (variable: Variable, useCurrentTime
if (!data || isEmpty(data.url)) {
return result
}
const timeRange = getNewestTimeRange()
const start = roundDsTime(timeRange.start.getTime() / 1000)
const end = roundDsTime(timeRange.end.getTime() / 1000)


const headers = {}
let url
if (!isEmpty(data.transformRequest)) {
const transformRequest = genDynamicFunction(data.transformRequest);
if (isFunction(transformRequest)) {
url = transformRequest(replaceWithVariables(data.url), headers, start, end, $variables.get())
} else {
return []
}

const ds = $datasources.get().find(ds => ds.id == variable.datasource)
if (!ds) {
console.error("datasource not found:",variable.datasource)
return result
}

try {
const res = await requestApi.get(`/common/proxy/${variable.id}?proxy_url=${encodeURIComponent(url)}`,{headers})
result.data = res
const timeRange = getNewestTimeRange()

if (!isEmpty(data.transformResult)) {
const transformResult = genDynamicFunction(data.transformResult);
if (isFunction(transformResult)) {
result = transformResult(res)
} else {
result.data = []
const query:PanelQuery = {
id: 65,
metrics: data.url,
data:{
[data.url]: {
params : data.params
}
}
} catch (error) {
console.error("variable http request error:",error)
},
}

const res = await runQuery(null, query, timeRange, ds, {})
if (res.error) {
result.error = res.error
return result
}

const res1 = queryPluginDataToValueList(res.data, query)
result.data = res1

return result
}


export const replaceDatavQueryWithVariables = (query: PanelQuery | string, interval: string) => {
const vars = $variables.get()
console.log("here444444:",query)
if (!query) {
return query
}
Expand Down

0 comments on commit 0314809

Please sign in to comment.