All Downloads are FREE. Search and download functionalities are using the official Maven repository.

router_ui.src.components.QueryList.jsx Maven / Gradle / Ivy

There is a newer version: 0.289
Show newest version
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React from "react";

import {
    formatDataSizeBytes,
    formatShortTime,
    getHumanReadableState,
    getProgressBarPercentage,
    getProgressBarTitle,
    getQueryStateColor,
    GLYPHICON_DEFAULT,
    GLYPHICON_HIGHLIGHT,
    parseDataSize,
    parseDuration,
    truncateString
} from "../utils";

export class QueryListItem extends React.Component {
    static stripQueryTextWhitespace(queryText) {
        const lines = queryText.split("\n");
        let minLeadingWhitespace = -1;
        for (let i = 0; i < lines.length; i++) {
            if (minLeadingWhitespace === 0) {
                break;
            }

            if (lines[i].trim().length === 0) {
                continue;
            }

            const leadingWhitespace = lines[i].search(/\S/);

            if (leadingWhitespace > -1 && ((leadingWhitespace < minLeadingWhitespace) || minLeadingWhitespace === -1)) {
                minLeadingWhitespace = leadingWhitespace;
            }
        }

        let formattedQueryText = "";

        for (let i = 0; i < lines.length; i++) {
            const trimmedLine = lines[i].substring(minLeadingWhitespace).replace(/\s+$/g, '');

            if (trimmedLine.length > 0) {
                formattedQueryText += trimmedLine;

                if (i < (lines.length - 1)) {
                    formattedQueryText += "\n";
                }
            }
        }

        return truncateString(formattedQueryText, 300);
    }

    render() {
        const query = this.props.query;
        const progressBarStyle = {width: getProgressBarPercentage(query) + "%", backgroundColor: getQueryStateColor(query)};

        const splitDetails = (
            
   {query.queryStats.completedDrivers}    {(query.state === "FINISHED" || query.state === "FAILED") ? 0 : query.queryStats.runningDrivers}    {(query.state === "FINISHED" || query.state === "FAILED") ? 0 : query.queryStats.queuedDrivers}
); const timingDetails = (
   {query.queryStats.executionTime}    {query.queryStats.elapsedTime}    {query.queryStats.totalCpuTime}
); const memoryDetails = (
   {query.queryStats.totalMemoryReservation}    {query.queryStats.peakTotalMemoryReservation}    {formatDataSizeBytes(query.queryStats.cumulativeUserMemory / 1000.0)}
); let user = ({query.session.user}); if (query.session.principal) { user = ( {query.session.user} ); } return (
{formatShortTime(new Date(Date.parse(query.queryStats.createTime)))}
   {truncateString(user, 35)}
   {truncateString(query.session.source, 35)}
{splitDetails}
{timingDetails}
{memoryDetails}
{getProgressBarTitle(query)}
{QueryListItem.stripQueryTextWhitespace(query.query)}
); } } class DisplayedQueriesList extends React.Component { render() { const queryNodes = this.props.queries.map(function (query) { return ( ); }.bind(this)); return (
{queryNodes}
); } } const FILTER_TYPE = { RUNNING: function (query) { return !(query.state === "QUEUED" || query.state === "FINISHED" || query.state === "FAILED"); }, QUEUED: function (query) { return query.state === "QUEUED"}, FINISHED: function (query) { return query.state === "FINISHED"}, }; const SORT_TYPE = { CREATED: function (query) {return Date.parse(query.queryStats.createTime)}, ELAPSED: function (query) {return parseDuration(query.queryStats.elapsedTime)}, EXECUTION: function (query) {return parseDuration(query.queryStats.executionTime)}, CPU: function (query) {return parseDuration(query.queryStats.totalCpuTime)}, CUMULATIVE_MEMORY: function (query) {return query.queryStats.cumulativeUserMemory}, CURRENT_MEMORY: function (query) {return parseDataSize(query.queryStats.userMemoryReservation)}, }; const ERROR_TYPE = { USER_ERROR: function (query) {return query.state === "FAILED" && query.errorType === "USER_ERROR"}, INTERNAL_ERROR: function (query) {return query.state === "FAILED" && query.errorType === "INTERNAL_ERROR"}, INSUFFICIENT_RESOURCES: function (query) {return query.state === "FAILED" && query.errorType === "INSUFFICIENT_RESOURCES"}, EXTERNAL: function (query) {return query.state === "FAILED" && query.errorType === "EXTERNAL"}, }; const SORT_ORDER = { ASCENDING: function (value) {return value}, DESCENDING: function (value) {return -value} }; export class QueryList extends React.Component { constructor(props) { super(props); this.state = { allQueries: [], displayedQueries: [], reorderInterval: 5000, currentSortType: SORT_TYPE.CREATED, currentSortOrder: SORT_ORDER.DESCENDING, stateFilters: [FILTER_TYPE.RUNNING, FILTER_TYPE.QUEUED], errorTypeFilters: [ERROR_TYPE.INTERNAL_ERROR, ERROR_TYPE.INSUFFICIENT_RESOURCES, ERROR_TYPE.EXTERNAL], searchString: '', maxQueries: 100, lastRefresh: Date.now(), lastReorder: Date.now(), initialized: false }; this.refreshLoop = this.refreshLoop.bind(this); this.handleSearchStringChange = this.handleSearchStringChange.bind(this); this.executeSearch = this.executeSearch.bind(this); this.handleSortClick = this.handleSortClick.bind(this); } sortAndLimitQueries(queries, sortType, sortOrder, maxQueries) { queries.sort(function (queryA, queryB) { return sortOrder(sortType(queryA) - sortType(queryB)); }, this); if (maxQueries !== 0 && queries.length > maxQueries) { queries.splice(maxQueries, (queries.length - maxQueries)); } } filterQueries(queries, stateFilters, errorTypeFilters, searchString) { const stateFilteredQueries = queries.filter(function (query) { for (let i = 0; i < stateFilters.length; i++) { if (stateFilters[i](query)) { return true; } } for (let i = 0; i < errorTypeFilters.length; i++) { if (errorTypeFilters[i](query)) { return true; } } return false; }); if (searchString === '') { return stateFilteredQueries; } else { return stateFilteredQueries.filter(function (query) { const term = searchString.toLowerCase(); if (query.queryId.toLowerCase().indexOf(term) !== -1 || getHumanReadableState(query).toLowerCase().indexOf(term) !== -1 || query.query.toLowerCase().indexOf(term) !== -1) { return true; } if (query.session.user && query.session.user.toLowerCase().indexOf(term) !== -1) { return true; } if (query.session.source && query.session.source.toLowerCase().indexOf(term) !== -1) { return true; } if (query.resourceGroupId && query.resourceGroupId.join(".").toLowerCase().indexOf(term) !== -1) { return true; } }, this); } } resetTimer() { clearTimeout(this.timeoutId); // stop refreshing when query finishes or fails if (this.state.query === null || !this.state.ended) { this.timeoutId = setTimeout(this.refreshLoop, 1000); } } refreshLoop() { clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously clearTimeout(this.searchTimeoutId); $.get('/v1/query', function (queryList) { const queryMap = queryList.reduce(function (map, query) { map[query.queryId] = query; return map; }, {}); let updatedQueries = []; this.state.displayedQueries.forEach(function (oldQuery) { if (oldQuery.queryId in queryMap) { updatedQueries.push(queryMap[oldQuery.queryId]); queryMap[oldQuery.queryId] = false; } }); let newQueries = []; for (const queryId in queryMap) { if (queryMap[queryId]) { newQueries.push(queryMap[queryId]); } } newQueries = this.filterQueries(newQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); const lastRefresh = Date.now(); let lastReorder = this.state.lastReorder; if (this.state.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= this.state.reorderInterval)) { updatedQueries = this.filterQueries(updatedQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); updatedQueries = updatedQueries.concat(newQueries); this.sortAndLimitQueries(updatedQueries, this.state.currentSortType, this.state.currentSortOrder, 0); lastReorder = Date.now(); } else { this.sortAndLimitQueries(newQueries, this.state.currentSortType, this.state.currentSortOrder, 0); updatedQueries = updatedQueries.concat(newQueries); } if (this.state.maxQueries !== 0 && (updatedQueries.length > this.state.maxQueries)) { updatedQueries.splice(this.state.maxQueries, (updatedQueries.length - this.state.maxQueries)); } this.setState({ allQueries: queryList, displayedQueries: updatedQueries, lastRefresh: lastRefresh, lastReorder: lastReorder, initialized: true }); this.resetTimer(); }.bind(this)) .error(function () { this.setState({ initialized: true, }); this.resetTimer(); }.bind(this)); } componentDidMount() { this.refreshLoop(); } handleSearchStringChange(event) { const newSearchString = event.target.value; clearTimeout(this.searchTimeoutId); this.setState({ searchString: newSearchString }); this.searchTimeoutId = setTimeout(this.executeSearch, 200); } executeSearch() { clearTimeout(this.searchTimeoutId); const newDisplayedQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); this.sortAndLimitQueries(newDisplayedQueries, this.state.currentSortType, this.state.currentSortOrder, this.state.maxQueries); this.setState({ displayedQueries: newDisplayedQueries }); } renderMaxQueriesListItem(maxQueries, maxQueriesText) { return (
  • {maxQueriesText}
  • ); } handleMaxQueriesClick(newMaxQueries) { const filteredQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); this.sortAndLimitQueries(filteredQueries, this.state.currentSortType, this.state.currentSortOrder, newMaxQueries); this.setState({ maxQueries: newMaxQueries, displayedQueries: filteredQueries }); } renderReorderListItem(interval, intervalText) { return (
  • {intervalText}
  • ); } handleReorderClick(interval) { if (this.state.reorderInterval !== interval) { this.setState({ reorderInterval: interval, }); } } renderSortListItem(sortType, sortText) { if (this.state.currentSortType === sortType) { const directionArrow = this.state.currentSortOrder === SORT_ORDER.ASCENDING ? : ; return (
  • {sortText} {directionArrow}
  • ); } else { return (
  • {sortText}
  • ); } } handleSortClick(sortType) { const newSortType = sortType; let newSortOrder = SORT_ORDER.DESCENDING; if (this.state.currentSortType === sortType && this.state.currentSortOrder === SORT_ORDER.DESCENDING) { newSortOrder = SORT_ORDER.ASCENDING; } const newDisplayedQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); this.sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, this.state.maxQueries); this.setState({ displayedQueries: newDisplayedQueries, currentSortType: newSortType, currentSortOrder: newSortOrder }); } renderFilterButton(filterType, filterText) { let checkmarkStyle = {color: '#57aac7'}; let classNames = "btn btn-sm btn-info style-check"; if (this.state.stateFilters.indexOf(filterType) > -1) { classNames += " active"; checkmarkStyle = {color: '#ffffff'}; } return ( ); } handleStateFilterClick(filter) { const newFilters = this.state.stateFilters.slice(); if (this.state.stateFilters.indexOf(filter) > -1) { newFilters.splice(newFilters.indexOf(filter), 1); } else { newFilters.push(filter); } const filteredQueries = this.filterQueries(this.state.allQueries, newFilters, this.state.errorTypeFilters, this.state.searchString); this.sortAndLimitQueries(filteredQueries, this.state.currentSortType, this.state.currentSortOrder); this.setState({ stateFilters: newFilters, displayedQueries: filteredQueries }); } renderErrorTypeListItem(errorType, errorTypeText) { let checkmarkStyle = {color: '#ffffff'}; if (this.state.errorTypeFilters.indexOf(errorType) > -1) { checkmarkStyle = GLYPHICON_HIGHLIGHT; } return (
  •  {errorTypeText}
  • ); } handleErrorTypeFilterClick(errorType) { const newFilters = this.state.errorTypeFilters.slice(); if (this.state.errorTypeFilters.indexOf(errorType) > -1) { newFilters.splice(newFilters.indexOf(errorType), 1); } else { newFilters.push(errorType); } const filteredQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, newFilters, this.state.searchString); this.sortAndLimitQueries(filteredQueries, this.state.currentSortType, this.state.currentSortOrder); this.setState({ errorTypeFilters: newFilters, displayedQueries: filteredQueries }); } render() { let queryList = ; if (this.state.displayedQueries === null || this.state.displayedQueries.length === 0) { let label = (
    Loading...
    ); if (this.state.initialized) { if (this.state.allQueries === null || this.state.allQueries.length === 0) { label = "No queries"; } else { label = "No queries matched filters"; } } queryList = (

    {label}

    ); } return (
    State:
    {this.renderFilterButton(FILTER_TYPE.RUNNING, "Running")} {this.renderFilterButton(FILTER_TYPE.QUEUED, "Queued")} {this.renderFilterButton(FILTER_TYPE.FINISHED, "Finished")}
      {this.renderErrorTypeListItem(ERROR_TYPE.INTERNAL_ERROR, "Internal Error")} {this.renderErrorTypeListItem(ERROR_TYPE.EXTERNAL, "External Error")} {this.renderErrorTypeListItem(ERROR_TYPE.INSUFFICIENT_RESOURCES, "Resources Error")} {this.renderErrorTypeListItem(ERROR_TYPE.USER_ERROR, "User Error")}
     
      {this.renderSortListItem(SORT_TYPE.CREATED, "Creation Time")} {this.renderSortListItem(SORT_TYPE.ELAPSED, "Elapsed Time")} {this.renderSortListItem(SORT_TYPE.CPU, "CPU Time")} {this.renderSortListItem(SORT_TYPE.EXECUTION, "Execution Time")} {this.renderSortListItem(SORT_TYPE.CURRENT_MEMORY, "Current Memory")} {this.renderSortListItem(SORT_TYPE.CUMULATIVE_MEMORY, "Cumulative User Memory")}
     
      {this.renderReorderListItem(1000, "1s")} {this.renderReorderListItem(5000, "5s")} {this.renderReorderListItem(10000, "10s")} {this.renderReorderListItem(30000, "30s")}
    • {this.renderReorderListItem(0, "Off")}
     
      {this.renderMaxQueriesListItem(20, "20 queries")} {this.renderMaxQueriesListItem(50, "50 queries")} {this.renderMaxQueriesListItem(100, "100 queries")}
    • {this.renderMaxQueriesListItem(0, "All queries")}
    {queryList}
    ); } }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy