github.com/matrixorigin/matrixone@v1.2.0/pkg/util/metric/mometric/stats_log_writer.go (about) 1 // Copyright 2023 Matrix Origin 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 mometric 16 17 import ( 18 "context" 19 "fmt" 20 "sync" 21 "sync/atomic" 22 "time" 23 24 "github.com/matrixorigin/matrixone/pkg/common/log" 25 "github.com/matrixorigin/matrixone/pkg/objectio" 26 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 27 "github.com/matrixorigin/matrixone/pkg/util/metric/stats" 28 ) 29 30 type StatsLogWriter struct { 31 isRunning int32 32 cancel context.CancelFunc 33 stopWg sync.WaitGroup 34 35 registry *stats.Registry 36 gatherInterval time.Duration 37 38 logger *log.MOLogger 39 } 40 41 func newStatsLogWriter(registry *stats.Registry, logger *log.MOLogger, gatherInterval time.Duration) *StatsLogWriter { 42 return &StatsLogWriter{ 43 registry: registry, 44 gatherInterval: gatherInterval, 45 logger: logger, 46 } 47 } 48 49 func (e *StatsLogWriter) Start(inputCtx context.Context) bool { 50 if atomic.SwapInt32(&e.isRunning, 1) == 1 { 51 return false 52 } 53 ctx, cancel := context.WithCancel(inputCtx) 54 e.cancel = cancel 55 e.stopWg.Add(1) 56 go func() { 57 defer e.stopWg.Done() 58 ticker := time.NewTicker(e.gatherInterval) 59 defer ticker.Stop() 60 for { 61 select { 62 case <-ticker.C: 63 e.gatherAndWrite(ctx) 64 case <-ctx.Done(): 65 return 66 } 67 } 68 }() 69 return true 70 } 71 72 func (e *StatsLogWriter) Stop(_ bool) (<-chan struct{}, bool) { 73 if atomic.SwapInt32(&e.isRunning, 0) == 0 { 74 return nil, false 75 } 76 e.cancel() 77 stopCh := make(chan struct{}) 78 go func() { e.stopWg.Wait(); close(stopCh) }() 79 return stopCh, true 80 } 81 82 // gatherAndWriter gathers all the logs from Stats and Writes to Log 83 // Example log output: 84 // 2023/03/15 02:37:31.767463 -0500 INFO cn-service mometric/stats_log_writer.go:86 MockServiceStats stats {"uuid": "test", "reads": 2, "hits": 1} 85 // 2023/03/15 02:37:33.767659 -0500 INFO cn-service mometric/stats_log_writer.go:86 MockServiceStats stats {"uuid": "test", "reads": 0, "hits": 0} 86 // 2023/03/15 02:37:35.767608 -0500 INFO cn-service mometric/stats_log_writer.go:86 MockServiceStats stats {"uuid": "test", "reads": 0, "hits": 0} 87 func (e *StatsLogWriter) gatherAndWrite(ctx context.Context) { 88 statsFamilies := e.registry.ExportLog() 89 for statsFName, statsFamily := range statsFamilies { 90 if len(statsFamily) > 1 { 91 e.logger.Info(statsFName, statsFamily...) 92 } 93 } 94 95 // logging block read statistics info here 96 v := ctx.Value(ServiceTypeKey).(string) 97 if v == metadata.ServiceType_name[int32(metadata.ServiceType_CN)] || v == LaunchMode { 98 e.writeBlkReadStats() 99 } 100 } 101 102 func (e *StatsLogWriter) writeBlkReadStats() { 103 blkHit, blkTotal := objectio.BlkReadStats.BlkCacheHitStats.ExportW() 104 blkHitRate := float32(1) 105 if blkTotal != 0 { 106 blkHitRate = float32(blkHit) / float32(blkTotal) 107 } 108 109 entryHit, entryTotal := objectio.BlkReadStats.EntryCacheHitStats.ExportW() 110 entryHitRate := float32(1) 111 if entryTotal != 0 { 112 entryHitRate = float32(entryHit) / float32(entryTotal) 113 } 114 115 readerNum, blkNum := objectio.BlkReadStats.BlksByReaderStats.ExportW() 116 blksInEachReader := float32(1) 117 if readerNum != 0 { 118 blksInEachReader = float32(blkNum) / float32(readerNum) 119 } 120 121 e.logger.Info(fmt.Sprintf("duration: %d, "+ 122 "blk hit rate: %d/%d=%.4f, entry hit rate: %d/%d=%.4f, (average) blks in each reader: %d/%d=%.4f", 123 e.gatherInterval, 124 blkHit, blkTotal, blkHitRate, 125 entryHit, entryTotal, entryHitRate, 126 blkNum, readerNum, blksInEachReader)) 127 128 }