Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ func RegisterMetrics() {
// StmtSummary
prometheus.MustRegister(StmtSummaryWindowRecordCount)
prometheus.MustRegister(StmtSummaryWindowEvictedCount)
prometheus.MustRegister(StmtSummaryEvictedLogCounter)

// Channelz
setupChannelzCollector()
Expand Down
14 changes: 14 additions & 0 deletions pkg/metrics/metrics_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ func readGaugeValue(t *testing.T, gauge prometheus.Gauge) float64 {
return m.GetGauge().GetValue()
}

func readCounterValue(t *testing.T, counter prometheus.Counter) float64 {
t.Helper()
m := &dto.Metric{}
require.NoError(t, counter.Write(m))
return m.GetCounter().GetValue()
}

func countCollectedMetrics(collector prometheus.Collector) int {
ch := make(chan prometheus.Metric, 16)
collector.Collect(ch)
Expand All @@ -53,6 +60,7 @@ func TestStmtSummaryMetricLabels(t *testing.T) {
InitStmtSummaryMetrics()
require.Equal(t, 0, countCollectedMetrics(StmtSummaryWindowRecordCount))
require.Equal(t, 0, countCollectedMetrics(StmtSummaryWindowEvictedCount))
require.Equal(t, 0, countCollectedMetrics(StmtSummaryEvictedLogCounter))

SetStmtSummaryWindowMetrics(StmtSummaryTypeV1, 3, 1)
require.Equal(t, 1, countCollectedMetrics(StmtSummaryWindowRecordCount))
Expand All @@ -65,6 +73,12 @@ func TestStmtSummaryMetricLabels(t *testing.T) {
require.Equal(t, 2, countCollectedMetrics(StmtSummaryWindowEvictedCount))
require.Equal(t, 5.0, readGaugeValue(t, StmtSummaryWindowRecordCount.WithLabelValues(StmtSummaryTypeV2)))
require.Equal(t, 2.0, readGaugeValue(t, StmtSummaryWindowEvictedCount.WithLabelValues(StmtSummaryTypeV2)))

StmtSummaryEvictedLogCounter.WithLabelValues(StmtSummaryTypeV2, StmtSummaryEvictedLogResultPersisted).Add(3)
StmtSummaryEvictedLogCounter.WithLabelValues(StmtSummaryTypeV2, StmtSummaryEvictedLogResultDropped).Inc()
require.Equal(t, 2, countCollectedMetrics(StmtSummaryEvictedLogCounter))
require.Equal(t, 3.0, readCounterValue(t, StmtSummaryEvictedLogCounter.WithLabelValues(StmtSummaryTypeV2, StmtSummaryEvictedLogResultPersisted)))
require.Equal(t, 1.0, readCounterValue(t, StmtSummaryEvictedLogCounter.WithLabelValues(StmtSummaryTypeV2, StmtSummaryEvictedLogResultDropped)))
}

func TestGrpcChannelzCollectorSingleton(t *testing.T) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/metrics/stmtsummary.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ const (
StmtSummaryTypeV1 = "v1"
// StmtSummaryTypeV2 marks metrics reported by the persistent statement summary implementation.
StmtSummaryTypeV2 = "v2"

// StmtSummaryEvictedLogResultPersisted marks evicted records submitted to the stmt log.
StmtSummaryEvictedLogResultPersisted = "persisted"
// StmtSummaryEvictedLogResultDropped marks evicted records dropped before reaching the stmt log.
StmtSummaryEvictedLogResultDropped = "dropped"
)

var (
Expand All @@ -39,6 +44,9 @@ var (
// This value resets to 0 when the window rotates.
StmtSummaryWindowEvictedCount *prometheus.GaugeVec

// StmtSummaryEvictedLogCounter counts v2 evicted-log persistence outcomes.
StmtSummaryEvictedLogCounter *prometheus.CounterVec

stmtSummaryWindowRecordCountV1 prometheus.Gauge
stmtSummaryWindowRecordCountV2 prometheus.Gauge
stmtSummaryWindowEvictedCountV1 prometheus.Gauge
Expand All @@ -65,6 +73,14 @@ func InitStmtSummaryMetrics() {
Help: "The number of LRU evictions in the current statement summary window.",
}, []string{LblType})

StmtSummaryEvictedLogCounter = metricscommon.NewCounterVec(
prometheus.CounterOpts{
Namespace: "tidb",
Subsystem: "stmt_summary",
Name: "evicted_log_total",
Help: "The number of v2 statement summary evicted-log records by result.",
}, []string{LblType, LblResult})

stmtSummaryWindowMetricsMu.Lock()
stmtSummaryWindowRecordCountV1 = nil
stmtSummaryWindowRecordCountV2 = nil
Expand Down
6 changes: 6 additions & 0 deletions pkg/sessionctx/vardef/tidb_vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,11 @@ const (
// TiDBStmtSummaryMaxSQLLength indicates the max length of displayed normalized sql and sample sql.
TiDBStmtSummaryMaxSQLLength = "tidb_stmt_summary_max_sql_length"

// TiDBStmtSummaryPersistEvicted controls whether per-record LRU evictions
// in the v2 (persistent) statement summary are persisted to the stmt log.
// Off by default because it adds log volume proportional to eviction rate.
TiDBStmtSummaryPersistEvicted = "tidb_stmt_summary_persist_evicted"

// TiDBIgnoreInlistPlanDigest enables TiDB to generate the same plan digest with SQL using different in-list arguments.
TiDBIgnoreInlistPlanDigest = "tidb_ignore_inlist_plan_digest"

Expand Down Expand Up @@ -1622,6 +1627,7 @@ const (
DefTiDBStmtSummaryHistorySize = 24
DefTiDBStmtSummaryMaxStmtCount = 3000
DefTiDBStmtSummaryMaxSQLLength = 32768
DefTiDBStmtSummaryPersistEvicted = false
DefTiDBCapturePlanBaseline = Off
DefTiDBIgnoreInlistPlanDigest = true
DefTiDBEnableIndexMerge = true
Expand Down
4 changes: 4 additions & 0 deletions pkg/sessionctx/variable/sysvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,10 @@ var defaultSysVars = []*SysVar{
SetGlobal: func(_ context.Context, s *SessionVars, val string) error {
return stmtsummaryv2.SetMaxSQLLength(TidbOptInt(val, vardef.DefTiDBStmtSummaryMaxSQLLength))
}},
{Scope: vardef.ScopeGlobal, Name: vardef.TiDBStmtSummaryPersistEvicted, Value: BoolToOnOff(vardef.DefTiDBStmtSummaryPersistEvicted), Type: vardef.TypeBool, AllowEmpty: true,
SetGlobal: func(_ context.Context, s *SessionVars, val string) error {
return stmtsummaryv2.SetPersistEvicted(TiDBOptOn(val))
}},
{Scope: vardef.ScopeGlobal, Name: vardef.TiDBCapturePlanBaseline, Value: vardef.DefTiDBCapturePlanBaseline, Type: vardef.TypeBool, AllowEmptyAll: true},
{Scope: vardef.ScopeGlobal, Name: vardef.TiDBEvolvePlanTaskMaxTime, Value: strconv.Itoa(vardef.DefTiDBEvolvePlanTaskMaxTime), Type: vardef.TypeInt, MinValue: -1, MaxValue: math.MaxInt64},
{Scope: vardef.ScopeGlobal, Name: vardef.TiDBEvolvePlanTaskStartTime, Value: vardef.DefTiDBEvolvePlanTaskStartTime, Type: vardef.TypeTime},
Expand Down
4 changes: 3 additions & 1 deletion pkg/util/stmtsummary/v2/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ go_test(
],
embed = [":stmtsummary"],
flaky = True,
shard_count = 15,
shard_count = 17,
deps = [
"//pkg/meta/model",
"//pkg/metrics",
Expand All @@ -64,5 +64,7 @@ go_test(
"@com_github_prometheus_client_model//go",
"@com_github_stretchr_testify//require",
"@org_uber_go_goleak//:goleak",
"@org_uber_go_zap//:zap",
"@org_uber_go_zap//zapcore",
],
)
46 changes: 42 additions & 4 deletions pkg/util/stmtsummary/v2/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package stmtsummary
import (
"encoding/json"
"fmt"
"strings"
"time"

"github.com/pingcap/log"
"github.com/pingcap/tidb/pkg/metrics"
"github.com/pingcap/tidb/pkg/util/logutil"
"go.uber.org/zap"
"go.uber.org/zap/buffer"
Expand Down Expand Up @@ -58,10 +60,10 @@ func (s *stmtLogStorage) persist(w *stmtWindow, end time.Time) {
r.Unlock()
}
w.evicted.Lock()
if w.evicted.other.ExecCount > 0 {
w.evicted.other.Begin = begin
w.evicted.other.End = end.Unix()
s.log(w.evicted.other)
if w.evicted.persistFallback.ExecCount > 0 {
w.evicted.persistFallback.Begin = begin
w.evicted.persistFallback.End = end.Unix()
s.log(w.evicted.persistFallback)
}
w.evicted.Unlock()
}
Expand All @@ -70,6 +72,42 @@ func (s *stmtLogStorage) sync() error {
return s.logger.Sync()
}

// logEvicted writes evicted records to the stmt log with an `"evicted":true`
// marker so downstream consumers can distinguish per-record eviction events
// from rotated-window records.
func (s *stmtLogStorage) logEvicted(records []*StmtRecord) {
Comment thread
nolouch marked this conversation as resolved.
var builder strings.Builder
persisted := 0
for _, r := range records {
b, err := json.Marshal(evictedStmtRecord{StmtRecord: r, Evicted: true})
if err != nil {
logutil.BgLogger().Warn("failed to marshal evicted statement summary", zap.Error(err))
continue
}
if builder.Len() > 0 {
builder.WriteByte('\n')
}
_, _ = builder.Write(b)
persisted++
}
if builder.Len() == 0 {
return
}
s.logger.Info(builder.String())
metrics.StmtSummaryEvictedLogCounter.WithLabelValues(
metrics.StmtSummaryTypeV2,
metrics.StmtSummaryEvictedLogResultPersisted,
).Add(float64(persisted))
}

// evictedStmtRecord embeds *StmtRecord and adds an "evicted" JSON tag.
// Keeping the embedded pointer means the JSON field order matches StmtRecord
// and parsers tolerant of the extra field work unchanged.
type evictedStmtRecord struct {
*StmtRecord
Evicted bool `json:"evicted"`
}

func (s *stmtLogStorage) log(r *StmtRecord) {
b, err := json.Marshal(r)
if err != nil {
Expand Down
10 changes: 5 additions & 5 deletions pkg/util/stmtsummary/v2/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,17 @@ func (r *MemReader) Rows() [][]types.Datum {
func() {
evicted.Lock()
defer evicted.Unlock()
if evicted.other.ExecCount == 0 {
if evicted.inMemoryAggregate.ExecCount == 0 {
return
}
if !r.checker.hasPrivilege(evicted.other.AuthUsers) {
if !r.checker.hasPrivilege(evicted.inMemoryAggregate.AuthUsers) {
return
}
evicted.other.Begin = w.begin.Unix()
evicted.other.End = end
evicted.inMemoryAggregate.Begin = w.begin.Unix()
evicted.inMemoryAggregate.End = end
row := make([]types.Datum, len(r.columnFactories))
for i, factory := range r.columnFactories {
row[i] = types.NewDatum(factory(r, evicted.other))
row[i] = types.NewDatum(factory(r, evicted.inMemoryAggregate))
}
rows = append(rows, row)
}()
Expand Down
Loading
Loading