github.com/wfusion/gofusion@v1.1.14/db/metrics.go (about) 1 package db 2 3 import ( 4 "context" 5 "log" 6 "syscall" 7 "time" 8 9 "github.com/wfusion/gofusion/common/utils" 10 "github.com/wfusion/gofusion/config" 11 "github.com/wfusion/gofusion/metrics" 12 ) 13 14 var ( 15 metricsPoolIdleKey = []string{"db", "idle"} 16 metricsPoolTotalKey = []string{"db", "total"} 17 metricsPoolInUseKey = []string{"db", "inuse"} 18 metricsPoolWaitCountKey = []string{"db", "wait", "count"} 19 metricsPoolWaitDurationKey = []string{"db", "wait", "duration"} 20 metricsLatencyKey = []string{"db", "latency"} 21 metricsLatencyBuckets = []float64{ 22 .1, .25, .5, .75, .90, .95, .99, 23 1, 2.5, 5, 7.5, 9, 9.5, 9.9, 24 10, 25, 50, 75, 90, 95, 99, 25 } 26 ) 27 28 func startDaemonRoutines(ctx context.Context, appName, name string, conf *Conf) { 29 ticker := time.Tick(time.Second * 5) 30 app := config.Use(appName).AppName() 31 labels := []metrics.Label{ 32 {Key: "config", Value: name}, 33 {Key: "database", Value: conf.DB}, 34 } 35 36 log.Printf("%v [Gofusion] %s %s %s metrics start", syscall.Getpid(), app, config.ComponentDB, name) 37 for { 38 select { 39 case <-ctx.Done(): 40 log.Printf("%v [Gofusion] %s %s %s metrics exited", 41 syscall.Getpid(), app, config.ComponentDB, name) 42 return 43 case <-ticker: 44 go metricDBStats(ctx, appName, name, labels) 45 go metricDBLatency(ctx, appName, name, labels) 46 } 47 } 48 } 49 50 func metricDBStats(ctx context.Context, appName, name string, labels []metrics.Label) { 51 select { 52 case <-ctx.Done(): 53 return 54 default: 55 } 56 57 _, _ = utils.Catch(func() { 58 rwlock.RLock() 59 defer rwlock.RUnlock() 60 61 instances, ok := appInstances[appName] 62 if !ok { 63 return 64 } 65 instance, ok := instances[name] 66 if !ok { 67 return 68 } 69 db := instance.GetProxy() 70 sqlDB, err := db.DB() 71 if err != nil { 72 return 73 } 74 75 app := config.Use(appName).AppName() 76 idleKey := append([]string{app}, metricsPoolIdleKey...) 77 inuseKey := append([]string{app}, metricsPoolInUseKey...) 78 totalKey := append([]string{app}, metricsPoolTotalKey...) 79 waitCountKey := append([]string{app}, metricsPoolWaitCountKey...) 80 waitDurationKey := append([]string{app}, metricsPoolWaitDurationKey...) 81 82 stats := sqlDB.Stats() 83 waitDuration := float64(stats.WaitDuration) / float64(time.Millisecond) 84 for _, m := range metrics.Internal(metrics.AppName(appName)) { 85 select { 86 case <-ctx.Done(): 87 return 88 default: 89 if m.IsEnableServiceLabel() { 90 m.SetGauge(ctx, idleKey, float64(stats.Idle), metrics.Labels(labels)) 91 m.SetGauge(ctx, inuseKey, float64(stats.InUse), metrics.Labels(labels)) 92 m.SetGauge(ctx, totalKey, float64(stats.OpenConnections), metrics.Labels(labels)) 93 m.SetGauge(ctx, waitCountKey, float64(stats.WaitCount), metrics.Labels(labels)) 94 m.SetGauge(ctx, waitDurationKey, waitDuration, metrics.Labels(labels)) 95 } else { 96 m.SetGauge(ctx, metricsPoolIdleKey, float64(stats.Idle), metrics.Labels(labels)) 97 m.SetGauge(ctx, metricsPoolInUseKey, float64(stats.InUse), metrics.Labels(labels)) 98 m.SetGauge(ctx, metricsPoolTotalKey, float64(stats.OpenConnections), metrics.Labels(labels)) 99 m.SetGauge(ctx, metricsPoolWaitCountKey, float64(stats.WaitCount), metrics.Labels(labels)) 100 m.SetGauge(ctx, metricsPoolWaitDurationKey, waitDuration, metrics.Labels(labels)) 101 } 102 } 103 } 104 }) 105 } 106 107 func metricDBLatency(ctx context.Context, appName, name string, labels []metrics.Label) { 108 select { 109 case <-ctx.Done(): 110 return 111 default: 112 } 113 114 _, _ = utils.Catch(func() { 115 rwlock.RLock() 116 defer rwlock.RUnlock() 117 instances, ok := appInstances[appName] 118 if !ok { 119 return 120 } 121 instance, ok := instances[name] 122 if !ok { 123 return 124 } 125 db := instance.GetProxy() 126 sqlDB, err := db.DB() 127 if err != nil { 128 return 129 } 130 131 begin := time.Now() 132 if err := sqlDB.Ping(); err != nil { 133 return 134 } 135 latency := float64(time.Since(begin)) / float64(time.Millisecond) 136 latencyKey := append([]string{config.Use(appName).AppName()}, metricsLatencyKey...) 137 for _, m := range metrics.Internal(metrics.AppName(appName)) { 138 select { 139 case <-ctx.Done(): 140 return 141 default: 142 if m.IsEnableServiceLabel() { 143 m.AddSample(ctx, latencyKey, latency, 144 metrics.Labels(labels), 145 metrics.PrometheusBuckets(metricsLatencyBuckets), 146 ) 147 } else { 148 m.AddSample(ctx, metricsLatencyKey, latency, 149 metrics.Labels(labels), 150 metrics.PrometheusBuckets(metricsLatencyBuckets), 151 ) 152 } 153 } 154 } 155 }) 156 }