Skip to content

Commit 1affba3

Browse files
app/vmui: vmalert ui for logs (#522)
1 parent 97ffbff commit 1affba3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+3203
-184
lines changed

app/vmui/Dockerfile-build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:20-alpine3.19
1+
FROM node:22-alpine3.22
22

33
# Sets a custom location for the npm cache, preventing access errors in system directories
44
ENV NPM_CONFIG_CACHE=/build/.npm

app/vmui/packages/vmui/src/App.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import ExploreLogs from "./pages/ExploreLogs/ExploreLogs";
66
import LogsLayout from "./layouts/LogsLayout/LogsLayout";
77
import StreamContext from "./pages/StreamContext/StreamContext";
88
import router from "./router";
9+
import ExploreRules from "./pages/ExploreAlerts/ExploreRules";
10+
import ExploreNotifiers from "./pages/ExploreAlerts/ExploreNotifiers";
911
import "./constants/markedPlugins";
1012

1113
const App: FC = () => {
@@ -30,6 +32,14 @@ const App: FC = () => {
3032
path={router.streamContext}
3133
element={<StreamContext/>}
3234
/>
35+
<Route
36+
path={router.rules}
37+
element={<ExploreRules/>}
38+
/>
39+
<Route
40+
path={router.notifiers}
41+
element={<ExploreNotifiers/>}
42+
/>
3343
</Route>
3444
</Routes>
3545
)}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export const getGroupsUrl = (server: string): string => {
2+
return `${server}/select/vmalert/api/v1/rules?datasource_type=vlogs`;
3+
};
4+
5+
export const getItemUrl = (
6+
server: string,
7+
groupId: string,
8+
id: string,
9+
mode: string,
10+
): string => {
11+
return `${server}/select/vmalert/api/v1/${mode}?group_id=${groupId}&${mode}_id=${id}`;
12+
};
13+
14+
export const getGroupUrl = (
15+
server: string,
16+
id: string,
17+
): string => {
18+
return `${server}/select/vmalert/api/v1/group?group_id=${id}`;
19+
};
20+
21+
export const getNotifiersUrl = (server: string): string => {
22+
return `${server}/select/vmalert/api/v1/notifiers`;
23+
};

app/vmui/packages/vmui/src/components/Configurators/TimeRangeSettings/ExecutionControls/ExecutionControls.tsx

Lines changed: 102 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ const delayOptions: AutoRefreshOption[] = [
3030
{ seconds: 7200, title: "2h" }
3131
];
3232

33-
export const ExecutionControls: FC = () => {
33+
interface ExecutionControlsProps {
34+
tooltip: string;
35+
useAutorefresh?: boolean;
36+
closeModal: () => void;
37+
}
38+
39+
export const ExecutionControls: FC<ExecutionControlsProps> = ({ tooltip, useAutorefresh, closeModal }) => {
3440
const { isMobile } = useDeviceDetect();
3541

3642
const dispatch = useTimeDispatch();
@@ -56,6 +62,9 @@ export const ExecutionControls: FC = () => {
5662

5763
const handleUpdate = () => {
5864
dispatch({ type: "RUN_QUERY" });
65+
if (!useAutorefresh && isMobile) {
66+
closeModal();
67+
}
5968
};
6069

6170
useEffect(() => {
@@ -84,84 +93,109 @@ export const ExecutionControls: FC = () => {
8493
"vm-execution-controls-buttons": true,
8594
"vm-execution-controls-buttons_mobile": isMobile,
8695
"vm-header-button": !appModeEnable,
96+
"vm-autorefresh": useAutorefresh,
8797
})}
8898
>
89-
{!isMobile && (
90-
<Tooltip title="Refresh dashboard">
99+
{useAutorefresh ? (
100+
isMobile ? (
101+
<div
102+
className="vm-mobile-option"
103+
onClick={toggleOpenOptions}
104+
>
105+
<span className="vm-mobile-option__icon"><RestartIcon/></span>
106+
<div className="vm-mobile-option-text">
107+
<span className="vm-mobile-option-text__label">Auto-refresh</span>
108+
<span className="vm-mobile-option-text__value">{selectedDelay.title}</span>
109+
</div>
110+
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
111+
</div>
112+
) : (
113+
<>
114+
<Tooltip title={tooltip}>
115+
<Button
116+
variant="contained"
117+
color="primary"
118+
onClick={handleUpdate}
119+
startIcon={<RefreshIcon/>}
120+
ariaLabel={tooltip}
121+
/>
122+
</Tooltip>
123+
<Tooltip title="Auto-refresh control">
124+
<div ref={optionsButtonRef}>
125+
<Button
126+
variant="contained"
127+
color="primary"
128+
fullWidth
129+
endIcon={(
130+
<div
131+
className={classNames({
132+
"vm-execution-controls-buttons__arrow": true,
133+
"vm-execution-controls-buttons__arrow_open": openOptions,
134+
})}
135+
>
136+
<ArrowDownIcon/>
137+
</div>
138+
)}
139+
onClick={toggleOpenOptions}
140+
>
141+
{selectedDelay.title}
142+
</Button>
143+
</div>
144+
</Tooltip>
145+
</>
146+
)
147+
) : (
148+
isMobile ? (
149+
<div
150+
className="vm-mobile-option"
151+
onClick={handleUpdate}
152+
>
153+
<span className="vm-mobile-option__icon"><RestartIcon/></span>
154+
<div className="vm-mobile-option-text">
155+
<span className="vm-mobile-option-text__label">Refresh</span>
156+
</div>
157+
</div>
158+
) : (
91159
<Button
92160
variant="contained"
93161
color="primary"
94162
onClick={handleUpdate}
95163
startIcon={<RefreshIcon/>}
96-
ariaLabel="refresh dashboard"
164+
ariaLabel={tooltip}
97165
/>
98-
</Tooltip>
99-
)}
100-
{isMobile ? (
101-
<div
102-
className="vm-mobile-option"
103-
onClick={toggleOpenOptions}
104-
>
105-
<span className="vm-mobile-option__icon"><RestartIcon/></span>
106-
<div className="vm-mobile-option-text">
107-
<span className="vm-mobile-option-text__label">Auto-refresh</span>
108-
<span className="vm-mobile-option-text__value">{selectedDelay.title}</span>
109-
</div>
110-
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
111-
</div>
112-
) : (
113-
<Tooltip title="Auto-refresh control">
114-
<div ref={optionsButtonRef}>
115-
<Button
116-
variant="contained"
117-
color="primary"
118-
fullWidth
119-
endIcon={(
120-
<div
121-
className={classNames({
122-
"vm-execution-controls-buttons__arrow": true,
123-
"vm-execution-controls-buttons__arrow_open": openOptions,
124-
})}
125-
>
126-
<ArrowDownIcon/>
127-
</div>
128-
)}
129-
onClick={toggleOpenOptions}
130-
>
131-
{selectedDelay.title}
132-
</Button>
133-
</div>
134-
</Tooltip>
166+
)
135167
)}
136168
</div>
137169
</div>
138-
<Popper
139-
open={openOptions}
140-
placement="bottom-right"
141-
onClose={handleCloseOptions}
142-
buttonRef={optionsButtonRef}
143-
title={isMobile ? "Auto-refresh duration" : undefined}
144-
>
145-
<div
146-
className={classNames({
147-
"vm-execution-controls-list": true,
148-
"vm-execution-controls-list_mobile": isMobile,
149-
})}
170+
{useAutorefresh && (
171+
<Popper
172+
open={openOptions}
173+
placement="bottom-right"
174+
onClose={handleCloseOptions}
175+
buttonRef={optionsButtonRef}
176+
title={isMobile ? "Auto-refresh duration" : undefined}
150177
>
151-
{delayOptions.map(d => (
152-
<div
153-
className={classNames({
154-
"vm-list-item": true,
155-
"vm-list-item_mobile": isMobile,
156-
"vm-list-item_active": d.seconds === selectedDelay.seconds
157-
})}
158-
key={d.seconds}
159-
onClick={createHandlerChange(d)}
160-
>
161-
{d.title}
162-
</div>
163-
))}
164-
</div>
165-
</Popper>
178+
<div
179+
className={classNames({
180+
"vm-execution-controls-list": true,
181+
"vm-execution-controls-list_mobile": isMobile,
182+
})}
183+
>
184+
{delayOptions.map(d => (
185+
<div
186+
className={classNames({
187+
"vm-list-item": true,
188+
"vm-list-item_mobile": isMobile,
189+
"vm-list-item_active": d.seconds === selectedDelay.seconds
190+
})}
191+
key={d.seconds}
192+
onClick={createHandlerChange(d)}
193+
>
194+
{d.title}
195+
</div>
196+
))}
197+
</div>
198+
</Popper>
199+
)}
166200
</>;
167201
};

app/vmui/packages/vmui/src/components/Configurators/TimeRangeSettings/ExecutionControls/style.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
display: flex;
88
justify-content: space-between;
99
border-radius: calc($button-radius + 1px);
10-
min-width: 107px;
10+
:is(.vm-autorefresh) {
11+
min-width: 107px;
12+
}
1113

1214
&_mobile {
1315
flex-direction: column;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import "./style.scss";
2+
import { ReactNode } from "react";
3+
4+
export type BadgeColor = "firing" | "inactive" | "pending" | "no-match" | "unhealthy" | "ok" | "passive";
5+
6+
interface BadgeItem {
7+
value?: number | string;
8+
color: BadgeColor;
9+
}
10+
11+
interface BadgesProps {
12+
items: Record<string, BadgeItem>;
13+
align?: "center" | "start" | "end";
14+
children?: ReactNode;
15+
}
16+
17+
const Badges = ({ items, children, align = "start" }: BadgesProps) => {
18+
return (
19+
<div
20+
className="vm-badges"
21+
style={{ "justify-content": align }}
22+
>
23+
{Object.entries(items).map(([name, props]) => (
24+
<span
25+
key={name}
26+
className={`vm-badge ${props.color}`}
27+
>{props.value ? `${name}: ${props.value}` : name}</span>
28+
))}
29+
{children}
30+
</div>
31+
);
32+
};
33+
34+
export default Badges;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
@use "src/styles/variables" as *;
2+
3+
$badge-colors: (
4+
"firing": $color-error,
5+
"inactive": $color-success,
6+
"pending": $color-warning,
7+
"no-match": $color-notice,
8+
"unhealthy": $color-broken,
9+
"ok": $color-info,
10+
"passive": $color-passive,
11+
"all": $color-passive,
12+
);
13+
14+
.vm-badges {
15+
display: flex;
16+
flex-wrap: wrap;
17+
gap: $padding-small;
18+
&.align-center {
19+
justify-content: center;
20+
}
21+
.vm-badge {
22+
padding: 0 $padding-tiny;
23+
width: fit-content;
24+
@each $class, $color in $badge-colors {
25+
&.#{$class} {
26+
border: 1px solid $color;
27+
color: $color;
28+
}
29+
}
30+
}
31+
}
32+
33+
.vm-badge-base {
34+
font-weight: 400;
35+
border-radius: $border-radius-small;
36+
}
37+
38+
.vm-badge-menu-item {
39+
@extend .vm-badge-base;
40+
overflow: hidden;
41+
white-space: nowrap;
42+
text-overflow: ellipsis;
43+
line-height: 22px;
44+
@each $class, $color in $badge-colors {
45+
&.#{$class} {
46+
border-right: $border-radius-small solid $color;
47+
}
48+
}
49+
}
50+
51+
.vm-badge-item {
52+
@extend .vm-badge-base;
53+
@each $class, $color in $badge-colors {
54+
&.#{$class} {
55+
border-left: $border-radius-small solid $color;
56+
}
57+
}
58+
}
59+
60+
.vm-badge {
61+
@extend .vm-badge-base;
62+
background-color: transparent;
63+
padding: 0 $padding-tiny;
64+
line-height: 22px;
65+
max-width: 300px;
66+
overflow: hidden;
67+
white-space: nowrap;
68+
text-overflow: ellipsis;
69+
}

0 commit comments

Comments
 (0)