blocklogger.go raw

   1  package netsync
   2  
   3  import (
   4  	"fmt"
   5  	"github.com/p9c/p9/pkg/block"
   6  	"sync"
   7  	"time"
   8  )
   9  
  10  // blockProgressLogger provides periodic logging for other services in order to show users progress of certain "actions"
  11  // involving some or all current blocks. Ex: syncing to best chain, indexing all blocks, etc.
  12  type blockProgressLogger struct {
  13  	receivedLogBlocks int64
  14  	receivedLogTx     int64
  15  	lastBlockLogTime  time.Time
  16  	// subsystemLogger   *log.Logger
  17  	progressAction string
  18  	sync.Mutex
  19  }
  20  
  21  // newBlockProgressLogger returns a new block progress logger. The progress message is templated as follows:
  22  // {progressAction } {numProcessed} {blocks|block} in the last {timePeriod} ({numTxs}, height {lastBlockHeight},
  23  // {lastBlockTimeStamp})
  24  func newBlockProgressLogger(progressMessage string) *blockProgressLogger {
  25  	return &blockProgressLogger{
  26  		lastBlockLogTime: time.Now(),
  27  		progressAction:   progressMessage,
  28  	}
  29  }
  30  
  31  // LogBlockHeight logs a new block height as an information message to show progress to the user.
  32  //
  33  // In order to prevent spam, it limits logging to one message every 10 seconds with duration and totals included.
  34  func (b *blockProgressLogger) LogBlockHeight(block *block.Block) {
  35  	b.Lock()
  36  	defer b.Unlock()
  37  	b.receivedLogBlocks++
  38  	b.receivedLogTx += int64(len(block.WireBlock().Transactions))
  39  	now := time.Now()
  40  	duration := now.Sub(b.lastBlockLogTime)
  41  	if duration < time.Second*2 {
  42  		return
  43  	}
  44  	// Truncate the duration to 10s of milliseconds.
  45  	durationMillis := int64(duration / time.Millisecond)
  46  	tDuration := 10 * time.Millisecond * time.Duration(durationMillis/10)
  47  	// Log information about new block height.
  48  	blockStr := "blocks"
  49  	if b.receivedLogBlocks == 1 {
  50  		blockStr = "block "
  51  	}
  52  	txStr := "transactions"
  53  	if b.receivedLogTx == 1 {
  54  		txStr = "transaction "
  55  	}
  56  	tD := tDuration.Seconds()
  57  	I.F(
  58  		"%s %6d %s in the last %s (%6d %s, height %8d, %s) %0.2f tx/s",
  59  		b.progressAction,
  60  		b.receivedLogBlocks,
  61  		blockStr,
  62  		fmt.Sprintf("%0.1fs", tD),
  63  		b.receivedLogTx,
  64  		txStr, block.Height(),
  65  		block.WireBlock().Header.Timestamp,
  66  		float64(b.receivedLogTx)/tD,
  67  	)
  68  	b.receivedLogBlocks = 0
  69  	b.receivedLogTx = 0
  70  	b.lastBlockLogTime = now
  71  }
  72  
  73  func (b *blockProgressLogger) SetLastLogTime(time time.Time) {
  74  	b.lastBlockLogTime = time
  75  }
  76