Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logutil, *: implement log desensitization #3011

Merged
merged 15 commits into from
Sep 24, 2020
63 changes: 63 additions & 0 deletions pkg/logutil/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"runtime"
"strings"
"sync"
"sync/atomic"

"github.com/coreos/pkg/capnslog"
zaplog "github.com/pingcap/log"
Expand Down Expand Up @@ -292,3 +293,65 @@ func LogPanic() {
zaplog.Fatal("panic", zap.Reflect("recover", e))
}
}

var (
enabledRedactLog atomic.Value
Yisaer marked this conversation as resolved.
Show resolved Hide resolved
)

func init() {
SetRedactLog(false)
}

// IsRedactLogEnabled indicates whether the log desensitization is enabled
func IsRedactLogEnabled() bool {
return enabledRedactLog.Load().(bool)
}

// SetRedactLog sets enabledRedactLog
func SetRedactLog(enabled bool) {
enabledRedactLog.Store(enabled)
}

// RedactBytes receives []byte argument and return omitted information if redact log enabled
func RedactBytes(arg []byte) []byte {
return redactArgIfNeeded(arg).([]byte)
}

// RedactString receives string argument and return omitted information if redact log enabled
func RedactString(arg string) string {
return redactArgIfNeeded(arg).(string)
}

// RedactStringer receives stringer argument and return omitted information if redact log enabled
func RedactStringer(arg fmt.Stringer) fmt.Stringer {
return redactArgIfNeeded(arg).(fmt.Stringer)
}

type stringer struct {
s string
Yisaer marked this conversation as resolved.
Show resolved Hide resolved
}

// String implement fmt.Stringer
func (s *stringer) String() string {
return s.s
}

// redactArgIfNeeded will omit the argument if RedactLog is enabled
func redactArgIfNeeded(arg interface{}) interface{} {
if IsRedactLogEnabled() {
if arg == nil {
return nil
}
switch arg.(type) {
case []byte:
return []byte("?")
case string:
return "?"
case fmt.Stringer:
return &stringer{s: "?"}
default:
return nil
}
}
return arg
}
51 changes: 51 additions & 0 deletions pkg/logutil/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,54 @@ func (s *testLogSuite) TestFileLog(c *C) {
c.Assert(InitFileLog(&zaplog.FileLogConfig{Filename: "/tmp"}), NotNil)
c.Assert(InitFileLog(&zaplog.FileLogConfig{Filename: "/tmp/test_file_log", MaxSize: 0}), IsNil)
}

func (s *testLogSuite) TestRedactLog(c *C) {
testcases := []struct {
name string
arg interface{}
enableRedactLog bool
expect interface{}
}{
{
name: "string arg, enable redact",
arg: "foo",
enableRedactLog: true,
expect: "?",
},
{
name: "string arg",
arg: "foo",
enableRedactLog: false,
expect: "foo",
},
{
name: "[]byte arg, enable redact",
arg: []byte("foo"),
enableRedactLog: true,
expect: []byte("?"),
},
{
name: "[]byte arg",
arg: []byte("foo"),
enableRedactLog: false,
expect: []byte("foo"),
},
{
name: "nil",
arg: nil,
enableRedactLog: true,
expect: nil,
},
}

for _, testcase := range testcases {
c.Log(testcase.name)
SetRedactLog(testcase.enableRedactLog)
r := redactArgIfNeeded(testcase.arg)
if testcase.expect == nil {
c.Assert(r, IsNil)
continue
}
c.Assert(r, DeepEquals, testcase.expect)
}
}
8 changes: 4 additions & 4 deletions server/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ func (c *RaftCluster) processRegionHeartbeat(region *core.RegionInfo) error {
if origin == nil {
log.Debug("insert new region",
zap.Uint64("region-id", region.GetID()),
zap.Stringer("meta-region", core.RegionToHexMeta(region.GetMeta())),
zap.Stringer("meta-region", logutil.RedactStringer(core.RegionToHexMeta(region.GetMeta()))),
)
saveKV, saveCache, isNew = true, true, true
} else {
Expand All @@ -554,7 +554,7 @@ func (c *RaftCluster) processRegionHeartbeat(region *core.RegionInfo) error {
if r.GetVersion() > o.GetVersion() {
log.Info("region Version changed",
zap.Uint64("region-id", region.GetID()),
zap.String("detail", core.DiffRegionKeyInfo(origin, region)),
zap.String("detail", logutil.RedactString(core.DiffRegionKeyInfo(origin, region))),
zap.Uint64("old-version", o.GetVersion()),
zap.Uint64("new-version", r.GetVersion()),
)
Expand Down Expand Up @@ -634,7 +634,7 @@ func (c *RaftCluster) processRegionHeartbeat(region *core.RegionInfo) error {
if err := c.storage.DeleteRegion(item.GetMeta()); err != nil {
log.Error("failed to delete region from storage",
zap.Uint64("region-id", item.GetID()),
zap.Stringer("region-meta", core.RegionToHexMeta(item.GetMeta())),
zap.Stringer("region-meta", logutil.RedactStringer(core.RegionToHexMeta(item.GetMeta()))),
errs.ZapError(err))
}
}
Expand Down Expand Up @@ -686,7 +686,7 @@ func (c *RaftCluster) processRegionHeartbeat(region *core.RegionInfo) error {
// after restart. Here we only log the error then go on updating cache.
log.Error("failed to save region to storage",
zap.Uint64("region-id", region.GetID()),
zap.Stringer("region-meta", core.RegionToHexMeta(region.GetMeta())),
zap.Stringer("region-meta", logutil.RedactStringer(core.RegionToHexMeta(region.GetMeta()))),
errs.ZapError(err))
}
regionEventCounter.WithLabelValues("update_kv").Inc()
Expand Down
14 changes: 8 additions & 6 deletions server/cluster/cluster_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/pingcap/kvproto/pkg/pdpb"
"github.com/pingcap/log"
"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/logutil"
"github.com/tikv/pd/server/core"
"github.com/tikv/pd/server/schedule"
"github.com/tikv/pd/server/versioninfo"
Expand All @@ -36,8 +37,9 @@ func (c *RaftCluster) HandleRegionHeartbeat(region *core.RegionInfo) error {

// If the region peer count is 0, then we should not handle this.
if len(region.GetPeers()) == 0 {
log.Warn("invalid region, zero region peer count", zap.Stringer("region-meta", core.RegionToHexMeta(region.GetMeta())))
return errors.Errorf("invalid region, zero region peer count: %v", core.RegionToHexMeta(region.GetMeta()))
log.Warn("invalid region, zero region peer count",
zap.Stringer("region-meta", logutil.RedactStringer(core.RegionToHexMeta(region.GetMeta()))))
return errors.Errorf("invalid region, zero region peer count: %v", logutil.RedactStringer(core.RegionToHexMeta(region.GetMeta())))
}

c.RLock()
Expand Down Expand Up @@ -87,7 +89,7 @@ func (c *RaftCluster) ValidRequestRegion(reqRegion *metapb.Region) error {
startKey := reqRegion.GetStartKey()
region := c.GetRegionByKey(startKey)
if region == nil {
return errors.Errorf("region not found, request region: %v", core.RegionToHexMeta(reqRegion))
return errors.Errorf("region not found, request region: %v", logutil.RedactStringer(core.RegionToHexMeta(reqRegion)))
}
// If the request epoch is less than current region epoch, then returns an error.
reqRegionEpoch := reqRegion.GetRegionEpoch()
Expand Down Expand Up @@ -190,8 +192,8 @@ func (c *RaftCluster) HandleReportSplit(request *pdpb.ReportSplitRequest) (*pdpb
err := c.checkSplitRegion(left, right)
if err != nil {
log.Warn("report split region is invalid",
zap.Stringer("left-region", core.RegionToHexMeta(left)),
zap.Stringer("right-region", core.RegionToHexMeta(right)),
zap.Stringer("left-region", logutil.RedactStringer(core.RegionToHexMeta(left))),
zap.Stringer("right-region", logutil.RedactStringer(core.RegionToHexMeta(right))),
errs.ZapError(err))
return nil, err
}
Expand All @@ -202,7 +204,7 @@ func (c *RaftCluster) HandleReportSplit(request *pdpb.ReportSplitRequest) (*pdpb
originRegion.StartKey = left.GetStartKey()
log.Info("region split, generate new region",
zap.Uint64("region-id", originRegion.GetId()),
zap.Stringer("region-meta", core.RegionToHexMeta(left)))
zap.Stringer("region-meta", logutil.RedactStringer(core.RegionToHexMeta(left))))
return &pdpb.ReportSplitResponse{}, nil
}

Expand Down
9 changes: 9 additions & 0 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/grpcutil"
"github.com/tikv/pd/pkg/logutil"
"github.com/tikv/pd/pkg/metricutil"
"github.com/tikv/pd/pkg/typeutil"
"github.com/tikv/pd/server/core/storelimit"
Expand Down Expand Up @@ -144,6 +145,8 @@ type Config struct {
Dashboard DashboardConfig `toml:"dashboard" json:"dashboard"`

ReplicationMode ReplicationModeConfig `toml:"replication-mode" json:"replication-mode"`
// EnableRedactLog indicates that whether redact log, 0 is disable. 1 is enable.
EnableRedactLog bool `toml:"enable-redact-log" json:"enable-redact-log"`
}

// NewConfig creates a new config.
Expand Down Expand Up @@ -221,6 +224,7 @@ const (
defaultDRWaitStoreTimeout = time.Minute
defaultDRWaitSyncTimeout = time.Minute
defaultDRWaitAsyncTimeout = 2 * time.Minute
defaultEnableRedactLog = false
)

var (
Expand Down Expand Up @@ -543,6 +547,10 @@ func (c *Config) Adjust(meta *toml.MetaData) error {

c.ReplicationMode.adjust(configMetaData.Child("replication-mode"))

if !configMetaData.IsDefined("enable-redact-log") {
c.EnableRedactLog = defaultEnableRedactLog
}

return nil
}

Expand Down Expand Up @@ -1143,6 +1151,7 @@ func (c *Config) SetupLogger() error {
}
c.logger = lg
c.logProps = p
logutil.SetRedactLog(c.EnableRedactLog)
return nil
}

Expand Down
1 change: 1 addition & 0 deletions server/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ leader-schedule-limit = 0
c.Assert(cfg.PreVote, IsTrue)
c.Assert(cfg.Schedule.MaxMergeRegionKeys, Equals, uint64(defaultMaxMergeRegionKeys))
c.Assert(cfg.PDServerCfg.MetricStorage, Equals, "http://127.0.0.1:9090")
c.Assert(cfg.EnableRedactLog, Equals, defaultEnableRedactLog)

// Check undefined config fields
cfgData = `
Expand Down
10 changes: 6 additions & 4 deletions server/core/region_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/pingcap/log"
"github.com/tikv/pd/pkg/btree"
"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/logutil"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -95,8 +96,8 @@ func (t *regionTree) update(region *RegionInfo) []*RegionInfo {
for _, item := range overlaps {
log.Debug("overlapping region",
zap.Uint64("region-id", item.GetID()),
zap.Stringer("delete-region", RegionToHexMeta(item.GetMeta())),
zap.Stringer("update-region", RegionToHexMeta(region.GetMeta())))
zap.Stringer("delete-region", logutil.RedactStringer(RegionToHexMeta(item.GetMeta()))),
zap.Stringer("update-region", logutil.RedactStringer(RegionToHexMeta(region.GetMeta()))))
t.tree.Delete(&regionItem{item})
}

Expand Down Expand Up @@ -229,8 +230,9 @@ func (t *regionTree) RandomRegion(ranges []KeyRange) *RegionInfo {
if endIndex <= startIndex {
if len(endKey) > 0 && bytes.Compare(startKey, endKey) > 0 {
log.Error("wrong range keys",
zap.String("start-key", string(HexRegionKey(startKey))),
zap.String("end-key", string(HexRegionKey(endKey))), errs.ZapError(errs.ErrWrongRangeKeys))
zap.String("start-key", logutil.RedactString(string(HexRegionKey(startKey)))),
zap.String("end-key", logutil.RedactString(string(HexRegionKey(endKey)))),
errs.ZapError(errs.ErrWrongRangeKeys))
}
continue
}
Expand Down
7 changes: 5 additions & 2 deletions server/replication/replication_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
pb "github.com/pingcap/kvproto/pkg/replication_modepb"
"github.com/pingcap/log"
"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/logutil"
"github.com/tikv/pd/server/config"
"github.com/tikv/pd/server/core"
"github.com/tikv/pd/server/schedule/opt"
Expand Down Expand Up @@ -435,7 +436,7 @@ func (m *ModeManager) updateProgress() {
for len(m.drRecoverKey) > 0 || m.drRecoverCount == 0 {
regions := m.cluster.ScanRegions(m.drRecoverKey, nil, regionScanBatchSize)
if len(regions) == 0 {
log.Warn("scan empty regions", zap.ByteString("recover-key", m.drRecoverKey))
log.Warn("scan empty regions", zap.ByteString("recover-key", logutil.RedactBytes(m.drRecoverKey)))
return
}
for i, r := range regions {
Expand Down Expand Up @@ -486,7 +487,9 @@ func (m *ModeManager) estimateProgress() float32 {

func (m *ModeManager) checkRegionRecover(region *core.RegionInfo, startKey []byte) bool {
if !bytes.Equal(startKey, region.GetStartKey()) {
log.Warn("found region gap", zap.ByteString("key", startKey), zap.ByteString("region-start-key", region.GetStartKey()), zap.Uint64("region-id", region.GetID()))
log.Warn("found region gap", zap.ByteString("key", logutil.RedactBytes(startKey)),
zap.ByteString("region-start-key", logutil.RedactBytes(region.GetStartKey())),
zap.Uint64("region-id", region.GetID()))
return false
}
return region.GetReplicationStatus().GetStateId() == m.drAutoSync.StateID &&
Expand Down
5 changes: 4 additions & 1 deletion server/schedule/checker/merge_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/tikv/pd/pkg/cache"
"github.com/tikv/pd/pkg/codec"
"github.com/tikv/pd/pkg/errs"
"github.com/tikv/pd/pkg/logutil"
"github.com/tikv/pd/server/config"
"github.com/tikv/pd/server/core"
"github.com/tikv/pd/server/schedule/operator"
Expand Down Expand Up @@ -123,7 +124,9 @@ func (m *MergeChecker) Check(region *core.RegionInfo) []*operator.Operator {
return nil
}

log.Debug("try to merge region", zap.Stringer("from", core.RegionToHexMeta(region.GetMeta())), zap.Stringer("to", core.RegionToHexMeta(target.GetMeta())))
log.Debug("try to merge region",
zap.Stringer("from", logutil.RedactStringer(core.RegionToHexMeta(region.GetMeta()))),
Yisaer marked this conversation as resolved.
Show resolved Hide resolved
zap.Stringer("to", logutil.RedactStringer(core.RegionToHexMeta(target.GetMeta()))))
ops, err := operator.CreateMergeRegionOperator("merge-region", m.cluster, region, target, operator.OpMerge)
if err != nil {
log.Warn("create merge region operator failed", errs.ZapError(err))
Expand Down