github.com/matrixorigin/matrixone@v0.7.0/pkg/util/metric/metric_test.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 package metric 15 16 import ( 17 "bytes" 18 "context" 19 "fmt" 20 "io" 21 "net/http" 22 "strings" 23 "testing" 24 "time" 25 26 "github.com/matrixorigin/matrixone/pkg/config" 27 "github.com/matrixorigin/matrixone/pkg/util/export/table" 28 prom "github.com/prometheus/client_golang/prometheus" 29 "github.com/stretchr/testify/assert" 30 "github.com/stretchr/testify/require" 31 ) 32 33 const InternalExecutor = "InternalExecutor" 34 const FileService = "FileService" 35 36 func TestMetric(t *testing.T) { 37 sqlch := make(chan string, 100) 38 factory := newExecutorFactory(sqlch) 39 40 withModifiedConfig(func() { 41 SV := &config.ObservabilityParameters{} 42 SV.SetDefaultValues("test") 43 SV.Host = "0.0.0.0" 44 SV.StatusPort = 7001 45 SV.EnableMetricToProm = true 46 SV.BatchProcessor = FileService 47 SV.MetricExportInterval = 1 48 SV.MetricMultiTable = true 49 defer setGatherInterval(setGatherInterval(30 * time.Millisecond)) 50 defer setRawHistBufLimit(setRawHistBufLimit(5)) 51 InitMetric(context.TODO(), factory, SV, "node_uuid", "test", WithInitAction(true)) 52 defer StopMetricSync() 53 54 const ( 55 none = "--None" 56 createDB = "create database" 57 createTbl = "create EXTERNAL table" 58 insertRow = "insert into" 59 ) 60 prevSqlKind := none 61 for sql := range sqlch { 62 if strings.HasPrefix(sql, prevSqlKind) { 63 continue 64 } 65 switch prevSqlKind { 66 case none: 67 require.True(t, strings.HasPrefix(sql, createDB), "income sql: %s", sql) 68 prevSqlKind = createDB 69 case createDB: 70 require.True(t, strings.HasPrefix(sql, createTbl), "income sql: %s", sql) 71 prevSqlKind = createTbl 72 case createTbl: 73 require.True(t, strings.HasPrefix(sql, insertRow), "income sql: %s", sql) 74 goto GOON 75 default: 76 require.True(t, false, "unknow sql kind %s", sql) 77 } 78 } 79 GOON: 80 client := http.Client{ 81 Timeout: 120 * time.Second, 82 } 83 r, err := client.Get("http://127.0.0.1:7001/metrics") 84 require.Nil(t, err) 85 require.Equal(t, r.StatusCode, 200) 86 87 content, _ := io.ReadAll(r.Body) 88 require.Contains(t, string(content), "# HELP") // check we have metrics output 89 }) 90 } 91 92 func TestMetricNoProm(t *testing.T) { 93 sqlch := make(chan string, 100) 94 factory := newExecutorFactory(sqlch) 95 96 withModifiedConfig(func() { 97 SV := &config.ObservabilityParameters{} 98 SV.SetDefaultValues("test") 99 SV.Host = "0.0.0.0" 100 SV.StatusPort = 7001 101 SV.EnableMetricToProm = false 102 SV.BatchProcessor = FileService 103 SV.MetricMultiTable = true 104 105 defer setGatherInterval(setGatherInterval(30 * time.Millisecond)) 106 defer setRawHistBufLimit(setRawHistBufLimit(5)) 107 InitMetric(context.TODO(), factory, SV, "node_uuid", "test", WithInitAction(true)) 108 defer StopMetricSync() 109 110 client := http.Client{ 111 Timeout: 120 * time.Second, 112 } 113 _, err := client.Get("http://127.0.0.1:7001/metrics") 114 require.NotNil(t, err) 115 require.Contains(t, err.Error(), "connection refused") 116 117 // make static-check(errcheck) happay 118 SV.EnableMetricToProm = true 119 }) 120 } 121 122 func TestDescExtra(t *testing.T) { 123 desc := prom.NewDesc("sys_xxx_yyy_FEFA", "help info", []string{"is_internal", "xy"}, map[string]string{"node": "1"}) 124 extra := newDescExtra(desc) 125 assert.Equal(t, extra.fqName, "sys_xxx_yyy_FEFA") 126 assert.Equal(t, extra.labels[0].GetName(), "is_internal") 127 assert.Equal(t, extra.labels[1].GetName(), "node") 128 assert.Equal(t, extra.labels[2].GetName(), "xy") 129 } 130 131 var dummyOptionsFactory = table.GetOptionFactory(context.TODO(), table.NormalTableEngine) 132 133 func TestCreateTable(t *testing.T) { 134 buf := new(bytes.Buffer) 135 name := "sql_test_counter" 136 sql := createTableSqlFromMetricFamily(prom.NewDesc(name, "", []string{"zzz", "aaa"}, nil), buf, dummyOptionsFactory) 137 assert.Equal(t, sql, fmt.Sprintf( 138 "create table if not exists %s.%s (`%s` datetime(6), `%s` double, `%s` varchar(36), `%s` varchar(20), `aaa` varchar(20), `zzz` varchar(20))", 139 MetricDBConst, name, lblTimeConst, lblValueConst, lblNodeConst, lblRoleConst, 140 )) 141 142 sql = createTableSqlFromMetricFamily(prom.NewDesc(name, "", nil, nil), buf, dummyOptionsFactory) 143 assert.Equal(t, sql, fmt.Sprintf( 144 "create table if not exists %s.%s (`%s` datetime(6), `%s` double, `%s` varchar(36), `%s` varchar(20))", 145 MetricDBConst, name, lblTimeConst, lblValueConst, lblNodeConst, lblRoleConst, 146 )) 147 } 148 149 func TestMetricSingleTable(t *testing.T) { 150 sqlch := make(chan string, 100) 151 factory := newExecutorFactory(sqlch) 152 153 withModifiedConfig(func() { 154 SV := &config.ObservabilityParameters{} 155 SV.SetDefaultValues("test") 156 SV.Host = "0.0.0.0" 157 SV.StatusPort = 7001 158 SV.EnableMetricToProm = true 159 SV.BatchProcessor = FileService 160 SV.MetricExportInterval = 1 161 SV.MetricMultiTable = false 162 defer setGatherInterval(setGatherInterval(30 * time.Millisecond)) 163 defer setRawHistBufLimit(setRawHistBufLimit(5)) 164 InitMetric(context.TODO(), factory, SV, "node_uuid", "test", WithInitAction(true)) 165 defer StopMetricSync() 166 167 const ( 168 none = "--None" 169 createDB = "create database" 170 createTbl = "CREATE EXTERNAL TABLE" 171 createView = "CREATE VIEW" 172 insertRow = "insert into" 173 ) 174 prevSqlKind := none 175 for sql := range sqlch { 176 t.Logf("sql: %s", sql) 177 if strings.HasPrefix(sql, prevSqlKind) { 178 continue 179 } 180 switch prevSqlKind { 181 case none: 182 require.True(t, strings.HasPrefix(sql, createDB), "income sql: %s", sql) 183 prevSqlKind = createDB 184 case createDB: 185 require.True(t, strings.HasPrefix(sql, createTbl), "income sql: %s", sql) 186 prevSqlKind = createTbl 187 case createTbl: 188 require.True(t, strings.HasPrefix(sql, createView), "income sql: %s", sql) 189 prevSqlKind = createView 190 case createView: 191 require.True(t, strings.HasPrefix(sql, insertRow), "income sql: %s", sql) 192 goto GOON 193 default: 194 require.True(t, false, "unknow sql kind %s", sql) 195 } 196 } 197 GOON: 198 client := http.Client{ 199 Timeout: 120 * time.Second, 200 } 201 r, err := client.Get("http://127.0.0.1:7001/metrics") 202 require.Nil(t, err) 203 require.Equal(t, r.StatusCode, 200) 204 205 content, _ := io.ReadAll(r.Body) 206 require.Contains(t, string(content), "# HELP") // check we have metrics output 207 }) 208 } 209 210 func TestGetSchemaForAccount(t *testing.T) { 211 type args struct { 212 account string 213 } 214 tests := []struct { 215 name string 216 args args 217 wantPath string 218 wantSche int 219 }{ 220 { 221 name: "test_account_user1", 222 args: args{ 223 account: "user1", 224 }, 225 wantPath: "/user1/*/*/*/*/metric/*", 226 wantSche: 7, 227 }, 228 } 229 ctx := context.Background() 230 for _, tt := range tests { 231 t.Run(tt.name, func(t *testing.T) { 232 schemas := GetSchemaForAccount(ctx, tt.args.account) 233 found := false 234 for _, sche := range schemas { 235 t.Logf("schma: %s", sche) 236 if strings.Contains(sche, tt.wantPath) { 237 found = true 238 } 239 } 240 require.Equal(t, tt.wantSche, len(schemas)) 241 require.Equal(t, true, found) 242 found = false 243 if strings.Contains(SingleMetricTable.ToCreateSql(ctx, true), "/*/*/*/*/*/metric/*") { 244 found = true 245 } 246 require.Equal(t, true, found) 247 }) 248 } 249 }