github.com/matrixorigin/matrixone@v0.7.0/pkg/util/metric/batch_collector.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 metric
    16  
    17  import (
    18  	"context"
    19  	"sync"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/logutil"
    22  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    23  	prom "github.com/prometheus/client_golang/prometheus"
    24  )
    25  
    26  type cacheKey = int
    27  
    28  const (
    29  	cacheKeyMemStats cacheKey = iota
    30  	cacheKeyProcess
    31  	cacheKeyDiskIO
    32  	cacheKeyNetIO
    33  )
    34  
    35  type statCaches struct {
    36  	newest int
    37  	//TODO(aptend): use array
    38  	entries map[cacheKey]cacheEntry
    39  }
    40  
    41  type cacheEntry struct {
    42  	version int
    43  	value   any
    44  }
    45  
    46  func (c *statCaches) invalidateAll() {
    47  	c.newest += 1
    48  }
    49  
    50  func (c *statCaches) get(key cacheKey) (any, bool) {
    51  	if entry, ok := c.entries[key]; !ok {
    52  		return nil, false
    53  	} else if entry.version != c.newest {
    54  		return nil, false
    55  	} else {
    56  		return entry.value, true
    57  	}
    58  }
    59  
    60  func (c *statCaches) put(key cacheKey, val any) {
    61  	c.entries[key] = cacheEntry{
    62  		version: c.newest,
    63  		value:   val,
    64  	}
    65  }
    66  
    67  func (c *statCaches) getOrInsert(key cacheKey, f func() any) any {
    68  	if val, ok := c.get(key); ok {
    69  		return val
    70  	}
    71  	toPut := f()
    72  	c.put(key, toPut)
    73  	return toPut
    74  }
    75  
    76  type simpleEntry interface {
    77  	Desc() *prom.Desc
    78  	// entry return the metric for now. it can fetch from the caches or just compute by itself
    79  	Metric(context.Context, *statCaches) (prom.Metric, error)
    80  }
    81  
    82  type batchStatsCollector struct {
    83  	selfAsPromCollector
    84  	entris    []simpleEntry
    85  	caches    *statCaches
    86  	collected bool
    87  	sync.Mutex
    88  }
    89  
    90  func newBatchStatsCollector(entries ...simpleEntry) Collector {
    91  	c := &batchStatsCollector{
    92  		entris: entries,
    93  		caches: &statCaches{
    94  			newest:  1,
    95  			entries: make(map[int]cacheEntry),
    96  		},
    97  	}
    98  	c.init(c)
    99  	return c
   100  }
   101  
   102  // Describe returns all descriptions of the collector.
   103  func (c *batchStatsCollector) Describe(ch chan<- *prom.Desc) {
   104  	for _, e := range c.entris {
   105  		ch <- e.Desc()
   106  	}
   107  }
   108  
   109  // Collect returns the current state of all metrics of the collector.
   110  func (c *batchStatsCollector) Collect(ch chan<- prom.Metric) {
   111  	c.Lock()
   112  	defer c.Unlock()
   113  	ctx, span := trace.Start(context.Background(), "batchStatsCollector.Collect")
   114  	defer span.End()
   115  	c.caches.invalidateAll()
   116  	for _, e := range c.entris {
   117  		m, err := e.Metric(ctx, c.caches)
   118  		if err != nil {
   119  			if err.Error() == "not implemented yet" && c.collected {
   120  				// log not implemented once, otherwise it is too annoying
   121  				continue
   122  			}
   123  			logutil.Warnf("[Metric] %s collect a error: %v", e.Desc().String(), err)
   124  		} else {
   125  			// as we logged already, no need to issue a InvalidMetric
   126  			ch <- m
   127  		}
   128  	}
   129  	c.collected = true
   130  }