github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/metrics/sinks/manager.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 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 sinks 16 17 import ( 18 "sync" 19 "time" 20 21 "github.com/golang/glog" 22 "github.com/prometheus/client_golang/prometheus" 23 "k8s.io/heapster/metrics/core" 24 ) 25 26 const ( 27 DefaultSinkStopTimeout = 60 * time.Second 28 ) 29 30 var ( 31 // Last time Heapster exported data since unix epoch in seconds. 32 lastExportTimestamp = prometheus.NewGaugeVec( 33 prometheus.GaugeOpts{ 34 Namespace: "heapster", 35 Subsystem: "exporter", 36 Name: "last_time_seconds", 37 Help: "Last time Heapster exported data since unix epoch in seconds.", 38 }, 39 []string{"exporter"}, 40 ) 41 42 // Time spent exporting data to sink in milliseconds. 43 exporterDuration = prometheus.NewSummaryVec( 44 prometheus.SummaryOpts{ 45 Namespace: "heapster", 46 Subsystem: "exporter", 47 Name: "duration_milliseconds", 48 Help: "Time spent exporting data to sink in milliseconds.", 49 }, 50 []string{"exporter"}, 51 ) 52 ) 53 54 func init() { 55 prometheus.MustRegister(lastExportTimestamp) 56 prometheus.MustRegister(exporterDuration) 57 } 58 59 type sinkHolder struct { 60 sink core.DataSink 61 dataBatchChannel chan *core.DataBatch 62 stopChannel chan bool 63 } 64 65 // Sink Manager - a special sink that distributes data to other sinks. It pushes data 66 // only to these sinks that completed their previous exports. Data that could not be 67 // pushed in the defined time is dropped and not retried. 68 type sinkManager struct { 69 sinkHolders []sinkHolder 70 exportDataTimeout time.Duration 71 stopTimeout time.Duration 72 } 73 74 func NewDataSinkManager(sinks []core.DataSink, exportDataTimeout, stopTimeout time.Duration) (core.DataSink, error) { 75 sinkHolders := []sinkHolder{} 76 for _, sink := range sinks { 77 sh := sinkHolder{ 78 sink: sink, 79 dataBatchChannel: make(chan *core.DataBatch), 80 stopChannel: make(chan bool), 81 } 82 sinkHolders = append(sinkHolders, sh) 83 go func(sh sinkHolder) { 84 for { 85 select { 86 case data := <-sh.dataBatchChannel: 87 export(sh.sink, data) 88 case isStop := <-sh.stopChannel: 89 glog.V(2).Infof("Stop received: %s", sh.sink.Name()) 90 if isStop { 91 sh.sink.Stop() 92 return 93 } 94 } 95 } 96 }(sh) 97 } 98 return &sinkManager{ 99 sinkHolders: sinkHolders, 100 exportDataTimeout: exportDataTimeout, 101 stopTimeout: stopTimeout, 102 }, nil 103 } 104 105 // Guarantees that the export will complete in sinkExportDataTimeout. 106 func (this *sinkManager) ExportData(data *core.DataBatch) { 107 var wg sync.WaitGroup 108 for _, sh := range this.sinkHolders { 109 wg.Add(1) 110 go func(sh sinkHolder, wg *sync.WaitGroup) { 111 defer wg.Done() 112 glog.V(2).Infof("Pushing data to: %s", sh.sink.Name()) 113 select { 114 case sh.dataBatchChannel <- data: 115 glog.V(2).Infof("Data push completed: %s", sh.sink.Name()) 116 // everything ok 117 case <-time.After(this.exportDataTimeout): 118 glog.Warningf("Failed to push data to sink: %s", sh.sink.Name()) 119 } 120 }(sh, &wg) 121 } 122 // Wait for all pushes to complete or timeout. 123 wg.Wait() 124 } 125 126 func (this *sinkManager) Name() string { 127 return "Manager" 128 } 129 130 func (this *sinkManager) Stop() { 131 for _, sh := range this.sinkHolders { 132 glog.V(2).Infof("Running stop for: %s", sh.sink.Name()) 133 134 go func(sh sinkHolder) { 135 select { 136 case sh.stopChannel <- true: 137 // everything ok 138 glog.V(2).Infof("Stop sent to sink: %s", sh.sink.Name()) 139 140 case <-time.After(this.stopTimeout): 141 glog.Warningf("Failed to stop sink: %s", sh.sink.Name()) 142 } 143 return 144 }(sh) 145 } 146 } 147 148 func export(s core.DataSink, data *core.DataBatch) { 149 startTime := time.Now() 150 151 defer func() { 152 lastExportTimestamp. 153 WithLabelValues(s.Name()). 154 Set(float64(time.Now().Unix())) 155 exporterDuration. 156 WithLabelValues(s.Name()). 157 Observe(float64(time.Since(startTime)) / float64(time.Millisecond)) 158 }() 159 160 s.ExportData(data) 161 }