Skip to content

Commit

Permalink
server: add more info the combined statement endpoint
Browse files Browse the repository at this point in the history
Previously, it was hard to know which tables were
used to populate the SQL Activity, making debug for it
complicated.
This commit adds extra information to the
`combinedstmts` to help:
- olderAggregatedTsReturned
- stmtsSourceTable
- txnsSourceTable

Returning a value for `olderAggregatedTsReturned` will
also allow us to show proper warning when the older
timestamp doesn't match the start date of the selected
time period on the Search Criteria.

Part Of cockroachdb#108989

Release note: None
  • Loading branch information
maryliag committed Aug 20, 2023
1 parent f3c92a0 commit 29fb2c6
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 25 deletions.
6 changes: 6 additions & 0 deletions docs/generated/http/full.md
Original file line number Diff line number Diff line change
Expand Up @@ -4102,6 +4102,9 @@ tenant pods.
| transactions | [StatementsResponse.ExtendedCollectedTransactionStatistics](#cockroach.server.serverpb.StatementsResponse-cockroach.server.serverpb.StatementsResponse.ExtendedCollectedTransactionStatistics) | repeated | Transactions is transaction-level statistics for the collection of statements in this response. | [reserved](#support-status) |
| stmts_total_runtime_secs | [float](#cockroach.server.serverpb.StatementsResponse-float) | | | [reserved](#support-status) |
| txns_total_runtime_secs | [float](#cockroach.server.serverpb.StatementsResponse-float) | | | [reserved](#support-status) |
| oldest_aggregated_ts_returned | [google.protobuf.Timestamp](#cockroach.server.serverpb.StatementsResponse-google.protobuf.Timestamp) | | OldestAggregatedTsReturned is the timestamp of the oldest entry returned, or null if there is no data returned. | [reserved](#support-status) |
| stmts_source_table | [string](#cockroach.server.serverpb.StatementsResponse-string) | | StmtsSourceTable returns the table used to return the statements data. | [reserved](#support-status) |
| txns_source_table | [string](#cockroach.server.serverpb.StatementsResponse-string) | | TxnsSourceTable returns the table used to return the transactions data. | [reserved](#support-status) |



Expand Down Expand Up @@ -4214,6 +4217,9 @@ Support status: [reserved](#support-status)
| transactions | [StatementsResponse.ExtendedCollectedTransactionStatistics](#cockroach.server.serverpb.StatementsResponse-cockroach.server.serverpb.StatementsResponse.ExtendedCollectedTransactionStatistics) | repeated | Transactions is transaction-level statistics for the collection of statements in this response. | [reserved](#support-status) |
| stmts_total_runtime_secs | [float](#cockroach.server.serverpb.StatementsResponse-float) | | | [reserved](#support-status) |
| txns_total_runtime_secs | [float](#cockroach.server.serverpb.StatementsResponse-float) | | | [reserved](#support-status) |
| oldest_aggregated_ts_returned | [google.protobuf.Timestamp](#cockroach.server.serverpb.StatementsResponse-google.protobuf.Timestamp) | | OldestAggregatedTsReturned is the timestamp of the oldest entry returned, or null if there is no data returned. | [reserved](#support-status) |
| stmts_source_table | [string](#cockroach.server.serverpb.StatementsResponse-string) | | StmtsSourceTable returns the table used to return the statements data. | [reserved](#support-status) |
| txns_source_table | [string](#cockroach.server.serverpb.StatementsResponse-string) | | TxnsSourceTable returns the table used to return the transactions data. | [reserved](#support-status) |



Expand Down
131 changes: 106 additions & 25 deletions pkg/server/combined_statement_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,29 @@ func getCombinedStatementStats(
return nil, srverrors.ServerError(ctx, err)
}

stmtsRunTime, txnsRunTime, err := getTotalRuntimeSecs(
stmtsRunTime, txnsRunTime, oldestDate, stmtSourceTable, txnSourceTable, err := getSourceStatsInfo(
ctx,
req,
ie,
testingKnobs,
activityHasAllData,
tableSuffix)
tableSuffix,
showInternal)

if err != nil {
return nil, srverrors.ServerError(ctx, err)
}

response := &serverpb.StatementsResponse{
Statements: statements,
Transactions: transactions,
LastReset: statsProvider.GetLastReset(),
InternalAppNamePrefix: catconstants.InternalAppNamePrefix,
StmtsTotalRuntimeSecs: stmtsRunTime,
TxnsTotalRuntimeSecs: txnsRunTime,
Statements: statements,
Transactions: transactions,
LastReset: statsProvider.GetLastReset(),
InternalAppNamePrefix: catconstants.InternalAppNamePrefix,
StmtsTotalRuntimeSecs: stmtsRunTime,
TxnsTotalRuntimeSecs: txnsRunTime,
OldestAggregatedTsReturned: oldestDate,
StmtsSourceTable: stmtSourceTable,
TxnsSourceTable: txnSourceTable,
}

return response, nil
Expand Down Expand Up @@ -249,14 +253,28 @@ FROM crdb_internal.statement_activity
return hasData, nil
}

func getTotalRuntimeSecs(
// getSourceStatsInfo returns information about the stats returned:
// - the total runtime (in seconds) on the selected period for
// statement and transactions
// - the oldest aggregated_ts we have data for on the
// selected period
// - which table the data was retrieve from
func getSourceStatsInfo(
ctx context.Context,
req *serverpb.CombinedStatementsStatsRequest,
ie *sql.InternalExecutor,
testingKnobs *sqlstats.TestingKnobs,
activityTableHasAllData bool,
tableSuffix string,
) (stmtsRuntime float32, txnsRuntime float32, err error) {
showInternal bool,
) (
stmtsRuntime float32,
txnsRuntime float32,
oldestDate *time.Time,
stmtSourceTable string,
txnSourceTable string,
err error,
) {
var buffer strings.Builder
buffer.WriteString(testingKnobs.GetAOSTClause())
var args []interface{}
Expand All @@ -277,6 +295,15 @@ func getTotalRuntimeSecs(

whereClause := buffer.String()

if !showInternal {
// Filter out internal statements by app name.
buffer.WriteString(fmt.Sprintf(
" AND app_name NOT LIKE '%s%%' AND app_name NOT LIKE '%s%%'",
catconstants.InternalAppNamePrefix,
catconstants.DelegatedAppNamePrefix))
}
whereClauseOldestDate := buffer.String()

getRuntime := func(table string) (float32, error) {
it, err := ie.QueryIteratorEx(
ctx,
Expand All @@ -300,12 +327,12 @@ FROM %s %s`, table, whereClause), args...)
return 0, err
}
if !ok {
return 0, errors.New("expected one row but got none on getTotalRuntimeSecs")
return 0, errors.New("expected one row but got none on getSourceStatsInfo.getRuntime")
}

var row tree.Datums
if row = it.Cur(); row == nil {
return 0, errors.New("unexpected null row on getTotalRuntimeSecs")
return 0, errors.New("unexpected null row on getSourceStatsInfo.getRuntime")
}

defer func() {
Expand All @@ -315,57 +342,111 @@ FROM %s %s`, table, whereClause), args...)
return float32(tree.MustBeDFloat(row[0])), nil
}

getOldestDate := func(table string) (*time.Time, error) {
it, err := ie.QueryIteratorEx(
ctx,
fmt.Sprintf(`console-combined-stmts-%s-oldest_date`, table),
nil,
sessiondata.NodeUserSessionDataOverride,
fmt.Sprintf(`
SELECT min(aggregated_ts)
FROM %s %s`, table, whereClauseOldestDate), args...)

if err != nil {
return nil, err
}
ok, err := it.Next(ctx)
if err != nil {
return nil, err
}
if !ok {
return nil, errors.New("expected one row but got none on getSourceStatsInfo.getOldestDate")
}

var row tree.Datums
if row = it.Cur(); row == nil {
return nil, nil
}
defer func() {
err = closeIterator(it, err)
}()

if row[0] == tree.DNull {
return nil, nil
}
oldestTs := tree.MustBeDTimestampTZ(row[0]).Time
return &oldestTs, nil
}

stmtsRuntime = 0
if req.FetchMode == nil || req.FetchMode.StatsType != serverpb.CombinedStatementsStatsRequest_TxnStatsOnly {
if activityTableHasAllData {
stmtsRuntime, err = getRuntime("crdb_internal.statement_activity")
stmtSourceTable = "crdb_internal.statement_activity"
stmtsRuntime, err = getRuntime(stmtSourceTable)
if err != nil {
return 0, 0, nil, stmtSourceTable, "", err
}
oldestDate, err = getOldestDate(stmtSourceTable)
if err != nil {
return 0, 0, err
return stmtsRuntime, 0, nil, stmtSourceTable, "", err
}
}
// If there are no results from the activity table, retrieve the data from the persisted table.
if stmtsRuntime == 0 {
stmtsRuntime, err = getRuntime("crdb_internal.statement_statistics_persisted" + tableSuffix)
stmtSourceTable = "crdb_internal.statement_statistics_persisted" + tableSuffix
stmtsRuntime, err = getRuntime(stmtSourceTable)
if err != nil {
return 0, 0, err
return 0, 0, nil, stmtSourceTable, "", err
}
oldestDate, err = getOldestDate(stmtSourceTable)
if err != nil {
return stmtsRuntime, 0, nil, stmtSourceTable, "", err
}
}
// If there are no results from the persisted table, retrieve the data from the combined view
// with data in-memory.
if stmtsRuntime == 0 {
stmtsRuntime, err = getRuntime("crdb_internal.statement_statistics")
stmtSourceTable = "crdb_internal.statement_statistics"
stmtsRuntime, err = getRuntime(stmtSourceTable)
if err != nil {
return 0, 0, nil, stmtSourceTable, "", err
}
oldestDate, err = getOldestDate(stmtSourceTable)
if err != nil {
return 0, 0, err
return stmtsRuntime, 0, nil, stmtSourceTable, "", err
}
}
}

txnsRuntime = 0
if req.FetchMode == nil || req.FetchMode.StatsType != serverpb.CombinedStatementsStatsRequest_StmtStatsOnly {
if activityTableHasAllData {
txnsRuntime, err = getRuntime("crdb_internal.transaction_activity")
txnSourceTable = "crdb_internal.transaction_activity"
txnsRuntime, err = getRuntime(txnSourceTable)
if err != nil {
return 0, 0, err
return 0, 0, nil, stmtSourceTable, txnSourceTable, err
}
}
// If there are no results from the activity table, retrieve the data from the persisted table.
if txnsRuntime == 0 {
txnsRuntime, err = getRuntime("crdb_internal.transaction_statistics_persisted" + tableSuffix)
txnSourceTable = "crdb_internal.transaction_statistics_persisted" + tableSuffix
txnsRuntime, err = getRuntime(txnSourceTable)
if err != nil {
return 0, 0, err
return 0, 0, nil, stmtSourceTable, txnSourceTable, err
}
}
// If there are no results from the persisted table, retrieve the data from the combined view
// with data in-memory.
if txnsRuntime == 0 {
txnsRuntime, err = getRuntime("crdb_internal.transaction_statistics")
txnSourceTable = "crdb_internal.transaction_statistics"
txnsRuntime, err = getRuntime(txnSourceTable)
if err != nil {
return 0, 0, err
return 0, 0, nil, stmtSourceTable, txnSourceTable, err
}
}
}

return stmtsRuntime, txnsRuntime, err
return stmtsRuntime, txnsRuntime, oldestDate, stmtSourceTable, txnSourceTable, err
}

// Return true is the limit request is within the limit
Expand Down
10 changes: 10 additions & 0 deletions pkg/server/serverpb/status.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,16 @@ message StatementsResponse {
float stmts_total_runtime_secs = 6;

float txns_total_runtime_secs = 7;

// OldestAggregatedTsReturned is the timestamp of the oldest entry returned,
// or null if there is no data returned.
google.protobuf.Timestamp oldest_aggregated_ts_returned = 8 [(gogoproto.stdtime) = true];

// StmtsSourceTable returns the table used to return the statements data.
string stmts_source_table = 9;

// TxnsSourceTable returns the table used to return the transactions data.
string txns_source_table = 10;
}

enum StatsSortOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ export const transaction = {
export const transactionDetailsData: StatementsResponse = {
stmts_total_runtime_secs: 1,
txns_total_runtime_secs: 1,
oldest_aggregated_ts_returned: timestamp,
stmts_source_table: "crdb_internal.statement_activity",
txns_source_table: "crdb_internal.transaction_activity",
statements: [
{
key: {
Expand Down

0 comments on commit 29fb2c6

Please sign in to comment.