- {groupData.map((item) => (
-
-
- Group by _stream:
- {item.pairs.map((pair) => (
-
-
+
+ {groupData.map((item, i) => (
+
+
+ Group by {groupBy}
:
+ {item.pairs.map((pair) => (
+
- {pair}
-
-
+
+ {pair}
+
+
+ ))}
+
{item.values.length} entries
+
+ )}
+ >
+
+ {item.values.map((value) => (
+
))}
- )}
- >
-
- {item.values.map((value) => (
-
- ))}
+
+
+ ))}
+
+
+
+ {settingsRef.current && React.createPortal((
+
+
+ : }
+ onClick={handleToggleExpandAll}
+ ariaLabel={expandAll ? "Collapse All" : "Expand All"}
+ />
+
+
+
+
-
+
+ {
+
+
+
+
+
+ {logsKeys.map(id => (
+
+ {id}
+
+ ))}
+
+
+ }
- ))}
-
+ ), settingsRef.current)}
+ >
);
};
diff --git a/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogsItem.tsx b/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogsItem.tsx
index 0cfa42bbc3..1136e760f1 100644
--- a/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogsItem.tsx
+++ b/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogsItem.tsx
@@ -7,19 +7,21 @@ import Tooltip from "../../../components/Main/Tooltip/Tooltip";
import { ArrowDownIcon, CopyIcon } from "../../../components/Main/Icons";
import useCopyToClipboard from "../../../hooks/useCopyToClipboard";
import classNames from "classnames";
+import { useLogsState } from "../../../state/logsPanel/LogsStateContext";
interface Props {
log: Logs;
- markdownParsing: boolean;
}
-const GroupLogsItem: FC
= ({ log, markdownParsing }) => {
+const GroupLogsItem: FC = ({ log }) => {
const {
value: isOpenFields,
toggle: toggleOpenFields,
} = useBoolean(false);
- const excludeKeys = ["_stream", "_msg", "_time", "_vmui_time", "_vmui_data", "_vmui_markdown"];
+ const { markdownParsing } = useLogsState();
+
+ const excludeKeys = ["_msg", "_vmui_time", "_vmui_data", "_vmui_markdown"];
const fields = Object.entries(log).filter(([key]) => !excludeKeys.includes(key));
const hasFields = fields.length > 0;
diff --git a/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/style.scss b/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/style.scss
index 7868be35b7..00c97496bb 100644
--- a/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/style.scss
+++ b/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/style.scss
@@ -3,6 +3,22 @@
.vm-group-logs {
margin-top: calc(-1 * $padding-medium);
+ &-header {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: $padding-global;
+
+ &-keys {
+ max-height: 300px;
+ overflow: auto;
+
+ &__search {
+ padding: $padding-small;
+ }
+ }
+ }
+
&-section {
&-keys {
display: flex;
@@ -14,6 +30,24 @@
&__title {
font-weight: bold;
+
+ code {
+ font-family: monospace;
+ &:before {
+ content: "\"";
+ }
+ &:after {
+ content: "\"";
+ }
+ }
+ }
+
+ &__count {
+ flex-grow: 1;
+ text-align: right;
+ font-size: $font-size-small;
+ color: $color-text-secondary;
+ padding-right: calc($padding-large * 3);
}
&__pair {
diff --git a/app/vmui/packages/vmui/src/state/logsPanel/LogsStateContext.tsx b/app/vmui/packages/vmui/src/state/logsPanel/LogsStateContext.tsx
new file mode 100644
index 0000000000..de5a4fda8f
--- /dev/null
+++ b/app/vmui/packages/vmui/src/state/logsPanel/LogsStateContext.tsx
@@ -0,0 +1,24 @@
+import React, { createContext, FC, useContext, useMemo, useReducer } from "preact/compat";
+import { LogsAction, LogsState, initialLogsState, reducer } from "./reducer";
+import { Dispatch } from "react";
+
+type LogsStateContextType = { state: LogsState, dispatch: Dispatch };
+
+export const LogsStateContext = createContext({} as LogsStateContextType);
+
+export const useLogsState = (): LogsState => useContext(LogsStateContext).state;
+export const useLogsDispatch = (): Dispatch => useContext(LogsStateContext).dispatch;
+
+export const LogsStateProvider: FC = ({ children }) => {
+ const [state, dispatch] = useReducer(reducer, initialLogsState);
+
+ const contextValue = useMemo(() => {
+ return { state, dispatch };
+ }, [state, dispatch]);
+
+ return
+ {children}
+ ;
+};
+
+
diff --git a/app/vmui/packages/vmui/src/state/logsPanel/reducer.ts b/app/vmui/packages/vmui/src/state/logsPanel/reducer.ts
new file mode 100644
index 0000000000..2b1094e2ee
--- /dev/null
+++ b/app/vmui/packages/vmui/src/state/logsPanel/reducer.ts
@@ -0,0 +1,26 @@
+import { getFromStorage, saveToStorage } from "../../utils/storage";
+
+export interface LogsState {
+ markdownParsing: boolean;
+}
+
+export type LogsAction =
+ | { type: "SET_MARKDOWN_PARSING", payload: boolean }
+
+
+export const initialLogsState: LogsState = {
+ markdownParsing: getFromStorage("LOGS_MARKDOWN") === "true",
+};
+
+export function reducer(state: LogsState, action: LogsAction): LogsState {
+ switch (action.type) {
+ case "SET_MARKDOWN_PARSING":
+ saveToStorage("LOGS_MARKDOWN", `${ action.payload}`);
+ return {
+ ...state,
+ markdownParsing: action.payload
+ };
+ default:
+ throw new Error();
+ }
+}
diff --git a/docs/VictoriaLogs/CHANGELOG.md b/docs/VictoriaLogs/CHANGELOG.md
index c3540eac40..af935872c0 100644
--- a/docs/VictoriaLogs/CHANGELOG.md
+++ b/docs/VictoriaLogs/CHANGELOG.md
@@ -17,6 +17,10 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
## tip
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): add fields for setting AccountID and ProjectID. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6631).
+* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): add a toggle button to the "Group" tab that allows users to expand or collapse all groups at once.
+* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): introduce the ability to select a key for grouping logs within the "Group" tab.
+* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): display the number of entries within each log group.
+* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): move the Markdown toggle to the general settings panel in the upper left corner.
## [v0.28.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.28.0-victorialogs)