{"version":3,"file":"pyroscopePlugin.eb14b78419d619d90dca.js","mappings":"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","sources":["webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/ConfigEditor.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/ProfileTypesCascader.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/VariableQueryEditor.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/VariableSupport.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/dataquery.gen.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/utils.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/datasource.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/Stack.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorRow.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorRows.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/pyroscopeql/index.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/pyroscopeql/pyroscopeql.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/autocomplete.ts","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/LabelsEditor.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryLinkExtension.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/EditorField.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryOptionGroup.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryOptions.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/QueryEditor.tsx","webpack://grafana/./public/app/plugins/datasource/grafana-pyroscope-datasource/module.ts","webpack://grafana/./node_modules/react-use/esm/useLatest.js"],"sourcesContent":["import React from 'react';\n\nimport { DataSourcePluginOptionsEditorProps } from '@grafana/data';\nimport { config } from '@grafana/runtime';\nimport { DataSourceHttpSettings, EventsWithValidation, LegacyForms, regexValidation } from '@grafana/ui';\n\nimport { PyroscopeDataSourceOptions } from './types';\n\ninterface Props extends DataSourcePluginOptionsEditorProps {}\n\nexport const ConfigEditor = (props: Props) => {\n const { options, onOptionsChange } = props;\n\n return (\n <>\n \n\n

Querying

\n
\n
\n
\n {\n onOptionsChange({\n ...options,\n jsonData: {\n ...options.jsonData,\n minStep: event.currentTarget.value,\n },\n });\n }}\n validationEvents={{\n [EventsWithValidation.onBlur]: [\n regexValidation(\n /^$|^\\d+(ms|[Mwdhmsy])$/,\n 'Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s'\n ),\n ],\n }}\n />\n }\n tooltip=\"Minimal step used for metric query. Should be the same or higher as the scrape interval setting in the Pyroscope database.\"\n />\n
\n
\n
\n \n );\n};\n","import React, { useEffect, useMemo, useState } from 'react';\n\nimport { TimeRange } from '@grafana/data';\nimport { Cascader, CascaderOption } from '@grafana/ui';\n\nimport { PyroscopeDataSource } from '../datasource';\nimport { ProfileTypeMessage } from '../types';\n\ntype Props = {\n initialProfileTypeId?: string;\n profileTypes?: ProfileTypeMessage[];\n onChange: (value: string) => void;\n placeholder?: string;\n width?: number;\n};\n\nexport function ProfileTypesCascader(props: Props) {\n const cascaderOptions = useCascaderOptions(props.profileTypes);\n\n return (\n \n );\n}\n\n// Turn profileTypes into cascader options\nfunction useCascaderOptions(profileTypes?: ProfileTypeMessage[]): CascaderOption[] {\n return useMemo(() => {\n if (!profileTypes) {\n return [];\n }\n let mainTypes = new Map();\n // Classify profile types by name then sample type.\n // The profileTypes are something like cpu:sample:nanoseconds:sample:count or app.something.something\n for (let profileType of profileTypes) {\n let parts: string[] = [];\n if (profileType.id.indexOf(':') > -1) {\n parts = profileType.id.split(':');\n }\n\n const [name, type] = parts;\n\n if (!mainTypes.has(name)) {\n mainTypes.set(name, {\n label: name,\n value: name,\n items: [],\n });\n }\n mainTypes.get(name)?.items!.push({\n label: type,\n value: profileType.id,\n });\n }\n return Array.from(mainTypes.values());\n }, [profileTypes]);\n}\n\n/**\n * Loads the profile types.\n *\n * This is exported and not used directly in the ProfileTypesCascader component because in some case we need to know\n * the profileTypes before rendering the cascader.\n * @param datasource\n * @param range Time range for the profile types query.\n */\nexport function useProfileTypes(datasource: PyroscopeDataSource, range?: TimeRange) {\n const [profileTypes, setProfileTypes] = useState();\n\n const impreciseRange = {\n to: Math.ceil((range?.to.valueOf() || 0) / 60000) * 60000,\n from: Math.floor((range?.from.valueOf() || 0) / 60000) * 60000,\n };\n\n useEffect(() => {\n (async () => {\n const profileTypes = await datasource.getProfileTypes(impreciseRange.from.valueOf(), impreciseRange.to.valueOf());\n setProfileTypes(profileTypes);\n })();\n }, [datasource, impreciseRange.from, impreciseRange.to]);\n\n return profileTypes;\n}\n","import React, { useEffect, useState } from 'react';\n\nimport { QueryEditorProps, SelectableValue, TimeRange } from '@grafana/data';\nimport { InlineField, InlineFieldRow, LoadingPlaceholder, Select } from '@grafana/ui';\n\nimport { ProfileTypesCascader, useProfileTypes } from './QueryEditor/ProfileTypesCascader';\nimport { PyroscopeDataSource } from './datasource';\nimport { Query, VariableQuery } from './types';\n\nexport function VariableQueryEditor(props: QueryEditorProps) {\n return (\n <>\n \n The Pyroscope data source plugin provides the following query types for template variables\n }\n >\n {\n if (value.value! === 'profileType') {\n props.onChange({\n ...props.query,\n type: value.value!,\n });\n }\n if (value.value! === 'label') {\n props.onChange({\n ...props.query,\n type: value.value!,\n profileTypeId: '',\n });\n }\n if (value.value! === 'labelValue') {\n props.onChange({\n ...props.query,\n type: value.value!,\n profileTypeId: '',\n labelName: '',\n });\n }\n }}\n value={props.query.type}\n />\n \n \n\n {(props.query.type === 'labelValue' || props.query.type === 'label') && (\n {\n // To make TS happy\n if (props.query.type === 'label' || props.query.type === 'labelValue') {\n props.onChange({ ...props.query, profileTypeId: val });\n }\n }}\n range={props.range}\n />\n )}\n\n {props.query.type === 'labelValue' && (\n {\n if (props.query.type === 'labelValue') {\n props.onChange({ ...props.query, labelName: val });\n }\n }}\n from={props.range?.from.valueOf() || Date.now().valueOf() - 1000 * 60 * 60 * 24}\n to={props.range?.to.valueOf() || Date.now().valueOf()}\n />\n )}\n \n );\n}\n\nfunction LabelRow(props: {\n datasource: PyroscopeDataSource;\n value?: string;\n profileTypeId?: string;\n from: number;\n to: number;\n onChange: (val: string) => void;\n}) {\n const [labels, setLabels] = useState();\n useEffect(() => {\n (async () => {\n setLabels(await props.datasource.getLabelNames((props.profileTypeId || '') + '{}', props.from, props.to));\n })();\n }, [props.datasource, props.profileTypeId, props.to, props.from]);\n\n const options = labels ? labels.map((v) => ({ label: v, value: v })) : [];\n if (labels && props.value && !labels.find((v) => v === props.value)) {\n options.push({ value: props.value, label: props.value });\n }\n\n return (\n \n Select label for which to retrieve available values}\n >\n props.onChange(option.value)}\n value={props.value}\n />\n \n \n );\n}\n\nfunction ProfileTypeRow(props: {\n datasource: PyroscopeDataSource;\n onChange: (val: string) => void;\n initialValue?: string;\n range?: TimeRange;\n}) {\n const profileTypes = useProfileTypes(props.datasource, props.range);\n return (\n \n Select profile type for which to retrieve available labels}\n >\n {profileTypes ? (\n \n ) : (\n \n )}\n \n \n );\n}\n","import { from, map, Observable, of } from 'rxjs';\n\nimport { CustomVariableSupport, DataQueryRequest, DataQueryResponse, MetricFindValue } from '@grafana/data';\n\nimport { VariableQueryEditor } from './VariableQueryEditor';\nimport { PyroscopeDataSource } from './datasource';\nimport { ProfileTypeMessage, VariableQuery } from './types';\n\nexport interface DataAPI {\n getProfileTypes(start: number, end: number): Promise;\n getLabelNames(query: string, start: number, end: number): Promise;\n getLabelValues(query: string, label: string, start: number, end: number): Promise;\n}\n\nexport class VariableSupport extends CustomVariableSupport {\n constructor(private readonly dataAPI: DataAPI) {\n super();\n }\n\n editor = VariableQueryEditor;\n\n query(request: DataQueryRequest): Observable {\n if (request.targets[0].type === 'profileType') {\n return from(this.dataAPI.getProfileTypes(request.range.from.valueOf(), request.range.to.valueOf())).pipe(\n map((values) => {\n return { data: values.map((v) => ({ text: v.label, value: v.id })) };\n })\n );\n }\n\n if (request.targets[0].type === 'label') {\n if (!request.targets[0].profileTypeId) {\n return of({ data: [] });\n }\n return from(\n this.dataAPI.getLabelNames(\n request.targets[0].profileTypeId + '{}',\n request.range.from.valueOf(),\n request.range.to.valueOf()\n )\n ).pipe(\n map((values) => {\n return { data: values.map((v) => ({ text: v })) };\n })\n );\n }\n\n if (request.targets[0].type === 'labelValue') {\n if (!request.targets[0].labelName || !request.targets[0].profileTypeId) {\n return of({ data: [] });\n }\n return from(\n this.dataAPI.getLabelValues(\n request.targets[0].profileTypeId + '{}',\n request.targets[0].labelName,\n request.range.from.valueOf(),\n request.range.to.valueOf()\n )\n ).pipe(\n map((values) => {\n return { data: values.map((v) => ({ text: v })) };\n })\n );\n }\n\n return of({ data: [] });\n }\n}\n","// Code generated - EDITING IS FUTILE. DO NOT EDIT.\n//\n// Generated by:\n// public/app/plugins/gen.go\n// Using jennies:\n// TSTypesJenny\n// PluginTSTypesJenny\n//\n// Run 'make gen-cue' from repository root to regenerate.\n\nimport * as common from '@grafana/schema';\n\nexport type PyroscopeQueryType = ('metrics' | 'profile' | 'both');\n\nexport const defaultPyroscopeQueryType: PyroscopeQueryType = 'both';\n\nexport interface GrafanaPyroscope extends common.DataQuery {\n /**\n * Allows to group the results.\n */\n groupBy: Array;\n /**\n * Specifies the query label selectors.\n */\n labelSelector: string;\n /**\n * Sets the maximum number of nodes in the flamegraph.\n */\n maxNodes?: number;\n /**\n * Specifies the type of profile to query.\n */\n profileTypeId: string;\n /**\n * Specifies the query span selectors.\n */\n spanSelector?: Array;\n}\n\nexport const defaultGrafanaPyroscope: Partial = {\n groupBy: [],\n labelSelector: '{}',\n spanSelector: [],\n};\n","import { invert } from 'lodash';\nimport { Token } from 'prismjs';\n\nimport { AbstractLabelMatcher, AbstractLabelOperator, AbstractQuery } from '@grafana/data';\n\nexport function extractLabelMatchers(tokens: Array): AbstractLabelMatcher[] {\n const labelMatchers: AbstractLabelMatcher[] = [];\n\n for (const token of tokens) {\n if (!(token instanceof Token)) {\n continue;\n }\n\n if (token.type === 'context-labels') {\n let labelKey = '';\n let labelValue = '';\n let labelOperator = '';\n\n const contentTokens = Array.isArray(token.content) ? token.content : [token.content];\n\n for (let currentToken of contentTokens) {\n if (typeof currentToken === 'string') {\n let currentStr: string;\n currentStr = currentToken;\n if (currentStr === '=' || currentStr === '!=' || currentStr === '=~' || currentStr === '!~') {\n labelOperator = currentStr;\n }\n } else if (currentToken instanceof Token) {\n switch (currentToken.type) {\n case 'label-key':\n labelKey = getMaybeTokenStringContent(currentToken);\n break;\n case 'label-value':\n labelValue = getMaybeTokenStringContent(currentToken);\n labelValue = labelValue.substring(1, labelValue.length - 1);\n const labelComparator = FromPromLikeMap[labelOperator];\n if (labelComparator) {\n labelMatchers.push({ name: labelKey, operator: labelComparator, value: labelValue });\n }\n break;\n }\n }\n }\n }\n }\n\n return labelMatchers;\n}\n\nexport function toPromLikeExpr(labelBasedQuery: AbstractQuery): string {\n const expr = labelBasedQuery.labelMatchers\n .map((selector: AbstractLabelMatcher) => {\n const operator = ToPromLikeMap[selector.operator];\n if (operator) {\n return `${selector.name}${operator}\"${selector.value}\"`;\n } else {\n return '';\n }\n })\n .filter((e: string) => e !== '')\n .join(', ');\n\n return expr ? `{${expr}}` : '';\n}\n\nfunction getMaybeTokenStringContent(token: Token): string {\n if (typeof token.content === 'string') {\n return token.content;\n }\n\n return '';\n}\n\nconst FromPromLikeMap: Record = {\n '=': AbstractLabelOperator.Equal,\n '!=': AbstractLabelOperator.NotEqual,\n '=~': AbstractLabelOperator.EqualRegEx,\n '!~': AbstractLabelOperator.NotEqualRegEx,\n};\n\nconst ToPromLikeMap: Record = invert(FromPromLikeMap) as Record<\n AbstractLabelOperator,\n string\n>;\n","import Prism, { Grammar } from 'prismjs';\nimport { Observable, of } from 'rxjs';\n\nimport {\n AbstractQuery,\n CoreApp,\n DataQueryRequest,\n DataQueryResponse,\n DataSourceInstanceSettings,\n ScopedVars,\n} from '@grafana/data';\nimport { DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime';\n\nimport { VariableSupport } from './VariableSupport';\nimport { defaultGrafanaPyroscope, defaultPyroscopeQueryType } from './dataquery.gen';\nimport { PyroscopeDataSourceOptions, Query, ProfileTypeMessage } from './types';\nimport { extractLabelMatchers, toPromLikeExpr } from './utils';\n\nexport class PyroscopeDataSource extends DataSourceWithBackend {\n constructor(\n instanceSettings: DataSourceInstanceSettings,\n private readonly templateSrv: TemplateSrv = getTemplateSrv()\n ) {\n super(instanceSettings);\n this.variables = new VariableSupport(this);\n }\n\n query(request: DataQueryRequest): Observable {\n const validTargets = request.targets\n .filter((t) => t.profileTypeId)\n .map((t) => {\n // Empty string errors out but honestly seems like we can just normalize it this way\n if (t.labelSelector === '') {\n return {\n ...t,\n labelSelector: '{}',\n };\n }\n return normalizeQuery(t, request.app);\n });\n if (!validTargets.length) {\n return of({ data: [] });\n }\n return super.query({\n ...request,\n targets: validTargets,\n });\n }\n\n async getProfileTypes(start: number, end: number): Promise {\n return await this.getResource('profileTypes', {\n start,\n end,\n });\n }\n\n async getAllProfileTypes(): Promise {\n return await this.getResource('profileTypes');\n }\n\n async getLabelNames(query: string, start: number, end: number): Promise {\n return await this.getResource('labelNames', { query: this.templateSrv.replace(query), start, end });\n }\n\n async getLabelValues(query: string, label: string, start: number, end: number): Promise {\n return await this.getResource('labelValues', {\n label: this.templateSrv.replace(label),\n query: this.templateSrv.replace(query),\n start,\n end,\n });\n }\n\n applyTemplateVariables(query: Query, scopedVars: ScopedVars): Query {\n return {\n ...query,\n labelSelector: this.templateSrv.replace(query.labelSelector ?? '', scopedVars),\n profileTypeId: this.templateSrv.replace(query.profileTypeId ?? '', scopedVars),\n };\n }\n\n async importFromAbstractQueries(abstractQueries: AbstractQuery[]): Promise {\n return abstractQueries.map((abstractQuery) => this.importFromAbstractQuery(abstractQuery));\n }\n\n importFromAbstractQuery(labelBasedQuery: AbstractQuery): Query {\n return {\n refId: labelBasedQuery.refId,\n labelSelector: toPromLikeExpr(labelBasedQuery),\n queryType: 'both',\n profileTypeId: '',\n groupBy: [],\n };\n }\n\n async exportToAbstractQueries(queries: Query[]): Promise {\n return queries.map((query) => this.exportToAbstractQuery(query));\n }\n\n exportToAbstractQuery(query: Query): AbstractQuery {\n const pyroscopeQuery = query.labelSelector;\n if (!pyroscopeQuery || pyroscopeQuery.length === 0) {\n return { refId: query.refId, labelMatchers: [] };\n }\n const tokens = Prism.tokenize(pyroscopeQuery, grammar);\n return {\n refId: query.refId,\n labelMatchers: extractLabelMatchers(tokens),\n };\n }\n\n getDefaultQuery(app: CoreApp): Partial {\n return defaultQuery;\n }\n}\n\nexport const defaultQuery: Partial = {\n ...defaultGrafanaPyroscope,\n queryType: defaultPyroscopeQueryType,\n};\n\nexport function normalizeQuery(query: Query, app?: CoreApp | string) {\n let normalized = { ...defaultQuery, ...query };\n if (app !== CoreApp.Explore && normalized.queryType === 'both') {\n // In dashboards and other places, we can't show both types of graphs at the same time.\n // This will also be a default when having 'both' query and adding it from explore to dashboard\n normalized.queryType = 'profile';\n }\n return normalized;\n}\n\nconst grammar: Grammar = {\n 'context-labels': {\n pattern: /\\{[^}]*(?=}?)/,\n greedy: true,\n inside: {\n comment: {\n pattern: /#.*/,\n },\n 'label-key': {\n pattern: /[a-zA-Z_]\\w*(?=\\s*(=|!=|=~|!~))/,\n alias: 'attr-name',\n greedy: true,\n },\n 'label-value': {\n pattern: /\"(?:\\\\.|[^\\\\\"])*\"/,\n greedy: true,\n alias: 'attr-value',\n },\n punctuation: /[{]/,\n },\n },\n punctuation: /[{}(),.]/,\n};\n","import { css } from '@emotion/css';\nimport React, { CSSProperties } from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2 } from '@grafana/ui';\n\ninterface StackProps {\n direction?: CSSProperties['flexDirection'];\n alignItems?: CSSProperties['alignItems'];\n wrap?: boolean;\n gap?: number;\n flexGrow?: CSSProperties['flexGrow'];\n children: React.ReactNode;\n}\n\nexport function Stack(props: StackProps) {\n const styles = useStyles2(getStyles, props);\n return
{props.children}
;\n}\n\nconst getStyles = (theme: GrafanaTheme2, props: StackProps) => ({\n root: css({\n display: 'flex',\n flexDirection: props.direction ?? 'row',\n flexWrap: props.wrap ?? true ? 'wrap' : undefined,\n alignItems: props.alignItems,\n gap: theme.spacing(props.gap ?? 2),\n flexGrow: props.flexGrow,\n }),\n});\n","import { css } from '@emotion/css';\nimport React from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2 } from '@grafana/ui';\n\nimport { Stack } from './Stack';\n\ninterface EditorRowProps {\n children: React.ReactNode;\n stackProps?: Partial>;\n}\n\nexport const EditorRow = ({ children, stackProps }: EditorRowProps) => {\n const styles = useStyles2(getStyles);\n\n return (\n
\n \n {children}\n \n
\n );\n};\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n root: css({\n padding: theme.spacing(1),\n backgroundColor: theme.colors.background.secondary,\n borderRadius: theme.shape.radius.default,\n }),\n };\n};\n","import React from 'react';\n\nimport { Stack } from './Stack';\n\ninterface EditorRowsProps {\n children: React.ReactNode;\n}\n\nexport const EditorRows = ({ children }: EditorRowsProps) => {\n return (\n \n {children}\n \n );\n};\n","import { language, languageConfiguration } from './pyroscopeql';\n\nexport const languageDefinition = {\n id: 'pyroscopeql',\n extensions: ['.pyroscopeql'],\n aliases: ['pyroscope', 'pyroscopeql'],\n mimetypes: [],\n def: {\n language,\n languageConfiguration,\n },\n};\n","import type { languages } from 'monaco-editor';\n\nexport const languageConfiguration: languages.LanguageConfiguration = {\n // the default separators except `@$`\n wordPattern: /(-?\\d*\\.\\d\\w*)|([^`~!#%^&*()=+\\[{\\]}\\\\|;:'\",<>\\/?\\s]+)/g,\n brackets: [['{', '}']],\n autoClosingPairs: [\n { open: '{', close: '}' },\n { open: '\"', close: '\"' },\n { open: \"'\", close: \"'\" },\n ],\n surroundingPairs: [\n { open: '{', close: '}' },\n { open: '\"', close: '\"' },\n { open: \"'\", close: \"'\" },\n ],\n folding: {},\n};\n\nexport const language: languages.IMonarchLanguage = {\n ignoreCase: false,\n defaultToken: '',\n tokenPostfix: '.pyroscopeql',\n\n keywords: [],\n operators: [],\n\n // we include these common regular expressions\n symbols: /[=>](?!@symbols)/, '@brackets'],\n [\n /@symbols/,\n {\n cases: {\n '@operators': 'delimiter',\n '@default': '',\n },\n },\n ],\n\n // numbers\n [/\\d+/, 'number'],\n [/\\d*\\d+[eE]([\\-+]?\\d+)?(@floatsuffix)/, 'number.float'],\n [/\\d*\\.\\d+([eE][\\-+]?\\d+)?(@floatsuffix)/, 'number.float'],\n [/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'],\n [/0[0-7']*[0-7](@integersuffix)/, 'number.octal'],\n [/0[bB][0-1']*[0-1](@integersuffix)/, 'number.binary'],\n [/\\d[\\d']*\\d(@integersuffix)/, 'number'],\n [/\\d(@integersuffix)/, 'number'],\n ],\n\n string_double: [\n [/[^\\\\\"]+/, 'string'],\n [/@escapes/, 'string.escape'],\n [/\\\\./, 'string.escape.invalid'],\n [/\"/, 'string', '@pop'],\n ],\n\n string_single: [\n [/[^\\\\']+/, 'string'],\n [/@escapes/, 'string.escape'],\n [/\\\\./, 'string.escape.invalid'],\n [/'/, 'string', '@pop'],\n ],\n\n clauses: [\n [/[^(,)]/, 'tag'],\n [/\\)/, 'identifier', '@pop'],\n ],\n\n whitespace: [[/[ \\t\\r\\n]+/, 'white']],\n },\n};\n","import { monacoTypes, Monaco } from '@grafana/ui';\n\n/**\n * Class that implements CompletionItemProvider interface and allows us to provide suggestion for the Monaco\n * autocomplete system.\n *\n * At this moment we just pass it all the labels/values we get from Pyroscope backend later on we may do something a bit\n * smarter if there will be lots of labels.\n */\nexport class CompletionProvider implements monacoTypes.languages.CompletionItemProvider {\n triggerCharacters = ['{', ',', '[', '(', '=', '~', ' ', '\"'];\n\n // We set these directly and ae required for the provider to function.\n monaco: Monaco | undefined;\n editor: monacoTypes.editor.IStandaloneCodeEditor | undefined;\n\n private labels: string[] = [];\n private getLabelValues: (label: string) => Promise = () => Promise.resolve([]);\n\n init(labels: string[], getLabelValues: (label: string) => Promise) {\n this.labels = labels;\n this.getLabelValues = getLabelValues;\n }\n\n provideCompletionItems(\n model: monacoTypes.editor.ITextModel,\n position: monacoTypes.Position\n ): monacoTypes.languages.ProviderResult {\n // Should not happen, this should not be called before it is initialized\n if (!(this.monaco && this.editor)) {\n throw new Error('provideCompletionItems called before CompletionProvider was initialized');\n }\n\n // if the model-id does not match, then this call is from a different editor-instance,\n // not \"our instance\", so return nothing\n if (this.editor.getModel()?.id !== model.id) {\n return { suggestions: [] };\n }\n\n const { range, offset } = getRangeAndOffset(this.monaco, model, position);\n const situation = getSituation(model.getValue(), offset);\n\n return this.getCompletions(situation).then((completionItems) => {\n // monaco by-default alphabetically orders the items.\n // to stop it, we use a number-as-string sortkey,\n // so that monaco keeps the order we use\n const maxIndexDigits = completionItems.length.toString().length;\n const suggestions: monacoTypes.languages.CompletionItem[] = completionItems.map((item, index) => ({\n kind: getMonacoCompletionItemKind(item.type, this.monaco!),\n label: item.label,\n insertText: item.insertText,\n sortText: index.toString().padStart(maxIndexDigits, '0'), // to force the order we have\n range,\n }));\n return { suggestions };\n });\n }\n\n /**\n * Get suggestion based on the situation we are in like whether we should suggest label names or values.\n * @param situation\n * @private\n */\n private async getCompletions(situation: Situation): Promise {\n switch (situation.type) {\n // Not really sure what would make sense to suggest in this case so just leave it\n case 'UNKNOWN': {\n return [];\n }\n case 'EMPTY': {\n return this.labels.map((key) => {\n return {\n label: key,\n insertText: `{${key}=\"`,\n type: 'LABEL_NAME',\n };\n });\n }\n case 'IN_LABEL_NAME':\n return this.labels.map((key) => {\n return {\n label: key,\n insertText: key,\n type: 'LABEL_NAME',\n };\n });\n case 'IN_LABEL_VALUE':\n let values = await this.getLabelValues(situation.labelName);\n return values\n ? values.map((key) => {\n return {\n label: key,\n insertText: situation.betweenQuotes ? key : `\"${key}\"`,\n type: 'LABEL_VALUE',\n };\n })\n : [];\n default:\n throw new Error(`Unexpected situation ${situation}`);\n }\n }\n}\n\n/**\n * Get item kind which is used for icon next to the suggestion.\n * @param type\n * @param monaco\n */\nfunction getMonacoCompletionItemKind(type: CompletionType, monaco: Monaco): monacoTypes.languages.CompletionItemKind {\n switch (type) {\n case 'LABEL_NAME':\n return monaco.languages.CompletionItemKind.Enum;\n case 'LABEL_VALUE':\n return monaco.languages.CompletionItemKind.EnumMember;\n default:\n throw new Error(`Unexpected CompletionType: ${type}`);\n }\n}\n\nexport type CompletionType = 'LABEL_NAME' | 'LABEL_VALUE';\ntype Completion = {\n type: CompletionType;\n label: string;\n insertText: string;\n};\n\nexport type Label = {\n name: string;\n value: string;\n};\n\nexport type Situation =\n | {\n type: 'UNKNOWN';\n }\n | {\n type: 'EMPTY';\n }\n | {\n type: 'IN_LABEL_NAME';\n otherLabels: Label[];\n }\n | {\n type: 'IN_LABEL_VALUE';\n labelName: string;\n betweenQuotes: boolean;\n otherLabels: Label[];\n };\n\nconst labelNameRegex = /[a-zA-Z_][a-zA-Z0-9_]*/;\nconst labelValueRegex = /[^\"]*/; // anything except a double quote\nconst labelPairsRegex = new RegExp(`(${labelNameRegex.source})=\"(${labelValueRegex.source})\"`, 'g');\nconst inLabelValueRegex = new RegExp(`(${labelNameRegex.source})=(\"?)${labelValueRegex.source}$`);\nconst inLabelNameRegex = new RegExp(/[{,]\\s*[a-zA-Z0-9_]*$/);\n\n/**\n * Figure out where is the cursor and what kind of suggestions are appropriate.\n * As currently Pyroscope handles just a simple {foo=\"bar\", baz=\"zyx\"} kind of values we can do with simple regex to figure\n * out where we are with the cursor.\n * @param text\n * @param offset\n */\nfunction getSituation(text: string, offset: number): Situation {\n if (text === '') {\n return {\n type: 'EMPTY',\n };\n }\n\n // Get all the labels so far in the query, so we can do some more filtering.\n const matches = text.matchAll(labelPairsRegex);\n const existingLabels = Array.from(matches).reduce((acc, match) => {\n const [_, name, value] = match[1];\n acc.push({ name, value });\n return acc;\n }, []);\n\n // Check if we are editing a label value right now. If so also get name of the label\n const matchLabelValue = text.substring(0, offset).match(inLabelValueRegex);\n if (matchLabelValue) {\n return {\n type: 'IN_LABEL_VALUE',\n labelName: matchLabelValue[1],\n betweenQuotes: !!matchLabelValue[2],\n otherLabels: existingLabels,\n };\n }\n\n // Check if we are editing a label name\n const matchLabelName = text.substring(0, offset).match(inLabelNameRegex);\n if (matchLabelName) {\n return {\n type: 'IN_LABEL_NAME',\n otherLabels: existingLabels,\n };\n }\n\n // Will happen only if user writes something that isn't really a label selector\n return {\n type: 'UNKNOWN',\n };\n}\n\nfunction getRangeAndOffset(monaco: Monaco, model: monacoTypes.editor.ITextModel, position: monacoTypes.Position) {\n const word = model.getWordAtPosition(position);\n const range =\n word != null\n ? monaco.Range.lift({\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n })\n : monaco.Range.fromPositions(position);\n\n // documentation says `position` will be \"adjusted\" in `getOffsetAt` so we clone it here just for sure.\n const positionClone = {\n column: position.column,\n lineNumber: position.lineNumber,\n };\n\n const offset = model.getOffsetAt(positionClone);\n return { offset, range };\n}\n","import { css } from '@emotion/css';\nimport React, { useEffect, useRef } from 'react';\nimport { useAsync, useLatest } from 'react-use';\n\nimport { CodeEditor, Monaco, useStyles2, monacoTypes } from '@grafana/ui';\n\nimport { languageDefinition } from '../pyroscopeql';\n\nimport { CompletionProvider } from './autocomplete';\n\ninterface Props {\n value: string;\n onChange: (val: string) => void;\n onRunQuery: (value: string) => void;\n labels?: string[];\n getLabelValues: (label: string) => Promise;\n}\n\nexport function LabelsEditor(props: Props) {\n const setupAutocompleteFn = useAutocomplete(props.getLabelValues, props.labels);\n const styles = useStyles2(getStyles);\n\n const onRunQueryRef = useLatest(props.onRunQuery);\n const containerRef = useRef(null);\n\n return (\n \n {\n setupAutocompleteFn(editor, monaco);\n\n const updateElementHeight = () => {\n const containerDiv = containerRef.current;\n if (containerDiv !== null) {\n const pixelHeight = editor.getContentHeight();\n containerDiv.style.height = `${pixelHeight + EDITOR_HEIGHT_OFFSET}px`;\n containerDiv.style.width = '100%';\n const pixelWidth = containerDiv.clientWidth;\n editor.layout({ width: pixelWidth, height: pixelHeight });\n }\n };\n\n editor.onDidContentSizeChange(updateElementHeight);\n updateElementHeight();\n\n editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Enter, () => {\n onRunQueryRef.current(editor.getValue());\n });\n }}\n />\n \n );\n}\n\n// this number was chosen by testing various values. it might be necessary\n// because of the width of the border, not sure.\n//it needs to do 2 things:\n// 1. when the editor is single-line, it should make the editor height be visually correct\n// 2. when the editor is multi-line, the editor should not be \"scrollable\" (meaning,\n// you do a scroll-movement in the editor, and it will scroll the content by a couple pixels\n// up & down. this we want to avoid)\nconst EDITOR_HEIGHT_OFFSET = 2;\n\n/**\n * Hook that returns function that will set up monaco autocomplete for the label selector\n */\nfunction useAutocomplete(getLabelValues: (label: string) => Promise, labels?: string[]) {\n const providerRef = useRef();\n if (providerRef.current === undefined) {\n providerRef.current = new CompletionProvider();\n }\n\n useAsync(async () => {\n if (providerRef.current) {\n providerRef.current.init(labels || [], getLabelValues);\n }\n }, [labels, getLabelValues]);\n\n const autocompleteDisposeFun = useRef<(() => void) | null>(null);\n useEffect(() => {\n // when we unmount, we unregister the autocomplete-function, if it was registered\n return () => {\n autocompleteDisposeFun.current?.();\n };\n }, []);\n\n // This should be run in monaco onEditorDidMount\n return (editor: monacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco) => {\n if (providerRef.current) {\n providerRef.current.editor = editor;\n providerRef.current.monaco = monaco;\n\n const { dispose } = monaco.languages.registerCompletionItemProvider(langId, providerRef.current);\n autocompleteDisposeFun.current = dispose;\n }\n };\n}\n\n// we must only run the setup code once\nlet pyroscopeqlSetupDone = false;\nconst langId = 'pyroscopeql';\n\nfunction ensurePyroscopeQL(monaco: Monaco) {\n if (pyroscopeqlSetupDone === false) {\n pyroscopeqlSetupDone = true;\n const { aliases, extensions, mimetypes, def } = languageDefinition;\n monaco.languages.register({ id: langId, aliases, extensions, mimetypes });\n monaco.languages.setMonarchTokensProvider(langId, def.language);\n monaco.languages.setLanguageConfiguration(langId, def.languageConfiguration);\n }\n}\n\nconst getStyles = () => {\n return {\n queryField: css`\n label: LabelsEditorQueryField;\n flex: 1;\n // Not exactly sure but without this the editor does not shrink after resizing (so you can make it bigger but not\n // smaller). At the same time this does not actually make the editor 100px because it has flex 1 so I assume\n // this should sort of act as a flex-basis (but flex-basis does not work for this). So yeah CSS magic.\n width: 100px;\n `,\n wrapper: css`\n label: LabelsEditorWrapper;\n display: flex;\n flex: 1;\n border: 1px solid rgba(36, 41, 46, 0.3);\n border-radius: 2px;\n `,\n };\n};\n","import { css } from '@emotion/css';\nimport React from 'react';\nimport { useAsync } from 'react-use';\n\nimport { GrafanaTheme2, QueryEditorProps, TimeRange } from '@grafana/data';\nimport { getBackendSrv, getPluginLinkExtensions } from '@grafana/runtime';\nimport { LinkButton, useStyles2 } from '@grafana/ui';\n\nimport { PyroscopeDataSource } from '../datasource';\nimport { PyroscopeDataSourceOptions, Query } from '../types';\n\nconst EXTENSION_POINT_ID = 'plugins/grafana-pyroscope-datasource/query-links';\n\n/** A subset of the datasource settings that are relevant for this integration */\ntype PyroscopeDatasourceSettings = {\n uid: string;\n url: string;\n type: string;\n basicAuthUser: string;\n};\n\n/** The context object that will be shared with the link extension's configure function */\ntype ExtensionQueryLinksContext = {\n datasourceUid: string;\n query: Query;\n range?: TimeRange | undefined;\n datasourceSettings?: PyroscopeDatasourceSettings;\n};\n\n/* Global promises to fetch pyroscope datasource settings by uid as encountered */\nconst pyroscopeDatasourceSettingsByUid: Record = {};\n\n/* Reset promises for testing purposes */\nexport function resetPyroscopeQueryLinkExtensionsFetches() {\n Object.keys(pyroscopeDatasourceSettingsByUid).forEach((key) => delete pyroscopeDatasourceSettingsByUid[key]);\n}\n\n/** A subset of the `PyroscopeDataSource` `QueryEditorProps` */\nexport type Props = Pick<\n QueryEditorProps,\n 'datasource' | 'query' | 'range'\n>;\n\nexport function PyroscopeQueryLinkExtensions(props: Props) {\n const {\n datasource: { uid: datasourceUid },\n query,\n range,\n } = props;\n\n const { value: datasourceSettings } = useAsync(async () => {\n if (pyroscopeDatasourceSettingsByUid[datasourceUid]) {\n return pyroscopeDatasourceSettingsByUid[datasourceUid];\n }\n const settings = await getBackendSrv().get(`/api/datasources/uid/${datasourceUid}`);\n pyroscopeDatasourceSettingsByUid[datasourceUid] = settings;\n return settings;\n }, [datasourceUid]);\n\n const context: ExtensionQueryLinksContext = {\n datasourceUid,\n query,\n range,\n datasourceSettings,\n };\n\n const { extensions } = getPluginLinkExtensions({\n extensionPointId: EXTENSION_POINT_ID,\n context,\n });\n\n const styles = useStyles2(getStyles);\n\n if (extensions.length === 0) {\n return null;\n }\n\n return (\n <>\n {extensions.map((extension) => (\n \n {extension.title}\n \n ))}\n \n );\n}\n\nfunction getStyles(theme: GrafanaTheme2) {\n return {\n linkButton: css({\n marginLeft: theme.spacing(1),\n }),\n };\n}\n","import { css } from '@emotion/css';\nimport React, { ComponentProps } from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { Field, Icon, PopoverContent, ReactUtils, Tooltip, useStyles2 } from '@grafana/ui';\n\ninterface EditorFieldProps extends ComponentProps {\n label: string;\n children: React.ReactElement;\n width?: number | string;\n optional?: boolean;\n tooltip?: PopoverContent;\n}\n\nexport const EditorField = (props: EditorFieldProps) => {\n const { label, optional, tooltip, children, width, ...fieldProps } = props;\n\n const styles = useStyles2(getStyles, width);\n\n // Null check for backward compatibility\n const childInputId = fieldProps?.htmlFor || ReactUtils?.getChildId(children);\n\n const labelEl = (\n <>\n \n \n \n );\n\n return (\n
\n \n {children}\n \n
\n );\n};\n\nconst getStyles = (theme: GrafanaTheme2, width?: number | string) => ({\n space: css({\n paddingRight: theme.spacing(0),\n paddingBottom: theme.spacing(0.5),\n }),\n root: css({\n minWidth: theme.spacing(width ?? 0),\n }),\n label: css({\n fontSize: 12,\n fontWeight: theme.typography.fontWeightMedium,\n }),\n optional: css({\n fontStyle: 'italic',\n color: theme.colors.text.secondary,\n }),\n field: css({\n marginBottom: 0, // GrafanaUI/Field has a bottom margin which we must remove\n }),\n icon: css({\n color: theme.colors.text.secondary,\n marginLeft: theme.spacing(1),\n ':hover': {\n color: theme.colors.text.primary,\n },\n }),\n});\n","import { css } from '@emotion/css';\nimport React from 'react';\nimport { useToggle } from 'react-use';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { Collapse, useStyles2, Stack } from '@grafana/ui';\n\nexport interface Props {\n title: string;\n collapsedInfo: string[];\n children: React.ReactNode;\n}\n\nexport function QueryOptionGroup({ title, children, collapsedInfo }: Props) {\n const [isOpen, toggleOpen] = useToggle(false);\n const styles = useStyles2(getStyles);\n\n return (\n
\n \n
{title}
\n {!isOpen && (\n
\n {collapsedInfo.map((x, i) => (\n {x}\n ))}\n
\n )}\n \n }\n >\n
{children}
\n \n
\n );\n}\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n collapse: css({\n backgroundColor: 'unset',\n border: 'unset',\n marginBottom: 0,\n\n ['> button']: {\n padding: theme.spacing(0, 1),\n },\n }),\n wrapper: css({\n width: '100%',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n }),\n title: css({\n flexGrow: 1,\n overflow: 'hidden',\n fontSize: theme.typography.bodySmall.fontSize,\n fontWeight: theme.typography.fontWeightMedium,\n margin: 0,\n }),\n description: css({\n color: theme.colors.text.secondary,\n fontSize: theme.typography.bodySmall.fontSize,\n fontWeight: theme.typography.bodySmall.fontWeight,\n paddingLeft: theme.spacing(2),\n gap: theme.spacing(2),\n display: 'flex',\n }),\n body: css({\n display: 'flex',\n gap: theme.spacing(2),\n flexWrap: 'wrap',\n }),\n };\n};\n","import { css } from '@emotion/css';\nimport React from 'react';\n\nimport { CoreApp, GrafanaTheme2, SelectableValue } from '@grafana/data';\nimport { useStyles2, RadioButtonGroup, MultiSelect, Input } from '@grafana/ui';\n\nimport { Query } from '../types';\n\nimport { EditorField } from './EditorField';\nimport { QueryOptionGroup } from './QueryOptionGroup';\nimport { Stack } from './Stack';\n\nexport interface Props {\n query: Query;\n onQueryChange: (query: Query) => void;\n app?: CoreApp;\n labels?: string[];\n}\n\nconst typeOptions: Array<{ value: Query['queryType']; label: string; description: string }> = [\n { value: 'metrics', label: 'Metric', description: 'Return aggregated metrics' },\n { value: 'profile', label: 'Profile', description: 'Return profile' },\n { value: 'both', label: 'Both', description: 'Return both metric and profile data' },\n];\n\nfunction getTypeOptions(app?: CoreApp) {\n if (app === CoreApp.Explore) {\n return typeOptions;\n }\n return typeOptions.filter((option) => option.value !== 'both');\n}\n\n/**\n * Base on QueryOptionGroup component from grafana/ui but that is not available yet.\n */\nexport function QueryOptions({ query, onQueryChange, app, labels }: Props) {\n const styles = useStyles2(getStyles);\n const typeOptions = getTypeOptions(app);\n const groupByOptions = labels\n ? labels.map((l) => ({\n label: l,\n value: l,\n }))\n : [];\n\n let collapsedInfo = [`Type: ${query.queryType}`];\n if (query.groupBy?.length) {\n collapsedInfo.push(`Group by: ${query.groupBy.join(', ')}`);\n }\n if (query.spanSelector?.length) {\n collapsedInfo.push(`Span ID: ${query.spanSelector.join(', ')}`);\n }\n if (query.maxNodes) {\n collapsedInfo.push(`Max nodes: ${query.maxNodes}`);\n }\n\n return (\n \n \n
\n \n onQueryChange({ ...query, queryType: value })}\n />\n \n \n Used to group the metric result by a specific label or set of labels. Does not apply to profile query.\n \n }\n >\n {\n const changes = change.map((c: SelectableValue) => {\n return c.value!;\n });\n onQueryChange({ ...query, groupBy: changes });\n }}\n />\n \n Sets the span ID from which to search for profiles.}>\n ) => {\n onQueryChange({\n ...query,\n spanSelector: event.currentTarget.value !== '' ? [event.currentTarget.value] : [],\n });\n }}\n />\n \n Sets the maximum number of nodes to return in the flamegraph.}>\n ) => {\n let newValue = parseInt(event.currentTarget.value, 10);\n newValue = isNaN(newValue) ? 0 : newValue;\n onQueryChange({ ...query, maxNodes: newValue });\n }}\n />\n \n
\n
\n
\n );\n}\n\nconst getStyles = (theme: GrafanaTheme2) => {\n return {\n switchLabel: css({\n color: theme.colors.text.secondary,\n cursor: 'pointer',\n fontSize: theme.typography.bodySmall.fontSize,\n '&:hover': {\n color: theme.colors.text.primary,\n },\n }),\n body: css({\n display: 'flex',\n paddingTop: theme.spacing(2),\n gap: theme.spacing(2),\n flexWrap: 'wrap',\n }),\n };\n};\n","import deepEqual from 'fast-deep-equal';\nimport { debounce } from 'lodash';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { CoreApp, QueryEditorProps, TimeRange } from '@grafana/data';\nimport { LoadingPlaceholder } from '@grafana/ui';\n\nimport { normalizeQuery, PyroscopeDataSource } from '../datasource';\nimport { ProfileTypeMessage, PyroscopeDataSourceOptions, Query } from '../types';\n\nimport { EditorRow } from './EditorRow';\nimport { EditorRows } from './EditorRows';\nimport { LabelsEditor } from './LabelsEditor';\nimport { ProfileTypesCascader, useProfileTypes } from './ProfileTypesCascader';\nimport { PyroscopeQueryLinkExtensions } from './QueryLinkExtension';\nimport { QueryOptions } from './QueryOptions';\n\nexport type Props = QueryEditorProps;\n\nconst labelSelectorRegex = /(\\w+)\\s*=\\s*(\"[^,\"]+\")/g;\n\nexport function QueryEditor(props: Props) {\n const { onChange, onRunQuery, datasource, query, range, app } = props;\n\n function handleRunQuery(value: string) {\n onChange({ ...query, labelSelector: value });\n onRunQuery();\n }\n\n const onLabelSelectorChange = useLabelSelector(query, onChange);\n\n const profileTypes = useProfileTypes(datasource, range);\n const { labels, getLabelValues } = useLabels(range, datasource, query);\n useNormalizeQuery(query, profileTypes, onChange, app);\n\n let cascader = ;\n\n // The cascader is uncontrolled component so if we want to set some default value we can do it only on initial\n // render, so we are waiting until we have the profileTypes and know what the default value should be before\n // rendering.\n if (profileTypes && query.profileTypeId !== undefined) {\n cascader = (\n {\n onChange({ ...query, profileTypeId: val });\n }}\n />\n );\n }\n\n return (\n \n \n {cascader}\n \n \n \n \n \n \n \n );\n}\n\nfunction useNormalizeQuery(\n query: Query,\n profileTypes: ProfileTypeMessage[] | undefined,\n onChange: (value: Query) => void,\n app?: CoreApp\n) {\n useEffect(() => {\n if (!profileTypes) {\n return;\n }\n const normalizedQuery = normalizeQuery(query, app);\n // We just check if profileTypeId is filled but don't check if it's one of the existing cause it can be template\n // variable\n if (!query.profileTypeId) {\n normalizedQuery.profileTypeId = defaultProfileType(profileTypes);\n }\n // Makes sure we don't have an infinite loop updates because the normalization creates a new object\n if (!deepEqual(query, normalizedQuery)) {\n onChange(normalizedQuery);\n }\n }, [app, query, profileTypes, onChange]);\n}\n\nfunction defaultProfileType(profileTypes: ProfileTypeMessage[]): string {\n const cpuProfiles = profileTypes.filter((p) => p.id.indexOf('cpu') >= 0);\n if (cpuProfiles.length) {\n // Prefer cpu time profile if available instead of samples\n const cpuTimeProfile = cpuProfiles.find((p) => p.id.indexOf('samples') === -1);\n if (cpuTimeProfile) {\n return cpuTimeProfile.id;\n }\n // Fallback to first cpu profile type\n return cpuProfiles[0].id;\n }\n\n // Fallback to first profile type from response data\n return profileTypes[0]?.id || '';\n}\n\nfunction useLabels(range: TimeRange | undefined, datasource: PyroscopeDataSource, query: Query) {\n // Round to nearest 5 seconds. If the range is something like last 1h then every render the range values change slightly\n // and what ever has range as dependency is rerun. So this effectively debounces the queries.\n const unpreciseRange = {\n to: Math.ceil((range?.to.valueOf() || 0) / 10000) * 10000,\n from: Math.floor((range?.from.valueOf() || 0) / 10000) * 10000,\n };\n\n // Transforms user input into a valid label selector including the profile type.\n // It can optionally remove a label, used to support editing existing label values.\n const createSelector = (rawInput: string, profileTypeId: string, labelToRemove: string): string => {\n let labels: string[] = [`__profile_type__=\\\"${profileTypeId}\\\"`];\n let match;\n while ((match = labelSelectorRegex.exec(rawInput)) !== null) {\n if (match[1] && match[2]) {\n if (match[1] === labelToRemove) {\n continue;\n }\n labels.push(`${match[1]}=${match[2]}`);\n }\n }\n return `{${labels.join(',')}}`;\n };\n\n const [labels, setLabels] = useState(() => ['']);\n\n useEffect(() => {\n const fetchData = async () => {\n const labels = await datasource.getLabelNames(\n createSelector(query.labelSelector, query.profileTypeId, ''),\n unpreciseRange.from,\n unpreciseRange.to\n );\n\n setLabels(labels);\n };\n fetchData();\n }, [query, unpreciseRange.from, unpreciseRange.to, datasource, setLabels]);\n\n // Create a function with range and query already baked in, so we don't have to send those everywhere\n const getLabelValues = useCallback(\n (label: string) => {\n const labelSelector = createSelector(query.labelSelector, query.profileTypeId, label);\n return datasource.getLabelValues(labelSelector, label, unpreciseRange.from, unpreciseRange.to);\n },\n [datasource, query.labelSelector, query.profileTypeId, unpreciseRange.to, unpreciseRange.from]\n );\n\n return { labels, getLabelValues };\n}\n\nfunction useLabelSelector(query: Query, onChange: (value: Query) => void) {\n // Need to reference the query as otherwise when the label selector is changed, only the initial value\n // of the query is passed into the LabelsEditor (onChange) which renders the CodeEditor for monaco.\n // The above needs to have a ref to the query so it can get the latest value.\n const queryRef = useRef(query);\n queryRef.current = query;\n\n const onChangeDebounced = debounce((value: string) => {\n if (onChange) {\n onChange({ ...queryRef.current, labelSelector: value });\n }\n }, 200);\n\n const onLabelSelectorChange = useCallback(\n (value: string) => {\n onChangeDebounced(value);\n },\n [onChangeDebounced]\n );\n\n return onLabelSelectorChange;\n}\n","import { DataSourcePlugin } from '@grafana/data';\n\nimport { ConfigEditor } from './ConfigEditor';\nimport { QueryEditor } from './QueryEditor/QueryEditor';\nimport { PyroscopeDataSource } from './datasource';\nimport { Query, PyroscopeDataSourceOptions } from './types';\n\nexport const plugin = new DataSourcePlugin(PyroscopeDataSource)\n .setConfigEditor(ConfigEditor)\n .setQueryEditor(QueryEditor);\n","import { useRef } from 'react';\nvar useLatest = function (value) {\n var ref = useRef(value);\n ref.current = value;\n return ref;\n};\nexport default useLatest;\n"],"names":["ConfigEditor","props","options","onOptionsChange","DataSourceHttpSettings","config","event","ProfileTypesCascader","cascaderOptions","useCascaderOptions","Cascader","profileTypes","mainTypes","profileType","parts","name","type","useProfileTypes","datasource","range","setProfileTypes","impreciseRange","VariableQueryEditor","InlineFieldRow","InlineField","Select","value","ProfileTypeRow","val","LabelRow","labels","setLabels","v","option","LoadingPlaceholder","VariableSupport","dataAPI","request","from","map","values","of","defaultPyroscopeQueryType","defaultGrafanaPyroscope","extractLabelMatchers","tokens","labelMatchers","token","labelKey","labelValue","labelOperator","contentTokens","currentToken","currentStr","getMaybeTokenStringContent","labelComparator","FromPromLikeMap","toPromLikeExpr","labelBasedQuery","expr","selector","operator","ToPromLikeMap","e","PyroscopeDataSource","DataSourceWithBackend","instanceSettings","templateSrv","validTargets","t","normalizeQuery","start","end","query","label","scopedVars","abstractQueries","abstractQuery","queries","pyroscopeQuery","grammar","app","defaultQuery","normalized","Stack","styles","getStyles","theme","EditorRow","children","stackProps","EditorRows","languageDefinition","CompletionProvider","getLabelValues","model","position","offset","getRangeAndOffset","situation","getSituation","completionItems","maxIndexDigits","item","index","getMonacoCompletionItemKind","key","monaco","labelNameRegex","labelValueRegex","labelPairsRegex","inLabelValueRegex","inLabelNameRegex","text","matches","existingLabels","acc","match","_","matchLabelValue","word","positionClone","LabelsEditor","setupAutocompleteFn","useAutocomplete","onRunQueryRef","useLatest","containerRef","CodeEditor","langId","ensurePyroscopeQL","editor","updateElementHeight","containerDiv","pixelHeight","EDITOR_HEIGHT_OFFSET","pixelWidth","providerRef","useAsync","autocompleteDisposeFun","dispose","pyroscopeqlSetupDone","aliases","extensions","mimetypes","def","EXTENSION_POINT_ID","pyroscopeDatasourceSettingsByUid","resetPyroscopeQueryLinkExtensionsFetches","PyroscopeQueryLinkExtensions","datasourceUid","datasourceSettings","settings","context","extension","EditorField","optional","tooltip","width","fieldProps","childInputId","labelEl","Tooltip","Icon","Field","QueryOptionGroup","title","collapsedInfo","isOpen","toggleOpen","useToggle","Collapse","x","i","typeOptions","getTypeOptions","QueryOptions","onQueryChange","groupByOptions","l","RadioButtonGroup","change","changes","c","Input","newValue","labelSelectorRegex","QueryEditor","onChange","onRunQuery","handleRunQuery","onLabelSelectorChange","useLabelSelector","useLabels","useNormalizeQuery","cascader","normalizedQuery","defaultProfileType","cpuProfiles","p","cpuTimeProfile","unpreciseRange","createSelector","rawInput","profileTypeId","labelToRemove","labelSelector","queryRef","onChangeDebounced","ref"],"sourceRoot":""}