diff --git a/.betterer.results b/.betterer.results index bc0bc0bc00e..fc71a114ad2 100644 --- a/.betterer.results +++ b/.betterer.results @@ -529,6 +529,9 @@ exports[`better eslint`] = { [0, 0, 0, "Styles should be written using objects.", "0"], [0, 0, 0, "Styles should be written using objects.", "1"] ], + "packages/grafana-o11y-ds-frontend/src/utils.ts:5381": [ + [0, 0, 0, "Do not use any type assertions.", "0"] + ], "packages/grafana-runtime/src/analytics/types.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], @@ -1051,14 +1054,6 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "2"] ], - "public/app/core/components/TraceToLogs/TagMappingInput.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], - "public/app/core/components/TraceToMetrics/TraceToMetricsSettings.tsx:5381": [ - [0, 0, 0, "Styles should be written using objects.", "0"], - [0, 0, 0, "Styles should be written using objects.", "1"], - [0, 0, 0, "Styles should be written using objects.", "2"] - ], "public/app/core/components/Upgrade/ProBadge.tsx:5381": [ [0, 0, 0, "Styles should be written using objects.", "0"] ], @@ -1202,9 +1197,6 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"] ], - "public/app/core/utils/tracing.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], "public/app/features/admin/LicenseChrome.tsx:5381": [ [0, 0, 0, "Styles should be written using objects.", "0"], [0, 0, 0, "Styles should be written using objects.", "1"], @@ -5750,17 +5742,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "2"] ], - "public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TagMappingInput.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], - "public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToMetrics/TraceToMetricsSettings.tsx:5381": [ - [0, 0, 0, "Styles should be written using objects.", "0"], - [0, 0, 0, "Styles should be written using objects.", "1"], - [0, 0, 0, "Styles should be written using objects.", "2"] - ], - "public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/utils.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], "public/app/plugins/datasource/tempo/_importedDependencies/store.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7c819a65e21..dacbaad9cbb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -340,9 +340,9 @@ /packages/grafana-flamegraph/ @grafana/observability-traces-and-profiling /plugins-bundled/ @grafana/plugins-platform-frontend /packages/grafana-plugin-configs/ @grafana/plugins-platform-frontend +/packages/grafana-o11y-ds-frontend/ @grafana/observability-logs @grafana/observability-traces-and-profiling - -# root files, mostly frontend +# root files, mostly frontend .browserslistrc @grafana/frontend-ops package.json @grafana/frontend-ops tsconfig.json @grafana/frontend-ops @@ -375,7 +375,6 @@ cypress.config.js @grafana/grafana-frontend-platform /public/app/core/ @grafana/grafana-frontend-platform /public/app/core/components/TimePicker/ @grafana/grafana-frontend-platform /public/app/core/components/Layers/ @grafana/dataviz-squad -/public/app/core/components/TraceToLogs @grafana/observability-traces-and-profiling /public/app/core/components/GraphNG/ @grafana/dataviz-squad /public/app/core/components/TimeSeries/ @grafana/dataviz-squad /public/app/core/components/TimelineChart/ @grafana/dataviz-squad diff --git a/package.json b/package.json index 98fa6085410..1f4217b9025 100644 --- a/package.json +++ b/package.json @@ -243,6 +243,7 @@ "@grafana/google-sdk": "0.1.2", "@grafana/lezer-logql": "0.2.2", "@grafana/monaco-logql": "^0.0.7", + "@grafana/o11y-ds-frontend": "workspace:*", "@grafana/runtime": "workspace:*", "@grafana/scenes": "1.30.0", "@grafana/schema": "workspace:*", diff --git a/packages/grafana-o11y-ds-frontend/package.json b/packages/grafana-o11y-ds-frontend/package.json new file mode 100644 index 00000000000..8b5f8c8bf62 --- /dev/null +++ b/packages/grafana-o11y-ds-frontend/package.json @@ -0,0 +1,51 @@ +{ + "author": "Grafana Labs", + "license": "AGPL-3.0-only", + "name": "@grafana/o11y-ds-frontend", + "private": true, + "version": "10.4.0-pre", + "description": "Library to manage traces in Grafana.", + "sideEffects": false, + "repository": { + "type": "git", + "url": "http://github.com/grafana/grafana.git", + "directory": "packages/grafana-o11y-ds-frontend" + }, + "main": "src/index.ts", + "types": "src/index.ts", + "scripts": { + "typecheck": "tsc --emitDeclarationOnly false --noEmit" + }, + "dependencies": { + "@emotion/css": "11.11.2", + "@grafana/data": "workspace:*", + "@grafana/e2e-selectors": "workspace:*", + "@grafana/experimental": "1.7.5", + "@grafana/runtime": "workspace:*", + "@grafana/schema": "workspace:*", + "@grafana/ui": "workspace:*", + "react": "18.2.0", + "react-use": "17.4.0", + "rxjs": "7.8.1", + "tslib": "2.6.0" + }, + "devDependencies": { + "@grafana/tsconfig": "^1.2.0-rc1", + "@testing-library/jest-dom": "^6.1.2", + "@testing-library/react": "14.1.2", + "@testing-library/user-event": "14.5.2", + "@types/jest": "^29.5.4", + "@types/react": "18.2.15", + "@types/systemjs": "6.13.5", + "@types/testing-library__jest-dom": "5.14.9", + "jest": "^29.6.4", + "react": "18.2.0", + "ts-jest": "29.1.1", + "ts-node": "10.9.1", + "typescript": "5.2.2" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + } +} diff --git a/public/app/core/components/IntervalInput/IntervalInput.test.tsx b/packages/grafana-o11y-ds-frontend/src/IntervalInput/IntervalInput.test.tsx similarity index 100% rename from public/app/core/components/IntervalInput/IntervalInput.test.tsx rename to packages/grafana-o11y-ds-frontend/src/IntervalInput/IntervalInput.test.tsx diff --git a/public/app/core/components/IntervalInput/IntervalInput.tsx b/packages/grafana-o11y-ds-frontend/src/IntervalInput/IntervalInput.tsx similarity index 100% rename from public/app/core/components/IntervalInput/IntervalInput.tsx rename to packages/grafana-o11y-ds-frontend/src/IntervalInput/IntervalInput.tsx diff --git a/public/app/core/components/IntervalInput/validation.test.ts b/packages/grafana-o11y-ds-frontend/src/IntervalInput/validation.test.ts similarity index 100% rename from public/app/core/components/IntervalInput/validation.test.ts rename to packages/grafana-o11y-ds-frontend/src/IntervalInput/validation.test.ts diff --git a/public/app/core/components/IntervalInput/validation.ts b/packages/grafana-o11y-ds-frontend/src/IntervalInput/validation.ts similarity index 100% rename from public/app/core/components/IntervalInput/validation.ts rename to packages/grafana-o11y-ds-frontend/src/IntervalInput/validation.ts diff --git a/public/app/core/components/TraceToLogs/TagMappingInput.tsx b/packages/grafana-o11y-ds-frontend/src/TraceToLogs/TagMappingInput.tsx similarity index 93% rename from public/app/core/components/TraceToLogs/TagMappingInput.tsx rename to packages/grafana-o11y-ds-frontend/src/TraceToLogs/TagMappingInput.tsx index 2dea321ab02..d263682a92f 100644 --- a/public/app/core/components/TraceToLogs/TagMappingInput.tsx +++ b/packages/grafana-o11y-ds-frontend/src/TraceToLogs/TagMappingInput.tsx @@ -3,7 +3,6 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { InlineLabel, SegmentInput, ToolbarButton, useStyles2 } from '@grafana/ui'; -import { ToolbarButtonVariant } from '@grafana/ui/src/components/ToolbarButton'; import { TraceToLogsTag } from './TraceToLogsSettings'; @@ -13,8 +12,6 @@ interface Props { id?: string; } -const VARIANT = 'none' as ToolbarButtonVariant; - export const TagMappingInput = ({ values, onChange, id }: Props) => { const styles = useStyles2(getStyles); @@ -60,7 +57,6 @@ export const TagMappingInput = ({ values, onChange, id }: Props) => { onClick={() => onChange([...values.slice(0, idx), ...values.slice(idx + 1)])} className={cx(styles.removeTag, 'query-part')} aria-label="Remove tag" - variant={VARIANT} type="button" icon="times" /> @@ -71,7 +67,6 @@ export const TagMappingInput = ({ values, onChange, id }: Props) => { className="query-part" aria-label="Add tag" type="button" - variant={VARIANT} icon="plus" /> ) : null} @@ -84,7 +79,6 @@ export const TagMappingInput = ({ values, onChange, id }: Props) => { className="query-part" aria-label="Add tag" type="button" - variant={VARIANT} /> )} diff --git a/public/app/core/components/TraceToLogs/TraceToLogsSettings.test.tsx b/packages/grafana-o11y-ds-frontend/src/TraceToLogs/TraceToLogsSettings.test.tsx similarity index 100% rename from public/app/core/components/TraceToLogs/TraceToLogsSettings.test.tsx rename to packages/grafana-o11y-ds-frontend/src/TraceToLogs/TraceToLogsSettings.test.tsx diff --git a/public/app/core/components/TraceToLogs/TraceToLogsSettings.tsx b/packages/grafana-o11y-ds-frontend/src/TraceToLogs/TraceToLogsSettings.tsx similarity index 98% rename from public/app/core/components/TraceToLogs/TraceToLogsSettings.tsx rename to packages/grafana-o11y-ds-frontend/src/TraceToLogs/TraceToLogsSettings.tsx index 1ad52864719..02c6d04ec0e 100644 --- a/public/app/core/components/TraceToLogs/TraceToLogsSettings.tsx +++ b/packages/grafana-o11y-ds-frontend/src/TraceToLogs/TraceToLogsSettings.tsx @@ -3,8 +3,8 @@ import React, { useCallback, useMemo } from 'react'; import { DataSourceJsonData, DataSourceInstanceSettings, DataSourcePluginOptionsEditorProps } from '@grafana/data'; import { ConfigDescriptionLink, ConfigSection } from '@grafana/experimental'; +import { DataSourcePicker } from '@grafana/runtime'; import { InlineField, InlineFieldRow, Input, InlineSwitch } from '@grafana/ui'; -import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; import { IntervalInput } from '../IntervalInput/IntervalInput'; diff --git a/public/app/core/components/TraceToMetrics/TraceToMetricsSettings.tsx b/packages/grafana-o11y-ds-frontend/src/TraceToMetrics/TraceToMetricsSettings.tsx similarity index 95% rename from public/app/core/components/TraceToMetrics/TraceToMetricsSettings.tsx rename to packages/grafana-o11y-ds-frontend/src/TraceToMetrics/TraceToMetricsSettings.tsx index 3168f8a8692..90249d4dd3f 100644 --- a/public/app/core/components/TraceToMetrics/TraceToMetricsSettings.tsx +++ b/packages/grafana-o11y-ds-frontend/src/TraceToMetrics/TraceToMetricsSettings.tsx @@ -9,8 +9,8 @@ import { updateDatasourcePluginJsonDataOption, } from '@grafana/data'; import { ConfigDescriptionLink, ConfigSection } from '@grafana/experimental'; +import { DataSourcePicker } from '@grafana/runtime'; import { Button, InlineField, InlineFieldRow, Input, useStyles2 } from '@grafana/ui'; -import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; import { IntervalInput } from '../IntervalInput/IntervalInput'; import { TagMappingInput } from '../TraceToLogs/TagMappingInput'; @@ -228,17 +228,17 @@ export const TraceToMetricsSection = ({ options, onOptionsChange }: DataSourcePl }; const getStyles = (theme: GrafanaTheme2) => ({ - infoText: css` - padding-bottom: ${theme.spacing(2)}; - color: ${theme.colors.text.secondary}; - `, - row: css` - label: row; - align-items: baseline; - `, - queryRow: css` - label: queryRow; - display: flex; - flex-flow: wrap; - `, + infoText: { + paddingBottom: theme.spacing(2), + color: theme.colors.text.secondary, + }, + row: css({ + label: 'row', + alignItems: 'baseline', + }), + queryRow: css({ + label: 'queryRow', + display: 'flex', + flexFlow: 'wrap', + }), }); diff --git a/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.test.tsx b/packages/grafana-o11y-ds-frontend/src/TraceToProfiles/TraceToProfilesSettings.test.tsx similarity index 100% rename from public/app/core/components/TraceToProfiles/TraceToProfilesSettings.test.tsx rename to packages/grafana-o11y-ds-frontend/src/TraceToProfiles/TraceToProfilesSettings.test.tsx diff --git a/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx b/packages/grafana-o11y-ds-frontend/src/TraceToProfiles/TraceToProfilesSettings.tsx similarity index 94% rename from public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx rename to packages/grafana-o11y-ds-frontend/src/TraceToProfiles/TraceToProfilesSettings.tsx index c5381ceb6c6..ebabc60dd01 100644 --- a/public/app/core/components/TraceToProfiles/TraceToProfilesSettings.tsx +++ b/packages/grafana-o11y-ds-frontend/src/TraceToProfiles/TraceToProfilesSettings.tsx @@ -9,13 +9,13 @@ import { updateDatasourcePluginJsonDataOption, } from '@grafana/data'; import { ConfigDescriptionLink, ConfigSection } from '@grafana/experimental'; -import { DataSourceWithBackend, getDataSourceSrv } from '@grafana/runtime'; +import { DataSourcePicker, DataSourceWithBackend, getDataSourceSrv } from '@grafana/runtime'; import { InlineField, InlineFieldRow, Input, InlineSwitch } from '@grafana/ui'; -import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker'; -import { ProfileTypesCascader } from 'app/plugins/datasource/grafana-pyroscope-datasource/QueryEditor/ProfileTypesCascader'; -import { ProfileTypeMessage } from 'app/plugins/datasource/grafana-pyroscope-datasource/types'; import { TagMappingInput } from '../TraceToLogs/TagMappingInput'; +import { ProfileTypesCascader } from '../pyroscope/ProfileTypesCascader'; +import { ProfileTypeMessage } from '../pyroscope/types'; + export interface TraceToProfilesOptions { datasourceUid?: string; tags?: Array<{ key: string; value?: string }>; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/index.ts b/packages/grafana-o11y-ds-frontend/src/index.ts similarity index 100% rename from public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/index.ts rename to packages/grafana-o11y-ds-frontend/src/index.ts diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/ProfileTypesCascader.tsx b/packages/grafana-o11y-ds-frontend/src/pyroscope/ProfileTypesCascader.tsx similarity index 100% rename from public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/ProfileTypesCascader.tsx rename to packages/grafana-o11y-ds-frontend/src/pyroscope/ProfileTypesCascader.tsx diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/dataquery.gen.ts b/packages/grafana-o11y-ds-frontend/src/pyroscope/dataquery.gen.ts similarity index 87% rename from public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/dataquery.gen.ts rename to packages/grafana-o11y-ds-frontend/src/pyroscope/dataquery.gen.ts index b6e39ae2c7d..1b4ed70c46f 100644 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/dataquery.gen.ts +++ b/packages/grafana-o11y-ds-frontend/src/pyroscope/dataquery.gen.ts @@ -36,9 +36,3 @@ export interface GrafanaPyroscope extends common.DataQuery { */ spanSelector?: Array; } - -export const defaultGrafanaPyroscope: Partial = { - groupBy: [], - labelSelector: '{}', - spanSelector: [], -}; diff --git a/packages/grafana-o11y-ds-frontend/src/pyroscope/datasource.ts b/packages/grafana-o11y-ds-frontend/src/pyroscope/datasource.ts new file mode 100644 index 00000000000..39bd35fb177 --- /dev/null +++ b/packages/grafana-o11y-ds-frontend/src/pyroscope/datasource.ts @@ -0,0 +1,13 @@ +import { Observable } from 'rxjs'; + +import { CoreApp, DataQueryRequest, DataQueryResponse, ScopedVars } from '@grafana/data'; +import { DataSourceWithBackend } from '@grafana/runtime'; + +import { PyroscopeDataSourceOptions, ProfileTypeMessage, Query } from './types'; + +export abstract class PyroscopeDataSource extends DataSourceWithBackend { + abstract applyTemplateVariables(query: Query, scopedVars: ScopedVars): Query; + abstract getDefaultQuery(app: CoreApp): Partial; + abstract getProfileTypes(): Promise; + abstract query(request: DataQueryRequest): Observable; +} diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/types.ts b/packages/grafana-o11y-ds-frontend/src/pyroscope/types.ts similarity index 100% rename from public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/types.ts rename to packages/grafana-o11y-ds-frontend/src/pyroscope/types.ts diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/utils.ts b/packages/grafana-o11y-ds-frontend/src/utils.ts similarity index 97% rename from public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/utils.ts rename to packages/grafana-o11y-ds-frontend/src/utils.ts index c0e94787628..3687db979e8 100644 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/utils.ts +++ b/packages/grafana-o11y-ds-frontend/src/utils.ts @@ -65,6 +65,7 @@ export function makeSpanMap(getSpan: (index: number) => { span: T; id: string } } } + // Discussion on this type assertion here: https://github.com/grafana/grafana/pull/80362/files#r1451019375 return spanMap as { [id: string]: { span: T; children: string[] } }; } diff --git a/packages/grafana-o11y-ds-frontend/tsconfig.json b/packages/grafana-o11y-ds-frontend/tsconfig.json new file mode 100644 index 00000000000..03aa83f469f --- /dev/null +++ b/packages/grafana-o11y-ds-frontend/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "declarationDir": "./compiled", + "emitDeclarationOnly": true, + "isolatedModules": true, + "rootDirs": ["."] + }, + "exclude": ["dist/**/*"], + "extends": "@grafana/tsconfig", + "include": ["src/**/*.ts*", "../../public/app/types/*.d.ts", "../grafana-ui/src/types/*.d.ts"] +} diff --git a/public/app/core/utils/tracing.ts b/public/app/core/utils/tracing.ts deleted file mode 100644 index c0e94787628..00000000000 --- a/public/app/core/utils/tracing.ts +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Get non overlapping duration of the ranges as they can overlap or have gaps. - */ -import { FieldType, MutableDataFrame, NodeGraphDataFrameFieldNames as Fields } from '@grafana/data'; - -export function getNonOverlappingDuration(ranges: Array<[number, number]>): number { - ranges.sort((a, b) => a[0] - b[0]); - const mergedRanges = ranges.reduce>((acc, range) => { - if (!acc.length) { - return [range]; - } - const tail = acc.slice(-1)[0]; - const [prevStart, prevEnd] = tail; - const [start, end] = range; - if (end < prevEnd) { - // In this case the range is completely inside the prev range so we can just ignore it. - return acc; - } - - if (start > prevEnd) { - // There is no overlap so we can just add it to stack - return [...acc, range]; - } - - // We know there is overlap and current range ends later than previous so we can just extend the range - return [...acc.slice(0, -1), [prevStart, end]]; - }, []); - - return mergedRanges.reduce((acc, range) => { - return acc + (range[1] - range[0]); - }, 0); -} - -/** - * Returns a map of the spans with children array for easier processing. It will also contain empty spans in case - * span is missing but other spans are its children. This is more generic because it needs to allow iterating over - * both arrays and dataframe views. - */ -export function makeSpanMap(getSpan: (index: number) => { span: T; id: string; parentIds: string[] } | undefined): { - [id: string]: { span: T; children: string[] }; -} { - const spanMap: { [id: string]: { span?: T; children: string[] } } = {}; - - let span; - for (let index = 0; (span = getSpan(index)), !!span; index++) { - if (!spanMap[span.id]) { - spanMap[span.id] = { - span: span.span, - children: [], - }; - } else { - spanMap[span.id].span = span.span; - } - - for (const parentId of span.parentIds) { - if (parentId) { - if (!spanMap[parentId]) { - spanMap[parentId] = { - span: undefined, - children: [span.id], - }; - } else { - spanMap[parentId].children.push(span.id); - } - } - } - } - return spanMap as { [id: string]: { span: T; children: string[] } }; -} - -export function getStats(duration: number, traceDuration: number, selfDuration: number) { - return { - main: `${toFixedNoTrailingZeros(duration)}ms (${toFixedNoTrailingZeros((duration / traceDuration) * 100)}%)`, - secondary: `${toFixedNoTrailingZeros(selfDuration)}ms (${toFixedNoTrailingZeros( - (selfDuration / duration) * 100 - )}%)`, - }; -} - -function toFixedNoTrailingZeros(n: number) { - return parseFloat(n.toFixed(2)); -} - -/** - * Create default frames used when returning data for node graph. - */ -export function makeFrames() { - const nodesFrame = new MutableDataFrame({ - fields: [ - { name: Fields.id, type: FieldType.string }, - { name: Fields.title, type: FieldType.string }, - { name: Fields.subTitle, type: FieldType.string }, - { name: Fields.mainStat, type: FieldType.string, config: { displayName: 'Total time (% of trace)' } }, - { name: Fields.secondaryStat, type: FieldType.string, config: { displayName: 'Self time (% of total)' } }, - { - name: Fields.color, - type: FieldType.number, - config: { color: { mode: 'continuous-GrYlRd' }, displayName: 'Self time / Trace duration' }, - }, - ], - meta: { - preferredVisualisationType: 'nodeGraph', - }, - }); - - const edgesFrame = new MutableDataFrame({ - fields: [ - { name: Fields.id, type: FieldType.string }, - { name: Fields.target, type: FieldType.string }, - { name: Fields.source, type: FieldType.string }, - ], - meta: { - preferredVisualisationType: 'nodeGraph', - }, - }); - - return [nodesFrame, edgesFrame]; -} diff --git a/public/app/features/explore/TraceView/TraceView.tsx b/public/app/features/explore/TraceView/TraceView.tsx index 641e135ed54..d4afe959b4f 100644 --- a/public/app/features/explore/TraceView/TraceView.tsx +++ b/public/app/features/explore/TraceView/TraceView.tsx @@ -14,13 +14,11 @@ import { mapInternalLinkToExplore, SplitOpen, } from '@grafana/data'; +import { getTraceToLogsOptions, TraceToMetricsData, TraceToProfilesData } from '@grafana/o11y-ds-frontend'; import { getTemplateSrv } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { useStyles2 } from '@grafana/ui'; import { TempoQuery } from '@grafana-plugins/tempo/types'; -import { getTraceToLogsOptions } from 'app/core/components/TraceToLogs/TraceToLogsSettings'; -import { TraceToMetricsData } from 'app/core/components/TraceToMetrics/TraceToMetricsSettings'; -import { TraceToProfilesData } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { getTimeZone } from 'app/features/profile/state/selectors'; import { useDispatch, useSelector } from 'app/types'; diff --git a/public/app/features/explore/TraceView/components/TracePageHeader/SpanFilters/SpanFilters.tsx b/public/app/features/explore/TraceView/components/TracePageHeader/SpanFilters/SpanFilters.tsx index e052ad598b7..5878c76d2a8 100644 --- a/public/app/features/explore/TraceView/components/TracePageHeader/SpanFilters/SpanFilters.tsx +++ b/public/app/features/explore/TraceView/components/TracePageHeader/SpanFilters/SpanFilters.tsx @@ -19,8 +19,8 @@ import React, { useState, useEffect, memo, useCallback } from 'react'; import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data'; import { AccessoryButton } from '@grafana/experimental'; +import { IntervalInput } from '@grafana/o11y-ds-frontend'; import { Collapse, HorizontalGroup, Icon, InlineField, InlineFieldRow, Select, Tooltip, useStyles2 } from '@grafana/ui'; -import { IntervalInput } from 'app/core/components/IntervalInput/IntervalInput'; import { defaultFilters, randomId, SearchProps, Tag } from '../../../useSearch'; import SearchBarInput from '../../common/SearchBarInput'; diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx index 631fef72849..88351d5dcca 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/SpanFlameGraph.tsx @@ -13,9 +13,9 @@ import { TimeZone, } from '@grafana/data'; import { FlameGraph } from '@grafana/flamegraph'; +import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend'; import { config, DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; -import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { PyroscopeQueryType } from 'app/plugins/datasource/grafana-pyroscope-datasource/dataquery.gen'; import { Query } from 'app/plugins/datasource/grafana-pyroscope-datasource/types'; diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx index 6e1c16988d1..abfde5fe3b6 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetail/index.tsx @@ -18,11 +18,11 @@ import cx from 'classnames'; import React from 'react'; import { DataFrame, dateTimeFormat, GrafanaTheme2, IconName, LinkModel } from '@grafana/data'; +import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend'; import { config, locationService, reportInteraction } from '@grafana/runtime'; import { TimeZone } from '@grafana/schema'; import { DataLinkButton, Icon, TextArea, useStyles2 } from '@grafana/ui'; import { RelatedProfilesTitle } from '@grafana-plugins/tempo/resultTransformer'; -import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { pyroscopeProfileIdTagKey } from '../../../createSpanLink'; import { autoColor } from '../../Theme'; diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.tsx index ac687cf875e..6ecfb228891 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/SpanDetailRow.tsx @@ -17,9 +17,9 @@ import classNames from 'classnames'; import React from 'react'; import { GrafanaTheme2, LinkModel } from '@grafana/data'; +import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend'; import { TimeZone } from '@grafana/schema'; import { Button, clearButtonStyles, stylesFactory, withTheme2 } from '@grafana/ui'; -import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { autoColor } from '../Theme'; import { SpanLinkFunc } from '../types'; diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/VirtualizedTraceView.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/VirtualizedTraceView.tsx index 8ae05209ecd..d1101c49ffa 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/VirtualizedTraceView.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/VirtualizedTraceView.tsx @@ -19,10 +19,10 @@ import * as React from 'react'; import { RefObject } from 'react'; import { GrafanaTheme2, LinkModel } from '@grafana/data'; +import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend'; import { config, reportInteraction } from '@grafana/runtime'; import { TimeZone } from '@grafana/schema'; import { stylesFactory, withTheme2, ToolbarButton } from '@grafana/ui'; -import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { PEER_SERVICE } from '../constants/tag-keys'; import { CriticalPathSection, SpanBarOptions, SpanLinkFunc, TNil } from '../types'; diff --git a/public/app/features/explore/TraceView/components/TraceTimelineViewer/index.tsx b/public/app/features/explore/TraceView/components/TraceTimelineViewer/index.tsx index 447a33d23c2..b2fccd6a996 100644 --- a/public/app/features/explore/TraceView/components/TraceTimelineViewer/index.tsx +++ b/public/app/features/explore/TraceView/components/TraceTimelineViewer/index.tsx @@ -16,10 +16,10 @@ import { css } from '@emotion/css'; import React, { RefObject } from 'react'; import { GrafanaTheme2, LinkModel } from '@grafana/data'; +import { TraceToProfilesOptions } from '@grafana/o11y-ds-frontend'; import { config, reportInteraction } from '@grafana/runtime'; import { TimeZone } from '@grafana/schema'; import { stylesFactory, withTheme2 } from '@grafana/ui'; -import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { autoColor } from '../Theme'; import { merge as mergeShortcuts } from '../keyboard-shortcuts'; diff --git a/public/app/features/explore/TraceView/createSpanLink.test.ts b/public/app/features/explore/TraceView/createSpanLink.test.ts index 8f37213d227..a40e81e00e7 100644 --- a/public/app/features/explore/TraceView/createSpanLink.test.ts +++ b/public/app/features/explore/TraceView/createSpanLink.test.ts @@ -7,11 +7,10 @@ import { FieldType, DataFrame, } from '@grafana/data'; +import { TraceToLogsOptionsV2, TraceToMetricsOptions } from '@grafana/o11y-ds-frontend'; import { config, DataSourceSrv, setDataSourceSrv, setTemplateSrv } from '@grafana/runtime'; -import { TraceToMetricsOptions } from 'app/core/components/TraceToMetrics/TraceToMetricsSettings'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { TraceToLogsOptionsV2 } from '../../../core/components/TraceToLogs/TraceToLogsSettings'; import { LinkSrv, setLinkSrv } from '../../panel/panellinks/link_srv'; import { TemplateSrv } from '../../templating/template_srv'; diff --git a/public/app/features/explore/TraceView/createSpanLink.tsx b/public/app/features/explore/TraceView/createSpanLink.tsx index a9c7f5bfc94..5c0e0432bfb 100644 --- a/public/app/features/explore/TraceView/createSpanLink.tsx +++ b/public/app/features/explore/TraceView/createSpanLink.tsx @@ -14,12 +14,16 @@ import { SplitOpen, TimeRange, } from '@grafana/data'; +import { + TraceToProfilesOptions, + TraceToMetricQuery, + TraceToMetricsOptions, + TraceToLogsOptionsV2, + TraceToLogsTag, +} from '@grafana/o11y-ds-frontend'; import { getTemplateSrv } from '@grafana/runtime'; import { DataQuery } from '@grafana/schema'; import { Icon } from '@grafana/ui'; -import { TraceToLogsOptionsV2, TraceToLogsTag } from 'app/core/components/TraceToLogs/TraceToLogsSettings'; -import { TraceToMetricQuery, TraceToMetricsOptions } from 'app/core/components/TraceToMetrics/TraceToMetricsSettings'; -import { TraceToProfilesOptions } from 'app/core/components/TraceToProfiles/TraceToProfilesSettings'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { PromQuery } from 'app/plugins/datasource/prometheus/types'; diff --git a/public/app/plugins/datasource/jaeger/configuration/ConfigEditor.tsx b/public/app/plugins/datasource/jaeger/configuration/ConfigEditor.tsx index 6e42dbab894..cb5b54a0712 100644 --- a/public/app/plugins/datasource/jaeger/configuration/ConfigEditor.tsx +++ b/public/app/plugins/datasource/jaeger/configuration/ConfigEditor.tsx @@ -3,11 +3,10 @@ import React from 'react'; import { DataSourcePluginOptionsEditorProps, GrafanaTheme2 } from '@grafana/data'; import { ConfigSection, DataSourceDescription } from '@grafana/experimental'; +import { TraceToLogsSection, TraceToMetricsSection } from '@grafana/o11y-ds-frontend'; import { config } from '@grafana/runtime'; import { DataSourceHttpSettings, useStyles2, Divider, Stack } from '@grafana/ui'; import { NodeGraphSection } from 'app/core/components/NodeGraphSettings'; -import { TraceToLogsSection } from 'app/core/components/TraceToLogs/TraceToLogsSettings'; -import { TraceToMetricsSection } from 'app/core/components/TraceToMetrics/TraceToMetricsSettings'; import { SpanBarSection } from 'app/features/explore/TraceView/components/settings/SpanBarSettings'; import { TraceIdTimeParams } from './TraceIdTimeParams'; diff --git a/public/app/plugins/datasource/jaeger/graphTransform.ts b/public/app/plugins/datasource/jaeger/graphTransform.ts index 357b36774ba..589729a8c4f 100644 --- a/public/app/plugins/datasource/jaeger/graphTransform.ts +++ b/public/app/plugins/datasource/jaeger/graphTransform.ts @@ -1,6 +1,5 @@ import { DataFrame, NodeGraphDataFrameFieldNames as Fields } from '@grafana/data'; - -import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '../../../core/utils/tracing'; +import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '@grafana/o11y-ds-frontend'; import { Span, TraceResponse } from './types'; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/ConfigDescriptionLink.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/ConfigDescriptionLink.tsx deleted file mode 100644 index c2cecc84cd9..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/ConfigDescriptionLink.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { css } from '@emotion/css'; -import React from 'react'; - -import { GrafanaTheme2 } from '@grafana/data'; -import { useStyles2 } from '@grafana/ui'; - -type Props = { - description: string; - suffix: string; - feature: string; -}; - -export function ConfigDescriptionLink(props: Props) { - const { description, suffix, feature } = props; - const text = `Learn more about ${feature}`; - const styles = useStyles2(getStyles); - - return ( - - {description} - - {text} - - - ); -} - -const getStyles = (theme: GrafanaTheme2) => { - return { - container: css({ - color: theme.colors.text.secondary, - a: css({ - color: theme.colors.text.link, - textDecoration: 'underline', - marginLeft: '5px', - '&:hover': { - textDecoration: 'none', - }, - }), - }), - }; -}; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/IntervalInput.test.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/IntervalInput.test.tsx deleted file mode 100644 index ed3464bfd6d..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/IntervalInput.test.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { render, screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { useState } from 'react'; - -import { invalidTimeShiftError } from '../TraceToLogs/TraceToLogsSettings'; - -import { IntervalInput } from './IntervalInput'; - -describe('IntervalInput', () => { - const IntervalInputtWithProps = ({ val }: { val: string }) => { - const [value, setValue] = useState(val); - - return ( - { - setValue(v); - }} - isInvalidError={invalidTimeShiftError} - /> - ); - }; - - describe('validates time shift correctly', () => { - it('for previosuly saved invalid value', async () => { - render(); - expect(screen.getByDisplayValue('77')).toBeInTheDocument(); - expect(screen.getByText(invalidTimeShiftError)).toBeInTheDocument(); - }); - - it('for previously saved empty value', async () => { - render(); - expect(screen.getByPlaceholderText('0')).toBeInTheDocument(); - expect(screen.queryByText(invalidTimeShiftError)).not.toBeInTheDocument(); - }); - - it('for empty (valid) value', async () => { - render(); - await userEvent.clear(screen.getByDisplayValue('1ms')); - await waitFor(() => { - expect(screen.queryByText(invalidTimeShiftError)).not.toBeInTheDocument(); - }); - }); - - it('for valid value', async () => { - render(); - expect(screen.queryByText(invalidTimeShiftError)).not.toBeInTheDocument(); - - const input = screen.getByDisplayValue('10ms'); - await userEvent.clear(input); - await userEvent.type(input, '100s'); - await waitFor(() => { - expect(screen.queryByText(invalidTimeShiftError)).not.toBeInTheDocument(); - }); - - await userEvent.clear(input); - await userEvent.type(input, '-77ms'); - await waitFor(() => { - expect(screen.queryByText(invalidTimeShiftError)).not.toBeInTheDocument(); - }); - }); - - it('for invalid value', async () => { - render(); - const input = screen.getByDisplayValue('10ms'); - await userEvent.clear(input); - await userEvent.type(input, 'abc'); - await waitFor(() => { - expect(screen.queryByText(invalidTimeShiftError)).toBeInTheDocument(); - }); - }); - }); -}); diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/IntervalInput.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/IntervalInput.tsx deleted file mode 100644 index 692845a3cdd..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/IntervalInput.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useState } from 'react'; -import { useDebounce } from 'react-use'; - -import { InlineField, Input } from '@grafana/ui'; - -import { validateInterval, validateIntervalRegex } from './validation'; - -interface Props { - value: string; - onChange: (val: string) => void; - isInvalidError: string; - placeholder?: string; - width?: number; - ariaLabel?: string; - label?: string; - tooltip?: string; - disabled?: boolean; - validationRegex?: RegExp; -} - -interface FieldProps { - labelWidth: number; - disabled: boolean; - invalid: boolean; - error: string; - label?: string; - tooltip?: string; -} - -export const IntervalInput = (props: Props) => { - const validationRegex = props.validationRegex || validateIntervalRegex; - const [intervalIsInvalid, setIntervalIsInvalid] = useState(() => { - return props.value ? validateInterval(props.value, validationRegex) : false; - }); - - useDebounce( - () => { - setIntervalIsInvalid(validateInterval(props.value, validationRegex)); - }, - 500, - [props.value] - ); - - const fieldProps: FieldProps = { - labelWidth: 26, - disabled: props.disabled ?? false, - invalid: intervalIsInvalid, - error: props.isInvalidError, - }; - if (props.label) { - fieldProps.label = props.label; - fieldProps.tooltip = props.tooltip || ''; - } - - return ( - - { - props.onChange(e.currentTarget.value); - }} - value={props.value} - aria-label={props.ariaLabel || 'interval input'} - /> - - ); -}; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/validation.test.ts b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/validation.test.ts deleted file mode 100644 index 8de4e2d4327..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/validation.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { validateInterval, validateIntervalRegex } from './validation'; - -describe('Validation', () => { - it('should validate incorrect values correctly', () => { - expect(validateInterval('-', validateIntervalRegex)).toBeTruthy(); - expect(validateInterval('1', validateIntervalRegex)).toBeTruthy(); - expect(validateInterval('test', validateIntervalRegex)).toBeTruthy(); - expect(validateInterval('1ds', validateIntervalRegex)).toBeTruthy(); - expect(validateInterval('10Ms', validateIntervalRegex)).toBeTruthy(); - expect(validateInterval('-9999999', validateIntervalRegex)).toBeTruthy(); - }); - - it('should validate correct values correctly', () => { - expect(validateInterval('1y', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('1M', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('1w', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('1d', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('2h', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('4m', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('8s', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('80ms', validateIntervalRegex)).toBeFalsy(); - expect(validateInterval('-80ms', validateIntervalRegex)).toBeFalsy(); - }); - - it('should not return error if no value provided', () => { - expect(validateInterval('', validateIntervalRegex)).toBeFalsy(); - }); -}); diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/validation.ts b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/validation.ts deleted file mode 100644 index 44fd754fa2b..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/IntervalInput/validation.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const validateIntervalRegex = /^(-?\d+(?:\.\d+)?)(ms|[Mwdhmsy])$/; - -export const validateInterval = (val: string, regex: RegExp) => { - const matches = val.match(regex); - return matches || !val ? false : true; -}; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TagMappingInput.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TagMappingInput.tsx deleted file mode 100644 index 2dea321ab02..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TagMappingInput.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { css, cx } from '@emotion/css'; -import React from 'react'; - -import { GrafanaTheme2 } from '@grafana/data'; -import { InlineLabel, SegmentInput, ToolbarButton, useStyles2 } from '@grafana/ui'; -import { ToolbarButtonVariant } from '@grafana/ui/src/components/ToolbarButton'; - -import { TraceToLogsTag } from './TraceToLogsSettings'; - -interface Props { - values: TraceToLogsTag[]; - onChange: (values: TraceToLogsTag[]) => void; - id?: string; -} - -const VARIANT = 'none' as ToolbarButtonVariant; - -export const TagMappingInput = ({ values, onChange, id }: Props) => { - const styles = useStyles2(getStyles); - - return ( -
- {values.length ? ( - values.map((value, idx) => ( -
- { - onChange( - values.map((v, i) => { - if (i === idx) { - return { ...v, key: String(e) }; - } - return v; - }) - ); - }} - /> - - as - - { - onChange( - values.map((v, i) => { - if (i === idx) { - return { ...v, value: String(e) }; - } - return v; - }) - ); - }} - /> - onChange([...values.slice(0, idx), ...values.slice(idx + 1)])} - className={cx(styles.removeTag, 'query-part')} - aria-label="Remove tag" - variant={VARIANT} - type="button" - icon="times" - /> - - {idx === values.length - 1 ? ( - onChange([...values, { key: '', value: '' }])} - className="query-part" - aria-label="Add tag" - type="button" - variant={VARIANT} - icon="plus" - /> - ) : null} -
- )) - ) : ( - onChange([...values, { key: '', value: '' }])} - className="query-part" - aria-label="Add tag" - type="button" - variant={VARIANT} - /> - )} -
- ); -}; - -const getStyles = (theme: GrafanaTheme2) => ({ - wrapper: css({ - display: 'flex', - flexDirection: 'column', - gap: `${theme.spacing(0.5)} 0`, - }), - pair: css({ - display: 'flex', - justifyContent: 'start', - alignItems: 'center', - }), - operator: css({ - color: theme.v1.palette.orange, - width: 'auto', - }), - removeTag: css({ - marginRight: theme.spacing(0.5), - }), -}); diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TraceToLogsSettings.test.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TraceToLogsSettings.test.tsx deleted file mode 100644 index d3b5fb8254d..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TraceToLogsSettings.test.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; - -import { DataSourceInstanceSettings, DataSourceSettings } from '@grafana/data'; -import { DataSourceSrv, setDataSourceSrv } from '@grafana/runtime'; - -import { TraceToLogsData, TraceToLogsSettings } from './TraceToLogsSettings'; - -const defaultOptionsOldFormat: DataSourceSettings = { - jsonData: { - tracesToLogs: { - datasourceUid: 'loki1_uid', - tags: ['someTag'], - mapTagNamesEnabled: false, - spanStartTimeShift: '1m', - spanEndTimeShift: '1m', - filterByTraceID: true, - filterBySpanID: true, - }, - }, -} as unknown as DataSourceSettings; - -const defaultOptionsNewFormat: DataSourceSettings = { - jsonData: { - tracesToLogsV2: { - datasourceUid: 'loki1_uid', - tags: [{ key: 'someTag', value: 'newName' }], - spanStartTimeShift: '1m', - spanEndTimeShift: '1m', - filterByTraceID: true, - filterBySpanID: true, - customQuery: true, - query: '{${__tags}}', - }, - }, -} as unknown as DataSourceSettings; - -const lokiSettings = { - uid: 'loki1_uid', - name: 'loki1', - type: 'loki', - meta: { info: { logos: { small: '' } } }, -} as unknown as DataSourceInstanceSettings; - -describe('TraceToLogsSettings', () => { - beforeAll(() => { - setDataSourceSrv({ - getList() { - return [lokiSettings]; - }, - getInstanceSettings() { - return lokiSettings; - }, - } as unknown as DataSourceSrv); - }); - - it('should render old format without error', () => { - expect(() => - render( {}} />) - ).not.toThrow(); - }); - - it('should render new format without error', () => { - expect(() => - render( {}} />) - ).not.toThrow(); - }); - - it('should render and transform data from old format correctly', () => { - render( {}} />); - expect(screen.getByText('someTag')).toBeInTheDocument(); - expect((screen.getByLabelText('Use custom query') as HTMLInputElement).checked).toBeFalsy(); - expect((screen.getByLabelText('Filter by trace ID') as HTMLInputElement).checked).toBeTruthy(); - expect((screen.getByLabelText('Filter by span ID') as HTMLInputElement).checked).toBeTruthy(); - }); - - it('renders old mapped tags correctly', () => { - const options = { - ...defaultOptionsOldFormat, - jsonData: { - ...defaultOptionsOldFormat.jsonData, - tracesToLogs: { - ...defaultOptionsOldFormat.jsonData.tracesToLogs, - tags: undefined, - mappedTags: [{ key: 'someTag', value: 'withNewName' }], - mapTagNamesEnabled: true, - }, - }, - }; - - render( {}} />); - expect(screen.getByText('someTag')).toBeInTheDocument(); - expect(screen.getByText('withNewName')).toBeInTheDocument(); - }); - - it('transforms old format to new on change', async () => { - const changeMock = jest.fn(); - render(); - const checkBox = screen.getByLabelText('Filter by trace ID'); - await userEvent.click(checkBox); - expect(changeMock.mock.calls[0]).toEqual([ - { - jsonData: { - tracesToLogs: undefined, - tracesToLogsV2: { - customQuery: false, - datasourceUid: 'loki1_uid', - filterBySpanID: true, - filterByTraceID: false, - spanEndTimeShift: '1m', - spanStartTimeShift: '1m', - tags: [ - { - key: 'someTag', - }, - ], - }, - }, - }, - ]); - }); -}); diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TraceToLogsSettings.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TraceToLogsSettings.tsx deleted file mode 100644 index 5a5e6262e11..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToLogs/TraceToLogsSettings.tsx +++ /dev/null @@ -1,275 +0,0 @@ -import { css } from '@emotion/css'; -import React, { useCallback, useMemo } from 'react'; - -import { DataSourceJsonData, DataSourceInstanceSettings, DataSourcePluginOptionsEditorProps } from '@grafana/data'; -import { ConfigSection } from '@grafana/experimental'; -import { DataSourcePicker } from '@grafana/runtime'; -import { InlineField, InlineFieldRow, Input, InlineSwitch } from '@grafana/ui'; - -import { ConfigDescriptionLink } from '../ConfigDescriptionLink'; -import { IntervalInput } from '../IntervalInput/IntervalInput'; - -import { TagMappingInput } from './TagMappingInput'; - -export interface TraceToLogsTag { - key: string; - value?: string; -} - -// @deprecated use getTraceToLogsOptions to get the v2 version of this config from jsonData -export interface TraceToLogsOptions { - datasourceUid?: string; - tags?: string[]; - mappedTags?: TraceToLogsTag[]; - mapTagNamesEnabled?: boolean; - spanStartTimeShift?: string; - spanEndTimeShift?: string; - filterByTraceID?: boolean; - filterBySpanID?: boolean; - lokiSearch?: boolean; // legacy -} - -export interface TraceToLogsOptionsV2 { - datasourceUid?: string; - tags?: TraceToLogsTag[]; - spanStartTimeShift?: string; - spanEndTimeShift?: string; - filterByTraceID?: boolean; - filterBySpanID?: boolean; - query?: string; - customQuery: boolean; -} - -export interface TraceToLogsData extends DataSourceJsonData { - tracesToLogs?: TraceToLogsOptions; - tracesToLogsV2?: TraceToLogsOptionsV2; -} - -/** - * Gets new version of the traceToLogs config from the json data either returning directly or transforming the old - * version to new and returning that. - */ -export function getTraceToLogsOptions(data?: TraceToLogsData): TraceToLogsOptionsV2 | undefined { - if (data?.tracesToLogsV2) { - return data.tracesToLogsV2; - } - if (!data?.tracesToLogs) { - return undefined; - } - const traceToLogs: TraceToLogsOptionsV2 = { - customQuery: false, - }; - traceToLogs.datasourceUid = data.tracesToLogs.datasourceUid; - traceToLogs.tags = data.tracesToLogs.mapTagNamesEnabled - ? data.tracesToLogs.mappedTags - : data.tracesToLogs.tags?.map((tag) => ({ key: tag })); - traceToLogs.filterByTraceID = data.tracesToLogs.filterByTraceID; - traceToLogs.filterBySpanID = data.tracesToLogs.filterBySpanID; - traceToLogs.spanStartTimeShift = data.tracesToLogs.spanStartTimeShift; - traceToLogs.spanEndTimeShift = data.tracesToLogs.spanEndTimeShift; - return traceToLogs; -} - -interface Props extends DataSourcePluginOptionsEditorProps {} - -export function TraceToLogsSettings({ options, onOptionsChange }: Props) { - const supportedDataSourceTypes = [ - 'loki', - 'elasticsearch', - 'grafana-splunk-datasource', // external - 'grafana-opensearch-datasource', // external - 'grafana-falconlogscale-datasource', // external - 'googlecloud-logging-datasource', // external - ]; - - const traceToLogs = useMemo( - (): TraceToLogsOptionsV2 => getTraceToLogsOptions(options.jsonData) || { customQuery: false }, - [options.jsonData] - ); - const { query = '', tags, customQuery } = traceToLogs; - - const updateTracesToLogs = useCallback( - (value: Partial) => { - // Cannot use updateDatasourcePluginJsonDataOption here as we need to update 2 keys, and they would overwrite each - // other as updateDatasourcePluginJsonDataOption isn't synchronized - onOptionsChange({ - ...options, - jsonData: { - ...options.jsonData, - tracesToLogsV2: { - ...traceToLogs, - ...value, - }, - tracesToLogs: undefined, - }, - }); - }, - [onOptionsChange, options, traceToLogs] - ); - - return ( -
- - - supportedDataSourceTypes.includes(ds.type)} - current={traceToLogs.datasourceUid} - noDefault={true} - width={40} - onChange={(ds: DataSourceInstanceSettings) => - updateTracesToLogs({ - datasourceUid: ds.uid, - }) - } - /> - - - - - { - updateTracesToLogs({ spanStartTimeShift: val }); - }} - isInvalidError={invalidTimeShiftError} - /> - - - - { - updateTracesToLogs({ spanEndTimeShift: val }); - }} - isInvalidError={invalidTimeShiftError} - /> - - - - - updateTracesToLogs({ tags: v })} /> - - - - updateTracesToLogs({ filterByTraceID: val })} - /> - updateTracesToLogs({ filterBySpanID: val })} - /> - - - - ) => - updateTracesToLogs({ customQuery: event.currentTarget.checked }) - } - /> - - - - {customQuery && ( - - updateTracesToLogs({ query: e.currentTarget.value })} - /> - - )} -
- ); -} - -interface IdFilterProps { - type: 'trace' | 'span'; - id: string; - value: boolean; - onChange: (val: boolean) => void; - disabled: boolean; -} -function IdFilter(props: IdFilterProps) { - return ( - - - ) => props.onChange(event.currentTarget.checked)} - /> - - - ); -} - -export const getTimeShiftLabel = (type: 'start' | 'end') => { - return `Span ${type} time shift`; -}; - -export const getTimeShiftTooltip = (type: 'start' | 'end', defaultVal: string) => { - return `Shifts the ${type} time of the span. Default: ${defaultVal} (Time units can be used here, for example: 5s, -1m, 3h)`; -}; - -export const invalidTimeShiftError = 'Invalid time shift. See tooltip for examples.'; - -export const TraceToLogsSection = ({ options, onOptionsChange }: DataSourcePluginOptionsEditorProps) => { - let suffix = options.type; - suffix += options.type === 'tempo' ? '/configure-tempo-data-source/#trace-to-logs' : '/#trace-to-logs'; - - return ( - - } - isCollapsible={true} - isInitiallyOpen={true} - > - - - ); -}; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToMetrics/TraceToMetricsSettings.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToMetrics/TraceToMetricsSettings.tsx deleted file mode 100644 index 91a6732f519..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToMetrics/TraceToMetricsSettings.tsx +++ /dev/null @@ -1,240 +0,0 @@ -import { css } from '@emotion/css'; -import React from 'react'; - -import { - DataSourceInstanceSettings, - DataSourceJsonData, - DataSourcePluginOptionsEditorProps, - GrafanaTheme2, - updateDatasourcePluginJsonDataOption, -} from '@grafana/data'; -import { ConfigSection } from '@grafana/experimental'; -import { DataSourcePicker } from '@grafana/runtime'; -import { Button, InlineField, InlineFieldRow, Input, useStyles2 } from '@grafana/ui'; - -import { ConfigDescriptionLink } from '../ConfigDescriptionLink'; -import { IntervalInput } from '../IntervalInput/IntervalInput'; -import { TagMappingInput } from '../TraceToLogs/TagMappingInput'; -import { getTimeShiftLabel, getTimeShiftTooltip, invalidTimeShiftError } from '../TraceToLogs/TraceToLogsSettings'; - -export interface TraceToMetricsOptions { - datasourceUid?: string; - tags?: Array<{ key: string; value: string }>; - queries: TraceToMetricQuery[]; - spanStartTimeShift?: string; - spanEndTimeShift?: string; -} - -export interface TraceToMetricQuery { - name?: string; - query?: string; -} - -export interface TraceToMetricsData extends DataSourceJsonData { - tracesToMetrics?: TraceToMetricsOptions; -} - -interface Props extends DataSourcePluginOptionsEditorProps {} - -export function TraceToMetricsSettings({ options, onOptionsChange }: Props) { - const styles = useStyles2(getStyles); - - return ( -
- - - - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToMetrics', { - ...options.jsonData.tracesToMetrics, - datasourceUid: ds.uid, - }) - } - /> - - {options.jsonData.tracesToMetrics?.datasourceUid ? ( - - ) : null} - - - - { - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToMetrics', { - ...options.jsonData.tracesToMetrics, - spanStartTimeShift: val, - }); - }} - placeholder={'-2m'} - isInvalidError={invalidTimeShiftError} - /> - - - - { - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToMetrics', { - ...options.jsonData.tracesToMetrics, - spanEndTimeShift: val, - }); - }} - placeholder={'2m'} - isInvalidError={invalidTimeShiftError} - /> - - - - - - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToMetrics', { - ...options.jsonData.tracesToMetrics, - tags: v, - }) - } - /> - - - - {options.jsonData.tracesToMetrics?.queries?.map((query, i) => ( -
- - { - let newQueries = options.jsonData.tracesToMetrics?.queries.slice() ?? []; - newQueries[i].name = e.currentTarget.value; - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToMetrics', { - ...options.jsonData.tracesToMetrics, - queries: newQueries, - }); - }} - /> - - - { - let newQueries = options.jsonData.tracesToMetrics?.queries.slice() ?? []; - newQueries[i].query = e.currentTarget.value; - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToMetrics', { - ...options.jsonData.tracesToMetrics, - queries: newQueries, - }); - }} - /> - - -
- ))} - - -
- ); -} - -export const TraceToMetricsSection = ({ options, onOptionsChange }: DataSourcePluginOptionsEditorProps) => { - let suffix = options.type; - suffix += options.type === 'tempo' ? '/configure-tempo-data-source/#trace-to-metrics' : '/#trace-to-metrics'; - - return ( - - } - isCollapsible={true} - isInitiallyOpen={true} - > - - - ); -}; - -const getStyles = (theme: GrafanaTheme2) => ({ - infoText: css` - padding-bottom: ${theme.spacing(2)}; - color: ${theme.colors.text.secondary}; - `, - row: css` - label: row; - align-items: baseline; - `, - queryRow: css` - label: queryRow; - display: flex; - flex-flow: wrap; - `, -}); diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToProfiles/TraceToProfilesSettings.test.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToProfiles/TraceToProfilesSettings.test.tsx deleted file mode 100644 index 0cf648def33..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToProfiles/TraceToProfilesSettings.test.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { render, screen, waitFor } from '@testing-library/react'; -import React from 'react'; - -import { DataSourceInstanceSettings, DataSourceSettings } from '@grafana/data'; -import { DataSourceSrv, setDataSourceSrv } from '@grafana/runtime'; - -import { TraceToProfilesData, TraceToProfilesSettings } from './TraceToProfilesSettings'; - -const defaultOption: DataSourceSettings = { - jsonData: { - tracesToProfiles: { - datasourceUid: 'profiling1_uid', - tags: [{ key: 'someTag', value: 'newName' }], - customQuery: true, - query: '{${__tags}}', - }, - }, -} as unknown as DataSourceSettings; - -const pyroSettings = { - uid: 'profiling1_uid', - name: 'profiling1', - type: 'grafana-pyroscope-datasource', - meta: { info: { logos: { small: '' } } }, -} as unknown as DataSourceInstanceSettings; - -describe('TraceToProfilesSettings', () => { - beforeAll(() => { - setDataSourceSrv({ - getList() { - return [pyroSettings]; - }, - getInstanceSettings() { - return pyroSettings; - }, - } as unknown as DataSourceSrv); - }); - - it('should render without error', () => { - waitFor(() => { - expect(() => - render( {}} />) - ).not.toThrow(); - }); - }); - - it('should render all options', () => { - render( {}} />); - expect(screen.getByText('Tags')).toBeInTheDocument(); - expect(screen.getByText('Profile type')).toBeInTheDocument(); - expect(screen.getByText('Use custom query')).toBeInTheDocument(); - }); -}); diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToProfiles/TraceToProfilesSettings.tsx b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToProfiles/TraceToProfilesSettings.tsx deleted file mode 100644 index ef6ff85dfe9..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/TraceToProfiles/TraceToProfilesSettings.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import { css } from '@emotion/css'; -import React, { useEffect, useMemo, useState } from 'react'; -import { useAsync } from 'react-use'; - -import { - DataSourceJsonData, - DataSourceInstanceSettings, - DataSourcePluginOptionsEditorProps, - updateDatasourcePluginJsonDataOption, -} from '@grafana/data'; -import { ConfigSection } from '@grafana/experimental'; -import { DataSourcePicker, getDataSourceSrv } from '@grafana/runtime'; -import { InlineField, InlineFieldRow, Input, InlineSwitch } from '@grafana/ui'; - -import { ConfigDescriptionLink } from '../ConfigDescriptionLink'; -import { TagMappingInput } from '../TraceToLogs/TagMappingInput'; -import { ProfileTypesCascader } from '../pyroscope/ProfileTypesCascader'; -import { PyroscopeDataSource } from '../pyroscope/datasource'; -import { ProfileTypeMessage } from '../pyroscope/types'; - -export interface TraceToProfilesOptions { - datasourceUid?: string; - tags?: Array<{ key: string; value?: string }>; - query?: string; - profileTypeId?: string; - customQuery: boolean; -} - -export interface TraceToProfilesData extends DataSourceJsonData { - tracesToProfiles?: TraceToProfilesOptions; -} - -interface Props extends DataSourcePluginOptionsEditorProps {} - -export function TraceToProfilesSettings({ options, onOptionsChange }: Props) { - const supportedDataSourceTypes = useMemo(() => ['grafana-pyroscope-datasource'], []); - - const [profileTypes, setProfileTypes] = useState([]); - const profileTypesPlaceholder = useMemo(() => { - let placeholder = profileTypes.length === 0 ? 'No profile types found' : 'Select profile type'; - if (!options.jsonData.tracesToProfiles?.datasourceUid) { - placeholder = 'Please select profiling data source'; - } - return placeholder; - }, [options.jsonData.tracesToProfiles?.datasourceUid, profileTypes]); - - const { value: dataSource } = useAsync(async () => { - return await getDataSourceSrv().get(options.jsonData.tracesToProfiles?.datasourceUid); - }, [options.jsonData.tracesToProfiles?.datasourceUid]); - - useEffect(() => { - if ( - dataSource && - dataSource instanceof PyroscopeDataSource && - supportedDataSourceTypes.includes(dataSource.type) && - dataSource.uid === options.jsonData.tracesToProfiles?.datasourceUid - ) { - dataSource.getProfileTypes().then((profileTypes) => { - setProfileTypes(profileTypes); - }); - } else { - setProfileTypes([]); - } - }, [dataSource, onOptionsChange, options, supportedDataSourceTypes]); - - return ( -
- - - supportedDataSourceTypes.includes(ds.type)} - current={options.jsonData.tracesToProfiles?.datasourceUid} - noDefault={true} - width={40} - onChange={(ds: DataSourceInstanceSettings) => { - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToProfiles', { - ...options.jsonData.tracesToProfiles, - datasourceUid: ds.uid, - }); - }} - /> - - - - - - { - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToProfiles', { - ...options.jsonData.tracesToProfiles, - tags: v, - }); - }} - /> - - - - - - { - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToProfiles', { - ...options.jsonData.tracesToProfiles, - profileTypeId: val, - }); - }} - width={40} - /> - - - - - - ) => - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToProfiles', { - ...options.jsonData.tracesToProfiles, - customQuery: event.currentTarget.checked, - }) - } - /> - - - - {options.jsonData.tracesToProfiles?.customQuery && ( - - - updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToProfiles', { - ...options.jsonData.tracesToProfiles, - query: e.currentTarget.value, - }) - } - /> - - )} -
- ); -} - -export const TraceToProfilesSection = ({ options, onOptionsChange }: DataSourcePluginOptionsEditorProps) => { - return ( - - } - isCollapsible={true} - isInitiallyOpen={true} - > - - - ); -}; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/index.d.ts b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/index.d.ts deleted file mode 100644 index f0d6e8e5536..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/index.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * A library containing logic to manage traces. - * - * @packageDocumentation - */ -type Props = {}; - -export { Props }; diff --git a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/datasource.ts b/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/datasource.ts deleted file mode 100644 index ed198f98004..00000000000 --- a/public/app/plugins/datasource/tempo/_importedDependencies/grafana-traces/src/pyroscope/datasource.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Observable } from 'rxjs'; - -import { AbstractQuery, CoreApp, DataQueryRequest, DataQueryResponse, ScopedVars } from '@grafana/data'; -import { DataSourceWithBackend } from '@grafana/runtime'; - -import { PyroscopeDataSourceOptions, Query, ProfileTypeMessage } from './types'; - -export abstract class PyroscopeDataSource extends DataSourceWithBackend { - abstract query(request: DataQueryRequest): Observable; - - abstract getProfileTypes(): Promise; - - abstract getLabelNames(query: string, start: number, end: number): Promise; - - abstract getLabelValues(query: string, label: string, start: number, end: number): Promise; - - abstract applyTemplateVariables(query: Query, scopedVars: ScopedVars): Query; - - abstract importFromAbstractQueries(abstractQueries: AbstractQuery[]): Promise; - - abstract importFromAbstractQuery(labelBasedQuery: AbstractQuery): Query; - - abstract exportToAbstractQueries(queries: Query[]): Promise; - - abstract exportToAbstractQuery(query: Query): AbstractQuery; - - abstract getDefaultQuery(app: CoreApp): Partial; -} diff --git a/public/app/plugins/datasource/tempo/configuration/ConfigEditor.tsx b/public/app/plugins/datasource/tempo/configuration/ConfigEditor.tsx index 94555c7e30a..e7e68a99d38 100644 --- a/public/app/plugins/datasource/tempo/configuration/ConfigEditor.tsx +++ b/public/app/plugins/datasource/tempo/configuration/ConfigEditor.tsx @@ -12,16 +12,12 @@ import { convertLegacyAuthProps, DataSourceDescription, } from '@grafana/experimental'; +import { TraceToLogsSection, TraceToMetricsSection, TraceToProfilesSection } from '@grafana/o11y-ds-frontend'; import { config } from '@grafana/runtime'; import { SecureSocksProxySettings, useStyles2, Divider, Stack } from '@grafana/ui'; import { NodeGraphSection } from '../_importedDependencies/components/NodeGraphSettings'; import { SpanBarSection } from '../_importedDependencies/components/TraceView/SpanBarSettings'; -import { - TraceToLogsSection, - TraceToMetricsSection, - TraceToProfilesSection, -} from '../_importedDependencies/grafana-traces/src'; import { LokiSearchSettings } from './LokiSearchSettings'; import { QuerySettings } from './QuerySettings'; diff --git a/public/app/plugins/datasource/tempo/configuration/QuerySettings.tsx b/public/app/plugins/datasource/tempo/configuration/QuerySettings.tsx index 540d4f34d37..45d6bb969bc 100644 --- a/public/app/plugins/datasource/tempo/configuration/QuerySettings.tsx +++ b/public/app/plugins/datasource/tempo/configuration/QuerySettings.tsx @@ -2,9 +2,9 @@ import { css } from '@emotion/css'; import React from 'react'; import { DataSourcePluginOptionsEditorProps, GrafanaTheme2, updateDatasourcePluginJsonDataOption } from '@grafana/data'; +import { IntervalInput, invalidTimeShiftError } from '@grafana/o11y-ds-frontend'; import { InlineField, InlineSwitch, useStyles2 } from '@grafana/ui'; -import { IntervalInput, invalidTimeShiftError } from '../_importedDependencies/grafana-traces/src'; import { TempoJsonData } from '../types'; interface Props extends DataSourcePluginOptionsEditorProps {} diff --git a/public/app/plugins/datasource/tempo/datasource.ts b/public/app/plugins/datasource/tempo/datasource.ts index 172154b8d37..1af07bd9453 100644 --- a/public/app/plugins/datasource/tempo/datasource.ts +++ b/public/app/plugins/datasource/tempo/datasource.ts @@ -21,6 +21,7 @@ import { TestDataSourceResponse, urlUtil, } from '@grafana/data'; +import { TraceToLogsOptions } from '@grafana/o11y-ds-frontend'; import { BackendSrvRequest, config, @@ -39,7 +40,6 @@ import { NodeGraphOptions } from './_importedDependencies/components/NodeGraphSe import { SpanBarOptions } from './_importedDependencies/components/TraceView/SpanBarSettings'; import { LokiOptions } from './_importedDependencies/datasources/loki/types'; import { PromQuery, PrometheusDatasource } from './_importedDependencies/datasources/prometheus/types'; -import { TraceToLogsOptions } from './_importedDependencies/grafana-traces/src'; import { TraceqlFilter, TraceqlSearchScope } from './dataquery.gen'; import { defaultTableFilter, diff --git a/public/app/plugins/datasource/tempo/graphTransform.ts b/public/app/plugins/datasource/tempo/graphTransform.ts index 681a853fb6b..189ba7a66b0 100644 --- a/public/app/plugins/datasource/tempo/graphTransform.ts +++ b/public/app/plugins/datasource/tempo/graphTransform.ts @@ -10,13 +10,7 @@ import { FieldType, toDataFrame, } from '@grafana/data'; - -import { - getStats, - getNonOverlappingDuration, - makeSpanMap, - makeFrames, -} from './_importedDependencies/grafana-traces/src'; +import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '@grafana/o11y-ds-frontend'; /** * Row in a trace dataFrame diff --git a/public/app/plugins/datasource/tempo/package.json b/public/app/plugins/datasource/tempo/package.json index 870157362e6..ddcd3531f34 100644 --- a/public/app/plugins/datasource/tempo/package.json +++ b/public/app/plugins/datasource/tempo/package.json @@ -11,6 +11,7 @@ "@grafana/lezer-logql": "0.2.2", "@grafana/lezer-traceql": "0.0.12", "@grafana/monaco-logql": "^0.0.7", + "@grafana/o11y-ds-frontend": "workspace:*", "@grafana/runtime": "workspace:*", "@grafana/schema": "workspace:*", "@grafana/ui": "workspace:*", diff --git a/public/app/plugins/datasource/tempo/resultTransformer.ts b/public/app/plugins/datasource/tempo/resultTransformer.ts index 6032a44f31c..b456a37c1b2 100644 --- a/public/app/plugins/datasource/tempo/resultTransformer.ts +++ b/public/app/plugins/datasource/tempo/resultTransformer.ts @@ -23,9 +23,9 @@ import { Field, DataLinkConfigOrigin, } from '@grafana/data'; +import { TraceToProfilesData } from '@grafana/o11y-ds-frontend'; import { config, getDataSourceSrv } from '@grafana/runtime'; -import { TraceToProfilesData } from './_importedDependencies/grafana-traces/src'; import { SearchTableType } from './dataquery.gen'; import { createGraphFrames } from './graphTransform'; import { Span, SpanAttributes, Spanset, TempoJsonData, TraceSearchMetadata } from './types'; diff --git a/public/app/plugins/datasource/tempo/types.ts b/public/app/plugins/datasource/tempo/types.ts index 91dd0f89d65..b6693078dfb 100644 --- a/public/app/plugins/datasource/tempo/types.ts +++ b/public/app/plugins/datasource/tempo/types.ts @@ -1,8 +1,8 @@ import { DataSourceJsonData } from '@grafana/data/src'; +import { TraceToLogsOptions } from '@grafana/o11y-ds-frontend'; import { NodeGraphOptions } from './_importedDependencies/components/NodeGraphSettings'; import { LokiQuery } from './_importedDependencies/datasources/loki/types'; -import { TraceToLogsOptions } from './_importedDependencies/grafana-traces/src'; import { TempoQuery as TempoBase, TempoQueryType, TraceqlFilter } from './dataquery.gen'; export interface SearchQueryParams { diff --git a/public/app/plugins/datasource/zipkin/ConfigEditor.tsx b/public/app/plugins/datasource/zipkin/ConfigEditor.tsx index 646e1eb9301..d461870bffb 100644 --- a/public/app/plugins/datasource/zipkin/ConfigEditor.tsx +++ b/public/app/plugins/datasource/zipkin/ConfigEditor.tsx @@ -3,11 +3,10 @@ import React from 'react'; import { DataSourcePluginOptionsEditorProps, GrafanaTheme2 } from '@grafana/data'; import { ConfigSection, DataSourceDescription } from '@grafana/experimental'; +import { TraceToLogsSection, TraceToMetricsSection } from '@grafana/o11y-ds-frontend'; import { config } from '@grafana/runtime'; import { DataSourceHttpSettings, useStyles2, Divider, Stack } from '@grafana/ui'; import { NodeGraphSection } from 'app/core/components/NodeGraphSettings'; -import { TraceToLogsSection } from 'app/core/components/TraceToLogs/TraceToLogsSettings'; -import { TraceToMetricsSection } from 'app/core/components/TraceToMetrics/TraceToMetricsSettings'; import { SpanBarSection } from 'app/features/explore/TraceView/components/settings/SpanBarSettings'; export type Props = DataSourcePluginOptionsEditorProps; diff --git a/public/app/plugins/datasource/zipkin/utils/graphTransform.ts b/public/app/plugins/datasource/zipkin/utils/graphTransform.ts index 03e441b97b9..f67ec7e8929 100644 --- a/public/app/plugins/datasource/zipkin/utils/graphTransform.ts +++ b/public/app/plugins/datasource/zipkin/utils/graphTransform.ts @@ -1,6 +1,6 @@ import { DataFrame, NodeGraphDataFrameFieldNames as Fields } from '@grafana/data'; +import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '@grafana/o11y-ds-frontend'; -import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '../../../../core/utils/tracing'; import { ZipkinSpan } from '../types'; interface Node { diff --git a/scripts/check-breaking-changes.sh b/scripts/check-breaking-changes.sh index 1a49e7646fd..5c7385d1314 100755 --- a/scripts/check-breaking-changes.sh +++ b/scripts/check-breaking-changes.sh @@ -4,7 +4,7 @@ PACKAGES=$(ls -d ./packages/*/) EXIT_CODE=0 GITHUB_MESSAGE="" -SKIP_PACKAGES=("grafana-eslint-rules" "grafana-plugin-configs") +SKIP_PACKAGES=("grafana-eslint-rules" "grafana-plugin-configs" "grafana-o11y-ds-frontend") # Loop through the packages while IFS=" " read -r -a package; do diff --git a/yarn.lock b/yarn.lock index 8758ebc6b19..6bacfff0a35 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3067,6 +3067,7 @@ __metadata: "@grafana/lezer-logql": "npm:0.2.2" "@grafana/lezer-traceql": "npm:0.0.12" "@grafana/monaco-logql": "npm:^0.0.7" + "@grafana/o11y-ds-frontend": "workspace:*" "@grafana/plugin-configs": "npm:10.4.0-pre" "@grafana/runtime": "workspace:*" "@grafana/schema": "workspace:*" @@ -3457,6 +3458,39 @@ __metadata: languageName: node linkType: hard +"@grafana/o11y-ds-frontend@workspace:*, @grafana/o11y-ds-frontend@workspace:packages/grafana-o11y-ds-frontend": + version: 0.0.0-use.local + resolution: "@grafana/o11y-ds-frontend@workspace:packages/grafana-o11y-ds-frontend" + dependencies: + "@emotion/css": "npm:11.11.2" + "@grafana/data": "workspace:*" + "@grafana/e2e-selectors": "workspace:*" + "@grafana/experimental": "npm:1.7.5" + "@grafana/runtime": "workspace:*" + "@grafana/schema": "workspace:*" + "@grafana/tsconfig": "npm:^1.2.0-rc1" + "@grafana/ui": "workspace:*" + "@testing-library/jest-dom": "npm:^6.1.2" + "@testing-library/react": "npm:14.1.2" + "@testing-library/user-event": "npm:14.5.2" + "@types/jest": "npm:^29.5.4" + "@types/react": "npm:18.2.15" + "@types/systemjs": "npm:6.13.5" + "@types/testing-library__jest-dom": "npm:5.14.9" + jest: "npm:^29.6.4" + react: "npm:18.2.0" + react-use: "npm:17.4.0" + rxjs: "npm:7.8.1" + ts-jest: "npm:29.1.1" + ts-node: "npm:10.9.1" + tslib: "npm:2.6.0" + typescript: "npm:5.2.2" + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + languageName: unknown + linkType: soft + "@grafana/plugin-configs@npm:10.4.0-pre, @grafana/plugin-configs@workspace:packages/grafana-plugin-configs": version: 0.0.0-use.local resolution: "@grafana/plugin-configs@workspace:packages/grafana-plugin-configs" @@ -16933,6 +16967,7 @@ __metadata: "@grafana/google-sdk": "npm:0.1.2" "@grafana/lezer-logql": "npm:0.2.2" "@grafana/monaco-logql": "npm:^0.0.7" + "@grafana/o11y-ds-frontend": "workspace:*" "@grafana/runtime": "workspace:*" "@grafana/scenes": "npm:1.30.0" "@grafana/schema": "workspace:*"