Files
grafana/public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryOptions.tsx
Joey f0cb88e3b5 Pyroscope: Add Span ID to options collapsed info (#79981)
* Pyroscope: Add Span ID to options collapsed info

* Update for multiple

* Update public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryOptions.tsx

Co-authored-by: Fabrizio <135109076+fabrizio-grafana@users.noreply.github.com>

---------

Co-authored-by: Fabrizio <135109076+fabrizio-grafana@users.noreply.github.com>
2024-01-08 12:07:19 +00:00

141 lines
4.6 KiB
TypeScript

import { css } from '@emotion/css';
import React from 'react';
import { CoreApp, GrafanaTheme2, SelectableValue } from '@grafana/data';
import { config } from '@grafana/runtime';
import { useStyles2, RadioButtonGroup, MultiSelect, Input } from '@grafana/ui';
import { QueryOptionGroup } from '../../prometheus/querybuilder/shared/QueryOptionGroup';
import { Query } from '../types';
import { EditorField } from './EditorField';
import { Stack } from './Stack';
export interface Props {
query: Query;
onQueryChange: (query: Query) => void;
app?: CoreApp;
labels?: string[];
}
const typeOptions: Array<{ value: Query['queryType']; label: string; description: string }> = [
{ value: 'metrics', label: 'Metric', description: 'Return aggregated metrics' },
{ value: 'profile', label: 'Profile', description: 'Return profile' },
{ value: 'both', label: 'Both', description: 'Return both metric and profile data' },
];
function getTypeOptions(app?: CoreApp) {
if (app === CoreApp.Explore) {
return typeOptions;
}
return typeOptions.filter((option) => option.value !== 'both');
}
/**
* Base on QueryOptionGroup component from grafana/ui but that is not available yet.
*/
export function QueryOptions({ query, onQueryChange, app, labels }: Props) {
const styles = useStyles2(getStyles);
const typeOptions = getTypeOptions(app);
const groupByOptions = labels
? labels.map((l) => ({
label: l,
value: l,
}))
: [];
let collapsedInfo = [`Type: ${query.queryType}`];
if (query.groupBy?.length) {
collapsedInfo.push(`Group by: ${query.groupBy.join(', ')}`);
}
if (query.spanSelector?.length) {
collapsedInfo.push(`Span ID: ${query.spanSelector.join(', ')}`);
}
if (query.maxNodes) {
collapsedInfo.push(`Max nodes: ${query.maxNodes}`);
}
return (
<Stack gap={0} direction="column">
<QueryOptionGroup title="Options" collapsedInfo={collapsedInfo}>
<div className={styles.body}>
<EditorField label={'Query Type'}>
<RadioButtonGroup
options={typeOptions}
value={query.queryType}
onChange={(value) => onQueryChange({ ...query, queryType: value })}
/>
</EditorField>
<EditorField
label={'Group by'}
tooltip={
<>
Used to group the metric result by a specific label or set of labels. Does not apply to profile query.
</>
}
>
<MultiSelect
placeholder="Label"
value={query.groupBy}
allowCustomValue
options={groupByOptions}
onChange={(change) => {
const changes = change.map((c: SelectableValue<string>) => {
return c.value!;
});
onQueryChange({ ...query, groupBy: changes });
}}
/>
</EditorField>
{config.featureToggles.traceToProfiles && (
<EditorField label={'Span ID'} tooltip={<>Sets the span ID from which to search for profiles.</>}>
<Input
value={query.spanSelector || ['']}
type="string"
placeholder="64f170a95f537095"
onChange={(event: React.SyntheticEvent<HTMLInputElement>) => {
onQueryChange({
...query,
spanSelector: event.currentTarget.value !== '' ? [event.currentTarget.value] : [],
});
}}
/>
</EditorField>
)}
<EditorField label={'Max Nodes'} tooltip={<>Sets the maximum number of nodes to return in the flamegraph.</>}>
<Input
value={query.maxNodes || ''}
type="number"
placeholder="16384"
onChange={(event: React.SyntheticEvent<HTMLInputElement>) => {
let newValue = parseInt(event.currentTarget.value, 10);
newValue = isNaN(newValue) ? 0 : newValue;
onQueryChange({ ...query, maxNodes: newValue });
}}
/>
</EditorField>
</div>
</QueryOptionGroup>
</Stack>
);
}
const getStyles = (theme: GrafanaTheme2) => {
return {
switchLabel: css({
color: theme.colors.text.secondary,
cursor: 'pointer',
fontSize: theme.typography.bodySmall.fontSize,
'&:hover': {
color: theme.colors.text.primary,
},
}),
body: css({
display: 'flex',
paddingTop: theme.spacing(2),
gap: theme.spacing(2),
flexWrap: 'wrap',
}),
};
};