1import React from 'react'; 2import useAsync from 'react-use/lib/useAsync'; 3import { getDS } from './utils'; 4import { InlineField, InlineFieldRow } from '@grafana/ui'; 5import { AdHocVariableFilter } from '../../../../features/variables/types'; 6import { TempoQuery } from '../datasource'; 7import { AdHocFilter } from '../../../../features/variables/adhoc/picker/AdHocFilter'; 8import { PrometheusDatasource } from '../../prometheus/datasource'; 9 10export function ServiceGraphSection({ 11 graphDatasourceUid, 12 query, 13 onChange, 14}: { 15 graphDatasourceUid?: string; 16 query: TempoQuery; 17 onChange: (value: TempoQuery) => void; 18}) { 19 const dsState = useAsync(() => getDS(graphDatasourceUid), [graphDatasourceUid]); 20 if (dsState.loading) { 21 return null; 22 } 23 24 const ds = dsState.value as PrometheusDatasource; 25 26 if (!graphDatasourceUid) { 27 return <div className="text-warning">Please set up a service graph datasource in the datasource settings.</div>; 28 } 29 30 if (graphDatasourceUid && !ds) { 31 return ( 32 <div className="text-warning"> 33 Service graph datasource is configured but the data source no longer exists. Please configure existing data 34 source to use the service graph functionality. 35 </div> 36 ); 37 } 38 const filters = queryToFilter(query.serviceMapQuery || ''); 39 40 return ( 41 <div> 42 <InlineFieldRow> 43 <InlineField label="Filter" labelWidth={14} grow> 44 <AdHocFilter 45 datasource={{ uid: graphDatasourceUid }} 46 filters={filters} 47 addFilter={(filter: AdHocVariableFilter) => { 48 onChange({ 49 ...query, 50 serviceMapQuery: filtersToQuery([...filters, filter]), 51 }); 52 }} 53 removeFilter={(index: number) => { 54 const newFilters = [...filters]; 55 newFilters.splice(index, 1); 56 onChange({ ...query, serviceMapQuery: filtersToQuery(newFilters) }); 57 }} 58 changeFilter={(index: number, filter: AdHocVariableFilter) => { 59 const newFilters = [...filters]; 60 newFilters.splice(index, 1, filter); 61 onChange({ ...query, serviceMapQuery: filtersToQuery(newFilters) }); 62 }} 63 /> 64 </InlineField> 65 </InlineFieldRow> 66 </div> 67 ); 68} 69 70function queryToFilter(query: string): AdHocVariableFilter[] { 71 let match; 72 let filters: AdHocVariableFilter[] = []; 73 const re = /([\w_]+)(=|!=|<|>|=~|!~)"(.*?)"/g; 74 while ((match = re.exec(query)) !== null) { 75 filters.push({ 76 key: match[1], 77 operator: match[2], 78 value: match[3], 79 condition: '', 80 }); 81 } 82 return filters; 83} 84 85function filtersToQuery(filters: AdHocVariableFilter[]): string { 86 return `{${filters.map((f) => `${f.key}${f.operator}"${f.value}"`).join(',')}}`; 87} 88