// CollectMetrics returns filled mts table with metric values. Limits and quotas // are colllected once per tenant. All hypervisor related statistics are collected // in one call. This method also performs lazy initalization of plugin. Error // is returned if initalization or any of required call failed. func (self *NovaPlugin) CollectMetrics(mts []plugin.MetricType) ([]plugin.MetricType, error) { if len(mts) > 0 { err := self.init(mts[0]) if err != nil { return nil, err } } else { return mts, nil } t := time.Now() limitsFor := map[string]bool{} quotasFor := map[string]bool{} hypervisors := false cluster := false results := make([]plugin.MetricType, len(mts)) for _, mt := range mts { id, group, subgroup, _ := parseName(mt.Namespace().Strings()) if group == GROUP_CLUSTER { cluster = true continue } if group == GROUP_HYPERVISOR { hypervisors = true } else { if subgroup == SUBGROUP_LIMITS { limitsFor[id] = true } else { quotasFor[id] = true } } } cachedLimits := map[string]map[string]interface{}{} for tenant, _ := range limitsFor { limits, err := self.collector.GetLimits(tenant) if err != nil { return nil, fmt.Errorf("cannot read limits for %v: (%v)", tenant, err) } cachedLimits[tenant] = limits } cachedQuotas := map[string]map[string]interface{}{} var tenantIds map[string]string = nil for tenant, _ := range quotasFor { if tenantIds == nil { tenantIds2, err := self.collector.GetTenants() if err != nil { return nil, fmt.Errorf("cannot get tenants list: (%v)", err) } tenantIds = tenantIds2 } quotas, err := self.collector.GetQuotas(tenant, tenantIds[tenant]) if err != nil { return nil, fmt.Errorf("cannot read quotas for %v: (%v)", tenant, err) } cachedQuotas[tenant] = quotas } cachedHypervisor := map[string]map[string]interface{}{} if hypervisors { hStats, err := self.collector.GetHypervisors() if err != nil { return nil, fmt.Errorf("cannot read hypervisors: (%v)", err) } cachedHypervisor = hStats } cachedClusterConfig := map[string]interface{}{} if cluster { cachedClusterConfig = self.collector.GetClusterConfig() } for i, mt := range mts { id, group, subgroup, metric := parseName(mt.Namespace().Strings()) mt := plugin.MetricType{ Namespace_: mt.Namespace(), Timestamp_: t, } if group == GROUP_CLUSTER && id == ID_CONFIG { mt.Data_ = cachedClusterConfig[metric] } else { if group == GROUP_HYPERVISOR { mt.Data_ = cachedHypervisor[id][metric] } else { if subgroup == SUBGROUP_LIMITS { mt.Data_ = cachedLimits[id][metric] } else { mt.Data_ = cachedQuotas[id][metric] } } } results[i] = mt } return results, nil }
func gathermts(host string, filter []string) ([]plugin.MetricType, error) { resp, err := http.Get(fmt.Sprintf("%s/metrics", host)) if err != nil { return nil, err } if resp.StatusCode != 200 { return nil, errReqFailed } mtsmap := make(map[string]plugin.MetricType) scanner := bufio.NewScanner(resp.Body) if err != nil { return nil, err } for scanner.Scan() { txt := scanner.Text() if !strings.Contains(txt, "{") && !strings.Contains(txt, "#") { nsslice := strings.Split(txt, " ") mtsmap[nsslice[0]] = plugin.MetricType{ Namespace_: core.NewNamespace("intel", "etcd", nsslice[0]), Data_: nsslice[1], Timestamp_: time.Now(), } } } // No filter given; this was a GetMetricTypes call. if len(filter) == 0 { mts := make([]plugin.MetricType, 0, len(mtsmap)+len(derivatives)) for _, v := range mtsmap { mts = append(mts, v) } for k := range derivatives { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace("intel", "etcd", "derivative", k)}) } return mts, nil } // Walk through filter and pluck out metrics. // if we find the requested metric in derivatives, // then derive the value from `from`. mts := make([]plugin.MetricType, 0, len(filter)) for _, f := range filter { from, ok := derivatives[f] if ok { mt := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "etcd", "derivative", f), Timestamp_: time.Now(), } sum, err := strconv.ParseFloat(mtsmap[from[0]].Data_.(string), 64) if err != nil { return nil, err } count, err := strconv.ParseFloat(mtsmap[from[1]].Data_.(string), 64) if err != nil { return nil, err } mt.Data_ = sum / count mts = append(mts, mt) continue } mt, ok := mtsmap[f] if ok { mts = append(mts, mt) } } return mts, nil }