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 cockroachdb#85968
Closes cockroachdb#85912
Closes cockroachdb#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 11, 2022
1 parent 9fb8d36 commit 59c7981
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 9 deletions.
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: false,
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
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 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 59c7981

Please sign in to comment.