mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-06 08:09:24 +00:00
fixed #4389 Make wrap columns false by default #4344 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced alert data retrieval to focus on the last 2 minutes instead of the last 15 minutes. - Improved refresh behavior for alerts, allowing for more frequent updates based on a new timing threshold. - **Bug Fixes** - Enhanced error handling in log management to prevent runtime exceptions when accessing potentially undefined properties. - Improved robustness in local storage handling to ensure reliable value assignments. - **Refactor** - Streamlined logic and data structures in various components for better clarity and maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
868 lines
25 KiB
TypeScript
868 lines
25 KiB
TypeScript
// Copyright 2023 Zinc Labs Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import config from "../aws-exports";
|
|
import { ref } from "vue";
|
|
import { DateTime } from "luxon";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
import { useQuasar } from "quasar";
|
|
import { useStore } from "vuex";
|
|
import useStreams from "@/composables/useStreams";
|
|
import userService from "@/services/users";
|
|
import { DateTime as _DateTime } from "luxon";
|
|
|
|
let moment: any;
|
|
let momentInitialized = false;
|
|
|
|
const importMoment = async () => {
|
|
if (!momentInitialized) {
|
|
const momentModule: any = await import("moment-timezone");
|
|
moment = momentModule.default;
|
|
momentInitialized = true;
|
|
}
|
|
return moment;
|
|
};
|
|
|
|
const useLocalStorage = (
|
|
key: string,
|
|
defaultValue: unknown,
|
|
isDelete: boolean = false,
|
|
isJSONValue: boolean = false,
|
|
) => {
|
|
try {
|
|
const value = ref(defaultValue);
|
|
const read = () => {
|
|
const v = window.localStorage.getItem(key);
|
|
|
|
if (v != null && isJSONValue === true) value.value = JSON.parse(v);
|
|
else if (v != null) value.value = v;
|
|
else value.value = null;
|
|
};
|
|
|
|
read();
|
|
|
|
window.addEventListener("load", () => {
|
|
window.addEventListener("storage", read);
|
|
});
|
|
|
|
// window.addEventListener("unload", () => {
|
|
// alert('asd')
|
|
// window.removeEventListener("storage", read);
|
|
// });
|
|
|
|
// onMounted(() => {
|
|
// window.addEventListener("storage", read);
|
|
// });
|
|
// onUnmounted(() => {
|
|
// alert("ad");
|
|
// window.removeEventListener("storage", read);
|
|
// });
|
|
|
|
const write = () => {
|
|
const val: unknown = isJSONValue
|
|
? JSON.stringify(defaultValue)
|
|
: defaultValue;
|
|
window.localStorage.setItem(key, String(val));
|
|
};
|
|
|
|
if (
|
|
window.localStorage.getItem(key) == null &&
|
|
!isDelete &&
|
|
defaultValue !== ""
|
|
)
|
|
write();
|
|
else if (value.value !== defaultValue && defaultValue !== "") write();
|
|
|
|
const remove = () => {
|
|
window.localStorage.removeItem(key);
|
|
};
|
|
|
|
if (isDelete) {
|
|
remove();
|
|
}
|
|
|
|
return value;
|
|
} catch (e) {
|
|
console.log(
|
|
`Error: Error in UseLocalStorage for key: ${key}, error-message : ${e}`,
|
|
);
|
|
}
|
|
};
|
|
|
|
export const getUserInfo = (loginString: string) => {
|
|
try {
|
|
let decToken = null;
|
|
const tokens = loginString.substring(1).split("&");
|
|
for (const token of tokens) {
|
|
const propArr = token.split("=");
|
|
if (propArr[0] == "id_token") {
|
|
const tokenString = propArr[1];
|
|
const parts = tokenString.split(".");
|
|
if (parts.length === 3) {
|
|
try {
|
|
// Attempt to parse the token as a JWT
|
|
const header = JSON.parse(b64DecodeUnicode(parts[0]) || "");
|
|
const payload = JSON.parse(b64DecodeUnicode(parts[1]) || "");
|
|
const signature = parts[2];
|
|
payload["family_name"] = payload["name"];
|
|
payload["given_name"] = "";
|
|
const encodedSessionData: any = b64EncodeStandard(
|
|
JSON.stringify(payload),
|
|
);
|
|
useLocalUserInfo(encodedSessionData);
|
|
decToken = payload;
|
|
} catch (error) {
|
|
// If parsing fails, it's not a valid JWT
|
|
console.error("Invalid JWT token:", error);
|
|
return null;
|
|
}
|
|
} else {
|
|
decToken = getDecodedAccessToken(propArr[1]);
|
|
const encodedSessionData: any = b64EncodeStandard(
|
|
JSON.stringify(decToken),
|
|
);
|
|
useLocalUserInfo(encodedSessionData);
|
|
}
|
|
}
|
|
}
|
|
|
|
return decToken;
|
|
} catch (e) {
|
|
console.log(`Error in getUserInfo util with loginString: ${loginString}`);
|
|
}
|
|
};
|
|
|
|
export const invlidateLoginData = () => {
|
|
userService.logout().then((res: any) => {});
|
|
};
|
|
|
|
export const getLoginURL = () => {
|
|
return `https://${config.oauth.domain}/oauth/v2/authorize?client_id=${config.aws_user_pools_web_client_id}&response_type=${config.oauth.responseType}&redirect_uri=${config.oauth.redirectSignIn}&scope=${config.oauth.scope}`;
|
|
};
|
|
|
|
export const getLogoutURL = () => {
|
|
return `https://${config.oauth.domain}/oidc/v1/end_session?client_id=${
|
|
config.aws_user_pools_web_client_id
|
|
}&id_token_hint=${useLocalUserInfo()}&post_logout_redirect_uri=${
|
|
config.oauth.redirectSignOut
|
|
}&state=random_string`;
|
|
};
|
|
|
|
export const getDecodedAccessToken = (token: string) => {
|
|
try {
|
|
const decodedString = b64DecodeStandard(token.split(".")[1]);
|
|
if (typeof decodedString == "string") {
|
|
return JSON.parse(decodedString);
|
|
} else {
|
|
return "";
|
|
}
|
|
} catch (e) {
|
|
console.log("error decoding token");
|
|
}
|
|
};
|
|
|
|
// url safe base64 encode
|
|
export const b64EncodeUnicode = (str: string) => {
|
|
try {
|
|
return btoa(
|
|
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
|
|
return String.fromCharCode(parseInt(`0x${p1}`));
|
|
}),
|
|
)
|
|
.replace(/\+/g, "-")
|
|
.replace(/\//g, "_")
|
|
.replace(/=/g, ".");
|
|
} catch (e) {
|
|
console.log("Error: getBase64Encode: error while encoding.");
|
|
return null;
|
|
}
|
|
};
|
|
|
|
//url safe base64 decode
|
|
export const b64DecodeUnicode = (str: string) => {
|
|
try {
|
|
return decodeURIComponent(
|
|
Array.prototype.map
|
|
.call(
|
|
atob(str.replace(/\-/g, "+").replace(/\_/g, "/").replace(/\./g, "=")),
|
|
function (c) {
|
|
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
},
|
|
)
|
|
.join(""),
|
|
);
|
|
} catch (e) {
|
|
console.log("Error: getBase64Decode: error while decoding.");
|
|
}
|
|
};
|
|
|
|
export const b64EncodeStandard = (str: string) => {
|
|
try {
|
|
return btoa(
|
|
encodeURIComponent(str).replace(
|
|
/%([0-9A-F]{2})/g,
|
|
function (match, p1: any) {
|
|
return String.fromCharCode(parseInt(`0x${p1}`));
|
|
},
|
|
),
|
|
);
|
|
} catch (e) {
|
|
console.log("Error: getBase64Encode: error while encoding.");
|
|
}
|
|
};
|
|
|
|
export const b64DecodeStandard = (str: string) => {
|
|
try {
|
|
return decodeURIComponent(
|
|
Array.prototype.map
|
|
.call(atob(str), function (c) {
|
|
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
})
|
|
.join(""),
|
|
);
|
|
} catch (e) {
|
|
console.log("Error: getBase64Decode: error while decoding.");
|
|
}
|
|
};
|
|
|
|
export const getSessionStorageVal = (key: string) => {
|
|
try {
|
|
return window.sessionStorage.getItem(key);
|
|
} catch (e) {
|
|
console.log(`Error: Error while pull sessionstorage value ${key}`);
|
|
}
|
|
};
|
|
|
|
export const useLocalOrganization = (val: any = "", isDelete = false) => {
|
|
return useLocalStorage("organization", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalCurrentUser = (val = "", isDelete = false) => {
|
|
return useLocalStorage("currentuser", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalLogsObj = (val = "", isDelete = false) => {
|
|
return useLocalStorage("logsobj", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalLogFilterField = (val = "", isDelete = false) => {
|
|
return useLocalStorage("logFilterField", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalTraceFilterField = (val = "", isDelete = false) => {
|
|
return useLocalStorage("traceFilterField", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalInterestingFields = (val = "", isDelete = false) => {
|
|
return useLocalStorage("interestingFields", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalSavedView = (val = "", isDelete = false) => {
|
|
return useLocalStorage("savedViews", val, isDelete, true);
|
|
};
|
|
|
|
export const useLocalUserInfo = (val = "", isDelete = false) => {
|
|
const userInfo: any = useLocalStorage("userInfo", val, isDelete);
|
|
return userInfo.value;
|
|
};
|
|
|
|
export const useLocalTimezone = (val = "", isDelete = false) => {
|
|
const timezone: any = useLocalStorage("timezone", val, isDelete);
|
|
return timezone.value;
|
|
};
|
|
|
|
export const useLocalWrapContent = (val = "", isDelete = false) => {
|
|
const wrapcontent: any = useLocalStorage("wrapcontent", val, isDelete);
|
|
return wrapcontent.value;
|
|
};
|
|
|
|
export const deleteSessionStorageVal = (key: string) => {
|
|
try {
|
|
return sessionStorage.removeItem(key);
|
|
} catch (e) {
|
|
console.log(`Error: Error while pull sessionstorage value ${key}`);
|
|
}
|
|
};
|
|
|
|
export const getDecodedUserInfo = () => {
|
|
try {
|
|
if (useLocalUserInfo() != null) {
|
|
const userinfo: any = useLocalUserInfo();
|
|
return b64DecodeStandard(userinfo);
|
|
} else {
|
|
return null;
|
|
}
|
|
} catch (e) {
|
|
console.log("Error: Error while pull sessionstorage value.");
|
|
}
|
|
};
|
|
|
|
export const validateEmail = (email: string) => {
|
|
try {
|
|
if (email != null) {
|
|
const re = /\S+@\S+\.\S+/;
|
|
return re.test(email);
|
|
} else {
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
console.log(`Error: Error while validatig email id ${email}`);
|
|
}
|
|
};
|
|
|
|
export const getLocalTime = (datetime: string) => {
|
|
try {
|
|
if (datetime !== null) {
|
|
const event = new Date(datetime);
|
|
const local = event.toString();
|
|
const dateobj = new Date(local);
|
|
|
|
return (
|
|
dateobj.getFullYear() +
|
|
"/" +
|
|
(dateobj.getMonth() + 1) +
|
|
"/" +
|
|
dateobj.getDate() +
|
|
" " +
|
|
dateobj.getHours() +
|
|
":" +
|
|
dateobj.getMinutes()
|
|
);
|
|
} else {
|
|
return datetime;
|
|
}
|
|
} catch (e) {
|
|
console.log(`Error: Error while covert localtime ${datetime}`);
|
|
}
|
|
};
|
|
|
|
export const getBasicAuth = (username: string, password: string) => {
|
|
const token = username + ":" + password;
|
|
const hash = window.btoa(token);
|
|
return "Basic " + hash;
|
|
};
|
|
|
|
export const getImageURL = (image_path: string) => {
|
|
return getPath() + "src/assets/" + image_path;
|
|
};
|
|
|
|
export const getPath = () => {
|
|
const pos = window.location.pathname.indexOf("/web/");
|
|
const path =
|
|
window.location.origin == "http://localhost:8081"
|
|
? "/"
|
|
: pos > -1
|
|
? window.location.pathname.slice(0, pos + 5)
|
|
: "";
|
|
const cloudPath = import.meta.env.BASE_URL;
|
|
return config.isCloud == "true" ? cloudPath : path;
|
|
};
|
|
|
|
export const routeGuard = async (to: any, from: any, next: any) => {
|
|
const store = useStore();
|
|
const q = useQuasar();
|
|
const { getStreams } = useStreams();
|
|
|
|
// if (
|
|
// config.isCloud &&
|
|
// store.state.selectedOrganization.subscription_type == config.freePlan
|
|
// ) {
|
|
// await billings
|
|
// .list_subscription(store.state.selectedOrganization.identifier)
|
|
// .then((res: any) => {
|
|
// if (res.data.data.length == 0) {
|
|
// next({ path: "/billings/plans" });
|
|
// }
|
|
|
|
// if (
|
|
// res.data.data.CustomerBillingObj.customer_id == null ||
|
|
// res.data.data.CustomerBillingObj.customer_id == ""
|
|
// ) {
|
|
// next({ path: "/billings/plans" });
|
|
// }
|
|
// });
|
|
// }
|
|
|
|
if (
|
|
to.path.indexOf("/ingestion") == -1 &&
|
|
to.path.indexOf("/iam") == -1 &&
|
|
store.state.zoConfig.hasOwnProperty("restricted_routes_on_empty_data") &&
|
|
store.state.zoConfig.restricted_routes_on_empty_data == true &&
|
|
store.state.organizationData.isDataIngested == false
|
|
) {
|
|
await getStreams("", false).then((response: any) => {
|
|
if (response.list.length == 0) {
|
|
store.dispatch("setIsDataIngested", false);
|
|
next({ path: "/ingestion" });
|
|
} else {
|
|
store.dispatch("setIsDataIngested", true);
|
|
next();
|
|
}
|
|
});
|
|
} else {
|
|
next();
|
|
}
|
|
|
|
// if (local_organization.value.value == null || config.isCloud == "false") {
|
|
// next();
|
|
// }
|
|
|
|
// if (local_organization.value.value.status == "pending-subscription") {
|
|
// Dialog.create({
|
|
// title: "Confirmation",
|
|
// message: "Please subscribe to a paid plan to continue.",
|
|
// cancel: true,
|
|
// persistent: true,
|
|
// })
|
|
// .onOk(() => {
|
|
// const nextURL = getPath().replace(".", "") + "billings/plans";
|
|
// next(nextURL);
|
|
// })
|
|
// .onCancel(() => {
|
|
// return false;
|
|
// });
|
|
// } else {
|
|
// next();
|
|
// }
|
|
};
|
|
|
|
export const convertToTitleCase = (str: string) => {
|
|
return str
|
|
.split("-")
|
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
.join(" ");
|
|
};
|
|
|
|
export const verifyOrganizationStatus = (Organizations: any, Router: any) => {
|
|
// for (const org of Organizations) {
|
|
// if (org.status == "pending-subscription") {
|
|
// Dialog.create({
|
|
// title: "Warning",
|
|
// message: "Please subscribe to a paid plan to continue.",
|
|
// });
|
|
// Router.push({ name: "plans" });
|
|
// }
|
|
// }
|
|
};
|
|
|
|
export const convertTimeFromMicroToMilli = (time: number) => {
|
|
const milliseconds = Math.floor(time / 1000);
|
|
const date = new Date(milliseconds);
|
|
return date.getTime();
|
|
};
|
|
|
|
export const formatLargeNumber = (number: number) => {
|
|
if (number >= 1000000000) {
|
|
return (number / 1000000000).toFixed(1) + "B";
|
|
} else if (number >= 1000000) {
|
|
return (number / 1000000).toFixed(1) + "M";
|
|
} else if (number >= 1000) {
|
|
return (number / 1000).toFixed(1) + "K";
|
|
} else {
|
|
return number.toString();
|
|
}
|
|
};
|
|
|
|
export const formatSizeFromMB = (sizeInMB: string) => {
|
|
let size = parseFloat(sizeInMB);
|
|
|
|
const units = ["KB", "MB", "GB", "TB", "PB"];
|
|
let index = 1; // Start from MB
|
|
|
|
while (size >= 1024 && index < units.length - 1) {
|
|
size /= 1024;
|
|
index++;
|
|
}
|
|
|
|
return `${size.toFixed(2)} ${units[index]}`;
|
|
};
|
|
|
|
/**
|
|
* @param us : Time in microseconds
|
|
*/
|
|
export const formatTimeWithSuffix = (us: number) => {
|
|
if (us >= 1000 * 1000) {
|
|
return `${(us / 1000 / 1000).toFixed(2)}s`;
|
|
}
|
|
|
|
if (us >= 1000) {
|
|
return `${(us / 1000).toFixed(2)}ms`;
|
|
}
|
|
|
|
return `${us.toFixed(2)}us`;
|
|
};
|
|
|
|
export const mergeRoutes: any = (route1: any, route2: any) => {
|
|
const mergedRoutes = [];
|
|
|
|
// Iterate through route1 and add its elements to mergedRoutes
|
|
for (const r1 of route1) {
|
|
const matchingRoute = route2.find(
|
|
(r2: any) => r2.path === r1.path && r2.name === r1.name,
|
|
);
|
|
|
|
if (matchingRoute) {
|
|
// If a matching route is found in route2, merge the children
|
|
const mergedChildren = mergeRoutes(
|
|
r1.children || [],
|
|
matchingRoute.children || [],
|
|
);
|
|
mergedRoutes.push({
|
|
...r1,
|
|
children: mergedChildren.length ? mergedChildren : undefined,
|
|
});
|
|
|
|
// Remove the matching route from route2
|
|
route2 = route2.filter((r2: any) => r2 !== matchingRoute);
|
|
} else {
|
|
// If no matching route is found in route2, add the route from route1 as is
|
|
mergedRoutes.push({ ...r1 });
|
|
}
|
|
}
|
|
|
|
// Add any remaining routes from route2 to mergedRoutes
|
|
mergedRoutes.push(...route2);
|
|
|
|
return mergedRoutes;
|
|
};
|
|
|
|
export function formatDuration(ms: number) {
|
|
const seconds = (ms / 1000).toFixed(2);
|
|
const minutes = (Number(seconds) / 60).toFixed(2);
|
|
const hours = (Number(minutes) / 60).toFixed(2);
|
|
const days = (Number(hours) / 24).toFixed(2);
|
|
|
|
let formatted = `${seconds} sec`;
|
|
|
|
if (ms > 86400000) {
|
|
formatted = `${days} days ${hours} hr`;
|
|
} else if (ms > 3600000) {
|
|
formatted = `${hours} hr `;
|
|
} else if (ms > 60000) {
|
|
formatted = `${minutes} min`;
|
|
}
|
|
|
|
return formatted.trim();
|
|
}
|
|
export const timestampToTimezoneDate = (
|
|
unixMilliTimestamp: number,
|
|
timezone: string = "UTC",
|
|
format: string = "yyyy-MM-dd HH:mm:ss.SSS",
|
|
) => {
|
|
return DateTime.fromMillis(Math.floor(unixMilliTimestamp))
|
|
.setZone(timezone)
|
|
.toFormat(format);
|
|
};
|
|
|
|
export const histogramDateTimezone: any = (
|
|
utcTime: any,
|
|
timezone: string = "UTC",
|
|
) => {
|
|
if (timezone == "UTC") return Math.floor(new Date(utcTime).getTime());
|
|
else {
|
|
return (
|
|
Math.floor(
|
|
DateTime.fromISO(utcTime, { zone: "UTC" })
|
|
.setZone(timezone)
|
|
.toSeconds(),
|
|
) * 1000
|
|
);
|
|
}
|
|
};
|
|
|
|
// // Example usage:
|
|
// const inputDatetime = "2023/10/26 17:34:00";
|
|
// const inputTimezone = "Pacific/Pitcairn";
|
|
export const convertToUtcTimestamp = (
|
|
inputDatetime: string,
|
|
inputTimezone: string,
|
|
) => {
|
|
// Create a DateTime object with the input datetime and timezone
|
|
const dt = DateTime.fromFormat(inputDatetime, "yyyy/MM/dd HH:mm:ss", {
|
|
zone: inputTimezone,
|
|
});
|
|
|
|
// Get the UTC timestamp in seconds (rounded to the nearest second)
|
|
const utcTimestamp = Math.round(dt.toUTC().toMillis());
|
|
|
|
return utcTimestamp * 1000;
|
|
};
|
|
|
|
export const localTimeSelectedTimezoneUTCTime = async (
|
|
time: any,
|
|
timezone: string,
|
|
) => {
|
|
await importMoment();
|
|
// Creating a Date object using the timestamp
|
|
const date = new Date(time);
|
|
|
|
// Extracting date and time components
|
|
const year = date.getFullYear();
|
|
const month = date.getMonth(); // Months are zero-indexed
|
|
const day = date.getDate();
|
|
const hour = date.getHours();
|
|
const minute = date.getMinutes();
|
|
const second = date.getSeconds();
|
|
|
|
// Create a moment object using the provided date, time, and timezone
|
|
const convertedDate = moment.tz(
|
|
{ year, month, day, hour, minute, second },
|
|
timezone,
|
|
);
|
|
|
|
// Convert the moment object to a Unix timestamp (in seconds)
|
|
const unixTimestamp = convertedDate.unix() * 1000000;
|
|
|
|
console.log(unixTimestamp);
|
|
return unixTimestamp;
|
|
};
|
|
|
|
const isObject = (obj: any) => obj !== null && typeof obj === "object";
|
|
|
|
const isValidKey = (key: string) => {
|
|
// Add any additional checks to ensure key validity
|
|
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
|
|
};
|
|
|
|
export const mergeDeep = (target: any, source: any) => {
|
|
if (isObject(target) && isObject(source)) {
|
|
for (const key in source) {
|
|
if (
|
|
isValidKey(key) &&
|
|
Object.prototype.hasOwnProperty.call(source, key)
|
|
) {
|
|
if (isObject(source[key])) {
|
|
if (!target[key]) target[key] = {};
|
|
mergeDeep(target[key], source[key]);
|
|
} else {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return target;
|
|
};
|
|
|
|
export function getUUID() {
|
|
return uuidv4();
|
|
}
|
|
|
|
export const maskText = (text: string) => {
|
|
// Disabled masking as it was not great usefully
|
|
// const visibleChars = 4; // Number of characters to keep visible at the beginning and end
|
|
// const maskedChars = text.length - visibleChars * 2;
|
|
|
|
// if (maskedChars > 0) {
|
|
// const maskedText =
|
|
// text.substring(0, visibleChars) +
|
|
// "*".repeat(maskedChars) +
|
|
// text.slice(-visibleChars);
|
|
// return maskedText;
|
|
// } else {
|
|
// return "*".repeat(text.length); // If the text is too short, mask all characters
|
|
// }
|
|
|
|
return text;
|
|
};
|
|
|
|
export const queryIndexSplit = (query: string, splitWord: string) => {
|
|
// Convert the query to lowercase to perform a case-insensitive search
|
|
const lowerCaseQuery: string = query.toLowerCase();
|
|
const lowerCaseSplitWord: string = splitWord.toLowerCase();
|
|
|
|
// Find the index of the split word in the query
|
|
const splitWordIndex = lowerCaseQuery.indexOf(lowerCaseSplitWord);
|
|
|
|
// If the split word is not found, return the entire query in the first element and an empty string in the second
|
|
if (splitWordIndex === -1) {
|
|
return [query, ""];
|
|
}
|
|
|
|
// Calculate the positions to slice the query
|
|
const beforeSplit = query.slice(0, splitWordIndex);
|
|
const afterSplit = query.slice(splitWordIndex + splitWord.length);
|
|
|
|
// Return the two parts as an array
|
|
return [beforeSplit, afterSplit];
|
|
};
|
|
export const convertToCamelCase = (str: string) => {
|
|
if (!str) {
|
|
return ""; // or handle the case as needed
|
|
}
|
|
|
|
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
};
|
|
|
|
// Function to generate error message for max query range limit on logs and dashboard page.
|
|
export const getFunctionErrorMessage = (
|
|
message: string,
|
|
newStartTime: number,
|
|
newEndTime: number,
|
|
timezone = "UTC",
|
|
) => {
|
|
try {
|
|
// Convert timestamps to formatted dates using timestampToTimezoneDate function
|
|
const startTimeFormatted = timestampToTimezoneDate(
|
|
newStartTime / 1000,
|
|
timezone,
|
|
"yyyy-MM-dd HH:mm:ss",
|
|
);
|
|
const endTimeFormatted = timestampToTimezoneDate(
|
|
newEndTime / 1000,
|
|
timezone,
|
|
"yyyy-MM-dd HH:mm:ss",
|
|
);
|
|
|
|
return `${message} (Data returned for: ${startTimeFormatted} to ${endTimeFormatted})`;
|
|
} catch (error) {
|
|
return message;
|
|
}
|
|
};
|
|
|
|
export const generateTraceContext = () => {
|
|
const traceId = getUUID().replace(/-/g, "");
|
|
const spanId = getUUID().replace(/-/g, "").slice(0, 16);
|
|
|
|
return {
|
|
traceparent: `00-${traceId}-${spanId}-01`,
|
|
traceId,
|
|
spanId,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Formats the duration in seconds into a human-readable string representation.
|
|
* The format of the output string is:
|
|
* - For durations less than 60 seconds, returns the duration in seconds.
|
|
* - For durations less than 3600 seconds (1 hour), returns minutes and seconds.
|
|
* - For durations less than 86400 seconds (1 day), returns hours, minutes, and seconds.
|
|
* - For durations equal to or greater than 1 day, returns days, hours, minutes, and seconds.
|
|
* - If no value(0) than removes the duration from the string.
|
|
*
|
|
* @param {number} durationInSeconds - The duration in seconds to be formatted.
|
|
* @return {string} The formatted duration string.
|
|
*/
|
|
export const durationFormatter = (durationInSeconds: number): string => {
|
|
let formattedDuration;
|
|
|
|
// If duration is invalid, set formatted duration to "Invalid duration"
|
|
// For example, if the duration is -1 seconds, the output string will be "Invalid duration".
|
|
if (durationInSeconds < 0) {
|
|
formattedDuration = "Invalid duration";
|
|
} else if (durationInSeconds < 60) {
|
|
// If duration is less than 60 seconds, return duration in seconds
|
|
// For example, if the duration is 30 seconds, the output string will be "30s".
|
|
formattedDuration = `${durationInSeconds}s`;
|
|
} else if (durationInSeconds < 3600) {
|
|
// If duration is less than 1 hour, calculate minutes and seconds and return
|
|
// For example, if the duration is 150 seconds, the output string will be "2m 30s".
|
|
const minutes = Math.floor(durationInSeconds / 60);
|
|
const seconds = durationInSeconds % 60;
|
|
formattedDuration = `${minutes > 0 ? `${minutes}m ` : ""}${
|
|
seconds > 0 ? `${seconds}s` : ""
|
|
}`.trim();
|
|
} else if (durationInSeconds < 86400) {
|
|
// If duration is less than 1 day, calculate hours, minutes, and seconds and return
|
|
// For example, if the duration is 7200 seconds, the output string will be "2h".
|
|
const hours = Math.floor(durationInSeconds / 3600);
|
|
const minutes = Math.floor((durationInSeconds % 3600) / 60);
|
|
const seconds = durationInSeconds % 60;
|
|
formattedDuration = `${hours > 0 ? `${hours}h ` : ""}${
|
|
minutes > 0 ? `${minutes}m ` : ""
|
|
}${seconds > 0 ? `${seconds}s` : ""}`.trim();
|
|
} else {
|
|
// If duration is equal to or greater than 1 day, calculate days, hours, minutes, and seconds and return
|
|
// For example, if the durartion is 86900 seconds, the output string will be "1d 8m 20s".
|
|
const days = Math.floor(durationInSeconds / 86400);
|
|
const hours = Math.floor((durationInSeconds % 86400) / 3600);
|
|
const minutes = Math.floor((durationInSeconds % 3600) / 60);
|
|
const seconds = durationInSeconds % 60;
|
|
formattedDuration = `${days > 0 ? `${days}d ` : ""}${
|
|
hours > 0 ? `${hours}h ` : ""
|
|
}${minutes > 0 ? `${minutes}m ` : ""}${
|
|
seconds > 0 ? `${seconds}s` : ""
|
|
}`.trim();
|
|
}
|
|
|
|
return formattedDuration;
|
|
};
|
|
|
|
export const getTimezoneOffset = () => {
|
|
const now = new Date();
|
|
|
|
// Get the day, month, and year from the date object
|
|
const day = String(now.getDate()).padStart(2, "0");
|
|
const month = String(now.getMonth() + 1).padStart(2, "0"); // January is 0!
|
|
const year = now.getFullYear();
|
|
|
|
// Combine them in the DD-MM-YYYY format
|
|
const scheduleDate = `${day}-${month}-${year}`;
|
|
|
|
// Get the hours and minutes, ensuring they are formatted with two digits
|
|
const hours = String(now.getHours()).padStart(2, "0");
|
|
const minutes = String(now.getMinutes()).padStart(2, "0");
|
|
|
|
// Combine them in the HH:MM format
|
|
const scheduleTime = `${hours}:${minutes}`;
|
|
|
|
const ScheduleTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
|
|
const convertedDateTime = convertDateToTimestamp(
|
|
scheduleDate,
|
|
scheduleTime,
|
|
ScheduleTimezone,
|
|
);
|
|
|
|
return convertedDateTime.offset;
|
|
};
|
|
|
|
export const convertDateToTimestamp = (
|
|
date: string,
|
|
time: string,
|
|
timezone: string,
|
|
) => {
|
|
const browserTime =
|
|
"Browser Time (" + Intl.DateTimeFormat().resolvedOptions().timeZone + ")";
|
|
|
|
const [day, month, year] = date.split("-");
|
|
const [hour, minute] = time.split(":");
|
|
|
|
const _date = {
|
|
year: Number(year),
|
|
month: Number(month),
|
|
day: Number(day),
|
|
hour: Number(hour),
|
|
minute: Number(minute),
|
|
};
|
|
|
|
if (timezone.toLowerCase() == browserTime.toLowerCase()) {
|
|
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
}
|
|
|
|
// Create a DateTime instance from date and time, then set the timezone
|
|
const dateTime = _DateTime.fromObject(_date, { zone: timezone });
|
|
|
|
// Convert the DateTime to a Unix timestamp in milliseconds
|
|
const unixTimestampMillis = dateTime.toMillis();
|
|
|
|
return { timestamp: unixTimestampMillis * 1000, offset: dateTime.offset }; // timestamp in microseconds
|
|
};
|
|
|
|
export const isValidResourceName = (name: string) => {
|
|
const roleNameRegex = /^[^:#?&%'"\s]+$/;
|
|
// Check if the role name is valid
|
|
return roleNameRegex.test(name);
|
|
};
|