Skip to content

Commit

Permalink
ui: introduce foundations to support configurable timezone display
Browse files Browse the repository at this point in the history
This commit adds the foundational dependencies and components needed
to display timestamps in DB console in a user's preferred timezone.

Introduced:
- A dependency on `moment-timezone` in DB console and Cluster UI.
- A cluster setting: `ui.display_timezone`.
- A timezone context with a default value of "UTC". This
  enables backwards-compatability for cluster-ui components.
  No changes in cloud are needed, and cluster-ui components will continue
  to display timestamps in UTC.
- A context provider at the top of DB console's component tree.

Epic: https://cockroachlabs.atlassian.net/browse/CRDB-24406
Release note: None
  • Loading branch information
Zach Lite committed Mar 29, 2023
1 parent 20e41ff commit a363091
Show file tree
Hide file tree
Showing 150 changed files with 982 additions and 462 deletions.
1 change: 1 addition & 0 deletions pkg/ui/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ go_library(
"//pkg/base",
"//pkg/build",
"//pkg/server/serverpb",
"//pkg/settings",
"//pkg/util/httputil",
"//pkg/util/log",
],
Expand Down
17 changes: 17 additions & 0 deletions pkg/ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,27 @@ import (
"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/build"
"github.com/cockroachdb/cockroach/pkg/server/serverpb"
"github.com/cockroachdb/cockroach/pkg/settings"
"github.com/cockroachdb/cockroach/pkg/util/httputil"
"github.com/cockroachdb/cockroach/pkg/util/log"
)

const (
utc int64 = iota
americaNewYork
)

var _ = settings.RegisterEnumSetting(
settings.SystemOnly,
"ui.display_timezone",
"the timezone used to format timestamps in the ui",
"UTC",
map[int64]string{
utc: "UTC",
americaNewYork: "America/New_York",
},
)

// Assets is used for embedded JS assets required for UI.
// In case the binary is built without UI, it provides single index.html file with
// the same content as indexHTML as a fallback.
Expand Down
4 changes: 4 additions & 0 deletions pkg/ui/workspaces/cluster-ui/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ DEPENDENCIES = [
"@npm_cluster_ui//less",
"@npm_cluster_ui//less-loader",
"@npm_cluster_ui//long",
"@npm_cluster_ui//moment",
"@npm_cluster_ui//moment-timezone",
"@npm_cluster_ui//moment-locales-webpack-plugin",
"@npm_cluster_ui//npm-run-all",
"@npm_cluster_ui//prettier",
Expand Down Expand Up @@ -162,6 +164,7 @@ ts_project(
"@npm_cluster_ui//classnames",
"@npm_cluster_ui//connected-react-router",
"@npm_cluster_ui//moment",
"@npm_cluster_ui//moment-timezone",
"@npm_cluster_ui//protobufjs",
"@npm_cluster_ui//redux",
"@npm_cluster_ui//redux-saga",
Expand Down Expand Up @@ -278,6 +281,7 @@ tsc_test(
"@npm_cluster_ui//classnames",
"@npm_cluster_ui//connected-react-router",
"@npm_cluster_ui//moment",
"@npm_cluster_ui//moment-timezone",
"@npm_cluster_ui//protobufjs",
"@npm_cluster_ui//redux",
"@npm_cluster_ui//redux-saga",
Expand Down
2 changes: 2 additions & 0 deletions pkg/ui/workspaces/cluster-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@
"less": "^3.12.2",
"less-loader": "^6.2.0",
"long": "^4.0.0",
"moment": "^2.29.4",
"moment-locales-webpack-plugin": "^1.2.0",
"moment-timezone": "^0.5.42",
"npm-run-all": "^4.1.5",
"prettier": "^2.6.2",
"protobufjs": "6.8.6",
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/clusterLocksApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";
import {
executeInternalSql,
LONG_TIMEOUT,
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/contentionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
formatApiResult,
} from "./sqlApi";
import { ContentionDetails } from "src/insights";
import moment from "moment";
import moment from "moment-timezone";

export type ContentionFilters = {
waitingTxnID?: string;
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/databaseDetailsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from "./sqlApi";
import { IndexUsageStatistic, recommendDropUnusedIndex } from "../insights";
import { Format, Identifier, QualifiedIdentifier } from "./safesql";
import moment from "moment";
import moment from "moment-timezone";
import { fromHexString, withTimeout } from "./util";
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";

Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/databasesApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
sqlResultsAreEmpty,
} from "./sqlApi";
import { withTimeout } from "./util";
import moment from "moment";
import moment from "moment-timezone";

export type DatabasesColumns = {
database_name: string;
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/eventsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
formatApiResult,
} from "./sqlApi";
import { withTimeout } from "./util";
import moment from "moment";
import moment from "moment-timezone";

// defaultEventsNumLimit is the default number of events to be returned.
export const defaultEventsNumLimit = 1000;
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/indexDetailsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
sqlResultsAreEmpty,
StatementRawFormat,
} from "src/api";
import moment from "moment";
import moment from "moment-timezone";
import { TimeScale, toRoundedDateRange } from "../timeScaleDropdown";
import { AggregateStatistics } from "../statementsTable";
import { INTERNAL_APP_NAME_PREFIX } from "../recentExecutions/recentStatementUtils";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/schedulesApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// licenses/APL.txt.

import Long from "long";
import moment from "moment";
import moment from "moment-timezone";
import {
executeInternalSql,
SqlExecutionRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";
import {
executeInternalSql,
SqlExecutionRequest,
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/statementsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
stringToTimestamp,
} from "src/util";
import Long from "long";
import moment from "moment";
import moment from "moment-timezone";

import { AggregateStatistics } from "../statementsTable";
const STATEMENTS_PATH = "/_status/combinedstmts";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/stmtInsightsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
StatementStatus,
StmtInsightEvent,
} from "src/insights";
import moment from "moment";
import moment from "moment-timezone";
import { INTERNAL_APP_NAME_PREFIX } from "src/recentExecutions/recentStatementUtils";
import { FixFingerprintHexValue } from "../util";
import { getContentionDetailsApi } from "./contentionApi";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/tableDetailsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
SqlTxnResult,
txnResultIsEmpty,
} from "./sqlApi";
import moment from "moment";
import moment from "moment-timezone";
import { fromHexString, withTimeout } from "./util";
import { Format, Identifier, Join, SQL } from "./safesql";
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/txnInsightsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
TxnInsightDetails,
TxnInsightEvent,
} from "src/insights";
import moment from "moment";
import moment from "moment-timezone";
import { FixFingerprintHexValue } from "../util";
import {
formatStmtInsights,
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/api/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";

export const PROMISE_TIMEOUT = moment.duration(30, "s"); // seconds

Expand Down
1 change: 1 addition & 0 deletions pkg/ui/workspaces/cluster-ui/src/contexts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
// licenses/APL.txt.

export * from "./cockroachCloudContext";
export * from "./timezoneContext";
26 changes: 26 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/contexts/timezoneContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import React from "react";
import { createContext, useContext } from "react";

export const TimezoneContext = createContext<string>("UTC");

// WithTimezone wraps a class component to provide the
// context's timezone value as a component prop.
export function WithTimezone(Component: any) {
return (props: any) => {
// This lambda is a React function component.
// It is safe to call a hook here.
// eslint-disable-next-line
const timezone = useContext(TimezoneContext);
return <Component timezone={timezone} {...props} />;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
} from "./databaseDetailsPage";

import * as H from "history";
import moment from "moment";
import moment from "moment-timezone";
import { defaultFilters } from "src/queryFilter";
const history = H.createHashHistory();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { mvccGarbage, syncHistory, unique } from "../util";
import styles from "./databaseDetailsPage.module.scss";
import sortableTableStyles from "src/sortedtable/sortedtable.module.scss";
import { baseHeadingClasses } from "src/transactionsPage/transactionsPageClasses";
import { Moment } from "moment";
import { Moment } from "moment-timezone";
import { Caution } from "@cockroachlabs/icons";
import { Anchor } from "../anchor";
import LoadingError from "../sqlActivity/errorComponent";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
randomTablePrivilege,
} from "src/storybook/fixtures";
import { DatabaseTablePage, DatabaseTablePageProps } from "./databaseTablePage";
import moment from "moment";
import moment from "moment-timezone";
import * as H from "history";
const history = H.createHashHistory();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import {
import styles from "./databaseTablePage.module.scss";
import { commonStyles } from "src/common";
import { baseHeadingClasses } from "src/transactionsPage/transactionsPageClasses";
import moment, { Moment } from "moment";
import moment, { Moment } from "moment-timezone";
import { Search as IndexIcon } from "@cockroachlabs/icons";
import booleanSettingStyles from "../settings/booleanSetting.module.scss";
import { CircleFilled } from "../icon";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import "antd/lib/time-picker/style";
import "antd/lib/icon/style";
import "antd/lib/date-picker/style";
import "antd/lib/alert/style";
import moment, { Moment } from "moment";
import moment, { Moment } from "moment-timezone";
import classNames from "classnames/bind";
import { Time as TimeIcon, ErrorCircleFilled } from "@cockroachlabs/icons";
import { Button } from "src/button";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/delayed/delayed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";
import React, { useState, useEffect } from "react";

type Props = {
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/graphs/utils/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// licenses/APL.txt.

import _ from "lodash";
import moment from "moment";
import moment from "moment-timezone";

import {
BytesFitScale,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { storiesOf } from "@storybook/react";
import { withBackground, withRouterProvider } from "src/storybook/decorators";
import { randomName } from "src/storybook/fixtures";
import { IndexDetailsPage, IndexDetailsPageProps } from "./indexDetailsPage";
import moment from "moment";
import moment from "moment-timezone";

const withData: IndexDetailsPageProps = {
databaseName: randomName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import "antd/lib/col/style";
import "antd/lib/row/style";
import "antd/lib/tooltip/style";
import { SummaryCard } from "../summaryCard";
import moment, { Moment } from "moment";
import moment, { Moment } from "moment-timezone";
import { Heading } from "@cockroachlabs/ui-components";
import { Anchor } from "../anchor";
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
recommendDropUnusedIndex,
} from "./indexUsageStatsRec";
import { ClusterIndexUsageStatistic } from "../../api";
import moment from "moment";
import moment from "moment-timezone";

describe("recommendDropUnusedIndex", () => {
const mockCurrentTime = moment();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";

export const indexNeverUsedReason =
"This index has not been used and can be removed for better write performance.";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/insights/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import { Moment } from "moment";
import { Moment } from "moment-timezone";
import { Filters } from "../queryFilter";

// This enum corresponds to the string enum for `problems` in `cluster_execution_insights`
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/insights/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";
import {
filterStatementInsights,
filterTransactionInsights,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import {
timeScaleRangeToObj,
} from "../../../timeScaleDropdown";
import { StmtInsightsReq } from "src/api/stmtInsightsApi";
import moment from "moment";
import moment from "moment-timezone";

import styles from "src/statementsPage/statementsPage.module.scss";
import sortableTableStyles from "src/sortedtable/sortedtable.module.scss";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import * as protos from "@cockroachlabs/crdb-protobuf-client";
import { createMemoryHistory } from "history";
import Long from "long";
import { JobsPageProps } from "./jobsPage";
import moment from "moment";
import moment from "moment-timezone";

import JobsResponse = cockroach.server.serverpb.JobsResponse;
import Job = cockroach.server.serverpb.IJobResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";
import { JobsPage, JobsPageProps } from "./jobsPage";
import { formatDuration } from "../util/duration";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// licenses/APL.txt.
import { cockroach, google } from "@cockroachlabs/crdb-protobuf-client";
import { InlineAlert } from "@cockroachlabs/ui-components";
import moment from "moment";
import moment from "moment-timezone";
import React from "react";
import { Helmet } from "react-helmet";
import { RouteComponentProps } from "react-router-dom";
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/jobs/util/duration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";
import moment from "moment";
import moment from "moment-timezone";
import React from "react";
import { TimestampToMoment } from "src/util";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// licenses/APL.txt.
import { google } from "@cockroachlabs/crdb-protobuf-client";
import { Tooltip } from "@cockroachlabs/ui-components";
import moment from "moment";
import moment from "moment-timezone";
import React from "react";
import { DATE_FORMAT_24_UTC } from "src/util/format";

Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/workspaces/cluster-ui/src/network/identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

import moment from "moment";
import moment from "moment-timezone";

export interface Identity {
nodeID: number;
Expand Down
Loading

0 comments on commit a363091

Please sign in to comment.