Skip to content

Commit 8559285

Browse files
committed
Display Loki labels in bold in filters dropdown
- Add lokiLabels to frontend config - Populate lokiLabels from Loki config
1 parent cabe8c5 commit 8559285

File tree

6 files changed

+49
-17
lines changed

6 files changed

+49
-17
lines changed

pkg/config/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ type Frontend struct {
134134
Fields []FieldConfig `yaml:"fields" json:"fields"`
135135
DataSources []string `yaml:"dataSources" json:"dataSources"`
136136
LokiMocks bool `yaml:"lokiMocks,omitempty" json:"lokiMocks,omitempty"`
137+
LokiLabels []string `yaml:"lokiLabels" json:"lokiLabels"`
137138
PromLabels []string `yaml:"promLabels" json:"promLabels"`
138139
MaxChunkAgeMs int `yaml:"maxChunkAgeMs,omitempty" json:"maxChunkAgeMs,omitempty"` // populated at query time
139140
}
@@ -191,6 +192,7 @@ func ReadFile(version, date, filename string) (*Config, error) {
191192
{Name: "DstAddr", Type: "string"},
192193
},
193194
DataSources: []string{},
195+
LokiLabels: []string{},
194196
PromLabels: []string{},
195197
},
196198
}
@@ -212,6 +214,7 @@ func ReadFile(version, date, filename string) (*Config, error) {
212214
if cfg.IsLokiEnabled() {
213215
cfg.Frontend.DataSources = append(cfg.Frontend.DataSources, string(constants.DataSourceLoki))
214216
cfg.Frontend.LokiMocks = cfg.Loki.UseMocks
217+
cfg.Frontend.LokiLabels = cfg.Loki.Labels
215218
cfg.Loki.FieldsType = make(map[string]string)
216219
cfg.Loki.FieldsFormat = make(map[string]string)
217220
for _, f := range cfg.Frontend.Fields {

web/src/api/routes.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -190,21 +190,22 @@ export const getConfig = (): Promise<Config> => {
190190
panels: r.data.panels,
191191
columns: r.data.columns,
192192
portNaming: {
193-
enable: r.data.portNaming.enable ?? defaultConfig.portNaming.enable,
194-
portNames: r.data.portNaming.portNames
195-
? new Map(Object.entries(r.data.portNaming.portNames))
196-
: defaultConfig.portNaming.portNames
193+
enable: r.data.portNaming.enable ?? defaultConfig.portNaming.enable,
194+
portNames: r.data.portNaming.portNames
195+
? new Map(Object.entries(r.data.portNaming.portNames))
196+
: defaultConfig.portNaming.portNames
197197
},
198-
filters: r.data.filters,
199-
scopes: r.data.scopes,
200-
quickFilters: r.data.quickFilters,
201-
alertNamespaces: r.data.alertNamespaces,
202-
sampling: r.data.sampling,
203-
features: r.data.features || defaultConfig.features,
204-
fields: r.data.fields || defaultConfig.fields,
205-
dataSources: r.data.dataSources || defaultConfig.dataSources,
206-
promLabels: r.data.promLabels || defaultConfig.promLabels,
207-
maxChunkAgeMs: r.data.maxChunkAgeMs
198+
filters: r.data.filters,
199+
scopes: r.data.scopes,
200+
quickFilters: r.data.quickFilters,
201+
alertNamespaces: r.data.alertNamespaces,
202+
sampling: r.data.sampling,
203+
features: r.data.features || defaultConfig.features,
204+
fields: r.data.fields || defaultConfig.fields,
205+
dataSources: r.data.dataSources || defaultConfig.dataSources,
206+
promLabels: r.data.promLabels || defaultConfig.promLabels,
207+
lokiLabels: r.data.lokiLabels || defaultConfig.lokiLabels,
208+
maxChunkAgeMs: r.data.maxChunkAgeMs
208209
};
209210
});
210211
};

web/src/components/toolbar/filters-toolbar.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { CompressIcon, ExpandIcon } from '@patternfly/react-icons';
1111
import * as _ from 'lodash';
1212
import * as React from 'react';
1313
import { useTranslation } from 'react-i18next';
14+
import { Config } from '../../model/config';
1415
import { Filter, FilterDefinition, Filters, FilterValue, findFromFilters } from '../../model/filters';
1516
import { QuickFilter } from '../../model/quick-filters';
1617
import { autoCompleteCache } from '../../utils/autocomplete-cache';
@@ -30,6 +31,7 @@ import { LinksOverflow } from './links-overflow';
3031

3132
export interface FiltersToolbarProps {
3233
id: string;
34+
config: Config;
3335
filters?: Filters;
3436
forcedFilters?: Filters | null;
3537
skipTipsDelay?: boolean;
@@ -45,6 +47,7 @@ export interface FiltersToolbarProps {
4547

4648
export const FiltersToolbar: React.FC<FiltersToolbarProps> = ({
4749
id,
50+
config,
4851
filters,
4952
forcedFilters,
5053
skipTipsDelay,
@@ -161,6 +164,7 @@ export const FiltersToolbar: React.FC<FiltersToolbarProps> = ({
161164
<div>
162165
<InputGroup>
163166
<FiltersDropdown
167+
config={config}
164168
filterDefinitions={filterDefinitions}
165169
selectedFilter={selectedFilter}
166170
setSelectedFilter={setSelectedFilter}
@@ -177,7 +181,7 @@ export const FiltersToolbar: React.FC<FiltersToolbarProps> = ({
177181
</Tooltip>
178182
</ToolbarItem>
179183
);
180-
}, [filterDefinitions, getFilterControl, message, selectedCompare, selectedFilter]);
184+
}, [config, filterDefinitions, getFilterControl, message, selectedCompare, selectedFilter]);
181185

182186
const isForced = !_.isEmpty(forcedFilters);
183187
const filtersOrForced = isForced ? forcedFilters : filters;

web/src/components/toolbar/filters/filters-dropdown.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,21 @@ import {
1010
} from '@patternfly/react-core';
1111
import * as React from 'react';
1212
import { useTranslation } from 'react-i18next';
13+
import { Config } from '../../../model/config';
1314
import { FilterDefinition } from '../../../model/filters';
14-
import { buildGroups, getFilterFullName } from '../../../utils/filters-helper';
15+
import { buildGroups, getFilterFullName, isLokiLabel } from '../../../utils/filters-helper';
1516
import { useOutsideClickEvent } from '../../../utils/outside-hook';
1617
import './filters-dropdown.css';
1718

1819
export interface FiltersDropdownProps {
20+
config: Config;
1921
filterDefinitions: FilterDefinition[];
2022
selectedFilter: FilterDefinition;
2123
setSelectedFilter: (f: FilterDefinition) => void;
2224
}
2325

2426
export const FiltersDropdown: React.FC<FiltersDropdownProps> = ({
27+
config,
2528
filterDefinitions,
2629
selectedFilter,
2730
setSelectedFilter
@@ -58,7 +61,7 @@ export const FiltersDropdown: React.FC<FiltersDropdownProps> = ({
5861
}}
5962
key={index}
6063
>
61-
{f.name}
64+
{isLokiLabel(f, config) ? <strong>{f.name}</strong> : f.name}
6265
</DropdownItem>
6366
))}
6467
</AccordionContent>

web/src/model/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type Config = {
3636
fields: FieldConfig[];
3737
dataSources: string[];
3838
lokiMocks: boolean;
39+
lokiLabels: string[];
3940
promLabels: string[];
4041
maxChunkAgeMs?: number;
4142
};
@@ -59,6 +60,7 @@ export const defaultConfig: Config = {
5960
fields: [],
6061
dataSources: ['loki', 'prom'],
6162
lokiMocks: false,
63+
lokiLabels: [],
6264
promLabels: [],
6365
maxChunkAgeMs: undefined
6466
};

web/src/utils/filters-helper.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TFunction } from 'i18next';
2+
import { Config } from '../model/config';
23
import { Filter, FilterDefinition, FilterId } from '../model/filters';
34
import { findFilter } from './filter-definitions';
45

@@ -58,3 +59,21 @@ export const swapFilters = (filterDefinitions: FilterDefinition[], filters: Filt
5859
return f;
5960
});
6061
};
62+
63+
export const isLokiLabel = (filter: FilterDefinition, config: Config): boolean => {
64+
const allowLoki = config.dataSources.some(ds => ds === 'loki');
65+
if (!allowLoki) {
66+
return false;
67+
}
68+
69+
// Encode a dummy query to check related labels
70+
const q = filter.encoder([{ v: 'any' }], false, false, false);
71+
const parts = q.split('&');
72+
for (let i = 0; i < parts.length; i++) {
73+
const kv = parts[i].split('=');
74+
if (kv.length === 0 || config.lokiLabels.includes(kv[0])) {
75+
return true;
76+
}
77+
}
78+
return false;
79+
};

0 commit comments

Comments
 (0)