vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/throttle/mysql/mysql_throttle_metric.go (about) 1 /* 2 Copyright 2017 GitHub Inc. 3 4 Licensed under MIT License. See https://github.com/github/freno/blob/master/LICENSE 5 */ 6 7 package mysql 8 9 import ( 10 "fmt" 11 "strings" 12 "time" 13 14 "github.com/patrickmn/go-cache" 15 16 "vitess.io/vitess/go/stats" 17 ) 18 19 // MetricsQueryType indicates the type of metrics query on MySQL backend. See following. 20 type MetricsQueryType int 21 22 const ( 23 // MetricsQueryTypeDefault indictes the default, internal implementation. Specifically, our throttler runs a replication lag query 24 MetricsQueryTypeDefault MetricsQueryType = iota 25 // MetricsQueryTypeShowGlobal indicatesa SHOW GLOBAL (STATUS|VARIABLES) query 26 MetricsQueryTypeShowGlobal 27 // MetricsQueryTypeSelect indicates a custom SELECT query 28 MetricsQueryTypeSelect 29 // MetricsQueryTypeUnknown is an unknown query type, which we cannot run. This is an error 30 MetricsQueryTypeUnknown 31 ) 32 33 var mysqlMetricCache = cache.New(cache.NoExpiration, 10*time.Second) 34 35 func getMySQLMetricCacheKey(probe *Probe) string { 36 return fmt.Sprintf("%s:%s", probe.Key, probe.MetricQuery) 37 } 38 39 func cacheMySQLThrottleMetric(probe *Probe, mySQLThrottleMetric *MySQLThrottleMetric) *MySQLThrottleMetric { 40 if mySQLThrottleMetric.Err != nil { 41 return mySQLThrottleMetric 42 } 43 if probe.CacheMillis > 0 { 44 mysqlMetricCache.Set(getMySQLMetricCacheKey(probe), mySQLThrottleMetric, time.Duration(probe.CacheMillis)*time.Millisecond) 45 } 46 return mySQLThrottleMetric 47 } 48 49 func getCachedMySQLThrottleMetric(probe *Probe) *MySQLThrottleMetric { 50 if probe.CacheMillis == 0 { 51 return nil 52 } 53 if metric, found := mysqlMetricCache.Get(getMySQLMetricCacheKey(probe)); found { 54 mySQLThrottleMetric, _ := metric.(*MySQLThrottleMetric) 55 return mySQLThrottleMetric 56 } 57 return nil 58 } 59 60 // GetMetricsQueryType analyzes the type of a metrics query 61 func GetMetricsQueryType(query string) MetricsQueryType { 62 if query == "" { 63 return MetricsQueryTypeDefault 64 } 65 if strings.HasPrefix(strings.ToLower(query), "select") { 66 return MetricsQueryTypeSelect 67 } 68 if strings.HasPrefix(strings.ToLower(query), "show global") { 69 return MetricsQueryTypeShowGlobal 70 } 71 return MetricsQueryTypeUnknown 72 } 73 74 // MySQLThrottleMetric has the probed metric for a mysql instance 75 type MySQLThrottleMetric struct { // nolint:revive 76 ClusterName string 77 Key InstanceKey 78 Value float64 79 Err error 80 } 81 82 // NewMySQLThrottleMetric creates a new MySQLThrottleMetric 83 func NewMySQLThrottleMetric() *MySQLThrottleMetric { 84 return &MySQLThrottleMetric{Value: 0} 85 } 86 87 // GetClusterInstanceKey returns the ClusterInstanceKey part of the metric 88 func (metric *MySQLThrottleMetric) GetClusterInstanceKey() ClusterInstanceKey { 89 return GetClusterInstanceKey(metric.ClusterName, &metric.Key) 90 } 91 92 // Get implements MetricResult 93 func (metric *MySQLThrottleMetric) Get() (float64, error) { 94 return metric.Value, metric.Err 95 } 96 97 // ReadThrottleMetric returns a metric for the given probe. Either by explicit query 98 // or via SHOW SLAVE STATUS 99 func ReadThrottleMetric(probe *Probe, clusterName string, overrideGetMetricFunc func() *MySQLThrottleMetric) (mySQLThrottleMetric *MySQLThrottleMetric) { 100 if mySQLThrottleMetric := getCachedMySQLThrottleMetric(probe); mySQLThrottleMetric != nil { 101 return mySQLThrottleMetric 102 // On cached results we avoid taking latency metrics 103 } 104 105 started := time.Now() 106 mySQLThrottleMetric = NewMySQLThrottleMetric() 107 mySQLThrottleMetric.ClusterName = clusterName 108 mySQLThrottleMetric.Key = probe.Key 109 110 defer func(metric *MySQLThrottleMetric, started time.Time) { 111 go func() { 112 stats.GetOrNewGauge("ThrottlerProbesLatency", "probes latency").Set(time.Since(started).Nanoseconds()) 113 stats.GetOrNewCounter("ThrottlerProbesTotal", "total probes").Add(1) 114 if metric.Err != nil { 115 stats.GetOrNewCounter("ThrottlerProbesError", "total probes errors").Add(1) 116 } 117 }() 118 }(mySQLThrottleMetric, started) 119 120 mySQLThrottleMetric = overrideGetMetricFunc() 121 return cacheMySQLThrottleMetric(probe, mySQLThrottleMetric) 122 }