mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-07-31 13:02:44 +03:00
Compare commits
1 Commits
master
...
vmui/show-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f14d96d20a |
@@ -1,4 +1,4 @@
|
||||
import { FC, useRef } from "preact/compat";
|
||||
import { forwardRef, useImperativeHandle, useRef } from "preact/compat";
|
||||
import ServerConfigurator from "./ServerConfigurator/ServerConfigurator";
|
||||
import { ArrowDownIcon, SettingsIcon } from "../../Main/Icons";
|
||||
import Button from "../../Main/Button/Button";
|
||||
@@ -19,7 +19,11 @@ export interface ChildComponentHandle {
|
||||
handleApply: () => void;
|
||||
}
|
||||
|
||||
const GlobalSettings: FC = () => {
|
||||
export interface GlobalSettingsHandle {
|
||||
open: () => void;
|
||||
}
|
||||
|
||||
const GlobalSettings = forwardRef<GlobalSettingsHandle>((_, ref) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
|
||||
const appModeEnable = getAppModeEnable();
|
||||
@@ -66,6 +70,10 @@ const GlobalSettings: FC = () => {
|
||||
}
|
||||
].filter(control => control.show);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
open: handleOpen,
|
||||
}));
|
||||
|
||||
return <>
|
||||
{isMobile ? (
|
||||
<div
|
||||
@@ -131,6 +139,6 @@ const GlobalSettings: FC = () => {
|
||||
</Modal>
|
||||
)}
|
||||
</>;
|
||||
};
|
||||
});
|
||||
|
||||
export default GlobalSettings;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { FC } from "preact/compat";
|
||||
import Button from "../../../Main/Button/Button";
|
||||
import { useTimeState } from "../../../../state/time/TimeStateContext";
|
||||
import useDeviceDetect from "../../../../hooks/useDeviceDetect";
|
||||
import { getUTCByTimezone } from "../../../../utils/time";
|
||||
import { useMemo } from "react";
|
||||
import { ArrowDownIcon, PlanetIcon } from "../../../Main/Icons";
|
||||
|
||||
type Props = {
|
||||
onOpenSettings?: () => void;
|
||||
}
|
||||
|
||||
const TimeZonePreview: FC<Props> = ({ onOpenSettings }) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
|
||||
const { timezone } = useTimeState();
|
||||
const utcOffset = useMemo(() => getUTCByTimezone(timezone), [timezone]);
|
||||
|
||||
const handleOpenSettings = () => {
|
||||
onOpenSettings && onOpenSettings();
|
||||
};
|
||||
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<button
|
||||
className="vm-mobile-option"
|
||||
onClick={handleOpenSettings}
|
||||
>
|
||||
<span className="vm-mobile-option__icon"><PlanetIcon/></span>
|
||||
<div className="vm-mobile-option-text">
|
||||
<span className="vm-mobile-option-text__label">Time zone</span>
|
||||
<span className="vm-mobile-option-text__value">{utcOffset}</span>
|
||||
</div>
|
||||
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
className="vm-header-button"
|
||||
onClick={handleOpenSettings}
|
||||
startIcon={<PlanetIcon/>}
|
||||
>
|
||||
{utcOffset}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default TimeZonePreview;
|
||||
@@ -117,6 +117,8 @@ const StepConfigurator: FC = () => {
|
||||
if (step === value || step === defaultStep) handleApply(defaultStep);
|
||||
}, [isHistogram, displayType]);
|
||||
|
||||
const textValue = isAutoStep ? `auto (${customStep})` : customStep;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="vm-step-control"
|
||||
@@ -130,7 +132,7 @@ const StepConfigurator: FC = () => {
|
||||
<span className="vm-mobile-option__icon"><TimelineIcon/></span>
|
||||
<div className="vm-mobile-option-text">
|
||||
<span className="vm-mobile-option-text__label">Step</span>
|
||||
<span className="vm-mobile-option-text__value">{customStep}</span>
|
||||
<span className="vm-mobile-option-text__value">{textValue}</span>
|
||||
</div>
|
||||
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
|
||||
</div>
|
||||
@@ -142,7 +144,7 @@ const StepConfigurator: FC = () => {
|
||||
startIcon={<TimelineIcon/>}
|
||||
onClick={toggleOpenOptions}
|
||||
>
|
||||
Step: {isAutoStep ? `auto (${customStep})` : customStep}
|
||||
Step: {textValue}
|
||||
</Button>
|
||||
)}
|
||||
<Popper
|
||||
|
||||
@@ -19,7 +19,11 @@ import useBoolean from "../../../../hooks/useBoolean";
|
||||
import useWindowSize from "../../../../hooks/useWindowSize";
|
||||
import usePrevious from "../../../../hooks/usePrevious";
|
||||
|
||||
export const TimeSelector: FC = () => {
|
||||
type Props = {
|
||||
onOpenSettings?: () => void;
|
||||
}
|
||||
|
||||
export const TimeSelector: FC<Props> = ({ onOpenSettings }) => {
|
||||
const { isMobile } = useDeviceDetect();
|
||||
const { isDarkTheme } = useAppState();
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
@@ -53,7 +57,7 @@ export const TimeSelector: FC = () => {
|
||||
setFrom(formatDateForNativeInput(dateFromSeconds(start)));
|
||||
}, [timezone, start]);
|
||||
|
||||
const setDuration = ({ duration, until, id }: {duration: string, until: Date, id: string}) => {
|
||||
const setDuration = ({ duration, until, id }: { duration: string, until: Date, id: string }) => {
|
||||
dispatch({ type: "SET_RELATIVE_TIME", payload: { duration, until, id } });
|
||||
handleCloseOptions();
|
||||
};
|
||||
@@ -75,16 +79,23 @@ export const TimeSelector: FC = () => {
|
||||
|
||||
const setTimeAndClosePicker = () => {
|
||||
if (from && until) {
|
||||
dispatch({ type: "SET_PERIOD", payload: {
|
||||
from: dayjs.tz(from).toDate(),
|
||||
to: dayjs.tz(until).toDate()
|
||||
} });
|
||||
dispatch({
|
||||
type: "SET_PERIOD", payload: {
|
||||
from: dayjs.tz(from).toDate(),
|
||||
to: dayjs.tz(until).toDate()
|
||||
}
|
||||
});
|
||||
}
|
||||
handleCloseOptions();
|
||||
};
|
||||
|
||||
const onSwitchToNow = () => dispatch({ type: "RUN_QUERY_TO_NOW" });
|
||||
|
||||
const handleOpenSettings = () => {
|
||||
onOpenSettings && onOpenSettings();
|
||||
handleCloseOptions();
|
||||
};
|
||||
|
||||
const onCancelClick = () => {
|
||||
setUntil(formatDateForNativeInput(dateFromSeconds(end)));
|
||||
setFrom(formatDateForNativeInput(dateFromSeconds(start)));
|
||||
@@ -140,6 +151,7 @@ export const TimeSelector: FC = () => {
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Popper
|
||||
open={openOptions}
|
||||
buttonRef={buttonRef}
|
||||
@@ -179,13 +191,17 @@ export const TimeSelector: FC = () => {
|
||||
onEnter={setTimeAndClosePicker}
|
||||
/>
|
||||
</div>
|
||||
<div className="vm-time-selector-left-timezone">
|
||||
<div className="vm-time-selector-left-timezone__title">{activeTimezone.region}</div>
|
||||
<div className="vm-time-selector-left-timezone__utc">{activeTimezone.utc}</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="vm-time-selector-left-timezone"
|
||||
onClick={handleOpenSettings}
|
||||
>
|
||||
<span className="vm-time-selector-left-timezone__title">{activeTimezone.region}</span>
|
||||
<span className="vm-time-selector-left-timezone__utc">{activeTimezone.utc}</span>
|
||||
</button>
|
||||
<Button
|
||||
variant="text"
|
||||
startIcon={<AlarmIcon />}
|
||||
startIcon={<AlarmIcon/>}
|
||||
onClick={onSwitchToNow}
|
||||
>
|
||||
switch to now
|
||||
|
||||
@@ -40,8 +40,12 @@
|
||||
gap: $padding-small;
|
||||
font-size: $font-size-small;
|
||||
margin-bottom: $padding-small;
|
||||
cursor: pointer;
|
||||
|
||||
&__title {}
|
||||
&:hover {
|
||||
color: $color-primary;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&__utc {
|
||||
display: inline-flex;
|
||||
|
||||
@@ -633,3 +633,14 @@ export const DebugIcon = () => (
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const PlanetIcon = () => (
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2M4 12c0-.61.08-1.21.21-1.78L8.99 15v1c0 1.1.9 2 2 2v1.93C7.06 19.43 4 16.07 4 12m13.89 5.4c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41C17.92 5.77 20 8.65 20 12c0 2.08-.81 3.98-2.11 5.4"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
&_mobile {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
flex-grow: initial;
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ import StepConfigurator from "../../components/Configurators/StepConfigurator/St
|
||||
import { TimeSelector } from "../../components/Configurators/TimeRangeSettings/TimeSelector/TimeSelector";
|
||||
import CardinalityDatePicker from "../../components/Configurators/CardinalityDatePicker/CardinalityDatePicker";
|
||||
import { ExecutionControls } from "../../components/Configurators/TimeRangeSettings/ExecutionControls/ExecutionControls";
|
||||
import GlobalSettings from "../../components/Configurators/GlobalSettings/GlobalSettings";
|
||||
import GlobalSettings, { GlobalSettingsHandle } from "../../components/Configurators/GlobalSettings/GlobalSettings";
|
||||
import ShortcutKeys from "../../components/Main/ShortcutKeys/ShortcutKeys";
|
||||
import { ControlsProps } from "../Header/HeaderControls/HeaderControls";
|
||||
import { useRef } from "react";
|
||||
import TimeZonePreview from "../../components/Configurators/GlobalSettings/TimeZonePreview/TimeZonePreview";
|
||||
|
||||
const ControlsMainLayout: FC<ControlsProps> = ({
|
||||
displaySidebar,
|
||||
@@ -17,6 +19,7 @@ const ControlsMainLayout: FC<ControlsProps> = ({
|
||||
accountIds,
|
||||
closeModal,
|
||||
}) => {
|
||||
const settingsRef = useRef<GlobalSettingsHandle>(null);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -27,14 +30,15 @@ const ControlsMainLayout: FC<ControlsProps> = ({
|
||||
>
|
||||
{headerSetup?.tenant && <TenantsConfiguration accountIds={accountIds || []}/>}
|
||||
{headerSetup?.stepControl && <StepConfigurator/>}
|
||||
{headerSetup?.timeSelector && <TimeSelector/>}
|
||||
{headerSetup?.timeSelector && <TimeSelector onOpenSettings={() => settingsRef.current?.open()}/>}
|
||||
{headerSetup?.cardinalityDatePicker && <CardinalityDatePicker/>}
|
||||
<TimeZonePreview onOpenSettings={() => settingsRef.current?.open()}/>
|
||||
{headerSetup?.executionControls && <ExecutionControls
|
||||
tooltip={headerSetup?.executionControls?.tooltip}
|
||||
useAutorefresh={headerSetup?.executionControls?.useAutorefresh}
|
||||
closeModal={closeModal}
|
||||
/>}
|
||||
<GlobalSettings/>
|
||||
<GlobalSettings ref={settingsRef}/>
|
||||
{!displaySidebar && <ShortcutKeys/>}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
@use "src/styles/variables" as *;
|
||||
|
||||
.vm-mobile-option {
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: $padding-small;
|
||||
padding: calc($padding-medium/2) 0;
|
||||
gap: $padding-global;
|
||||
padding: $padding-global $padding-small;
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
|
||||
@@ -17,14 +18,33 @@
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
color: $color-primary;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.1;
|
||||
background-color: currentColor;
|
||||
border-radius: $border-radius-medium;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 21px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__arrow {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: rotate(-90deg);
|
||||
color: $color-primary;
|
||||
}
|
||||
@@ -32,11 +52,13 @@
|
||||
&-text {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
height: 100%;
|
||||
gap: calc($padding-small / 2);
|
||||
flex-grow: 1;
|
||||
text-align: left;
|
||||
|
||||
&__label {
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__value {
|
||||
|
||||
@@ -42,6 +42,7 @@ See also [LTS releases](https://docs.victoriametrics.com/victoriametrics/lts-rel
|
||||
* FEATURE: [vmctl](https://docs.victoriametrics.com/victoriametrics/vmctl/): support [Prometheus native histograms](https://prometheus.io/docs/specs/native_histograms/) migration in [remote read mode](https://docs.victoriametrics.com/victoriametrics/vmctl/remoteread/). Native histograms are converted into `_count`, `_sum` and `_bucket` series with `vmrange` labels in the same way as VictoriaMetrics converts native histograms received via Prometheus remote write protocol, except that for native histograms with custom buckets the original bucket bounds are preserved instead of being estimated with the exponential formula. Previously native histograms were silently ignored in `SAMPLES` mode, while in stream mode the migration failed with `EOF` error. See [#11292](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11292). Thanks to @liuxu623 for contribution.
|
||||
* FEATURE: `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): enable [slowness-based re-routing](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/#slowness-based-re-routing) by default. Previously, `-disableRerouting` defaulted to `true`, which limited ingestion throughput to the slowest `vmstorage` node. Now `-disableRerouting` defaults to `false`, so `vminsert` automatically routes data away from the slowest `vmstorage` node, improving overall ingestion performance. Slowness re-routing is automatically disabled when `-replicationFactor` is greater than 1. See [#11287](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11287).
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): persist the selected auto-refresh interval in the URL. See [VictoriaLogs#1310](https://github.com/VictoriaMetrics/VictoriaLogs/issues/1310).
|
||||
* FEATURE: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): show the selected time zone UTC offset next to the date/time controls and allow opening time zone settings from it.
|
||||
|
||||
* BUGFIX: [MetricsQL](https://docs.victoriametrics.com/victoriametrics/metricsql/): properly drop data points filtered out by an inner [comparison operation](https://prometheus.io/docs/prometheus/latest/querying/operators/#comparison-binary-operators) when its result is used on the right side of another comparison. Previously, queries like `foo != (bar > 100)` could return unexpected results because filtered-out data points are represented internally as `NaN`, and `value != NaN` evaluates to `true`. Comparisons against explicitly present `NaN` values keep the previous behavior. See [#10018](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10018). Thanks to @zasdaym for contribution.
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/) and [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/): ignore HTTP proxy environment variables when scraping targets over Unix domain sockets. See [#11318](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/11318). Thanks to @lwmacct for contribution.
|
||||
|
||||
Reference in New Issue
Block a user