Skip to content

Commit 814dec5

Browse files
authored
Merge pull request #114824 from maryliag/backport23.2-112106-114743
release-23.2: server, ui: show internal stats with cluster setting enabled
2 parents 4a9ae28 + 47cf8ce commit 814dec5

File tree

15 files changed

+615
-59
lines changed

15 files changed

+615
-59
lines changed

pkg/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,7 @@ GO_TARGETS = [
21242124
"//pkg/sql/sqlstats/insights/integration:integration_test",
21252125
"//pkg/sql/sqlstats/insights:insights",
21262126
"//pkg/sql/sqlstats/insights:insights_test",
2127+
"//pkg/sql/sqlstats/persistedsqlstats/sqlstatstestutil:sqlstatstestutil",
21272128
"//pkg/sql/sqlstats/persistedsqlstats/sqlstatsutil:sqlstatsutil",
21282129
"//pkg/sql/sqlstats/persistedsqlstats/sqlstatsutil:sqlstatsutil_test",
21292130
"//pkg/sql/sqlstats/persistedsqlstats:persistedsqlstats",

pkg/server/application_api/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ go_test(
6767
"//pkg/sql/sessiondata",
6868
"//pkg/sql/sqlstats",
6969
"//pkg/sql/sqlstats/persistedsqlstats",
70+
"//pkg/sql/sqlstats/persistedsqlstats/sqlstatstestutil",
7071
"//pkg/testutils",
7172
"//pkg/testutils/diagutils",
7273
"//pkg/testutils/serverutils",

pkg/server/application_api/sql_stats_test.go

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,19 @@ import (
2222

2323
"github.com/cockroachdb/cockroach/pkg/base"
2424
"github.com/cockroachdb/cockroach/pkg/security/username"
25+
"github.com/cockroachdb/cockroach/pkg/server"
2526
"github.com/cockroachdb/cockroach/pkg/server/apiconstants"
2627
"github.com/cockroachdb/cockroach/pkg/server/serverpb"
2728
"github.com/cockroachdb/cockroach/pkg/server/srvtestutils"
29+
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
2830
"github.com/cockroachdb/cockroach/pkg/spanconfig"
2931
"github.com/cockroachdb/cockroach/pkg/sql"
3032
"github.com/cockroachdb/cockroach/pkg/sql/appstatspb"
3133
"github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"
3234
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
3335
"github.com/cockroachdb/cockroach/pkg/sql/sqlstats"
36+
"github.com/cockroachdb/cockroach/pkg/sql/sqlstats/persistedsqlstats"
37+
"github.com/cockroachdb/cockroach/pkg/sql/sqlstats/persistedsqlstats/sqlstatstestutil"
3438
"github.com/cockroachdb/cockroach/pkg/testutils"
3539
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
3640
"github.com/cockroachdb/cockroach/pkg/testutils/skip"
@@ -1129,3 +1133,273 @@ func TestUnprivilegedUserResetIndexUsageStats(t *testing.T) {
11291133

11301134
require.Contains(t, err.Error(), "requires admin privilege")
11311135
}
1136+
1137+
// TestCombinedStatementUsesCorrectSourceTable tests that requests read from
1138+
// the expected crdb_internal table given the table states. We have a lot of
1139+
// different tables that requests could potentially read from (in-memory, cached,
1140+
// system tables etc.), so we should sanity check that we are using the expected ones.
1141+
// given some simple table states.
1142+
func TestCombinedStatementUsesCorrectSourceTable(t *testing.T) {
1143+
defer leaktest.AfterTest(t)()
1144+
defer log.Scope(t).Close(t)
1145+
1146+
ctx := context.Background()
1147+
1148+
// Disable flushing sql stats so we can manually set the table states
1149+
// without worrying about unexpected stats appearing.
1150+
settings := cluster.MakeTestingClusterSettings()
1151+
statsKnobs := sqlstats.CreateTestingKnobs()
1152+
defaultMockInsertedAggTs := timeutil.Unix(1696906800, 0)
1153+
statsKnobs.StubTimeNow = func() time.Time { return defaultMockInsertedAggTs }
1154+
persistedsqlstats.SQLStatsFlushEnabled.Override(ctx, &settings.SV, false)
1155+
srv := serverutils.StartServerOnly(t, base.TestServerArgs{
1156+
Settings: settings,
1157+
Knobs: base.TestingKnobs{
1158+
SQLStatsKnobs: statsKnobs,
1159+
},
1160+
})
1161+
defer srv.Stopper().Stop(ctx)
1162+
1163+
conn := sqlutils.MakeSQLRunner(srv.ApplicationLayer().SQLConn(t))
1164+
conn.Exec(t, "SET application_name = $1", server.CrdbInternalStmtStatsCombined)
1165+
conn.Exec(t, "SET CLUSTER SETTING sql.stats.activity.flush.enabled = 'f'")
1166+
// Clear the in-memory stats so we only have the above app name.
1167+
// Then populate it with 1 query.
1168+
conn.Exec(t, "SELECT crdb_internal.reset_sql_stats()")
1169+
conn.Exec(t, "SELECT 1")
1170+
1171+
type testCase struct {
1172+
name string
1173+
tableSetupFn func() error
1174+
expectedStmtsTable string
1175+
expectedTxnsTable string
1176+
reqs []serverpb.CombinedStatementsStatsRequest
1177+
isEmpty bool
1178+
returnInternal bool
1179+
}
1180+
1181+
ie := srv.InternalExecutor().(*sql.InternalExecutor)
1182+
1183+
defaultMockOneEach := func() error {
1184+
startTs := defaultMockInsertedAggTs
1185+
stmt := sqlstatstestutil.GetRandomizedCollectedStatementStatisticsForTest(t)
1186+
stmt.ID = 1
1187+
stmt.AggregatedTs = startTs
1188+
stmt.Key.App = server.CrdbInternalStmtStatsPersisted
1189+
stmt.Key.TransactionFingerprintID = 1
1190+
require.NoError(t, sqlstatstestutil.InsertMockedIntoSystemStmtStats(ctx, ie, &stmt, 1 /* nodeId */, nil))
1191+
1192+
stmt.Key.App = server.CrdbInternalStmtStatsCached
1193+
require.NoError(t, sqlstatstestutil.InsertMockedIntoSystemStmtActivity(ctx, ie, &stmt, nil))
1194+
1195+
txn := sqlstatstestutil.GetRandomizedCollectedTransactionStatisticsForTest(t)
1196+
txn.StatementFingerprintIDs = []appstatspb.StmtFingerprintID{1}
1197+
txn.TransactionFingerprintID = 1
1198+
txn.AggregatedTs = startTs
1199+
txn.App = server.CrdbInternalTxnStatsPersisted
1200+
require.NoError(t, sqlstatstestutil.InsertMockedIntoSystemTxnStats(ctx, ie, &txn, 1, nil))
1201+
txn.App = server.CrdbInternalTxnStatsCached
1202+
require.NoError(t, sqlstatstestutil.InsertMockedIntoSystemTxnActivity(ctx, ie, &txn, nil))
1203+
1204+
return nil
1205+
}
1206+
testCases := []testCase{
1207+
{
1208+
name: "activity and persisted tables empty",
1209+
tableSetupFn: func() error { return nil },
1210+
// We should attempt to read from the in-memory tables, since
1211+
// they are the last resort.
1212+
expectedStmtsTable: server.CrdbInternalStmtStatsCombined,
1213+
expectedTxnsTable: server.CrdbInternalTxnStatsCombined,
1214+
reqs: []serverpb.CombinedStatementsStatsRequest{
1215+
{FetchMode: createTxnFetchMode(0)},
1216+
},
1217+
returnInternal: false,
1218+
},
1219+
{
1220+
name: "all tables have data in selected range",
1221+
tableSetupFn: defaultMockOneEach,
1222+
expectedStmtsTable: server.CrdbInternalStmtStatsCached,
1223+
expectedTxnsTable: server.CrdbInternalTxnStatsCached,
1224+
reqs: []serverpb.CombinedStatementsStatsRequest{
1225+
{Start: defaultMockInsertedAggTs.Unix()},
1226+
{
1227+
Start: defaultMockInsertedAggTs.Unix(),
1228+
End: defaultMockInsertedAggTs.Unix(),
1229+
},
1230+
},
1231+
returnInternal: false,
1232+
},
1233+
{
1234+
name: "all tables have data but no start range is provided",
1235+
tableSetupFn: defaultMockOneEach,
1236+
// When no date range is provided, we should default to reading from
1237+
// persisted or in-memory (whichever has data first). In this case the
1238+
// persisted table has data.
1239+
expectedStmtsTable: server.CrdbInternalStmtStatsPersisted,
1240+
expectedTxnsTable: server.CrdbInternalTxnStatsPersisted,
1241+
reqs: []serverpb.CombinedStatementsStatsRequest{
1242+
{},
1243+
{End: defaultMockInsertedAggTs.Unix()},
1244+
},
1245+
returnInternal: false,
1246+
},
1247+
{
1248+
name: "all tables have data but not in the selected range",
1249+
tableSetupFn: defaultMockOneEach,
1250+
expectedStmtsTable: server.CrdbInternalStmtStatsCombined,
1251+
expectedTxnsTable: server.CrdbInternalTxnStatsCombined,
1252+
reqs: []serverpb.CombinedStatementsStatsRequest{
1253+
{Start: defaultMockInsertedAggTs.Add(time.Hour).Unix()},
1254+
{End: defaultMockInsertedAggTs.Truncate(time.Hour * 2).Unix()},
1255+
},
1256+
isEmpty: true,
1257+
returnInternal: false,
1258+
},
1259+
{
1260+
name: "activity table has data in range with specified sort, fetchmode=txns",
1261+
tableSetupFn: defaultMockOneEach,
1262+
// For txn mode, we should not use the activity table for stmts.
1263+
expectedStmtsTable: server.CrdbInternalStmtStatsPersisted,
1264+
expectedTxnsTable: server.CrdbInternalTxnStatsCached,
1265+
// These sort options do exist on the activity table.
1266+
reqs: []serverpb.CombinedStatementsStatsRequest{
1267+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(0)},
1268+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(1)},
1269+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(2)},
1270+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(3)},
1271+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(4)},
1272+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(5)},
1273+
},
1274+
returnInternal: false,
1275+
},
1276+
{
1277+
name: "activity table has data in range with specified sort, fetchmode=stmts",
1278+
tableSetupFn: defaultMockOneEach,
1279+
expectedStmtsTable: server.CrdbInternalStmtStatsCached,
1280+
expectedTxnsTable: "",
1281+
// These sort options do exist on the activity table.
1282+
reqs: []serverpb.CombinedStatementsStatsRequest{
1283+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(0)},
1284+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(1)},
1285+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(2)},
1286+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(3)},
1287+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(4)},
1288+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(5)},
1289+
},
1290+
returnInternal: false,
1291+
},
1292+
{
1293+
name: "activity table has data in range, but selected sort is not on it, fetchmode=txns",
1294+
tableSetupFn: defaultMockOneEach,
1295+
expectedStmtsTable: server.CrdbInternalStmtStatsPersisted,
1296+
expectedTxnsTable: server.CrdbInternalTxnStatsPersisted,
1297+
// These sort options do not exist on the activity table.
1298+
reqs: []serverpb.CombinedStatementsStatsRequest{
1299+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(6)},
1300+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(7)},
1301+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(8)},
1302+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(9)},
1303+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(10)},
1304+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(11)},
1305+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(12)},
1306+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(13)},
1307+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createTxnFetchMode(14)},
1308+
},
1309+
returnInternal: false,
1310+
},
1311+
{
1312+
name: "activity table has data in range, but selected sort is not on it, fetchmode=stmts",
1313+
tableSetupFn: defaultMockOneEach,
1314+
expectedStmtsTable: server.CrdbInternalStmtStatsPersisted,
1315+
expectedTxnsTable: "",
1316+
// These sort options do not exist on the activity table.
1317+
reqs: []serverpb.CombinedStatementsStatsRequest{
1318+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(6)},
1319+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(7)},
1320+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(8)},
1321+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(9)},
1322+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(10)},
1323+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(11)},
1324+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(12)},
1325+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(13)},
1326+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(14)},
1327+
},
1328+
returnInternal: false,
1329+
},
1330+
{
1331+
name: "activity table has data in range with specified sort, fetchmode=stmts",
1332+
tableSetupFn: defaultMockOneEach,
1333+
expectedStmtsTable: server.CrdbInternalStmtStatsPersisted,
1334+
expectedTxnsTable: "",
1335+
// These sort options do exist on the activity table.
1336+
reqs: []serverpb.CombinedStatementsStatsRequest{
1337+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(0)},
1338+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(1)},
1339+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(2)},
1340+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(3)},
1341+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(4)},
1342+
{Start: defaultMockInsertedAggTs.Unix(), FetchMode: createStmtFetchMode(5)},
1343+
},
1344+
returnInternal: true,
1345+
},
1346+
}
1347+
1348+
client := srv.ApplicationLayer().GetStatusClient(t)
1349+
1350+
for _, tc := range testCases {
1351+
t.Run(tc.name, func(t *testing.T) {
1352+
require.NoError(t, tc.tableSetupFn())
1353+
1354+
defer func() {
1355+
// Reset tables.
1356+
conn.Exec(t, "SELECT crdb_internal.reset_sql_stats()")
1357+
conn.Exec(t, "SELECT crdb_internal.reset_activity_tables()")
1358+
conn.Exec(t, "SELECT 1")
1359+
}()
1360+
1361+
for _, r := range tc.reqs {
1362+
conn.Exec(t, fmt.Sprintf("SET CLUSTER SETTING sql.stats.response.show_internal.enabled=%v", tc.returnInternal))
1363+
resp, err := client.CombinedStatementStats(ctx, &r)
1364+
require.NoError(t, err)
1365+
1366+
require.Equal(t, tc.expectedStmtsTable, resp.StmtsSourceTable, "req: %v", r)
1367+
require.Equal(t, tc.expectedTxnsTable, resp.TxnsSourceTable, "req: %v", r)
1368+
1369+
if tc.isEmpty {
1370+
continue
1371+
}
1372+
1373+
require.NotZero(t, len(resp.Statements), "req: %v", r)
1374+
// Verify we used the correct queries to return data.
1375+
require.Equal(t, tc.expectedStmtsTable, resp.Statements[0].Key.KeyData.App, "req: %v", r)
1376+
if tc.expectedTxnsTable == server.CrdbInternalTxnStatsCombined {
1377+
// For the combined query, we're using in-mem data and we set the
1378+
// app name there to the in-memory stmts table.
1379+
require.Equal(t, server.CrdbInternalStmtStatsCombined, resp.Transactions[0].StatsData.App, "req: %v", r)
1380+
} else if tc.expectedTxnsTable != "" {
1381+
require.NotZero(t, len(resp.Transactions))
1382+
require.Equal(t, tc.expectedTxnsTable, resp.Transactions[0].StatsData.App, "req: %v", r)
1383+
}
1384+
}
1385+
1386+
})
1387+
}
1388+
}
1389+
1390+
func createStmtFetchMode(
1391+
sort serverpb.StatsSortOptions,
1392+
) *serverpb.CombinedStatementsStatsRequest_FetchMode {
1393+
return &serverpb.CombinedStatementsStatsRequest_FetchMode{
1394+
StatsType: serverpb.CombinedStatementsStatsRequest_StmtStatsOnly,
1395+
Sort: sort,
1396+
}
1397+
}
1398+
func createTxnFetchMode(
1399+
sort serverpb.StatsSortOptions,
1400+
) *serverpb.CombinedStatementsStatsRequest_FetchMode {
1401+
return &serverpb.CombinedStatementsStatsRequest_FetchMode{
1402+
StatsType: serverpb.CombinedStatementsStatsRequest_TxnStatsOnly,
1403+
Sort: sort,
1404+
}
1405+
}

0 commit comments

Comments
 (0)