mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Instrument transformations (#64960)
* Instrument transformations * Fix any * Fix any * Fix unit test
This commit is contained in:
@@ -2900,10 +2900,6 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"],
|
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"],
|
||||||
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "2"]
|
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "2"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/components/TransformationsEditor/TransformationOperationRow.tsx:5381": [
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
|
||||||
],
|
|
||||||
"public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx:5381": [
|
"public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx:5381": [
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||||
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"],
|
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"],
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useCallback } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
import { config, reportInteraction } from '@grafana/runtime';
|
||||||
import { Tab, TabContent, TabsBar, toIconName, useForceUpdate, useStyles2 } from '@grafana/ui';
|
import { Tab, TabContent, TabsBar, toIconName, useForceUpdate, useStyles2 } from '@grafana/ui';
|
||||||
import AlertTabIndex from 'app/features/alerting/AlertTabIndex';
|
import AlertTabIndex from 'app/features/alerting/AlertTabIndex';
|
||||||
import { PanelAlertTab } from 'app/features/alerting/unified/PanelAlertTab';
|
import { PanelAlertTab } from 'app/features/alerting/unified/PanelAlertTab';
|
||||||
@@ -26,6 +26,17 @@ export const PanelEditorTabs = React.memo(({ panel, dashboard, tabs, onChangeTab
|
|||||||
const forceUpdate = useForceUpdate();
|
const forceUpdate = useForceUpdate();
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
|
const instrumentedOnChangeTab = useCallback(
|
||||||
|
(tab) => {
|
||||||
|
if (!tab.active) {
|
||||||
|
reportInteraction('panel_editor_tabs_changed', { tab_id: tab.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeTab(tab);
|
||||||
|
},
|
||||||
|
[onChangeTab]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const eventSubs = new Subscription();
|
const eventSubs = new Subscription();
|
||||||
eventSubs.add(panel.events.subscribe(PanelQueriesChangedEvent, forceUpdate));
|
eventSubs.add(panel.events.subscribe(PanelQueriesChangedEvent, forceUpdate));
|
||||||
@@ -44,14 +55,14 @@ export const PanelEditorTabs = React.memo(({ panel, dashboard, tabs, onChangeTab
|
|||||||
<TabsBar className={styles.tabBar} hideBorder>
|
<TabsBar className={styles.tabBar} hideBorder>
|
||||||
{tabs.map((tab) => {
|
{tabs.map((tab) => {
|
||||||
if (tab.id === PanelEditorTabId.Alert) {
|
if (tab.id === PanelEditorTabId.Alert) {
|
||||||
return renderAlertTab(tab, panel, dashboard, onChangeTab);
|
return renderAlertTab(tab, panel, dashboard, instrumentedOnChangeTab);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Tab
|
<Tab
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
label={tab.text}
|
label={tab.text}
|
||||||
active={tab.active}
|
active={tab.active}
|
||||||
onChangeTab={() => onChangeTab(tab)}
|
onChangeTab={() => instrumentedOnChangeTab(tab)}
|
||||||
icon={toIconName(tab.icon)}
|
icon={toIconName(tab.icon)}
|
||||||
counter={getCounter(panel, tab)}
|
counter={getCounter(panel, tab)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
|
|||||||
import { useToggle } from 'react-use';
|
import { useToggle } from 'react-use';
|
||||||
|
|
||||||
import { DataFrame, DataTransformerConfig, TransformerRegistryItem, FrameMatcherID } from '@grafana/data';
|
import { DataFrame, DataTransformerConfig, TransformerRegistryItem, FrameMatcherID } from '@grafana/data';
|
||||||
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { HorizontalGroup } from '@grafana/ui';
|
import { HorizontalGroup } from '@grafana/ui';
|
||||||
import { OperationRowHelp } from 'app/core/components/QueryOperationRow/OperationRowHelp';
|
import { OperationRowHelp } from 'app/core/components/QueryOperationRow/OperationRowHelp';
|
||||||
import { QueryOperationAction } from 'app/core/components/QueryOperationRow/QueryOperationAction';
|
import { QueryOperationAction } from 'app/core/components/QueryOperationRow/QueryOperationAction';
|
||||||
@@ -19,7 +20,7 @@ interface TransformationOperationRowProps {
|
|||||||
id: string;
|
id: string;
|
||||||
index: number;
|
index: number;
|
||||||
data: DataFrame[];
|
data: DataFrame[];
|
||||||
uiConfig: TransformerRegistryItem<any>;
|
uiConfig: TransformerRegistryItem<null>;
|
||||||
configs: TransformationsEditorTransformation[];
|
configs: TransformationsEditorTransformation[];
|
||||||
onRemove: (index: number) => void;
|
onRemove: (index: number) => void;
|
||||||
onChange: (index: number, config: DataTransformerConfig) => void;
|
onChange: (index: number, config: DataTransformerConfig) => void;
|
||||||
@@ -65,6 +66,21 @@ export const TransformationOperationRow = ({
|
|||||||
onChange(index, current);
|
onChange(index, current);
|
||||||
}, [onChange, index, configs]);
|
}, [onChange, index, configs]);
|
||||||
|
|
||||||
|
// Instrument toggle callback
|
||||||
|
const instrumentToggleCallback = useCallback(
|
||||||
|
(callback: (e: React.MouseEvent) => void, toggleId: string, active: boolean | undefined) =>
|
||||||
|
(e: React.MouseEvent) => {
|
||||||
|
reportInteraction('panel_editor_tabs_transformations_toggle', {
|
||||||
|
action: active ? 'off' : 'on',
|
||||||
|
toggleId,
|
||||||
|
transformationId: configs[index].transformation.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(e);
|
||||||
|
},
|
||||||
|
[configs, index]
|
||||||
|
);
|
||||||
|
|
||||||
const renderActions = ({ isOpen }: QueryOperationRowRenderProps) => {
|
const renderActions = ({ isOpen }: QueryOperationRowRenderProps) => {
|
||||||
return (
|
return (
|
||||||
<HorizontalGroup align="center" width="auto">
|
<HorizontalGroup align="center" width="auto">
|
||||||
@@ -72,15 +88,28 @@ export const TransformationOperationRow = ({
|
|||||||
<QueryOperationAction
|
<QueryOperationAction
|
||||||
title="Show/hide transform help"
|
title="Show/hide transform help"
|
||||||
icon="info-circle"
|
icon="info-circle"
|
||||||
onClick={toggleHelp}
|
onClick={instrumentToggleCallback(toggleHelp, 'help', showHelp)}
|
||||||
active={showHelp}
|
active={showHelp}
|
||||||
/>
|
/>
|
||||||
{showFilter && <QueryOperationAction title="Filter" icon="filter" onClick={toggleFilter} active={filter} />}
|
{showFilter && (
|
||||||
<QueryOperationAction title="Debug" disabled={!isOpen} icon="bug" onClick={toggleDebug} active={showDebug} />
|
<QueryOperationAction
|
||||||
|
title="Filter"
|
||||||
|
icon="filter"
|
||||||
|
onClick={instrumentToggleCallback(toggleFilter, 'filter', filter)}
|
||||||
|
active={filter}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<QueryOperationAction
|
||||||
|
title="Debug"
|
||||||
|
disabled={!isOpen}
|
||||||
|
icon="bug"
|
||||||
|
onClick={instrumentToggleCallback(toggleDebug, 'debug', showDebug)}
|
||||||
|
active={showDebug}
|
||||||
|
/>
|
||||||
<QueryOperationAction
|
<QueryOperationAction
|
||||||
title="Disable/Enable transformation"
|
title="Disable/Enable transformation"
|
||||||
icon={disabled ? 'eye-slash' : 'eye'}
|
icon={disabled ? 'eye-slash' : 'eye'}
|
||||||
onClick={() => onDisableToggle(index)}
|
onClick={instrumentToggleCallback(() => onDisableToggle(index), 'disabled', disabled)}
|
||||||
active={disabled}
|
active={disabled}
|
||||||
/>
|
/>
|
||||||
<QueryOperationAction title="Remove" icon="trash-alt" onClick={() => onRemove(index)} />
|
<QueryOperationAction title="Remove" icon="trash-alt" onClick={() => onRemove(index)} />
|
||||||
@@ -113,7 +142,7 @@ export const TransformationOperationRow = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function prepMarkdown(uiConfig: TransformerRegistryItem<any>) {
|
function prepMarkdown(uiConfig: TransformerRegistryItem<null>) {
|
||||||
let helpMarkdown = uiConfig.help ?? uiConfig.description;
|
let helpMarkdown = uiConfig.help ?? uiConfig.description;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
TransformerRegistryItem,
|
TransformerRegistryItem,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Button,
|
Button,
|
||||||
@@ -144,6 +145,10 @@ class UnThemedTransformationsEditor extends React.PureComponent<TransformationsE
|
|||||||
};
|
};
|
||||||
|
|
||||||
onTransformationAdd = (selectable: SelectableValue<string>) => {
|
onTransformationAdd = (selectable: SelectableValue<string>) => {
|
||||||
|
reportInteraction('panel_editor_tabs_transformations_management', {
|
||||||
|
action: 'add',
|
||||||
|
transformationId: selectable.value,
|
||||||
|
});
|
||||||
const { transformations } = this.state;
|
const { transformations } = this.state;
|
||||||
|
|
||||||
const nextId = this.getTransformationNextId(selectable.value!);
|
const nextId = this.getTransformationNextId(selectable.value!);
|
||||||
@@ -163,6 +168,10 @@ class UnThemedTransformationsEditor extends React.PureComponent<TransformationsE
|
|||||||
onTransformationChange = (idx: number, config: DataTransformerConfig) => {
|
onTransformationChange = (idx: number, config: DataTransformerConfig) => {
|
||||||
const { transformations } = this.state;
|
const { transformations } = this.state;
|
||||||
const next = Array.from(transformations);
|
const next = Array.from(transformations);
|
||||||
|
reportInteraction('panel_editor_tabs_transformations_management', {
|
||||||
|
action: 'change',
|
||||||
|
transformationId: next[idx].transformation.id,
|
||||||
|
});
|
||||||
next[idx].transformation = config;
|
next[idx].transformation = config;
|
||||||
this.onChange(next);
|
this.onChange(next);
|
||||||
};
|
};
|
||||||
@@ -170,6 +179,10 @@ class UnThemedTransformationsEditor extends React.PureComponent<TransformationsE
|
|||||||
onTransformationRemove = (idx: number) => {
|
onTransformationRemove = (idx: number) => {
|
||||||
const { transformations } = this.state;
|
const { transformations } = this.state;
|
||||||
const next = Array.from(transformations);
|
const next = Array.from(transformations);
|
||||||
|
reportInteraction('panel_editor_tabs_transformations_management', {
|
||||||
|
action: 'remove',
|
||||||
|
transformationId: next[idx].transformation.id,
|
||||||
|
});
|
||||||
next.splice(idx, 1);
|
next.splice(idx, 1);
|
||||||
this.onChange(next);
|
this.onChange(next);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user