Skip to content

Commit b27094b

Browse files
craig[bot]fantapopyuzefovich
committed
107718: ui: add an overridable logger r=fantapop a=fantapop A setLogger and getLogger method are added to cluster-ui so that the cockroach cloud console can use them to pass a custom logger which embellishes each log invocation with the cluster version and cluster id. CC-24092 Release Note: none 107822: geo: fix panic in GeometryToEncodedPolyline for GeometryCollection r=yuzefovich a=yuzefovich This is not supported in Postgres and results in an error, but we previously would crash. Now fixed. Fixes: cockroachdb#107773. Release note (bug fix): CockroachDB would previously crash when evaluating `st_asencodedpolyline` builtin on 'GeometryCollection' geometry type. The bug was introduced before 22.1 and is now fixed. Co-authored-by: Christopher Fitzner <[email protected]> Co-authored-by: Yahor Yuzefovich <[email protected]>
3 parents 45cd1c9 + 9d3ecc3 + f4cd3ce commit b27094b

File tree

11 files changed

+128
-11
lines changed

11 files changed

+128
-11
lines changed

pkg/geo/parse.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ func GeometryToEncodedPolyline(g Geometry, p int) (string, error) {
264264
if gt.SRID() != 4326 {
265265
return "", pgerror.Newf(pgcode.InvalidParameterValue, "only SRID 4326 is supported")
266266
}
267+
if _, ok := gt.(*geom.GeometryCollection); ok {
268+
return "", pgerror.Newf(pgcode.InvalidParameterValue, "'GeometryCollection' geometry type not supported")
269+
}
267270

268271
return encodePolylinePoints(gt.FlatCoords(), p), nil
269272
}

pkg/sql/logictest/testdata/logic_test/geospatial_regression

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ CREATE TABLE regression_81609 (
77
statement error cannot index a geometry with NaN coordinates
88
INSERT INTO regression_81609 SELECT st_rotatex('0105000000060000000102000000020000002CF565DB1790F041C2509EC57231F2411C1E119D614AE7C166AFF2D39B030142010200000003000000809745B2972CF84160399714F897E241E0D03302F1C6D6410EFC89BE9FE20042F83C7FD5C4ACD6411854CBFDFF42DE41010200000004000000C4A695BE1FC2FD411CE9BCE66C42D8C142F59F55FD7800424C0D1238165FE041A07574B08DC0D94170D034F5A969EB41D843A641FF49E741B6F0864FF80E0242010200000004000000781D60294113F2412C338441624C02C2100451CE196BED41525C0281389BEEC11430818C69A2EF415C09A4FD752D024200E4B02D00CB9341C047BBFE74DDE44101020000000400000040B0B6B74C96A0C162D23CFAACB8E7C11CD943F294E9E5C187C18248646102C2709F7E29F32AC4C160D1A56EC799FAC1607737DC4662E941ADC9125B944FF6C1010200000004000000F097AF975517F441714AF1717A16F0C15442BA391710F841BEBE416B6780F241E01C9C5F7602B6413CC620A0C9C3E14140E714D68300E2C1A0C4038270B4BAC1':::GEOMETRY::GEOMETRY, '-Inf':::FLOAT8)::GEOMETRY;
99

10+
statement error 'GeometryCollection' geometry type not supported
11+
SELECT st_asencodedpolyline(geomfromewkb(('01070000A0E61000000300000001060000A0E6100000040000000103000080010000000B0000006F9AF3F7D81863C057397A0B3ACD42C006ED79D13D2DF24130E1CBF62A4A45C01B6DC0D279F452C022F8C672D2C1F9C140DB9D23050141C0B53FBA6E396656C0C0A1842E2B53EC413A8DC94C568D61401BEF0352091651C05C681DE175D2FD41A048C859DF7C5440C00E327AC97FF63F68BBA8144D0EF8416E6042F340DD6040805791CE56602740DC6C3922676401C29C6D4009B1334E40625E855D7A7E5140D4241F7D86D2D5C14B1E4BCA077A58C07806BF9D4D084D4074E74BE4DCAA00C2C11D020045A051C0D81F8E3DD0AE3740B8315FF7F63AF4C1BAD97494BA9860C07411EFAF0A6C3D4038E26DE7A194F4C16F9AF3F7D81863C057397A0B3ACD42C006ED79D13D2DF2410103000080010000000B000000610D90AE22A55FC0B8265672F7562940CE3E91EB7A320042CC96C05617B649C085229B1A09E153C0D84FA7998764EB4190FEB5A7C71B2DC03EBBCB6B588F4DC02891E1ED4A7DE6417C0F7BBC14C75840E08D4D210E2F21C04180E453EDEDFFC112E57185B2435240F0D20FC2D7C11640F8BF2E3AB98DD2C1D0A9A94D6EA14140FCABD1E5BF074B400010C2F75AA16F4166BC301BE6FB55C002F9F182DE3D53400038B551BC0495C199463681FA6E5CC0184D3E0AE179554030323F0F2525F4415791FBE04FEA61C0361E8733C77A5240C84AEBEAD466EEC1D5012A75E04F63C0A8BF403F623D4240182CFEFA9071E0C1610D90AE22A55FC0B8265672F7562940CE3E91EB7A3200420103000080010000000C000000004CADA6B302E0BF3EE5FA281ACE3BC0E051ABD6580901429B65A22CCBDC53C003DEBC27260E4AC07E45691D3E7AF541408E6FAB9A1008C016E33E2631FD40C0EEF80F0FF3E8F341A8C5EAA8B0C836409E85B8193CE952C0F4448FFF9B31F24190F9A9FCD2AC604004F99C51ED4356C0903A1F652902D4C1C01B737BD389554080315427550738C05C51AE075475F64124F6F92382235C40148AB5FED33D38C048960D3AC6D7E8412C2E310EABA5514058EA10C427562EC0A82D4D1A69D7FE41621FC77070C26540FE84B78FE5BE51400962385E53FAFEC1483899F770B14DC020BD4BBBAB604D401C08306EA143E84140337962764325C0002F089A1DF3F83FAC9B66F32C2BE841004CADA6B302E0BF3EE5FA281ACE3BC0E051ABD65809014201030000800100000006000000D03FF366A2C95C40E59BFCECDD7553C0D028B038BB63D041A40AEF5CB0195840006FB928107F084020CA0A39A4AED34100F09D4126336140E8AC65DAC4954C4024406D4040D1EE41F04B3F3DA6C75740106594C0ADCE4440A498B6372039FD4155D08A1E777452C084CC004170E949409C87DF53EB9AFDC1D03FF366A2C95C40E59BFCECDD7553C0D028B038BB63D04101020000A0E61000000200000074F55D784E5F50408F7DE14351CD41C0FCCCE7B1B166F541583C392FCD7554409022EAF3EFCC39C03CDE1C0E29A7EB4101040000A0E6100000060000000101000080E8801DFC8A2130C04401B4AE182F50C0BC13340EB7E2E1C1010100008010DC3F808D824D406C9927CDAE5144409A464D93BBD7F94101010000806F0682A50FE253C030E1964D47F74BC00E752ECB60B0F441010100008014F5242FC2C444C01257DB8E51FA51404449E2FB7D2AFFC1010100008069945BA1FD2E50C0501CA74B7A661C40CB83CB9A4894F1C10101000080C0BBBC345A4B51C0E08F6EBB2F250E400681A78F4FFCF741'::GEOGRAPHY)::BYTEA)::GEOMETRY);

pkg/ui/workspaces/cluster-ui/src/api/contentionApi.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from "./sqlApi";
2020
import { ContentionDetails } from "src/insights";
2121
import moment from "moment-timezone";
22+
import { getLogger } from "../util";
2223

2324
export type ContentionFilters = {
2425
waitingTxnID?: string;
@@ -62,8 +63,9 @@ export async function getContentionDetailsApi(
6263
if (sqlResultsAreEmpty(result)) {
6364
if (result.error) {
6465
// We don't return an error if it failed to retrieve the contention information.
65-
console.error(
66-
`Insights encounter an error while retrieving contention information: ${result.error}`,
66+
getLogger().error(
67+
"Insights encounter an error while retrieving contention information.",
68+
{ resultError: result.error },
6769
);
6870
}
6971
return formatApiResult<ContentionDetails[]>(

pkg/ui/workspaces/cluster-ui/src/api/databaseDetailsApi.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { Format, Identifier, QualifiedIdentifier } from "./safesql";
2626
import moment from "moment-timezone";
2727
import { fromHexString, withTimeout } from "./util";
2828
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";
29+
import { getLogger } from "../util";
2930

3031
const { ZoneConfig } = cockroach.config.zonepb;
3132
const { ZoneConfigurationLevel } = cockroach.server.serverpb;
@@ -264,8 +265,10 @@ const getDatabaseZoneConfig: DatabaseDetailsQuery<DatabaseZoneConfigRow> = {
264265
);
265266
resp.zoneConfigResp.zone_config_level = ZoneConfigurationLevel.DATABASE;
266267
} catch (e) {
267-
console.error(
268+
getLogger().error(
268269
`Database Details API - encountered an error decoding zone config string: ${zoneConfigHexString}`,
270+
/* additional context */ undefined,
271+
e,
269272
);
270273
// Catch and assign the error if we encounter one decoding.
271274
resp.zoneConfigResp.error = e;

pkg/ui/workspaces/cluster-ui/src/api/tableDetailsApi.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { fromHexString, withTimeout } from "./util";
2626
import { Format, Identifier, Join, SQL } from "./safesql";
2727
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";
2828
import { IndexUsageStatistic, recommendDropUnusedIndex } from "../insights";
29+
import { getLogger } from "../util";
2930

3031
const { ZoneConfig } = cockroach.config.zonepb;
3132
const { ZoneConfigurationLevel } = cockroach.server.serverpb;
@@ -314,8 +315,10 @@ const getTableZoneConfig: TableDetailsQuery<TableZoneConfigRow> = {
314315
);
315316
resp.zoneConfigResp.zone_config_level = configLevel;
316317
} catch (e) {
317-
console.error(
318+
getLogger().error(
318319
`Table Details API - encountered an error decoding zone config string: ${hexString}`,
320+
/* additional context */ undefined,
321+
e,
319322
);
320323
// Catch and assign the error if we encounter one decoding.
321324
resp.zoneConfigResp.error = e;

pkg/ui/workspaces/cluster-ui/src/loading/loading.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
Spinner,
1818
InlineAlertIntent,
1919
} from "@cockroachlabs/ui-components";
20-
import { adminUIAccess, isForbiddenRequestError } from "src/util";
20+
import { adminUIAccess, getLogger, isForbiddenRequestError } from "src/util";
2121
import styles from "./loading.module.scss";
2222
import { Anchor } from "../anchor";
2323

@@ -68,7 +68,14 @@ export const Loading: React.FC<LoadingProps> = props => {
6868
// Check for `error` before `loading`, since tests for `loading` often return
6969
// true even if CachedDataReducer has an error and is no longer really "loading".
7070
if (errors) {
71-
console.error(`Error Loading ${props.page}: ${errors}`);
71+
getLogger().error(
72+
errors.length === 1
73+
? `Error Loading ${props.page}`
74+
: `Multiple errors seen Loading ${props.page}: ${errors}`,
75+
/* additional context */ undefined,
76+
errors[0],
77+
);
78+
7279
// - map Error to InlineAlert props. RestrictedPermissions handled as "info" message;
7380
// - group errors by intend to show separate alerts per intent.
7481
const errorAlerts = chain(errors)

pkg/ui/workspaces/cluster-ui/src/store/uiConfig/uiConfig.sagas.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { getUserSQLRoles } from "../../api/userApi";
1414
import { CACHE_INVALIDATION_PERIOD, throttleWithReset } from "../utils";
1515
import { rootActions } from "../reducers";
1616
import { cockroach } from "@cockroachlabs/crdb-protobuf-client";
17+
import { getLogger } from "../../util";
1718

1819
export function* refreshUserSQLRolesSaga(): any {
1920
yield put(actions.requestUserSQLRoles());
@@ -26,7 +27,7 @@ export function* requestUserSQLRolesSaga(): any {
2627
);
2728
yield put(actions.receivedUserSQLRoles(result.roles));
2829
} catch (e) {
29-
console.warn(e.message);
30+
getLogger().warn(e.message, /* additional context */ undefined, e);
3031
}
3132
}
3233

pkg/ui/workspaces/cluster-ui/src/timeScaleDropdown/timeScaleDropdown.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { defaultTimeScaleOptions, findClosestTimeScale } from "./utils";
2626

2727
import styles from "./timeScale.module.scss";
2828
import { TimezoneContext } from "../contexts";
29-
import { FormatWithTimezone } from "../util";
29+
import { FormatWithTimezone, getLogger } from "../util";
3030

3131
const cx = classNames.bind(styles);
3232

@@ -186,7 +186,7 @@ export const TimeScaleDropdown: React.FC<TimeScaleDropdownProps> = ({
186186
isMoving = true;
187187
break;
188188
default:
189-
console.error("Unknown direction: ", direction);
189+
getLogger().error("Unknown direction: ", direction);
190190
}
191191

192192
// If the timescale extends into the future then fallback to a default

pkg/ui/workspaces/cluster-ui/src/util/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export * from "./docs";
1717
export * from "./fixLong";
1818
export * from "./format";
1919
export * from "./formatDate";
20+
export * from "./logger";
2021
export * from "./requestError";
2122
export * from "./sql/summarize";
2223
export * from "./query";
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2023 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the Business Source License
4+
// included in the file licenses/BSL.txt.
5+
//
6+
// As of the Change Date specified in that file, in accordance with
7+
// the Business Source License, use of this software will be governed
8+
// by the Apache License, Version 2.0, included in the file
9+
// licenses/APL.txt.
10+
11+
type JSONValue =
12+
| null
13+
| boolean
14+
| number
15+
| string
16+
| JSONValue[]
17+
| { [key: string]: JSONValue };
18+
19+
interface Logger {
20+
/**
21+
* Logs a message with additional context and an optional error at debug
22+
* level.
23+
* @param msg - the string message to log
24+
* @param context - additional structured context to include with the
25+
* message when shipped to a remote service
26+
* @param error - a possible JS Error to include with the message when
27+
* shipped to a remote service. Typed as unknown for convenience but
28+
* anything passed here which is not instanceof Error will not be attached.
29+
*/
30+
debug(
31+
msg: string,
32+
context?: Record<string, JSONValue>,
33+
error?: unknown,
34+
): void;
35+
/**
36+
* Logs a message with additional context and an optional error at info
37+
* level.
38+
* @param msg - the string message to log
39+
* @param context - additional structured context to include with the
40+
* message when shipped to a remote service
41+
* @param error - a possible JS Error to include with the message when
42+
* shipped to a remote service. Typed as unknown for convenience but
43+
* anything passed here which is not instanceof Error will not be attached.
44+
*/
45+
info(msg: string, context?: Record<string, JSONValue>, error?: unknown): void;
46+
/**
47+
* Logs a message with additional context and an optional error at warn
48+
* level.
49+
* @param msg - the string message to log
50+
* @param context - additional structured context to include with the
51+
* message when shipped to a remote service
52+
* @param error - a possible JS Error to include with the message when
53+
* shipped to a remote service. Typed as unknown for convenience but
54+
* anything passed here which is not instanceof Error will not be attached.
55+
*/
56+
warn(msg: string, context?: Record<string, JSONValue>, error?: unknown): void;
57+
/**
58+
* Logs a message with additional context and an optional error at error
59+
* level.
60+
* @param msg - the string message to log
61+
* @param context - additional structured context to include with the
62+
* message when shipped to a remote service
63+
* @param error - a possible JS Error to include with the message when
64+
* shipped to a remote service. Typed as unknown for convenience but
65+
* anything passed here which is not instanceof Error will not be attached.
66+
*/
67+
error(
68+
msg: string,
69+
context?: Record<string, JSONValue>,
70+
error?: unknown,
71+
): void;
72+
}
73+
74+
let logger: Logger = console;
75+
76+
/**
77+
* Sets the logger returned by {@link getLogger}. It was added to allow
78+
* cockroach cloud to pass in a custom logger which attaches additional metadata
79+
* to each call and sends errors up to datadog.
80+
* @param newLogger the Logger to set
81+
*/
82+
export function setLogger(newLogger: Logger) {
83+
logger = newLogger;
84+
}
85+
86+
/**
87+
* @returns the most recent logger set by {@link setLogger}, or console if one was never set.
88+
*/
89+
export function getLogger(): Logger {
90+
return logger;
91+
}

0 commit comments

Comments
 (0)