github.com/matrixorigin/matrixone@v1.2.0/pkg/util/metric/mometric/metric_exporter.go (about) 1 // Copyright 2022 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 "sync" 20 "sync/atomic" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/logutil" 24 pb "github.com/matrixorigin/matrixone/pkg/pb/metric" 25 "github.com/matrixorigin/matrixone/pkg/util/metric" 26 prom "github.com/prometheus/client_golang/prometheus" 27 ) 28 29 const defaultGatherInterval = 15 * time.Second 30 31 type metricExporter struct { 32 localCollector MetricCollector 33 nodeUUID string 34 role string 35 gather prom.Gatherer 36 isRunning int32 37 cancel context.CancelFunc 38 stopWg sync.WaitGroup 39 sync.Mutex 40 histFamilies []*pb.MetricFamily 41 now func() int64 42 43 gatherInterval time.Duration 44 } 45 46 type ExporterOption func(*metricExporter) 47 48 func WithGatherInterval(interval time.Duration) ExporterOption { 49 return func(e *metricExporter) { 50 e.gatherInterval = interval 51 } 52 } 53 54 func newMetricExporter(gather prom.Gatherer, collector MetricCollector, node, role string, opts ...ExporterOption) metric.MetricExporter { 55 m := &metricExporter{ 56 localCollector: collector, 57 nodeUUID: node, 58 role: role, 59 gather: gather, 60 now: func() int64 { return time.Now().UnixMicro() }, 61 gatherInterval: defaultGatherInterval, 62 } 63 for _, opt := range opts { 64 opt(m) 65 } 66 return m 67 } 68 69 func (e *metricExporter) ExportMetricFamily(ctx context.Context, mf *pb.MetricFamily) error { 70 // already batched RawHist metric will be send immediately 71 if metric.IsFullBatchRawHist(mf) { 72 mfs := []*pb.MetricFamily{mf} 73 mfs = e.prepareSend(mfs) 74 e.send(mfs) 75 } else { 76 e.Lock() 77 defer e.Unlock() 78 e.histFamilies = append(e.histFamilies, mf) 79 } 80 return nil 81 } 82 83 func (e *metricExporter) Stop(_ bool) (<-chan struct{}, bool) { 84 if atomic.SwapInt32(&e.isRunning, 0) == 0 { 85 return nil, false 86 } 87 e.cancel() 88 stopCh := make(chan struct{}) 89 go func() { e.stopWg.Wait(); close(stopCh) }() 90 return stopCh, true 91 } 92 93 func (e *metricExporter) Start(inputCtx context.Context) bool { 94 if atomic.SwapInt32(&e.isRunning, 1) == 1 { 95 return false 96 } 97 ctx, cancel := context.WithCancel(inputCtx) 98 e.cancel = cancel 99 e.stopWg.Add(1) 100 go func() { 101 defer e.stopWg.Done() 102 ticker := time.NewTicker(e.gatherInterval) 103 defer ticker.Stop() 104 for { 105 select { 106 case <-ticker.C: 107 e.gatherAndSend() 108 case <-ctx.Done(): 109 return 110 } 111 } 112 }() 113 return true 114 } 115 116 func (e *metricExporter) send(mfs []*pb.MetricFamily) { 117 if e.localCollector == nil { 118 panic("[Metric] Only a local MetricCollector") 119 } 120 err := e.localCollector.SendMetrics(context.TODO(), mfs) 121 if err != nil { 122 logutil.Errorf("[Metric] exporter send err: %v", err) 123 } 124 } 125 126 func (e *metricExporter) addCommonInfo(mfs []*pb.MetricFamily) { 127 now := e.now() 128 for _, mf := range mfs { 129 mf.Role = e.role 130 mf.Node = e.nodeUUID 131 for _, m := range mf.Metric { 132 m.Collecttime = now 133 } 134 } 135 } 136 137 func (e *metricExporter) prepareSend(mfs []*pb.MetricFamily) []*pb.MetricFamily { 138 e.Lock() 139 mfs = append(mfs, e.histFamilies...) 140 e.histFamilies = e.histFamilies[:0] 141 e.Unlock() 142 e.addCommonInfo(mfs) 143 return mfs 144 } 145 146 func (e *metricExporter) gatherAndSend() { 147 prommfs, err := e.gather.Gather() 148 if err != nil { 149 logutil.Errorf("[Metric] gather error: %v", err) 150 } 151 mfs := pb.P2MMetricFamilies(prommfs) 152 mfs = e.prepareSend(mfs) 153 e.send(mfs) 154 }