From 6779fe45de44b03be790fce01f946e8d0b85dbe6 Mon Sep 17 00:00:00 2001 From: kozhuhds Date: Fri, 14 Feb 2025 20:50:45 +0100 Subject: [PATCH 1/3] feat: open in explore traces button --- .../OpenInExploreTracesButton.tsx | 57 +++++++++++++++++++ .../OpenInExploreTracesButton/types.ts | 14 +++++ src/exposedComponents.tsx | 27 +++++++++ src/module.tsx | 6 ++ src/plugin.json | 7 +++ 5 files changed, 111 insertions(+) create mode 100644 src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx create mode 100644 src/components/OpenInExploreTracesButton/types.ts create mode 100644 src/exposedComponents.tsx diff --git a/src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx b/src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx new file mode 100644 index 0000000..cb4e12d --- /dev/null +++ b/src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx @@ -0,0 +1,57 @@ +import { useReturnToPrevious } from '@grafana/runtime'; +import { LinkButton } from '@grafana/ui'; +import React, { useMemo } from 'react'; +import { OpenInExploreTracesButtonProps } from './types'; +import pluginJson from '../../plugin.json'; + + +export default function OpenInExploreLogsButton({ + datasourceUid, + matchers, + from, + to, + returnToPreviousSource, + renderButton, +}: OpenInExploreTracesButtonProps) { + const setReturnToPrevious = useReturnToPrevious(); + + const href = useMemo(() => { + let params = new URLSearchParams(); + + if (datasourceUid) { + params.append('var-ds', datasourceUid); + } + + if (from) { + params.append('from', from); + } + + if (to) { + params.append('to', to); + } + + matchers.forEach((streamSelector) => { + params.append('var-filters', `${streamSelector.name}|${streamSelector.operator}|${streamSelector.value}`); + }); + + return `a/${pluginJson.id}/explore?${params.toString()}`; + }, [datasourceUid, from, to, matchers]); + + if (!href) { + return null; + } + + if (renderButton) { + return renderButton({ href }); + } + + return ( + setReturnToPrevious(returnToPreviousSource || 'previous')} + > + Open in Explore Traces + + ); +} diff --git a/src/components/OpenInExploreTracesButton/types.ts b/src/components/OpenInExploreTracesButton/types.ts new file mode 100644 index 0000000..0e4457b --- /dev/null +++ b/src/components/OpenInExploreTracesButton/types.ts @@ -0,0 +1,14 @@ +export type TempoMatcher = { + name: string; + value: string; + operator: '=' | '!=' | '>' | '<'; +}; + +export interface OpenInExploreTracesButtonProps { + datasourceUid?: string; + matchers: TempoMatcher[]; + from?: string; + to?: string; + returnToPreviousSource?: string; + renderButton?: (props: { href: string }) => React.ReactElement; +} diff --git a/src/exposedComponents.tsx b/src/exposedComponents.tsx new file mode 100644 index 0000000..9d9b31c --- /dev/null +++ b/src/exposedComponents.tsx @@ -0,0 +1,27 @@ +import { LinkButton } from '@grafana/ui'; +import { OpenInExploreTracesButtonProps } from 'components/OpenInExploreTracesButton/types'; +import React, { lazy, Suspense } from 'react'; +const OpenInExploreTracesButton = lazy(() => import('components/OpenInExploreTracesButton/OpenInExploreTracesButton')); + +function SuspendedOpenInExploreTracesButton(props: OpenInExploreTracesButtonProps) { + return ( + + Open in Explore Traces + + } + > + + + ); +} + +export const exposedComponents = [ + { + id: 'grafana-exploretraces-app/open-in-explore-traces-button/v1', + title: 'Open in Explore Traces button', + description: 'A button that opens a traces view in the Explore Traces app.', + component: SuspendedOpenInExploreTracesButton, + }, +]; \ No newline at end of file diff --git a/src/module.tsx b/src/module.tsx index 102441c..bce6d8b 100644 --- a/src/module.tsx +++ b/src/module.tsx @@ -4,6 +4,7 @@ import { AppPlugin } from '@grafana/data'; // @ts-ignore new API that is not yet in stable release import { sidecarServiceSingleton_EXPERIMENTAL } from '@grafana/runtime'; import pluginJson from './plugin.json'; +import { exposedComponents } from 'exposedComponents'; const App = lazy(() => import('./components/App/App')); const AppConfig = lazy(() => import('./components/AppConfig/AppConfig')); @@ -23,3 +24,8 @@ export const plugin = new AppPlugin<{}>().setRootPage(App).addConfigPage({ sidecarServiceSingleton_EXPERIMENTAL?.openApp(pluginJson.id, helpers.context); }, }); + + +for (const exposedComponentConfig of exposedComponents) { + plugin.exposeComponent(exposedComponentConfig); +} \ No newline at end of file diff --git a/src/plugin.json b/src/plugin.json index ffb00ba..f59a486 100644 --- a/src/plugin.json +++ b/src/plugin.json @@ -57,6 +57,13 @@ "plugins": [] }, "extensions": { + "exposedComponents": [ + { + "id": "grafana-exploretraces-app/open-in-explore-traces-button/v1", + "title": "Open in Explore Traces button", + "description": "A button that opens a traces view in the Explore Traces app." + } + ], "addedLinks": [ { "targets": ["grafana-lokiexplore-app/toolbar-open-related/v1"], From c670e4801bc5a37ff205b671a1b9653edf901be2 Mon Sep 17 00:00:00 2001 From: kozhuhds Date: Fri, 14 Feb 2025 20:54:39 +0100 Subject: [PATCH 2/3] style: fixing eslint --- src/exposedComponents.tsx | 2 +- src/module.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exposedComponents.tsx b/src/exposedComponents.tsx index 9d9b31c..46ed7cc 100644 --- a/src/exposedComponents.tsx +++ b/src/exposedComponents.tsx @@ -24,4 +24,4 @@ export const exposedComponents = [ description: 'A button that opens a traces view in the Explore Traces app.', component: SuspendedOpenInExploreTracesButton, }, -]; \ No newline at end of file +]; diff --git a/src/module.tsx b/src/module.tsx index bce6d8b..da147ab 100644 --- a/src/module.tsx +++ b/src/module.tsx @@ -28,4 +28,4 @@ export const plugin = new AppPlugin<{}>().setRootPage(App).addConfigPage({ for (const exposedComponentConfig of exposedComponents) { plugin.exposeComponent(exposedComponentConfig); -} \ No newline at end of file +} From 58f6041a5c25db6d525f8fd2815f84bd67e4864c Mon Sep 17 00:00:00 2001 From: kozhuhds Date: Thu, 20 Feb 2025 11:59:25 +0100 Subject: [PATCH 3/3] chore: re-arranging files, adding bundle types action --- .github/workflows/bundle-types.yml | 25 +++++++++++++++++++ .../OpenInExploreTracesButton.tsx | 7 +++--- .../index.tsx} | 10 ++++---- .../types.ts | 1 + src/plugin.json | 4 +-- tsconfig-for-bundle-types.json | 9 +++++++ 6 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/bundle-types.yml rename src/{components => exposedComponents}/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx (89%) rename src/{exposedComponents.tsx => exposedComponents/index.tsx} (59%) rename src/{components/OpenInExploreTracesButton => exposedComponents}/types.ts (99%) create mode 100644 tsconfig-for-bundle-types.json diff --git a/.github/workflows/bundle-types.yml b/.github/workflows/bundle-types.yml new file mode 100644 index 0000000..74d9db0 --- /dev/null +++ b/.github/workflows/bundle-types.yml @@ -0,0 +1,25 @@ +name: Bundle Types + +on: + push: + tags: + - 'v*' # Run workflow on version tags, e.g. v1.0.0. + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# These permissions are needed to assume roles from Github's OIDC. +permissions: + contents: read + id-token: write + +jobs: + bundle-types: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: grafana/plugin-actions/bundle-types@main + with: + entry-point: ./src/externalComponents/types.ts + ts-config: ./tsconfig-for-bundle-types.json \ No newline at end of file diff --git a/src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx b/src/exposedComponents/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx similarity index 89% rename from src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx rename to src/exposedComponents/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx index cb4e12d..c1f1fa7 100644 --- a/src/components/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx +++ b/src/exposedComponents/OpenInExploreTracesButton/OpenInExploreTracesButton.tsx @@ -1,11 +1,10 @@ import { useReturnToPrevious } from '@grafana/runtime'; import { LinkButton } from '@grafana/ui'; import React, { useMemo } from 'react'; -import { OpenInExploreTracesButtonProps } from './types'; +import { OpenInExploreTracesButtonProps } from '../types'; import pluginJson from '../../plugin.json'; - -export default function OpenInExploreLogsButton({ +export default function OpenInExploreTracesButton({ datasourceUid, matchers, from, @@ -51,7 +50,7 @@ export default function OpenInExploreLogsButton({ href={href} onClick={() => setReturnToPrevious(returnToPreviousSource || 'previous')} > - Open in Explore Traces + Open in Traces drilldown ); } diff --git a/src/exposedComponents.tsx b/src/exposedComponents/index.tsx similarity index 59% rename from src/exposedComponents.tsx rename to src/exposedComponents/index.tsx index 46ed7cc..f904861 100644 --- a/src/exposedComponents.tsx +++ b/src/exposedComponents/index.tsx @@ -1,14 +1,14 @@ import { LinkButton } from '@grafana/ui'; -import { OpenInExploreTracesButtonProps } from 'components/OpenInExploreTracesButton/types'; +import { OpenInExploreTracesButtonProps } from 'exposedComponents/types'; import React, { lazy, Suspense } from 'react'; -const OpenInExploreTracesButton = lazy(() => import('components/OpenInExploreTracesButton/OpenInExploreTracesButton')); +const OpenInExploreTracesButton = lazy(() => import('exposedComponents/OpenInExploreTracesButton/OpenInExploreTracesButton')); function SuspendedOpenInExploreTracesButton(props: OpenInExploreTracesButtonProps) { return ( - Open in Explore Traces + Open in Traces drilldown } > @@ -20,8 +20,8 @@ function SuspendedOpenInExploreTracesButton(props: OpenInExploreTracesButtonProp export const exposedComponents = [ { id: 'grafana-exploretraces-app/open-in-explore-traces-button/v1', - title: 'Open in Explore Traces button', - description: 'A button that opens a traces view in the Explore Traces app.', + title: 'Open in Traces drilldown button', + description: 'A button that opens a traces view in the Traces drilldown app.', component: SuspendedOpenInExploreTracesButton, }, ]; diff --git a/src/components/OpenInExploreTracesButton/types.ts b/src/exposedComponents/types.ts similarity index 99% rename from src/components/OpenInExploreTracesButton/types.ts rename to src/exposedComponents/types.ts index 0e4457b..6a3ec32 100644 --- a/src/components/OpenInExploreTracesButton/types.ts +++ b/src/exposedComponents/types.ts @@ -1,3 +1,4 @@ + export type TempoMatcher = { name: string; value: string; diff --git a/src/plugin.json b/src/plugin.json index f59a486..365f1d7 100644 --- a/src/plugin.json +++ b/src/plugin.json @@ -60,8 +60,8 @@ "exposedComponents": [ { "id": "grafana-exploretraces-app/open-in-explore-traces-button/v1", - "title": "Open in Explore Traces button", - "description": "A button that opens a traces view in the Explore Traces app." + "title": "Open in Traces drilldown button", + "description": "A button that opens a traces view in the Traces drilldown app." } ], "addedLinks": [ diff --git a/tsconfig-for-bundle-types.json b/tsconfig-for-bundle-types.json new file mode 100644 index 0000000..5a37ca0 --- /dev/null +++ b/tsconfig-for-bundle-types.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "declaration": true, + "esModuleInterop": true, + "skipLibCheck": true, + "jsx": "react", + "resolveJsonModule": true + } +} \ No newline at end of file