github.com/m3db/m3@v1.5.0/src/dbnode/storage/bootstrap/bootstrapper/peers/source_instrumentation.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package peers 22 23 import ( 24 "time" 25 26 "github.com/opentracing/opentracing-go" 27 opentracinglog "github.com/opentracing/opentracing-go/log" 28 "github.com/uber-go/tally" 29 "go.uber.org/zap" 30 "go.uber.org/zap/zapcore" 31 32 "github.com/m3db/m3/src/dbnode/tracepoint" 33 "github.com/m3db/m3/src/x/clock" 34 "github.com/m3db/m3/src/x/context" 35 "github.com/m3db/m3/src/x/ident" 36 "github.com/m3db/m3/src/x/instrument" 37 ) 38 39 type instrumentationContext struct { 40 nowFn clock.NowFn 41 log *zap.Logger 42 start time.Time 43 span opentracing.Span 44 bootstrapDataDuration tally.Timer 45 bootstrapIndexDuration tally.Timer 46 profiler instrument.Profiler 47 } 48 49 func newInstrumentationContext( 50 nowFn clock.NowFn, 51 log *zap.Logger, 52 span opentracing.Span, 53 scope tally.Scope, 54 profiler instrument.Profiler, 55 ) *instrumentationContext { 56 return &instrumentationContext{ 57 nowFn: nowFn, 58 log: log, 59 span: span, 60 profiler: profiler, 61 bootstrapDataDuration: scope.Timer("data-duration"), 62 bootstrapIndexDuration: scope.Timer("index-duration"), 63 } 64 } 65 66 const ( 67 dataProfile = "peers-data" 68 indexProfile = "peers-index" 69 ) 70 71 func (i *instrumentationContext) finish() { 72 i.span.Finish() 73 } 74 75 func (i *instrumentationContext) startCPUProfile(name string) { 76 err := i.profiler.StartCPUProfile(name) 77 if err != nil { 78 i.log.Error("unable to start cpu profile", zap.Error(err)) 79 } 80 } 81 82 func (i *instrumentationContext) stopCPUProfile() { 83 if err := i.profiler.StopCPUProfile(); err != nil { 84 i.log.Error("unable to stop cpu profile", zap.Error(err)) 85 } 86 } 87 88 func (i *instrumentationContext) writeHeapProfile(name string) { 89 err := i.profiler.WriteHeapProfile(name) 90 if err != nil { 91 i.log.Error("unable to write heap profile", zap.Error(err)) 92 } 93 } 94 95 func (i *instrumentationContext) bootstrapDataStarted() { 96 i.log.Info("bootstrapping time series data start") 97 i.span.LogFields(opentracinglog.String("event", "bootstrap_data_start")) 98 i.start = i.nowFn() 99 i.startCPUProfile(dataProfile) 100 i.writeHeapProfile(dataProfile) 101 } 102 103 func (i *instrumentationContext) bootstrapDataCompleted() { 104 duration := i.nowFn().Sub(i.start) 105 i.bootstrapDataDuration.Record(duration) 106 i.log.Info("bootstrapping time series data success", zap.Duration("took", duration)) 107 i.span.LogFields(opentracinglog.String("event", "bootstrap_data_done")) 108 i.stopCPUProfile() 109 i.writeHeapProfile(dataProfile) 110 } 111 112 func (i *instrumentationContext) bootstrapIndexStarted() { 113 i.log.Info("bootstrapping index metadata start") 114 i.span.LogFields(opentracinglog.String("event", "bootstrap_index_start")) 115 i.start = i.nowFn() 116 i.startCPUProfile(indexProfile) 117 i.writeHeapProfile(indexProfile) 118 } 119 120 func (i *instrumentationContext) bootstrapIndexCompleted() { 121 duration := i.nowFn().Sub(i.start) 122 i.bootstrapIndexDuration.Record(duration) 123 i.log.Info("bootstrapping index metadata success", zap.Duration("took", duration)) 124 i.span.LogFields(opentracinglog.String("event", "bootstrap_index_done")) 125 i.stopCPUProfile() 126 i.writeHeapProfile(indexProfile) 127 } 128 129 type instrumentationReadShardsContext struct { 130 namespaceID ident.ID 131 nowFn clock.NowFn 132 log *zap.Logger 133 start time.Time 134 bootstrapShardsDuration tally.Timer 135 } 136 137 func newInstrumentationReadShardsContext( 138 namespaceID ident.ID, 139 nowFn clock.NowFn, 140 log *zap.Logger, 141 scope tally.Scope, 142 ) *instrumentationReadShardsContext { 143 return &instrumentationReadShardsContext{ 144 namespaceID: namespaceID, 145 nowFn: nowFn, 146 log: log, 147 start: nowFn(), 148 bootstrapShardsDuration: scope.Timer("shards-duration"), 149 } 150 } 151 152 func (i *instrumentationReadShardsContext) bootstrapShardsCompleted() { 153 duration := i.nowFn().Sub(i.start) 154 i.bootstrapShardsDuration.Record(duration) 155 i.log.Info("bootstrapping shards success", 156 zap.Stringer("namespace", i.namespaceID), 157 zap.Duration("took", duration)) 158 } 159 160 type instrumentation struct { 161 opts Options 162 profiler instrument.Profiler 163 scope tally.Scope 164 log *zap.Logger 165 nowFn clock.NowFn 166 persistedIndexBlocksOutOfRetention tally.Counter 167 } 168 169 func newInstrumentation(opts Options) *instrumentation { 170 var ( 171 scope = opts.ResultOptions().InstrumentOptions(). 172 MetricsScope().SubScope("peers-bootstrapper") 173 instrumentOptions = opts.ResultOptions().InstrumentOptions().SetMetricsScope(scope) 174 ) 175 176 return &instrumentation{ 177 opts: opts, 178 profiler: instrumentOptions.Profiler(), 179 scope: scope, 180 log: instrumentOptions.Logger().With(zap.String("bootstrapper", "peers")), 181 nowFn: opts.ResultOptions().ClockOptions().NowFn(), 182 persistedIndexBlocksOutOfRetention: scope.Counter("persist-index-blocks-out-of-retention"), 183 } 184 } 185 186 func (i *instrumentation) peersBootstrapperSourceReadStarted( 187 ctx context.Context, 188 ) *instrumentationContext { 189 _, span, _ := ctx.StartSampledTraceSpan(tracepoint.BootstrapperPeersSourceRead) 190 return newInstrumentationContext( 191 i.nowFn, 192 i.log, 193 span, 194 i.scope, 195 i.profiler, 196 ) 197 } 198 199 func (i *instrumentation) bootstrapShardsStarted( 200 namespaceID ident.ID, 201 count int, 202 concurrency int, 203 shouldPersist bool, 204 ) *instrumentationReadShardsContext { 205 i.log.Info("peers bootstrapper bootstrapping shards for ranges", 206 zap.Stringer("namespace", namespaceID), 207 zap.Int("shards", count), 208 zap.Int("concurrency", concurrency), 209 zap.Bool("shouldPersist", shouldPersist)) 210 return newInstrumentationReadShardsContext( 211 namespaceID, 212 i.nowFn, 213 i.log, 214 i.scope, 215 ) 216 } 217 218 func (i *instrumentation) outOfRetentionIndexSegmentSkipped(fields []zapcore.Field) { 219 i.log.Debug("skipping out of retention index segment", fields...) 220 i.persistedIndexBlocksOutOfRetention.Inc(1) 221 }