github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/event.go (about)

     1  // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package bitalosdb
    16  
    17  import (
    18  	"time"
    19  
    20  	"github.com/zuoyebang/bitalosdb/internal/humanize"
    21  
    22  	"github.com/cockroachdb/redact"
    23  )
    24  
    25  type DiskSlowInfo struct {
    26  	Path     string
    27  	Duration time.Duration
    28  }
    29  
    30  func (i DiskSlowInfo) String() string {
    31  	return redact.StringWithoutMarkers(i)
    32  }
    33  
    34  func (i DiskSlowInfo) SafeFormat(w redact.SafePrinter, _ rune) {
    35  	w.Printf("disk slowness detected: write to file %s has been ongoing for %0.1fs",
    36  		i.Path, redact.Safe(i.Duration.Seconds()))
    37  }
    38  
    39  type FlushInfo struct {
    40  	Index               int
    41  	Reason              string
    42  	Input               int
    43  	Iterated            uint64
    44  	Written             int64
    45  	keyWritten          int64
    46  	keyPrefixDeleteKind int64
    47  	prefixDeleteNum     int64
    48  	Duration            time.Duration
    49  	Done                bool
    50  	Err                 error
    51  }
    52  
    53  func (i FlushInfo) String() string {
    54  	return redact.StringWithoutMarkers(i)
    55  }
    56  
    57  func (i FlushInfo) SafeFormat(w redact.SafePrinter, _ rune) {
    58  	if i.Err != nil {
    59  		w.Printf("[BITOWER %d] flush error: %s", i.Index, i.Err)
    60  		return
    61  	}
    62  
    63  	if !i.Done {
    64  		w.Printf("[BITOWER %d] flushing %d memtable to bitforest", i.Index, i.Input)
    65  		return
    66  	}
    67  
    68  	w.Printf("[BITOWER %d] flushed %d memtable to bitforest iterated(%s) written(%s) keys(%d) keysPdKind(%d) pdNum(%d), in %.3fs, output rate %s/s",
    69  		i.Index,
    70  		i.Input,
    71  		humanize.Uint64(i.Iterated),
    72  		humanize.Int64(i.Written),
    73  		i.keyWritten,
    74  		i.keyPrefixDeleteKind,
    75  		i.prefixDeleteNum,
    76  		i.Duration.Seconds(),
    77  		humanize.Uint64(uint64(float64(i.Written)/i.Duration.Seconds())))
    78  }
    79  
    80  type WALCreateInfo struct {
    81  	Index           int
    82  	Path            string
    83  	FileNum         FileNum
    84  	RecycledFileNum FileNum
    85  	Err             error
    86  }
    87  
    88  func (i WALCreateInfo) String() string {
    89  	return redact.StringWithoutMarkers(i)
    90  }
    91  
    92  func (i WALCreateInfo) SafeFormat(w redact.SafePrinter, _ rune) {
    93  	if i.Err != nil {
    94  		w.Printf("[BITOWER %d] WAL create error: %s", redact.Safe(i.Index), i.Err)
    95  		return
    96  	}
    97  
    98  	if i.RecycledFileNum == 0 {
    99  		w.Printf("[BITOWER %d] WAL created %s", redact.Safe(i.Index), redact.Safe(i.FileNum))
   100  		return
   101  	}
   102  
   103  	w.Printf("[BITOWER %d] WAL created %s (recycled %s)",
   104  		redact.Safe(i.Index), redact.Safe(i.FileNum), redact.Safe(i.RecycledFileNum))
   105  }
   106  
   107  type WALDeleteInfo struct {
   108  	Index   int
   109  	Path    string
   110  	FileNum FileNum
   111  	Err     error
   112  }
   113  
   114  func (i WALDeleteInfo) String() string {
   115  	return redact.StringWithoutMarkers(i)
   116  }
   117  
   118  func (i WALDeleteInfo) SafeFormat(w redact.SafePrinter, _ rune) {
   119  	if i.Err != nil {
   120  		w.Printf("[BITOWER %d] WAL delete error: %s", redact.Safe(i.Index), i.Err)
   121  		return
   122  	}
   123  	w.Printf("[BITOWER %d] WAL deleted %s", redact.Safe(i.Index), redact.Safe(i.FileNum))
   124  }
   125  
   126  type WriteStallBeginInfo struct {
   127  	Index  int
   128  	Reason string
   129  }
   130  
   131  func (i WriteStallBeginInfo) String() string {
   132  	return redact.StringWithoutMarkers(i)
   133  }
   134  
   135  func (i WriteStallBeginInfo) SafeFormat(w redact.SafePrinter, _ rune) {
   136  	w.Printf("[BITOWER %d] write stall beginning: %s", redact.Safe(i.Index), redact.Safe(i.Reason))
   137  }
   138  
   139  type EventListener struct {
   140  	BackgroundError func(error)
   141  	DiskSlow        func(DiskSlowInfo)
   142  	FlushBegin      func(FlushInfo)
   143  	FlushEnd        func(FlushInfo)
   144  	WALCreated      func(WALCreateInfo)
   145  	WALDeleted      func(WALDeleteInfo)
   146  	WriteStallBegin func(WriteStallBeginInfo)
   147  	WriteStallEnd   func()
   148  }
   149  
   150  func (l *EventListener) EnsureDefaults(logger Logger) {
   151  	if l.BackgroundError == nil {
   152  		if logger != nil {
   153  			l.BackgroundError = func(err error) {
   154  				logger.Errorf("background error: %s", err)
   155  			}
   156  		} else {
   157  			l.BackgroundError = func(error) {}
   158  		}
   159  	}
   160  	if l.DiskSlow == nil {
   161  		l.DiskSlow = func(info DiskSlowInfo) {}
   162  	}
   163  	if l.FlushBegin == nil {
   164  		l.FlushBegin = func(info FlushInfo) {}
   165  	}
   166  	if l.FlushEnd == nil {
   167  		l.FlushEnd = func(info FlushInfo) {}
   168  	}
   169  	if l.WALCreated == nil {
   170  		l.WALCreated = func(info WALCreateInfo) {}
   171  	}
   172  	if l.WALDeleted == nil {
   173  		l.WALDeleted = func(info WALDeleteInfo) {}
   174  	}
   175  	if l.WriteStallBegin == nil {
   176  		l.WriteStallBegin = func(info WriteStallBeginInfo) {}
   177  	}
   178  	if l.WriteStallEnd == nil {
   179  		l.WriteStallEnd = func() {}
   180  	}
   181  }
   182  
   183  func MakeLoggingEventListener(logger Logger) EventListener {
   184  	if logger == nil {
   185  		logger = DefaultLogger
   186  	}
   187  
   188  	return EventListener{
   189  		BackgroundError: func(err error) {
   190  			logger.Infof("background error: %s", err)
   191  		},
   192  		DiskSlow: func(info DiskSlowInfo) {
   193  			logger.Infof("%s", info)
   194  		},
   195  		FlushBegin: func(info FlushInfo) {
   196  			logger.Infof("%s", info)
   197  		},
   198  		FlushEnd: func(info FlushInfo) {
   199  			logger.Infof("%s", info)
   200  		},
   201  		WALCreated: func(info WALCreateInfo) {
   202  			logger.Infof("%s", info)
   203  		},
   204  		WALDeleted: func(info WALDeleteInfo) {
   205  			logger.Infof("%s", info)
   206  		},
   207  		WriteStallBegin: func(info WriteStallBeginInfo) {
   208  			logger.Infof("%s", info)
   209  		},
   210  		WriteStallEnd: func() {
   211  			logger.Infof("write stall ending")
   212  		},
   213  	}
   214  }
   215  
   216  func TeeEventListener(a, b EventListener) EventListener {
   217  	a.EnsureDefaults(nil)
   218  	b.EnsureDefaults(nil)
   219  	return EventListener{
   220  		BackgroundError: func(err error) {
   221  			a.BackgroundError(err)
   222  			b.BackgroundError(err)
   223  		},
   224  		DiskSlow: func(info DiskSlowInfo) {
   225  			a.DiskSlow(info)
   226  			b.DiskSlow(info)
   227  		},
   228  		FlushBegin: func(info FlushInfo) {
   229  			a.FlushBegin(info)
   230  			b.FlushBegin(info)
   231  		},
   232  		FlushEnd: func(info FlushInfo) {
   233  			a.FlushEnd(info)
   234  			b.FlushEnd(info)
   235  		},
   236  		WALCreated: func(info WALCreateInfo) {
   237  			a.WALCreated(info)
   238  			b.WALCreated(info)
   239  		},
   240  		WALDeleted: func(info WALDeleteInfo) {
   241  			a.WALDeleted(info)
   242  			b.WALDeleted(info)
   243  		},
   244  		WriteStallBegin: func(info WriteStallBeginInfo) {
   245  			a.WriteStallBegin(info)
   246  			b.WriteStallBegin(info)
   247  		},
   248  		WriteStallEnd: func() {
   249  			a.WriteStallEnd()
   250  			b.WriteStallEnd()
   251  		},
   252  	}
   253  }