Skip to content

Commit

Permalink
cluster-ui: update active execution and sessions details
Browse files Browse the repository at this point in the history
Fixes #85968
Closes #85912
Closes #85973

This commit adds new details to the active execution details pages:
full scan (both stmt and txn), priority (txn only), and last retry
reason (txn only). New information is also added to the sessions
table and details pages: transaction count, active duration,
recent txn fingerprint ids (cache size comes from a cluster setting).

This commit also fixes a bug in the sessions overview UI where
the duration for closed sessions was incorrectly calcualted based
on the current time instead of the session end time.

Release note (ui change): the following fields have been added to
the active stmt/txn details pages:
- Full Scan: indicates if the execution contains a full scan
- Last Retry Reason (txn page only): the last recorded reason the
txn was retried
- Priority (txn page only): the txn priority
The following fields have been added to the sessions table and page:
- Transaction  count: the number of txns executed by the session
- Session active duration: the time a session spent executing txns
- Session most recent fingerprint ids
  • Loading branch information
xinhaoz committed Aug 12, 2022
1 parent 9fb8d36 commit ac161dd
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const defaultActiveStatement: ActiveStatement = {
application: "test",
user: "user",
clientAddress: "clientAddress",
isFullScan: false,
};

// makeActiveStatement creates an ActiveStatement object with the default active statement above
Expand All @@ -83,6 +84,9 @@ function makeActiveTxn(
query: defaultActiveStatement.query,
statementID: defaultActiveStatement.statementID,
retries: 3,
lastAutoRetryReason: null,
isFullScan: defaultActiveStatement.isFullScan,
priority: "Normal",
statementCount: 5,
status: "Executing",
...props,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export function getActiveExecutionsFromSessions(
application: session.application_name,
user: session.username,
clientAddress: session.client_address,
isFullScan: query.is_full_scan || false, // Or here is for conversion in case the field is null.
};

statements.push(stmt);
Expand All @@ -138,6 +139,9 @@ export function getActiveExecutionsFromSessions(
application: session.application_name,
retries: activeTxn.num_auto_retries,
statementCount: activeTxn.num_statements_executed,
isFullScan: session.active_queries.some(query => query.is_full_scan),
lastAutoRetryReason: activeTxn.last_auto_retry_reason,
priority: activeTxn.priority,
});
});

Expand All @@ -147,6 +151,7 @@ export function getActiveExecutionsFromSessions(
if (!mostRecentStmt) return txn;
txn.query = mostRecentStmt.query;
txn.statementID = mostRecentStmt.statementID;
txn.isFullScan = mostRecentStmt.isFullScan;
return txn;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ import { SortSetting } from "../../sortedtable";
import { ActiveTransaction, ExecutionType } from "../types";
import { isSelectedColumn } from "../../columnsSelector/utils";
import { Link } from "react-router-dom";
import { StatusIcon } from "../statusIcon";
import {
getLabel,
executionsTableTitles,
ExecutionsColumn,
activeTransactionColumnsFromCommon,
} from "../execTableCommon";
import { DATE_FORMAT, Duration } from "../../util";

interface ActiveTransactionsTable {
data: ActiveTransaction[];
Expand Down
3 changes: 3 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/activeExecutions/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface ActiveExecution {
application: string;
query?: string; // Possibly empty for a transaction.
timeSpentWaiting?: moment.Duration;
isFullScan: boolean;
}

export type ActiveStatement = ActiveExecution &
Expand All @@ -45,6 +46,8 @@ export type ActiveStatement = ActiveExecution &
export type ActiveTransaction = ActiveExecution & {
statementCount: number;
retries: number;
lastAutoRetryReason?: string;
priority: string;
};

export type ActiveExecutions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,13 @@
fill: $colors--neutral-4;
}
}

.session-txn-fingerprints {
margin-top: 12px;
max-height: 300px;
overflow-y: scroll;

div {
margin-bottom: 8px;
}
}
44 changes: 38 additions & 6 deletions pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
import { SummaryCard, SummaryCardItem } from "../summaryCard";
import SQLActivityError from "../sqlActivity/errorComponent";

import { TimestampToMoment } from "src/util/convert";
import { DurationToMomentDuration, TimestampToMoment } from "src/util/convert";
import { Bytes, DATE_FORMAT } from "src/util/format";
import { Col, Row } from "antd";
import "antd/lib/col/style";
Expand All @@ -41,10 +41,7 @@ import { Button } from "../button";
import { ArrowLeft } from "@cockroachlabs/icons";
import { Text, TextTypes } from "../text";
import { SqlBox } from "src/sql/box";
import {
NodeLink,
StatementLinkTarget,
} from "src/statementsTable/statementsTableContent";
import { NodeLink } from "src/statementsTable/statementsTableContent";

import {
ICancelQueryRequest,
Expand Down Expand Up @@ -256,7 +253,7 @@ export class SessionDetails extends React.Component<SessionDetailsProps> {
}

let txnInfo = <React.Fragment>No Active Transaction</React.Fragment>;
if (session.active_txn) {
if (session.active_txn && session.end == null) {
const txn = session.active_txn;
const start = TimestampToMoment(txn.start);
txnInfo = (
Expand Down Expand Up @@ -352,6 +349,20 @@ export class SessionDetails extends React.Component<SessionDetailsProps> {
value={TimestampToMoment(session.start).format(DATE_FORMAT)}
className={cx("details-item")}
/>
{session.end && (
<SummaryCardItem
label={"Session End Time"}
value={TimestampToMoment(session.end).format(DATE_FORMAT)}
className={cx("details-item")}
/>
)}
<SummaryCardItem
label={"Session Active Duration"}
value={DurationToMomentDuration(
session.total_active_time,
).humanize()}
className={cx("details-item")}
/>
{!isTenant && (
<SummaryCardItem
label={"Gateway Node"}
Expand Down Expand Up @@ -404,6 +415,11 @@ export class SessionDetails extends React.Component<SessionDetailsProps> {
value={session.username}
className={cx("details-item")}
/>
<SummaryCardItem
label="Transaction Count"
value={session.num_txns_executed}
className={cx("details-item")}
/>
</Col>
</Row>
</SummaryCard>
Expand All @@ -415,6 +431,22 @@ export class SessionDetails extends React.Component<SessionDetailsProps> {
Most Recent Statement
</Text>
{curStmtInfo}
<div>
<Text textType={TextTypes.Heading5} className={cx("details-header")}>
Most Recent Transaction Fingerprints Executed
</Text>
<Text textType={TextTypes.Caption}>
A list of the most recent transaction fingerprint IDs executed by
this session represented in hexadecimal.
</Text>
<SummaryCard
className={cx("details-section", "session-txn-fingerprints")}
>
{session.txn_fingerprint_ids.map((txnFingerprintID, i) => (
<div key={i}>{txnFingerprintID.toString(16)}</div>
))}
</SummaryCard>
</div>
</React.Fragment>
);
};
Expand Down
29 changes: 27 additions & 2 deletions pkg/ui/workspaces/cluster-ui/src/sessions/sessionsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
import classNames from "classnames/bind";

import styles from "./sessionsTable.module.scss";
import { TimestampToMoment } from "src/util/convert";
import {
DurationToMomentDuration,
DurationToNumber,
TimestampToMoment,
} from "src/util/convert";
import { BytesWithPrecision } from "src/util/format";
import { Link } from "react-router-dom";
import React from "react";
Expand Down Expand Up @@ -175,9 +179,23 @@ export function makeSessionsColumns(
name: "sessionDuration",
title: statisticsTableTitles.sessionDuration(statType),
className: cx("cl-table__col-session"),
cell: session => TimestampToMoment(session.session.start).fromNow(true),
cell: session => {
const startMoment = TimestampToMoment(session.session.start);
if (session.session.end != null) {
return TimestampToMoment(session.session.end).from(startMoment, true);
}
return startMoment.fromNow(true);
},
sort: session => TimestampToMoment(session.session.start).valueOf(),
},
{
name: "sessionActiveDuration",
title: statisticsTableTitles.sessionActiveDuration(statType),
className: cx("cl-table__col-session"),
cell: session =>
DurationToMomentDuration(session.session.total_active_time).humanize(),
sort: session => DurationToNumber(session.session.total_active_time),
},
{
name: "status",
title: statisticsTableTitles.status(statType),
Expand All @@ -202,6 +220,13 @@ export function makeSessionsColumns(
? session.session.active_queries[0].start.seconds
: 0,
},
{
name: "sessionTxnCount",
title: statisticsTableTitles.sessionTxnCount(statType),
className: cx("cl-table__col-session"),
cell: session => session.session?.num_txns_executed,
sort: session => session.session?.num_txns_executed,
},
{
name: "memUsage",
title: statisticsTableTitles.memUsage(statType),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ export const ActiveStatementDetails: React.FC<ActiveStatementDetailsProps> = ({
</>
}
/>
<SummaryCardItem
label="Full Scan"
value={statement.isFullScan.toString()}
/>
</Col>
</Row>
</SummaryCard>
Expand Down
26 changes: 26 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/statsTableUtil/statsTableUtil.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export type NodeNames = { [nodeId: string]: string };
export const statisticsColumnLabels = {
sessionStart: "Session Start Time (UTC)",
sessionDuration: "Session Duration",
sessionActiveDuration: "Session Active Duration",
sessionTxnCount: "Transaction Count",
mostRecentStatement: "Most Recent Statement",
status: "Status",
statementStartTime: "Statement Start Time (UTC)",
Expand Down Expand Up @@ -133,6 +135,30 @@ export const statisticsTableTitles: StatisticTableTitleType = {
</Tooltip>
);
},
sessionActiveDuration: () => {
return (
<Tooltip
style="tableTitle"
placement="bottom"
content={
"The amount of time the session has been actively running transactions."
}
>
{getLabel("sessionActiveDuration")}
</Tooltip>
);
},
sessionTxnCount: () => {
return (
<Tooltip
style="tableTitle"
placement="bottom"
content={"The number of transactions executed in this session."}
>
{getLabel("sessionTxnCount")}
</Tooltip>
);
},
status: () => {
return (
<Tooltip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { executionIdAttr } from "../util";
import styles from "../statementDetails/statementDetails.module.scss";
import { WaitTimeInsightsPanel } from "src/detailsPanels/waitTimeInsightsPanel";
import { Duration } from "../util/format";
import { capitalize } from "src/activeExecutions/execTableCommon";
const cx = classNames.bind(styles);
const summaryCardStylesCx = classNames.bind(summaryCardStyles);

Expand All @@ -53,11 +54,14 @@ export const ActiveTxnInsightsLabels = {
START_TIME: "Start Time (UTC)",
ELAPSED_TIME: "Elapsed Time",
STATUS: "Status",
RETRY_COUNT: "Number of Retries",
RETRY_COUNT: "Internal Retries",
RETRY_REASON: "Last Retry Reason",
STATEMENT_COUNT: "Number of Statements",
APPLICATION_NAME: "Application Name",
LAST_STATEMENT_EXEC_ID: "Most Recent Statement Execution ID",
SESSION_ID: "Session ID",
PRIORITY: "Priority",
FULL_SCAN: "Full Scan",
};

export const RECENT_STATEMENT_NOT_FOUND_MESSAGE =
Expand Down Expand Up @@ -135,6 +139,14 @@ export const ActiveTransactionDetails: React.FC<
</>
}
/>
<SummaryCardItem
label={ActiveTxnInsightsLabels.PRIORITY}
value={capitalize(transaction.priority)}
/>
<SummaryCardItem
label={ActiveTxnInsightsLabels.FULL_SCAN}
value={transaction.isFullScan.toString()}
/>
</Col>
</Row>
</SummaryCard>
Expand All @@ -145,6 +157,10 @@ export const ActiveTransactionDetails: React.FC<
label={ActiveTxnInsightsLabels.RETRY_COUNT}
value={transaction.retries}
/>
<SummaryCardItem
label={ActiveTxnInsightsLabels.RETRY_REASON}
value={transaction.lastAutoRetryReason || "N/A"}
/>
<SummaryCardItem
label={ActiveTxnInsightsLabels.STATEMENT_COUNT}
value={transaction.statementCount}
Expand Down
17 changes: 17 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/util/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@ export function DurationToNumber(
return duration.seconds.toNumber() + NanoToMilli(duration.nanos) * 1e-3;
}

/**
* DurationToMomentDuration converts a Duration object, as seen in wire.proto,
* to a duration object from momentjs. If timestamp is null it returns the `defaultIfNull`
* value which is by default 0, as momentjs duration.
*/
export function DurationToMomentDuration(
duration?: protos.google.protobuf.IDuration,
defaultIfNullSeconds = 0,
): moment.Duration {
if (!duration) {
return moment.duration(defaultIfNullSeconds, "seconds");
}

const seconds = duration.seconds.toNumber() + duration.nanos * 1e-9;
return moment.duration(seconds, "seconds");
}

/**
* NumberToDuration converts a number representing a duration in seconds
* to a Duration object.
Expand Down

0 comments on commit ac161dd

Please sign in to comment.