yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/monitor.go (about) 1 // Copyright 2019 Yunion 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 apsara 16 17 import ( 18 "fmt" 19 "time" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/log" 23 "yunion.io/x/pkg/errors" 24 25 "yunion.io/x/cloudmux/pkg/cloudprovider" 26 ) 27 28 const ( 29 APSARA_API_VERSION_METRICS = "2019-01-01" 30 ) 31 32 func (self *SApsaraClient) metricsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) { 33 client, err := self.getDefaultClient("") 34 if err != nil { 35 return nil, errors.Wrap(err, "getDefaultClient") 36 } 37 domain := self.getDomain(APSARA_PRODUCT_METRICS) 38 return productRequest(client, APSARA_PRODUCT_METRICS, domain, APSARA_API_VERSION_METRICS, action, params, self.debug) 39 } 40 41 type MetricData struct { 42 Timestamp int64 43 BucketName string 44 InstanceId string 45 UserId string 46 Value float64 47 Average float64 48 Minimum float64 49 Maximum float64 50 Diskname string 51 Device string 52 } 53 54 func (d MetricData) GetValue() float64 { 55 if d.Average > 0 { 56 return d.Average 57 } 58 if d.Maximum > 0 { 59 return d.Maximum 60 } 61 if d.Minimum > 0 { 62 return d.Minimum 63 } 64 if d.Value > 0 { 65 return d.Value 66 } 67 return 0.0 68 } 69 70 func (d MetricData) GetTags() map[string]string { 71 ret := map[string]string{} 72 if len(d.Device) > 0 { 73 ret[cloudprovider.METRIC_TAG_DEVICE] = fmt.Sprintf("%s(%s)", d.Device, d.Diskname) 74 } 75 return ret 76 } 77 78 func (self *SApsaraClient) ListMetrics(ns, metricName string, start, end time.Time) ([]MetricData, error) { 79 result := []MetricData{} 80 nextToken := "" 81 for { 82 part, next, err := self.listMetrics(ns, metricName, nextToken, start, end) 83 if err != nil { 84 return nil, errors.Wrap(err, "listMetrics") 85 } 86 result = append(result, part...) 87 if len(next) == 0 { 88 break 89 } 90 nextToken = next 91 } 92 return result, nil 93 } 94 95 func (self *SApsaraClient) listMetrics(ns, metricName, nextToken string, start, end time.Time) ([]MetricData, string, error) { 96 params := make(map[string]string) 97 params["MetricName"] = metricName 98 params["Namespace"] = ns 99 params["Length"] = "2000" 100 if len(nextToken) > 0 { 101 params["NextToken"] = nextToken 102 } 103 if len(self.organizationId) > 0 { 104 params["Department"] = self.organizationId 105 } 106 params["StartTime"] = fmt.Sprintf("%d", start.UnixMilli()) 107 params["EndTime"] = fmt.Sprintf("%d", end.UnixMilli()) 108 resp, err := self.metricsRequest("DescribeMetricList", params) 109 if err != nil { 110 return nil, "", errors.Wrap(err, "DescribeMetricList") 111 } 112 ret := struct { 113 NextToken string 114 Datapoints string 115 }{} 116 err = resp.Unmarshal(&ret) 117 if err != nil { 118 return nil, "", errors.Wrapf(err, "resp.Unmarshal") 119 } 120 obj, err := jsonutils.ParseString(ret.Datapoints) 121 if err != nil { 122 return nil, "", errors.Wrap(err, "jsonutils.ParseString") 123 } 124 result := []MetricData{} 125 err = obj.Unmarshal(&result) 126 if err != nil { 127 return nil, "", errors.Wrapf(err, "obj.Unmarshal") 128 } 129 return result, ret.NextToken, nil 130 } 131 132 func (self *SApsaraClient) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 133 switch opts.ResourceType { 134 case cloudprovider.METRIC_RESOURCE_TYPE_SERVER: 135 return self.GetEcsMetrics(opts) 136 case cloudprovider.METRIC_RESOURCE_TYPE_BUCKET: 137 return self.GetOssMetrics(opts) 138 case cloudprovider.METRIC_RESOURCE_TYPE_REDIS: 139 return self.GetRedisMetrics(opts) 140 case cloudprovider.METRIC_RESOURCE_TYPE_RDS: 141 return self.GetRdsMetrics(opts) 142 case cloudprovider.METRIC_RESOURCE_TYPE_LB: 143 return self.GetElbMetrics(opts) 144 default: 145 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.ResourceType) 146 } 147 } 148 149 func (self *SApsaraClient) GetEcsMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 150 metricTags, tagKey := map[string]string{}, "" 151 switch opts.MetricType { 152 case cloudprovider.VM_METRIC_TYPE_CPU_USAGE: 153 metricTags = map[string]string{ 154 "CPUUtilization": "", 155 } 156 case cloudprovider.VM_METRIC_TYPE_NET_BPS_RX: 157 metricTags = map[string]string{ 158 "InternetInRate": cloudprovider.METRIC_TAG_NET_TYPE_INTERNET, 159 "IntranetInRate": cloudprovider.METRIC_TAG_NET_TYPE_INTRANET, 160 } 161 tagKey = cloudprovider.METRIC_TAG_NET_TYPE 162 case cloudprovider.VM_METRIC_TYPE_NET_BPS_TX: 163 metricTags = map[string]string{ 164 "InternetOutRate": cloudprovider.METRIC_TAG_NET_TYPE_INTERNET, 165 "IntranetOutRate": cloudprovider.METRIC_TAG_NET_TYPE_INTRANET, 166 } 167 tagKey = cloudprovider.METRIC_TAG_NET_TYPE 168 case cloudprovider.VM_METRIC_TYPE_DISK_IO_READ_BPS: 169 metricTags = map[string]string{ 170 "DiskReadBPS": "", 171 } 172 case cloudprovider.VM_METRIC_TYPE_DISK_IO_WRITE_BPS: 173 metricTags = map[string]string{ 174 "DiskWriteBPS": "", 175 } 176 case cloudprovider.VM_METRIC_TYPE_DISK_IO_READ_IOPS: 177 metricTags = map[string]string{ 178 "DiskReadIOPS": "", 179 } 180 case cloudprovider.VM_METRIC_TYPE_DISK_IO_WRITE_IOPS: 181 metricTags = map[string]string{ 182 "DiskWriteIOPS": "", 183 } 184 case cloudprovider.VM_METRIC_TYPE_MEM_USAGE: 185 metricTags = map[string]string{ 186 "memory_usedutilization": "", 187 } 188 case cloudprovider.VM_METRIC_TYPE_DISK_USAGE: 189 metricTags = map[string]string{ 190 "diskusage_utilization": "", 191 } 192 default: 193 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.MetricType) 194 } 195 ret := []cloudprovider.MetricValues{} 196 for metric, tag := range metricTags { 197 result, err := self.ListMetrics("acs_ecs_dashboard", metric, opts.StartTime, opts.EndTime) 198 if err != nil { 199 log.Errorf("ListMetric(%s) error: %v", metric, err) 200 continue 201 } 202 tags := map[string]string{} 203 if len(tag) > 0 && len(tagKey) > 0 { 204 tags[tagKey] = tag 205 } 206 for i := range result { 207 dataTag := result[i].GetTags() 208 for k, v := range tags { 209 dataTag[k] = v 210 } 211 ret = append(ret, cloudprovider.MetricValues{ 212 Id: result[i].InstanceId, 213 MetricType: opts.MetricType, 214 Values: []cloudprovider.MetricValue{ 215 { 216 Timestamp: time.UnixMilli(result[i].Timestamp), 217 Value: result[i].GetValue(), 218 Tags: dataTag, 219 }, 220 }, 221 }) 222 } 223 } 224 return ret, nil 225 } 226 227 func (self *SApsaraClient) GetOssMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 228 metricTags, tagKey := map[string]string{}, "" 229 switch opts.MetricType { 230 case cloudprovider.BUCKET_METRIC_TYPE_LATECY: 231 metricTags = map[string]string{ 232 "GetObjectE2eLatency": cloudprovider.METRIC_TAG_REQUST_GET, 233 "PostObjectE2eLatency": cloudprovider.METRIC_TAG_REQUST_GET, 234 } 235 tagKey = cloudprovider.METRIC_TAG_REQUST 236 case cloudprovider.BUCKET_METRIC_TYPE_NET_BPS_TX: 237 metricTags = map[string]string{ 238 "InternetSend": cloudprovider.METRIC_TAG_NET_TYPE_INTERNET, 239 "IntranetSend": cloudprovider.METRIC_TAG_NET_TYPE_INTRANET, 240 } 241 tagKey = cloudprovider.METRIC_TAG_REQUST 242 case cloudprovider.BUCKET_METRIC_TYPE_NET_BPS_RX: 243 metricTags = map[string]string{ 244 "InternetRecv": cloudprovider.METRIC_TAG_NET_TYPE_INTERNET, 245 "IntranetRecv": cloudprovider.METRIC_TAG_NET_TYPE_INTRANET, 246 } 247 tagKey = cloudprovider.METRIC_TAG_NET_TYPE 248 case cloudprovider.BUCKET_METRYC_TYPE_REQ_COUNT: 249 metricTags = map[string]string{ 250 "GetObjectCount": cloudprovider.METRIC_TAG_REQUST_GET, 251 "PostObjectCount": cloudprovider.METRIC_TAG_REQUST_POST, 252 "ServerErrorCount": cloudprovider.METRIC_TAG_REQUST_5XX, 253 } 254 tagKey = cloudprovider.METRIC_TAG_REQUST 255 default: 256 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.MetricType) 257 } 258 ret := []cloudprovider.MetricValues{} 259 for metric, tag := range metricTags { 260 result, err := self.ListMetrics("acs_oss_dashboard", metric, opts.StartTime, opts.EndTime) 261 if err != nil { 262 log.Errorf("ListMetric(%s) error: %v", metric, err) 263 continue 264 } 265 for i := range result { 266 ret = append(ret, cloudprovider.MetricValues{ 267 Id: result[i].BucketName, 268 MetricType: opts.MetricType, 269 Values: []cloudprovider.MetricValue{ 270 { 271 Timestamp: time.UnixMilli(result[i].Timestamp), 272 Value: result[i].GetValue(), 273 Tags: map[string]string{ 274 tagKey: tag, 275 }, 276 }, 277 }, 278 }) 279 } 280 } 281 return ret, nil 282 } 283 284 func (self *SApsaraClient) GetRedisMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 285 metricTags, tagKey := map[string]string{}, "" 286 switch opts.MetricType { 287 case cloudprovider.REDIS_METRIC_TYPE_CPU_USAGE: 288 metricTags = map[string]string{ 289 "CpuUsage": "", 290 } 291 case cloudprovider.REDIS_METRIC_TYPE_MEM_USAGE: 292 metricTags = map[string]string{ 293 "MemoryUsage": "", 294 } 295 case cloudprovider.REDIS_METRIC_TYPE_NET_BPS_RX: 296 metricTags = map[string]string{ 297 "IntranetIn": "", 298 } 299 case cloudprovider.REDIS_METRIC_TYPE_NET_BPS_TX: 300 metricTags = map[string]string{ 301 "IntranetOut": "", 302 } 303 case cloudprovider.REDIS_METRIC_TYPE_USED_CONN: 304 metricTags = map[string]string{ 305 "UsedConnection": "", 306 } 307 case cloudprovider.REDIS_METRIC_TYPE_OPT_SES: 308 metricTags = map[string]string{ 309 "UsedQPS": "", 310 } 311 case cloudprovider.REDIS_METRIC_TYPE_CACHE_KEYS: 312 metricTags = map[string]string{ 313 "Keys": "", 314 } 315 case cloudprovider.REDIS_METRIC_TYPE_CACHE_EXP_KEYS: 316 metricTags = map[string]string{ 317 "ExpiredKeys": "", 318 } 319 case cloudprovider.REDIS_METRIC_TYPE_DATA_MEM_USAGE: 320 metricTags = map[string]string{ 321 "UsedMemory": "", 322 } 323 default: 324 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.MetricType) 325 } 326 ret := []cloudprovider.MetricValues{} 327 for metric, tag := range metricTags { 328 result, err := self.ListMetrics("acs_kvstore", metric, opts.StartTime, opts.EndTime) 329 if err != nil { 330 log.Errorf("ListMetric(%s) error: %v", metric, err) 331 continue 332 } 333 tags := map[string]string{} 334 if len(tag) > 0 && len(tagKey) > 0 { 335 tags[tagKey] = tag 336 } 337 for i := range result { 338 ret = append(ret, cloudprovider.MetricValues{ 339 Id: result[i].InstanceId, 340 MetricType: opts.MetricType, 341 Values: []cloudprovider.MetricValue{ 342 { 343 Timestamp: time.UnixMilli(result[i].Timestamp), 344 Value: result[i].GetValue(), 345 Tags: tags, 346 }, 347 }, 348 }) 349 } 350 } 351 return ret, nil 352 } 353 354 func (self *SApsaraClient) GetRdsMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 355 metrics := map[string]string{} 356 switch opts.MetricType { 357 case cloudprovider.RDS_METRIC_TYPE_CPU_USAGE: 358 metrics = map[string]string{ 359 "CpuUsage": "", 360 } 361 case cloudprovider.RDS_METRIC_TYPE_MEM_USAGE: 362 metrics = map[string]string{ 363 "MemoryUsage": "", 364 } 365 case cloudprovider.RDS_METRIC_TYPE_NET_BPS_RX: 366 metrics = map[string]string{ 367 "MySQL_NetworkInNew": "", 368 "SQLServer_NetworkInNew": "", 369 } 370 case cloudprovider.RDS_METRIC_TYPE_NET_BPS_TX: 371 metrics = map[string]string{ 372 "MySQL_NetworkOutNew": "", 373 "SQLServer_NetworkOutNew": "", 374 } 375 case cloudprovider.RDS_METRIC_TYPE_DISK_USAGE: 376 metrics = map[string]string{ 377 "DiskUsage": "", 378 } 379 case cloudprovider.RDS_METRIC_TYPE_CONN_USAGE: 380 metrics = map[string]string{ 381 "ConnectionUsage": "", 382 } 383 default: 384 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.MetricType) 385 } 386 ret := []cloudprovider.MetricValues{} 387 for metric := range metrics { 388 result, err := self.ListMetrics("acs_rds_dashboard", metric, opts.StartTime, opts.EndTime) 389 if err != nil { 390 log.Errorf("ListMetric(%s) error: %v", metric, err) 391 continue 392 } 393 for i := range result { 394 ret = append(ret, cloudprovider.MetricValues{ 395 Id: result[i].InstanceId, 396 MetricType: opts.MetricType, 397 Values: []cloudprovider.MetricValue{ 398 { 399 Timestamp: time.UnixMilli(result[i].Timestamp), 400 Value: result[i].GetValue(), 401 }, 402 }, 403 }) 404 } 405 } 406 return ret, nil 407 } 408 409 func (self *SApsaraClient) GetElbMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 410 metricTags, tagKey := map[string]string{}, "" 411 switch opts.MetricType { 412 case cloudprovider.LB_METRIC_TYPE_NET_BPS_RX: 413 metricTags = map[string]string{ 414 "InstanceTrafficRX": "", 415 } 416 case cloudprovider.LB_METRIC_TYPE_NET_BPS_TX: 417 metricTags = map[string]string{ 418 "InstanceTrafficTX": "", 419 } 420 case cloudprovider.LB_METRIC_TYPE_HRSP_COUNT: 421 metricTags = map[string]string{ 422 "InstanceStatusCode2xx": cloudprovider.METRIC_TAG_REQUST_2XX, 423 "InstanceStatusCode3xx": cloudprovider.METRIC_TAG_REQUST_3XX, 424 "InstanceStatusCode4xx": cloudprovider.METRIC_TAG_REQUST_4XX, 425 "InstanceStatusCode5xx": cloudprovider.METRIC_TAG_REQUST_5XX, 426 } 427 tagKey = cloudprovider.METRIC_TAG_REQUST 428 default: 429 return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "%s", opts.MetricType) 430 } 431 ret := []cloudprovider.MetricValues{} 432 for metric, tag := range metricTags { 433 result, err := self.ListMetrics("acs_slb_dashboard", metric, opts.StartTime, opts.EndTime) 434 if err != nil { 435 log.Errorf("ListMetric(%s) error: %v", metric, err) 436 continue 437 } 438 tags := map[string]string{} 439 if len(tag) > 0 && len(tagKey) > 0 { 440 tags[tagKey] = tag 441 } 442 for i := range result { 443 ret = append(ret, cloudprovider.MetricValues{ 444 Id: result[i].InstanceId, 445 MetricType: opts.MetricType, 446 Values: []cloudprovider.MetricValue{ 447 { 448 Timestamp: time.UnixMilli(result[i].Timestamp), 449 Value: result[i].GetValue(), 450 Tags: tags, 451 }, 452 }, 453 }) 454 } 455 } 456 return ret, nil 457 }