Add the ability to convert specific tags to columns on problems panel (#2113)
This closes #2112 Added the ability on problems panel to specify a comma separated list of tag names to be converted to columns. If a tag name is present multiple times, it will return the value of all tags separated with comma. For optimum readability, the tag names are Capitalized for the visible column name. Also, for optimum readability, the custom tags are always placed before the "Tags" column. In case a tag is not there for a problem, an empty string is returned. --------- Co-authored-by: Jocelyn Collado-Kuri <jcolladokuri@icloud.com>
This commit is contained in:
committed by
GitHub
parent
95554b0b8c
commit
3ada0d15e6
5
.changeset/wet-monkeys-smoke.md
Normal file
5
.changeset/wet-monkeys-smoke.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'grafana-zabbix': patch
|
||||
---
|
||||
|
||||
Enhance the problems panel with the ability to convert specific tags to columns. Single or multiple tags supported.
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from '@tanstack/react-table';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import { ProblemDetails } from './ProblemDetails';
|
||||
import { capitalizeFirstLetter, parseCustomTagColumns } from './utils';
|
||||
|
||||
export interface ProblemListProps {
|
||||
problems: ProblemDTO[];
|
||||
@@ -47,6 +48,33 @@ export interface ProblemListProps {
|
||||
|
||||
const columnHelper = createColumnHelper<ProblemDTO>();
|
||||
|
||||
const buildCustomTagColumns = (customTagColumns?: string) => {
|
||||
const tagNames = parseCustomTagColumns(customTagColumns);
|
||||
|
||||
return tagNames.map((tagName) =>
|
||||
columnHelper.accessor(
|
||||
(row) => {
|
||||
const tags = row.tags ?? [];
|
||||
const values = tags
|
||||
.filter((t) => t.tag === tagName)
|
||||
.map((t) => t.value)
|
||||
.filter(Boolean);
|
||||
|
||||
return values.length ? values.join(', ') : '';
|
||||
},
|
||||
{
|
||||
id: `problem-tag_${tagName}`,
|
||||
header: capitalizeFirstLetter(tagName),
|
||||
size: 150,
|
||||
meta: {
|
||||
className: `problem-tag_${tagName}`,
|
||||
},
|
||||
cell: ({ getValue }) => <span>{getValue() as string}</span>,
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const ProblemList = (props: ProblemListProps) => {
|
||||
const {
|
||||
pageSize,
|
||||
@@ -72,6 +100,8 @@ export const ProblemList = (props: ProblemListProps) => {
|
||||
const columns = useMemo(() => {
|
||||
const highlightNewerThan = panelOptions.highlightNewEvents && panelOptions.highlightNewerThan;
|
||||
|
||||
const customTagColumns = buildCustomTagColumns(panelOptions.customTagColumns);
|
||||
|
||||
return [
|
||||
columnHelper.accessor('host', {
|
||||
header: 'Host',
|
||||
@@ -146,6 +176,7 @@ export const ProblemList = (props: ProblemListProps) => {
|
||||
size: 70,
|
||||
cell: ({ cell }) => <AckCell acknowledges={cell.row.original.acknowledges} />,
|
||||
}),
|
||||
...customTagColumns,
|
||||
columnHelper.accessor('tags', {
|
||||
header: 'Tags',
|
||||
size: 150,
|
||||
|
||||
38
src/panel-triggers/components/Problems/utils.test.ts
Normal file
38
src/panel-triggers/components/Problems/utils.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { capitalizeFirstLetter, parseCustomTagColumns } from './utils';
|
||||
|
||||
describe('capitalizeFirstLetter', () => {
|
||||
it('capitalizes first letter and lowercases the rest', () => {
|
||||
expect(capitalizeFirstLetter('zabbixgrafana')).toBe('Zabbixgrafana');
|
||||
expect(capitalizeFirstLetter('ZABBIXGRAFANA')).toBe('Zabbixgrafana');
|
||||
expect(capitalizeFirstLetter('zAbBiXgRaFaNa')).toBe('Zabbixgrafana');
|
||||
});
|
||||
|
||||
it('returns empty string for empty input', () => {
|
||||
expect(capitalizeFirstLetter('')).toBe('');
|
||||
});
|
||||
|
||||
it('handles single-character strings', () => {
|
||||
expect(capitalizeFirstLetter('a')).toBe('A');
|
||||
expect(capitalizeFirstLetter('A')).toBe('A');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseCustomTagColumns', () => {
|
||||
it('returns empty array for undefined or empty input', () => {
|
||||
expect(parseCustomTagColumns(undefined)).toEqual([]);
|
||||
expect(parseCustomTagColumns('')).toEqual([]);
|
||||
expect(parseCustomTagColumns(' ')).toEqual([]);
|
||||
});
|
||||
|
||||
it('splits comma-separated values and trims whitespace', () => {
|
||||
expect(parseCustomTagColumns('env, region ,service')).toEqual(['env', 'region', 'service']);
|
||||
});
|
||||
|
||||
it('filters out empty values', () => {
|
||||
expect(parseCustomTagColumns('env,, ,region,')).toEqual(['env', 'region']);
|
||||
});
|
||||
|
||||
it('preserves order', () => {
|
||||
expect(parseCustomTagColumns('a,b,c')).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
||||
12
src/panel-triggers/components/Problems/utils.ts
Normal file
12
src/panel-triggers/components/Problems/utils.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
||||
|
||||
export const parseCustomTagColumns = (customTagColumns?: string): string[] => {
|
||||
if (!customTagColumns) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return customTagColumns
|
||||
.split(',')
|
||||
.map((tagName) => tagName.trim())
|
||||
.filter(Boolean);
|
||||
};
|
||||
@@ -220,6 +220,17 @@ export const plugin = new PanelPlugin<ProblemsPanelOptions, {}>(ProblemsPanel)
|
||||
name: 'Datasource name',
|
||||
defaultValue: defaultPanelOptions.showDatasourceName,
|
||||
category: ['Fields'],
|
||||
})
|
||||
// Select tag name to display as column
|
||||
.addTextInput({
|
||||
path: 'customTagColumns',
|
||||
name: 'Tags to columns',
|
||||
defaultValue: '',
|
||||
description: 'Comma-separated list of tag names to display as columns (e.g., component, scope, environment)',
|
||||
settings: {
|
||||
placeholder: 'component, scope, target',
|
||||
},
|
||||
category: ['Fields'],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ export interface ProblemsPanelOptions {
|
||||
okEventColor: TriggerColor;
|
||||
ackEventColor: TriggerColor;
|
||||
markAckEvents?: boolean;
|
||||
// Custom tag names to display as column
|
||||
customTagColumns?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SEVERITY: TriggerSeverity[] = [
|
||||
|
||||
Reference in New Issue
Block a user