github.com/polarismesh/polaris@v1.17.8/plugin/statis/base/cachecall.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package base
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"sync"
    24  	"time"
    25  
    26  	commonlog "github.com/polarismesh/polaris/common/log"
    27  	"github.com/polarismesh/polaris/common/metrics"
    28  	commontime "github.com/polarismesh/polaris/common/time"
    29  )
    30  
    31  // CacheCall 接口调用
    32  type CacheCall struct {
    33  	cacheType string
    34  	miss      bool
    35  	count     int32
    36  }
    37  
    38  // CacheCallStatisItem 接口调用统计条目
    39  type CacheCallStatisItem struct {
    40  	cacheType string
    41  	hitCount  int64
    42  	missCount int64
    43  	hitRate   float64
    44  }
    45  
    46  // ComponentCacheStatics statics components
    47  type CacheStatics struct {
    48  	mutex           *sync.Mutex
    49  	statis          map[string]*CacheCallStatisItem
    50  	CacheCallStatis *CacheCallStatis
    51  }
    52  
    53  func NewCacheStatics(statis *CacheCallStatis) *CacheStatics {
    54  	return &CacheStatics{
    55  		mutex:           &sync.Mutex{},
    56  		statis:          make(map[string]*CacheCallStatisItem),
    57  		CacheCallStatis: statis,
    58  	}
    59  }
    60  
    61  func (c *CacheStatics) Add(ac metrics.CallMetric) {
    62  	index := fmt.Sprintf("%v", ac.Protocol)
    63  	item, exist := c.statis[index]
    64  	if !exist {
    65  		c.statis[index] = &CacheCallStatisItem{
    66  			cacheType: ac.Protocol,
    67  		}
    68  	}
    69  
    70  	item = c.statis[index]
    71  	if ac.Success {
    72  		item.hitCount += int64(ac.Times)
    73  	} else {
    74  		item.missCount += int64(ac.Times)
    75  
    76  	}
    77  }
    78  
    79  func (c *CacheStatics) printStatics(staticsSlice []*CacheCallStatisItem, startStr string) {
    80  	c.mutex.Lock()
    81  	defer c.mutex.Unlock()
    82  	msg := fmt.Sprintf("Statis %s:\n", startStr)
    83  
    84  	msg += fmt.Sprintf(
    85  		"%-48v|%12v|%12v|%12v|\n", "", "HitCount", "MissCount", "HitRate")
    86  
    87  	for _, item := range staticsSlice {
    88  		if item.hitCount == 0 && item.missCount == 0 {
    89  			continue
    90  		}
    91  		msg += fmt.Sprintf("%-48v|%12v|%12v|%12.3f|\n",
    92  			item.cacheType, item.hitCount, item.missCount,
    93  			float64(item.hitCount)/float64(item.hitCount+item.missCount),
    94  		)
    95  	}
    96  	commonlog.Info(msg)
    97  }
    98  
    99  // log and print the statics messages
   100  func (c *CacheStatics) log() {
   101  	if len(c.statis) == 0 {
   102  		return
   103  	}
   104  
   105  	duplicateStatis := make([]*CacheCallStatisItem, 0, len(c.statis))
   106  	for _, item := range c.statis {
   107  		duplicateStatis = append(duplicateStatis, item)
   108  	}
   109  	c.statis = make(map[string]*CacheCallStatisItem)
   110  
   111  	go c.printStatics(duplicateStatis, commontime.Time2String(time.Now()))
   112  }
   113  
   114  // CacheCallStatis 接口调用统计
   115  type CacheCallStatis struct {
   116  	cacheCall    chan metrics.CallMetric
   117  	cacheStatics *CacheStatics
   118  }
   119  
   120  func NewCacheCallStatis(ctx context.Context) (*CacheCallStatis, error) {
   121  	value := &CacheCallStatis{
   122  		cacheCall: make(chan metrics.CallMetric, 1024),
   123  	}
   124  	value.cacheStatics = NewCacheStatics(value)
   125  
   126  	go func() {
   127  		for {
   128  			select {
   129  			case <-ctx.Done():
   130  				return
   131  			case ac := <-value.cacheCall:
   132  				value.cacheStatics.Add(ac)
   133  			}
   134  		}
   135  	}()
   136  
   137  	return value, nil
   138  }
   139  
   140  // add 添加接口调用数据
   141  func (a *CacheCallStatis) Add(ac metrics.CallMetric) {
   142  	select {
   143  	case a.cacheCall <- ac:
   144  	}
   145  }
   146  
   147  // log 打印接口调用统计
   148  func (a *CacheCallStatis) deal() {
   149  	a.cacheStatics.log()
   150  }