diff --git a/src/actions/loadLabels.js b/src/actions/loadLabels.js
index 764f8484..8649f907 100644
--- a/src/actions/loadLabels.js
+++ b/src/actions/loadLabels.js
@@ -2,6 +2,7 @@ import axios from "axios";
import { setLabels } from "./setLabels";
import setLoading from "./setLoading";
import { setApiError } from "./setApiError";
+import { createAlert } from "./createAlert";
export default function loadLabels(apiUrl) {
const origin = window.location.origin;
@@ -26,30 +27,34 @@ export default function loadLabels(apiUrl) {
.get(`${url.trim()}/loki/api/v1/labels`, options)
?.then((response) => {
if (response) {
- if (response?.data?.data === [])
if (response?.data?.data?.length > 0) {
- const labels = response?.data?.data
- .sort()
- .map((label) => ({
+ let labels = response?.data?.data
+ ?.sort()
+ ?.map((label) => ({
name: label,
selected: false,
values: [],
}));
- dispatch(setLabels(labels || []));
-
- dispatch(setApiError(""));
+ if (labels) {
+ dispatch(setLabels(labels || []));
+ dispatch(setApiError(""));
+ dispatch(setLoading(false));
+ }
+ } else {
+ dispatch(createAlert({type:'info',message:'No labels available for this API'}))
}
} else {
dispatch(setLoading(false));
- dispatch(
- setApiError("")
- );
+
+ dispatch(setApiError(""));
dispatch(setLabels([]));
-
}
})
.catch((error) => {
- console.log(error);
+ dispatch(createAlert({
+ type:"error",
+ message:'API NOT FOUND'
+ }))
dispatch(setLoading(false));
dispatch(setLabels([]));
});
diff --git a/src/actions/loadLogs.js b/src/actions/loadLogs.js
index dda20106..58051e05 100644
--- a/src/actions/loadLogs.js
+++ b/src/actions/loadLogs.js
@@ -21,15 +21,21 @@ export default function loadLogs() {
} = localStore;
let { start: startTs, stop: stopTs } = localStore;
+ function adjustForTimezone(date){
+
+ var timeOffsetInMS = date.getTimezoneOffset() * 60000;
+ date.setTime(date.getTime() + timeOffsetInMS);
+ return date
+ }
+
function getTimeParsed(time) {
return time.getTime() + "000000";
}
+ const timeZone = new Date().getTimezoneOffset()
const parsedStart = getTimeParsed(startTs);
const parsedStop = getTimeParsed(stopTs);
-
const parsedTime = "&start=" + (from || parsedStart) + "&end=" + (to || parsedStop);
-
if (findRangeByLabel(rangeLabel)) {
({ dateStart: startTs, dateEnd: stopTs } =
findRangeByLabel(rangeLabel));
@@ -37,6 +43,7 @@ export default function loadLogs() {
store.dispatch(setStartTime(startTs));
store.dispatch(setStopTime(stopTs));
+
const origin = window.location.origin;
const url = apiUrl;
const queryStep = `&step=${step || 120}`;
@@ -113,13 +120,13 @@ export default function loadLogs() {
dispatch(setMatrixData(idResult || []));
dispatch(setLoading(false));
}
- dispatch(setLoading(false));
+ // dispatch(setLoading(false));
} else {
dispatch(setLogs([]));
dispatch(setMatrixData([]));
dispatch(setLoading(false));
}
- dispatch(setLoading(false));
+ // dispatch(setLoading(false));
})
.catch((error) => {
diff --git a/src/components/DataView/DataView.js b/src/components/DataView/DataView.js
index 3eb86a2f..b5f9d1ab 100644
--- a/src/components/DataView/DataView.js
+++ b/src/components/DataView/DataView.js
@@ -1,72 +1,73 @@
-import React, { Component } from "react";
-import { connect } from "react-redux";
-
-import { DataViewCont, DataViewStyled, Loader } from "./styled";
-
-import ClokiChart from "../../plugins/charts";
-import QueryHistory from "../../plugins/queryhistory";
-import LogsRow from "./LogsRow";
-import EmptyView from "./EmptyView";
-
-class DataView extends Component {
- constructor(props) {
- super(props);
- this.state = {
- limit: props.limit || 100,
- messages: props.messages || [],
- matrixData: props.matrixData || [],
- loading: false,
- };
- }
-
- getMatrixForChart = () => {
- return this.props.matrixData;
- };
- getLimit = () => {
- return this.props.limit;
- };
-
- render() {
- return (
-
-
- {this.props.messages.length > 0 &&
- this.getMatrixForChart().length < 1
- ? this.props.messages.map((message, key) => (
-
- ))
- : null}
-
- {this.getMatrixForChart().length > 0 ? (
-
- ) : null}
- {this.props.messages.length < 1 &&
- this.getMatrixForChart().length < 1 &&
- !this.props.loading && }
-
- {this.props.loading && }
-
-
- );
- }
-}
-
-const mapStateToProps = (state) => {
- return {
- messages: state.logs,
- start: state.start,
- stop: state.stop,
- limit: state.limit,
- loading: state.loading,
- matrixData: state.matrixData,
- };
-};
-
-export default connect(mapStateToProps)(DataView);
+import React, { Component } from "react";
+import { connect } from "react-redux";
+
+import { DataViewCont, DataViewStyled, Loader } from "./styled";
+import ClokiChart from "../../plugins/charts";
+import QueryHistory from "../../plugins/queryhistory";
+import LogsRow from "./LogsRow";
+import EmptyView from "./EmptyView";
+// import Table from "../../plugins/tables/Table";
+
+class DataView extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ limit: props.limit || 100,
+ messages: props.messages || [],
+ matrixData: props.matrixData || [],
+ loading: false,
+ };
+ }
+
+ getMatrixForChart = () => {
+ return this.props.matrixData;
+ };
+ getLimit = () => {
+ return this.props.limit;
+ };
+
+ render() {
+ return (
+
+
+ {/* */}
+ {this.props.messages.length > 0 &&
+ this.getMatrixForChart().length < 1
+ ? this.props.messages.map((message, key) => (
+
+ ))
+ : null}
+
+ {this.getMatrixForChart().length > 0 ? (
+
+ ) : null}
+ {this.props.messages.length < 1 &&
+ this.getMatrixForChart().length < 1 &&
+ !this.props.loading && }
+
+ {this.props.loading && }
+
+
+ );
+ }
+}
+
+const mapStateToProps = (state) => {
+ return {
+ messages: state.logs,
+ start: state.start,
+ stop: state.stop,
+ limit: state.limit,
+ loading: state.loading,
+ matrixData: state.matrixData,
+ };
+};
+
+export default connect(mapStateToProps)(DataView);
diff --git a/src/components/DataView/LogsRow.js b/src/components/DataView/LogsRow.js
index 0531f568..c5cbb756 100644
--- a/src/components/DataView/LogsRow.js
+++ b/src/components/DataView/LogsRow.js
@@ -1,38 +1,39 @@
-import { formatDate, getRowColor, toggleActiveStyles } from "./helpers";
-import { LogRow, RowLogContent, RowTimestamp } from "./styled";
-import ValueTags from "./ValueTags";
-import { useSelector, useDispatch } from "react-redux";
-import setLogs from "../../actions/setLogs";
-
-export default function LogsRow({ message }) {
- const dispatch = useDispatch();
- const messages = useSelector((store) => store.logs);
-
- function toggleTagsActive(idx) {
- let arrCopy = [...messages];
- arrCopy.forEach((entry) => {
- if (entry.id === idx) {
- entry.showLabels = entry.showLabels ? false : true;
- }
- });
- dispatch(setLogs(arrCopy));
- }
-
- return (
- {
- toggleTagsActive(message.id);
- }}
- >
- {formatDate(message.timestamp)}
- {message.text}
-
- {message.tags && (
-
-
-
- )}
-
- );
-}
+import { formatDate, getRowColor, toggleActiveStyles } from "./helpers";
+import { LogRow, RowLogContent, RowTimestamp } from "./styled";
+import ValueTags from "./ValueTags";
+import { useSelector, useDispatch } from "react-redux";
+import setLogs from "../../actions/setLogs";
+
+export default function LogsRow({ message }) {
+ const dispatch = useDispatch();
+ const messages = useSelector((store) => store.logs);
+
+ function toggleTagsActive(idx) {
+ let arrCopy = [...messages];
+ arrCopy.forEach((entry) => {
+ if (entry.id === idx) {
+ entry.showLabels = entry.showLabels ? false : true;
+ }
+ });
+ dispatch(setLogs(arrCopy));
+ }
+
+ return (
+ {
+ toggleTagsActive(message.id);
+ }}
+ >
+
+ {formatDate(message.timestamp)}
+ {message.text}
+
+ {message.tags && (
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/DataView/consts/consts.js b/src/components/DataView/consts/consts.js
index 936604e8..f2d24937 100644
--- a/src/components/DataView/consts/consts.js
+++ b/src/components/DataView/consts/consts.js
@@ -1,8 +1,8 @@
-export const TAGS_LEVEL = {
- critical: ["emerg", "fatal", "alert", "crit", "critical"],
- error: ["err", "eror", "error", "warning"],
- warning: ["warn", "warning"],
- info: ["info", "information", "notice"],
- debug: ["dbug", "debug"],
- trace: ["trace"],
-};
\ No newline at end of file
+export const TAGS_LEVEL = {
+ critical: ["emerg", "fatal", "alert", "crit", "critical"],
+ error: ["err", "eror", "error"],
+ warning: ["warn", "warning"],
+ info: ["info", "information", "notice"],
+ debug: ["dbug", "debug"],
+ trace: ["trace"],
+};
diff --git a/src/components/DataView/helpers/index.js b/src/components/DataView/helpers/index.js
index a25dba0e..d70e87f4 100644
--- a/src/components/DataView/helpers/index.js
+++ b/src/components/DataView/helpers/index.js
@@ -1,24 +1,25 @@
-import { LEVEL_COLORS as lColors } from "../theme/theme";
-import { TAGS_LEVEL as tLevel } from "../consts/consts";
-import * as moment from "moment";
-
-export function getRowColor(tags) {
- if (tags?.["level"]) {
- const level = Object.keys(tLevel).find((level) =>
- tLevel[level].includes(tags.level.toLowerCase())
- );
- return lColors[level];
- } else {
- return lColors["unknown"];
- }
-}
-
-export function toggleActiveStyles(idx) {
- return idx.showLabels
- ? "value-tags-container labelsActive"
- : "value-tags-container labelsInactive";
-}
-
-export function formatDate(timestamp) {
- return moment(parseInt(timestamp)).format("YYYY-MM-DD HH:mm:ss.SSS UTC");
-}
+import { LEVEL_COLORS as lColors } from "../theme/theme";
+import { TAGS_LEVEL as tLevel } from "../consts/consts";
+import * as moment from "moment";
+
+export function getRowColor(tags) {
+ const type = tags?.severity || tags?.level;
+ if (type) {
+ const level = Object.keys(tLevel).find((level) =>
+ tLevel[level].includes(type.toLowerCase())
+ );
+ return lColors[level];
+ } else {
+ return lColors["unknown"];
+ }
+}
+
+export function toggleActiveStyles(idx) {
+ return idx.showLabels
+ ? "value-tags-container labelsActive"
+ : "value-tags-container labelsInactive";
+}
+
+export function formatDate(timestamp) {
+ return moment(parseInt(timestamp)).format("YYYY-MM-DD HH:mm:ss.SSS UTC");
+}
diff --git a/src/components/DataView/styled/index.js b/src/components/DataView/styled/index.js
index 7ed2ed64..17208569 100644
--- a/src/components/DataView/styled/index.js
+++ b/src/components/DataView/styled/index.js
@@ -1,5 +1,4 @@
import styled from "@emotion/styled";
-import { THEME_COLORS } from '../theme/theme';
import { CircularProgress } from "@mui/material";
import darkTheme from "../../../theme/dark";
@@ -44,14 +43,18 @@ export const DataViewCont = styled.div`
`;
export const LogRow = styled.div`
- padding: 0.3rem;
+ font-family: monospace;
color: white;
font-size: 12px;
cursor: pointer;
- margin-bottom: 4px;
padding-left: 0.5rem;
margin-left: 0.25rem;
transition: 0.2s all;
+ display: flex;
+ flex-direction: column;
+ border-left: 4px solid ${(props) => props.rowColor};
+ margin-bottom: 2px;
+ margin-top: 2px;
&:hover {
background: black;
}
@@ -59,13 +62,14 @@ export const LogRow = styled.div`
p {
display: inline-block;
}
-
- border-left: 4px solid ${(props) => props.rowColor};
+ .log-ts-row {
+ display: flex;
+ }
`;
export const RowLogContent = styled.span`
font-size: 12px;
- font-family: monospace;
+
color: ${theme.textWhite};
line-height: 1.5;
`;
@@ -74,6 +78,8 @@ export const RowTimestamp = styled.span`
position: relative;
color: ${theme.textColor};
margin-right: 0.25rem;
+ white-space: nowrap;
+ line-height: 1.5;
`;
export const Loader = styled(CircularProgress)`
diff --git a/src/components/DataView/theme/theme.js b/src/components/DataView/theme/theme.js
index 0137ae4a..db2fab4c 100644
--- a/src/components/DataView/theme/theme.js
+++ b/src/components/DataView/theme/theme.js
@@ -1,19 +1,17 @@
-
-export const THEME_COLORS = {
- logsTimestamp: "#e8e8e8",
- scrollbarThumb: "#616161",
- logContent: "#ddd",
- dataViewBackground: "#1a1a1a",
- emptyViewMessage: "#aaa",
-};
-
-
-export const LEVEL_COLORS = {
- critical: "purple",
- error: "red",
- warning: "yellow",
- info: "green",
- debug: "blue",
- trace: "lightblue",
- unknown: "gray",
-};
\ No newline at end of file
+export const THEME_COLORS = {
+ logsTimestamp: "#e8e8e8",
+ scrollbarThumb: "#616161",
+ logContent: "#ddd",
+ dataViewBackground: "#1a1a1a",
+ emptyViewMessage: "#aaa",
+};
+
+export const LEVEL_COLORS = {
+ critical: "purple",
+ error: "red",
+ warning: "orange",
+ info: "green",
+ debug: "blue",
+ trace: "lightblue",
+ unknown: "gray",
+};
diff --git a/src/components/LabelBrowser/QueryBar.js b/src/components/LabelBrowser/QueryBar.js
index 51242be7..d7bc36d9 100644
--- a/src/components/LabelBrowser/QueryBar.js
+++ b/src/components/LabelBrowser/QueryBar.js
@@ -39,10 +39,12 @@ export const QueryBar = () => {
const labels = useSelector(store => store.labels)
const queryHistory = useSelector((store) => store.queryHistory);
const saveUrl = localUrl();
+ // const loading = useSelector( store => store.loading)
useEffect(() => {
const dLog = debugLog(query);
debug && dLog.logicQueryBar();
const labels = sendLabels(apiUrl)
+
if (isEmbed) dispatch(loadLogs())
if (query.length > 0) {
debug && dLog.queryBarDispatch();
@@ -144,6 +146,7 @@ export const QueryBar = () => {
@@ -165,6 +168,7 @@ export const QueryBar = () => {
/>
diff --git a/src/components/LabelBrowser/ValuesList.js b/src/components/LabelBrowser/ValuesList.js
index 9b6f9bbf..5aa0e23a 100644
--- a/src/components/LabelBrowser/ValuesList.js
+++ b/src/components/LabelBrowser/ValuesList.js
@@ -49,13 +49,13 @@ export const ValuesList = (props) => {
}
return state.labels;
});
-
+ //const labels = useSelector((store)=> store.labels)
const [labelList, setLabelList] = useState(labels);
const dispatch = useDispatch();
const debug = useSelector((store) => store.debugMode);
const apiUrl = useSelector((store) => store.apiUrl);
- if (debug) console.log('🚧 LOGIC/LabelBrowser/ValuesList', apiUrl)
+ if (debug) console.log("🚧 LOGIC/LabelBrowser/ValuesList", apiUrl);
const labelsBrowserOpen = useSelector((store) => store.labelsBrowserOpen);
const CLEAR = "clear";
useEffect(() => {
@@ -110,8 +110,8 @@ export const ValuesList = (props) => {
} else return {};
};
const isString = (value) => {
- return typeof value === 'string'
- }
+ return typeof value === "string";
+ };
return (
labelsBrowserOpen && (
@@ -136,7 +136,7 @@ export const ValuesList = (props) => {
{labelList &&
labelList?.map((value, key) => (
{
-
{labelSelected.name} (
{labelSelected.values.length})
@@ -181,17 +180,17 @@ export const ValuesList = (props) => {
"valuelist-content column"
}
>
-
{labelSelected?.values?.map(
- (value, key) => (
-
+ (value, key) =>
isString(value.name) ? (
-
{
)
}
>
-
{value.name}
- ) : (unknown)
-
- )
+ ) : (
+
+ unknown
+
+ )
)}
diff --git a/src/components/LabelBrowser/components/ShowLogsButton/ShowLogsButton.js b/src/components/LabelBrowser/components/ShowLogsButton/ShowLogsButton.js
index 4293f06f..658ff158 100644
--- a/src/components/LabelBrowser/components/ShowLogsButton/ShowLogsButton.js
+++ b/src/components/LabelBrowser/components/ShowLogsButton/ShowLogsButton.js
@@ -1,15 +1,47 @@
-import { ShowLogsBtn } from "../styled";
-
-export default function ShowLogsButton({ disabled, onClick, isMobile }) {
- const SHOW_LOGS = "Show Logs";
- return (
-
- {SHOW_LOGS}
-
- );
-}
+import { useState, useEffect } from "react";
+import { useSelector } from "react-redux";
+import { LoadingBtn, ShowLogsBtn } from "../styled";
+
+export default function ShowLogsButton({
+ disabled,
+ onClick,
+ isMobile,
+
+}) {
+ const SHOW_LOGS = "Show Logs";
+
+const loading = useSelector(store => store.loading)
+
+ const [isLoading,setIsLoading] = useState(loading)
+
+
+
+ return (
+ <>
+ {loading ? (
+
+
+
+{SHOW_LOGS}
+
+
+ ) : (
+
+ {SHOW_LOGS}
+
+ )}
+ >
+ );
+}
diff --git a/src/components/LabelBrowser/components/styled/index.js b/src/components/LabelBrowser/components/styled/index.js
index c9218a7f..5635c072 100644
--- a/src/components/LabelBrowser/components/styled/index.js
+++ b/src/components/LabelBrowser/components/styled/index.js
@@ -58,7 +58,7 @@ export const QueryBarContainer = styled.div`
border-radius: 3px;
`;
export const ShowLogsBtn = styled(BtnSmall)`
- background: ${theme.primaryDark};
+ background: ${theme.primaryDark};
color: ${theme.buttonText};
margin-left: 10px;
transition: 0.25s all;
@@ -77,6 +77,10 @@ export const ShowLogsBtn = styled(BtnSmall)`
}
`;
+export const LoadingBtn = styled(ShowLogsBtn)`
+background:green;
+`
+
export const MobileTopQueryMenu = styled.div`
display: none;
@media screen and (max-width: 864px) {
diff --git a/src/components/LabelBrowser/index.js b/src/components/LabelBrowser/index.js
index 91ff6f7d..e4d8175f 100644
--- a/src/components/LabelBrowser/index.js
+++ b/src/components/LabelBrowser/index.js
@@ -7,9 +7,9 @@ export default function LabelBrowser() {
return (
- {labelsBrowserOpen && (
+
- )}
+
);
diff --git a/src/components/StatusBar/components/apiselector/ApiSelector.js b/src/components/StatusBar/components/apiselector/ApiSelector.js
index 9b56455b..07e9224b 100644
--- a/src/components/StatusBar/components/apiselector/ApiSelector.js
+++ b/src/components/StatusBar/components/apiselector/ApiSelector.js
@@ -18,17 +18,18 @@ export function ApiSelector() {
const apiUrl = useSelector((store) => store.apiUrl);
const apiError = useSelector((store) => store.apiErrors);
const [editedUrl, setEditedUrl] = useState(apiUrl);
-
const [apiSelectorOpen, setApiSelectorOpen] = useState(false);
const dispatch = useDispatch();
const API_URL = "API URL";
+
useEffect(() => {
setEditedUrl(apiUrl);
}, []);
useEffect(() => {
setEditedUrl(apiUrl);
- dispatch(loadLabels(apiUrl))
+
+ dispatch(loadLabels(apiUrl));
}, [apiUrl]);
useEffect(() => {
@@ -51,12 +52,15 @@ export function ApiSelector() {
e.preventDefault();
setEditedUrl(e.target.value);
};
+
const onUrlSubmit = (e) => {
dispatch(setApiUrl(editedUrl));
+
setEditedUrl(editedUrl);
- dispatch(loadLabels(editedUrl))
- dispatch(setLabelsBrowserOpen(false));
+ dispatch(loadLabels(editedUrl));
+
+ dispatch(setLabelsBrowserOpen(false));
};
return (
diff --git a/src/helpers/error.interceptor.js b/src/helpers/error.interceptor.js
index 1a4cbf46..bd761a8e 100644
--- a/src/helpers/error.interceptor.js
+++ b/src/helpers/error.interceptor.js
@@ -12,7 +12,6 @@ const errorInterceptor = (axiosInstance) => {
(error) => {
if (error.response) {
-
const handler = errorHandler(error)
if (error?.response?.status === 401) {
@@ -49,6 +48,9 @@ const errorInterceptor = (axiosInstance) => {
}
} else {
+
+ // 1- get error by parsing json
+
const error_parsed = JSON.parse(JSON.stringify(error));
const networkError = {
url: error_parsed.config.url,
@@ -56,16 +58,22 @@ const errorInterceptor = (axiosInstance) => {
name: error_parsed.name
}
+ // 2-
store.dispatch(setApiWarning({ type: 'labels', message: 'Labels not available', }))
const { url } = networkError
-
+
const apiWarning = store.getState().apiWarning
- if (apiWarning && url.includes('query')) {
+ if (apiWarning && url.includes('query') && store.getState().notifications.length < 1) {
apiWarning.num++
store.dispatch(createAlert({
type: 'error',
message: `API not found, please adjust API URL`
}))
+ } else if( url.includes('labels') && store.getState().notifications.length < 1) {
+ store.dispatch(createAlert({
+ type: 'error',
+ message: 'API not found, please adjust API URL'
+ }))
}
}
diff --git a/src/plugins/notifications/index.js b/src/plugins/notifications/index.js
index b00af526..b06389af 100644
--- a/src/plugins/notifications/index.js
+++ b/src/plugins/notifications/index.js
@@ -1,51 +1,51 @@
-import { useEffect } from "react";
-
-import { useSelector, useDispatch } from "react-redux";
-import { Alert} from "@mui/material";
-import { removeAlert } from "../../actions";
-
-
-
-export function Notification() {
- const { notifications } = useSelector(state => state);
- const dispatch = useDispatch();
- const handleClose = (index) => {
- dispatch(removeAlert(index))
- };
- const Expire = props => {
- useEffect(() => {
- setTimeout(() => {
- dispatch(removeAlert(props.index))
- }, props.delay);
- }, [props]);
-
- return {props.children}
;
- };
-
- return (
-
- {
- notifications.map((notification, index) => {
- if (notification.visible) {
- return
-
-
handleClose(index)}
- severity={notification.type}
- sx={{ width: "100%" }}
- >
- {notification.message}
-
-
-
- } else {
- return undefined;
- }
- }
- )
- }
-
- );
+import { useEffect } from "react";
+
+import { useSelector, useDispatch } from "react-redux";
+import { Alert} from "@mui/material";
+import { removeAlert } from "../../actions";
+
+
+
+export function Notification() {
+ const { notifications } = useSelector(state => state);
+ const dispatch = useDispatch();
+ const handleClose = (index) => {
+ dispatch(removeAlert(index))
+ };
+ const Expire = props => {
+ useEffect(() => {
+ setTimeout(() => {
+ dispatch(removeAlert(props.index))
+ }, props.delay);
+ }, [props]);
+
+ return {props.children}
;
+ };
+
+ return (
+
+ {
+ notifications.map((notification, index) => {
+ if (notification.visible) {
+ return
+
+
handleClose(index)}
+ severity={notification.type}
+ sx={{ width: "100%" }}
+ >
+ {notification.message}
+
+
+
+ } else {
+ return undefined;
+ }
+ }
+ )
+ }
+
+ );
}
\ No newline at end of file