// GetMetricTypes returns metric types for testing func (f *AnotherMock) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) { mts := []plugin.MetricType{} if _, ok := cfg.Table()["test-fail"]; ok { return mts, fmt.Errorf("testing") } if _, ok := cfg.Table()["test"]; ok { mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "anothermock", "test"), Description_: "anothermock description", Unit_: "anothermock unit", }) } mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "anothermock", "foo"), Description_: "anothermock description", Unit_: "anothermock unit", }) mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "anothermock", "bar"), Description_: "anothermock description", Unit_: "anothermock unit", }) mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "anothermock"). AddDynamicElement("host", "name of the host"). AddStaticElement("baz"), Description_: "anothermock description", Unit_: "anothermock unit", }) return mts, nil }
func TestPsutilCollectMetrics(t *testing.T) { Convey("psutil collector", t, func() { p := &Psutil{} Convey("collect metrics", func() { mts := []plugin.MetricType{ plugin.MetricType{ Namespace_: core.NewNamespace("intel", "psutil", "load", "load1"), }, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "psutil", "load", "load5"), }, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "psutil", "load", "load15"), }, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "psutil", "vm", "total"), }, } if runtime.GOOS != "darwin" { mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("intel", "psutil", "cpu", "cpu0", "user"), }) } metrics, err := p.CollectMetrics(mts) So(err, ShouldBeNil) So(metrics, ShouldNotBeNil) }) Convey("get metric types", func() { mts, err := p.GetMetricTypes(plugin.ConfigType{}) So(err, ShouldBeNil) So(mts, ShouldNotBeNil) }) }) }
func TestHANAPublish(t *testing.T) { var buf bytes.Buffer metrics := []plugin.MetricType{ *plugin.NewMetricType(core.NewNamespace("test_string"), time.Now(), nil, "", "example_string"), *plugin.NewMetricType(core.NewNamespace("test_int"), time.Now(), nil, "", 1), *plugin.NewMetricType(core.NewNamespace("test_string_slice"), time.Now(), nil, "", []string{"str1", "str2"}), *plugin.NewMetricType(core.NewNamespace("test_string_slice"), time.Now(), nil, "", []int{1, 2}), *plugin.NewMetricType(core.NewNamespace("test_uint8"), time.Now(), nil, "", uint8(1)), } config := make(map[string]ctypes.ConfigValue) enc := gob.NewEncoder(&buf) enc.Encode(metrics) Convey("TestHANAPublish", t, func() { config["username"] = ctypes.ConfigValueStr{Value: "root"} config["password"] = ctypes.ConfigValueStr{Value: "root"} config["database"] = ctypes.ConfigValueStr{Value: "SNAP_TEST"} config["host"] = ctypes.ConfigValueStr{Value: "localhost"} config["port"] = ctypes.ConfigValueStr{Value: "1433"} config["tablename"] = ctypes.ConfigValueStr{Value: "info"} sp := NewHANAPublisher() cp, _ := sp.GetConfigPolicy() cfg, _ := cp.Get([]string{""}).Process(config) err := sp.Publish("", buf.Bytes(), *cfg) Convey("So not passing in a content type should result in an error", func() { So(err, ShouldResemble, errors.New("Unknown content type ''")) }) err = sp.Publish(plugin.SnapGOBContentType, buf.Bytes(), *cfg) Convey("So publishing metrics should not result in an error", func() { So(err, ShouldBeNil) }) }) }
func TestSubscribe(t *testing.T) { ns := []core.Namespace{ core.NewNamespace("test1"), core.NewNamespace("test2"), core.NewNamespace("test3"), } lp := new(loadedPlugin) ts := time.Now() mt := []*metricType{ newMetricType(ns[0], ts, lp), newMetricType(ns[1], ts, lp), newMetricType(ns[2], ts, lp), } mc := newMetricCatalog() for _, v := range mt { mc.Add(v) } Convey("when the metric is not in the table", t, func() { Convey("then it returns an error", func() { err := mc.Subscribe([]string{"test4"}, -1) So(err.Error(), ShouldContainSubstring, "Metric not found:") }) }) Convey("when the metric is in the table", t, func() { Convey("then it gets correctly increments the count", func() { err := mc.Subscribe([]string{"test1"}, -1) So(err, ShouldBeNil) m, err2 := mc.Get(core.NewNamespace("test1"), -1) So(err2, ShouldBeNil) So(m.subscriptions, ShouldEqual, 1) }) }) }
//GetMetricTypes returns metric types for testing func (n *Ns1) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) { mts := []plugin.MetricType{} mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("raintank", "apps", "ns1", "zones", "*", "qps"), Config_: cfg.ConfigDataNode, }) mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("raintank", "apps", "ns1", "monitoring", "*", "*", "state"), Config_: cfg.ConfigDataNode, }) mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("raintank", "apps", "ns1", "monitoring", "*", "*", "rtt"), Config_: cfg.ConfigDataNode, }) mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("raintank", "apps", "ns1", "monitoring", "*", "*", "loss"), Config_: cfg.ConfigDataNode, }) mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("raintank", "apps", "ns1", "monitoring", "*", "*", "connect"), Config_: cfg.ConfigDataNode, }) return mts, nil }
func TestMetricStaticDynamicNamespace(t *testing.T) { Convey("validateStaticDynamic()", t, func() { Convey("has static elements only", func() { ns := core.NewNamespace("mock", "foo", "bar") err := validateMetricNamespace(ns) So(err, ShouldBeNil) }) Convey("had both static and dynamic elements", func() { ns := core.NewNamespace("mock", "foo", "*", "bar") ns[2].Name = "dynamic element" err := validateMetricNamespace(ns) So(err, ShouldBeNil) }) Convey("has name for a static element", func() { ns := core.NewNamespace("mock", "foo") ns[0].Name = "static element" err := validateMetricNamespace(ns) So(err, ShouldNotBeNil) }) Convey("has * but no name", func() { ns := core.NewNamespace("mock", "foo", "*", "bar") err := validateMetricNamespace(ns) So(err, ShouldNotBeNil) }) }) }
func prepareTestCases() []testCase { hostname, _ := hostnameReader.Hostname() fooTags := map[string]string{ "foo_tag": "foo_val", } barTags := map[string]string{ "foobar_tag": "foobar_val", } tarTags := map[string]string{ "tarqaz_tag": "tarqaz_val", } allTags := map[string]map[string]string{ foo: fooTags, bar: barTags, tar: tarTags, } foobazMetric := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "foo", "baz"), } foobarMetric := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "foo", "bar"), } tarqazMetric := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "tar", "qaz"), } stdMetric := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "std"), } foobazExpected := map[string]string{ core.STD_TAG_PLUGIN_RUNNING_ON: hostname, "foo_tag": "foo_val", } foobarExpected := map[string]string{ core.STD_TAG_PLUGIN_RUNNING_ON: hostname, "foo_tag": "foo_val", "foobar_tag": "foobar_val", } tarqazExpected := map[string]string{ core.STD_TAG_PLUGIN_RUNNING_ON: hostname, "tarqaz_tag": "tarqaz_val", } stdExpected := map[string]string{ core.STD_TAG_PLUGIN_RUNNING_ON: hostname, } testCases := []testCase{ {foobazMetric, allTags, foobazExpected}, {foobarMetric, allTags, foobarExpected}, {tarqazMetric, allTags, tarqazExpected}, {stdMetric, allTags, stdExpected}, {foobazMetric, nil, stdExpected}, } return testCases }
func TestMatchQueryToNamespaces(t *testing.T) { Convey("RPC client errors", t, func() { input := core.NewNamespace("testing", "this") proxy := ControlProxy{Client: mockClient{RpcErr: true}} ns, err := proxy.ExpandWildcards(input) Convey("So the error should be passed through", func() { So(err.Error(), ShouldResemble, rpcErr.Error()) }) Convey("So The namespace ShouldBeNil", func() { So(ns, ShouldBeNil) }) }) Convey("call to Control.MatchQueryToNamespaces returns error", t, func() { input := core.NewNamespace("testing", "this") reply := &rpc.ExpandWildcardsReply{ Error: &common.SnapError{ ErrorFields: map[string]string{}, ErrorString: "Error from control", }, } proxy := ControlProxy{Client: mockClient{MatchReply: reply}} ns, err := proxy.MatchQueryToNamespaces(input) Convey("So the err should be: "+reply.Error.ErrorString, func() { So(err.Error(), ShouldResemble, common.ToSnapError(reply.Error).Error()) }) Convey("So Namespaces should be nil", func() { So(ns, ShouldBeNil) }) }) Convey("Control.MatchQueryToNamespaces returns successfully", t, func() { input := core.NewNamespace("testing", "this") a := core.NewNamespace("testing", "this") b := core.NewNamespace("stuff", "more") proto_a := &rpc.ArrString{S: common.ToNamespace(a)} proto_b := &rpc.ArrString{S: common.ToNamespace(b)} reply := &rpc.ExpandWildcardsReply{ Error: nil, NSS: []*rpc.ArrString{proto_a, proto_b}, } proxy := ControlProxy{Client: mockClient{MatchReply: reply}} ns, err := proxy.MatchQueryToNamespaces(input) Convey("so the err Should be nil", func() { So(err, ShouldBeNil) }) Convey("So namespaces should resemble:"+a.String()+","+b.String(), func() { So(ns, ShouldResemble, []core.Namespace{a, b}) }) }) }
func getMetrics(webserver string, metrics []string) ([]plugin.MetricType, error) { tr := &http.Transport{} client := &http.Client{Transport: tr} resp, err := client.Get(webserver) if err != nil { return nil, err } if resp.StatusCode != 200 { defer resp.Body.Close() return nil, errReqFailed } defer resp.Body.Close() mtsmap := make(map[string]plugin.MetricType) scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { var ns string line := scanner.Text() lineslice := strings.Split(line, ": ") if strings.Contains(line, "Scoreboard") { line = strings.Trim(line, "Scoreboard") for ns := range workers { data := strings.Count(line, workers[ns]) mtsmap[ns] = plugin.MetricType{ Namespace_: core.NewNamespace("intel", "apache", "workers", ns), Data_: data, Timestamp_: time.Now(), } } } else { ns = strings.Replace(lineslice[0], " ", "_", -1) data, err := strconv.ParseFloat(lineslice[1], 64) if err != nil { return nil, err } mtsmap[ns] = plugin.MetricType{ Namespace_: core.NewNamespace("intel", "apache", ns), Data_: data, Timestamp_: time.Now(), } } } if len(metrics) == 0 { mts := make([]plugin.MetricType, 0, len(mtsmap)) for _, v := range mtsmap { mts = append(mts, v) } return mts, nil } mts := make([]plugin.MetricType, 0, len(metrics)) for _, v := range metrics { mt, ok := mtsmap[v] if ok { mts = append(mts, mt) } } return mts, nil }
func TestCreateMetricNamespace(t *testing.T) { Convey("create metric namespace", t, func() { nscreator := nsCreator{} Convey("return an error when metric name is empty", func() { ns, err := nscreator.createMetricNamespace(core.NewNamespace(), "") So(err, ShouldNotBeNil) So(ns, ShouldBeNil) }) Convey("when metric name contains only static elements", func() { ns, err := nscreator.createMetricNamespace(core.NewNamespace("vendor", "plugin"), "disk/total_usage") So(err, ShouldBeNil) So(ns, ShouldNotBeNil) So(ns.String(), ShouldEqual, "/vendor/plugin/disk/total_usage") }) Convey("when metric name contains dynamic element", func() { Convey("return an error for unknown dynamic element", func() { ns, err := nscreator.createMetricNamespace(core.NewNamespace("vendor", "plugin"), "disk/*/usage") So(err, ShouldNotBeNil) So(ns, ShouldBeNil) So(err.Error(), ShouldEqual, "Unknown dynamic element in metric `disk/*/usage` under index 1") }) Convey("successful create metric namespace with dynamic element", func() { // set definition of dynamic element (its name and description) nscreator.dynamicElements = map[string]dynamicElement{ "disk": dynamicElement{"disk_id", "id of disk"}, } ns, err := nscreator.createMetricNamespace(core.NewNamespace("vendor", "plugin"), "disk/*/usage") So(err, ShouldBeNil) So(ns, ShouldNotBeEmpty) So(ns.String(), ShouldEqual, "/vendor/plugin/disk/*/usage") So(ns.Element(3).Description, ShouldEqual, nscreator.dynamicElements["disk"].description) So(ns.Element(3).Name, ShouldEqual, nscreator.dynamicElements["disk"].name) }) Convey("successful create metric namespace with dynamic element at the end of metric name", func() { nscreator.dynamicElements = map[string]dynamicElement{ "percpu_usage": dynamicElement{"cpu_id", "id of cpu"}, } ns, err := nscreator.createMetricNamespace(core.NewNamespace("vendor", "plugin"), "percpu_usage/*") So(err, ShouldBeNil) So(ns, ShouldNotBeEmpty) // metric namespace should not end with an asterisk, // so element `value` is expected to be added So(ns.String(), ShouldEqual, "/vendor/plugin/percpu_usage/*/value") So(ns.Element(3).Description, ShouldEqual, nscreator.dynamicElements["percpu_usage"].description) So(ns.Element(3).Name, ShouldEqual, nscreator.dynamicElements["percpu_usage"].name) }) }) }) }
func (n *Ns1) MonitorsMetrics(client *Client, mts []plugin.MetricType) ([]plugin.MetricType, error) { metrics := make([]plugin.MetricType, 0) conf := mts[0].Config().Table() jobId, ok := conf["jobId"] if !ok || jobId.(ctypes.ConfigValueStr).Value == "" { LogError("jobId missing from config.") return metrics, nil } jobName, ok := conf["jobName"] if !ok || jobName.(ctypes.ConfigValueStr).Value == "" { LogError("jobName missing from config.") return metrics, nil } jSlug := slug.Make(jobName.(ctypes.ConfigValueStr).Value) j, err := client.MonitoringJobById(jobId.(ctypes.ConfigValueStr).Value) if err != nil { LogError("failed to query for job.", err) return nil, err } for region, status := range j.Status { data, ok := statusMap[status.Status] if !ok { return nil, fmt.Errorf("Unknown monitor status") } metrics = append(metrics, plugin.MetricType{ Data_: data, Namespace_: core.NewNamespace("raintank", "apps", "ns1", "monitoring", jSlug, region, "state"), Timestamp_: time.Now(), Version_: mts[0].Version(), }) } jobMetrics, err := client.MonitoringMetics(j.Id) if err != nil { return nil, err } for _, jm := range jobMetrics { for stat, m := range jm.Metrics { metrics = append(metrics, plugin.MetricType{ Data_: m.Avg, Namespace_: core.NewNamespace("raintank", "apps", "ns1", "monitoring", jSlug, jm.Region, stat), Timestamp_: time.Now(), Version_: mts[0].Version(), }) } } return metrics, nil }
func (s *CollectorSuite) TestCollectMetrics() { Convey("Given set of metric types", s.T(), func() { cfg := setupCfg(s.server.URL, "me", "secret", "admin") m1 := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "openstack", "cinder", "demo", "limits", "MaxTotalVolumeGigabytes"), Config_: cfg.ConfigDataNode} m2 := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "openstack", "cinder", "demo", "volumes", "count"), Config_: cfg.ConfigDataNode} m3 := plugin.MetricType{ Namespace_: core.NewNamespace("intel", "openstack", "cinder", "demo", "snapshots", "bytes"), Config_: cfg.ConfigDataNode} Convey("When ColelctMetrics() is called", func() { collector := New() mts, err := collector.CollectMetrics([]plugin.MetricType{m1, m2, m3}) Convey("Then no error should be reported", func() { So(err, ShouldBeNil) }) Convey("and proper metric types are returned", func() { metricNames := map[string]interface{}{} for _, m := range mts { ns := m.Namespace().String() metricNames[ns] = m.Data() fmt.Println(ns, "=", m.Data()) } So(len(mts), ShouldEqual, 3) val, ok := metricNames["/intel/openstack/cinder/demo/limits/MaxTotalVolumeGigabytes"] So(ok, ShouldBeTrue) So(val, ShouldEqual, s.MaxTotalVolumeGigabytes) val, ok = metricNames["/intel/openstack/cinder/demo/volumes/count"] So(ok, ShouldBeTrue) So(val, ShouldEqual, 1) val, ok = metricNames["/intel/openstack/cinder/demo/snapshots/bytes"] So(ok, ShouldBeTrue) So(val, ShouldEqual, s.SnapShotSize*1024*1024*1024) }) }) }) }
//GetMetricTypes returns metric types for testing func (f *Mock) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) { mts := []plugin.MetricType{} if _, ok := cfg.Table()["test-fail"]; ok { return mts, fmt.Errorf("missing on-load plugin config entry 'test'") } if _, ok := cfg.Table()["test"]; ok { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace("intel", "mock", "test")}) } mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace("intel", "mock", "foo")}) mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace("intel", "mock", "bar")}) mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace("intel", "mock"). AddDynamicElement("host", "name of the host"). AddStaticElement("baz")}) return mts, nil }
// GetMetricTypes returns list of available metric types // It returns error in case retrieval was not successful func (c *collector) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) { mts := []plugin.MetricType{} var err error c.allTenants, err = getTenants(cfg) if err != nil { return nil, err } // Generate available namespace for limits namespaces := []string{} for _, tenantName := range c.allTenants { // Construct temporary struct to generate namespace based on tags var metrics struct { S types.Snapshots `json:"snapshots"` V types.Volumes `json:"volumes"` L types.Limits `json:"limits"` } current := strings.Join([]string{vendor, fs, name, tenantName}, "/") ns.FromCompositionTags(metrics, current, &namespaces) } for _, namespace := range namespaces { mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace(strings.Split(namespace, "/")...), Config_: cfg.ConfigDataNode, }) } return mts, nil }
// integration test func TestRiemannPublish(t *testing.T) { // This integration test requires a Riemann Server broker := os.Getenv("SNAP_TEST_RIEMANN") if broker == "" { fmt.Println("Skipping integration tests") return } var buf bytes.Buffer buf.Reset() r := NewRiemannPublisher() config := make(map[string]ctypes.ConfigValue) config["broker"] = ctypes.ConfigValueStr{Value: broker} cp, _ := r.GetConfigPolicy() cfg, _ := cp.Get([]string{""}).Process(config) tags := map[string]string{} tags[core.STD_TAG_PLUGIN_RUNNING_ON] = "bacon-powered" metrics := []plugin.MetricType{ *plugin.NewMetricType(core.NewNamespace("intel", "cpu", "temp"), time.Now(), tags, "some unit", 100), } enc := gob.NewEncoder(&buf) enc.Encode(metrics) err := r.Publish(plugin.SnapGOBContentType, buf.Bytes(), *cfg) Convey("Publish metric to Riemann", t, func() { Convey("So err should not be returned", func() { So(err, ShouldBeNil) }) Convey("So metric retrieved equals metric published", func() { c, _ := raidman.Dial("tcp", broker) events, _ := c.Query("host = \"bacon-powered\"") So(len(events), ShouldBeGreaterThan, 0) }) }) }
func buildMetricTypes(pct plugin.ConfigType) { host := getServer(pct) mMap, err := getNodeMetrics(host) handleErr(err) mts := []plugin.MetricType{} for _, n := range mMap { for ns := range n { namespace := strings.Split(ns, "/") namespace[3] = "*" nss := core.NewNamespace(namespace...) nss[3].Name = "host ID" nss[3].Description = "ID of ES host" mts = append(mts, plugin.MetricType{Namespace_: nss}) } break } metrics, err := getClusterMetrics(host) handleErr(err) for _, m := range metrics { mts = append(mts, plugin.MetricType{Namespace_: m.Namespace()}) } writeMetricTypes(mts) }
func TestCpuPlugin(t *testing.T) { httpmock.Mock = true Convey("getcpuTime Should return cputime value", t, func() { defer httpmock.ResetResponders() httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/trace/count", `{"time_ms": 144123232, "list": []}`, 200) cpuTime, err := getCPUTime("http://192.168.192.200:8000") So(err, ShouldBeNil) So(cpuTime, ShouldEqual, 144123232) }) Convey("CpuStat Should return pluginMetricType Data", t, func() { defer httpmock.ResetResponders() httpmock.RegisterResponder("GET", "http://192.168.192.200:8000/trace/count", `{"time_ms": 144123232, "list": []}`, 200) ns := core.NewNamespace("intel", "osv", "cpu", "cputime") cpuTime, err := cpuStat(ns, "http://192.168.192.200:8000") So(err, ShouldBeNil) So(cpuTime.Namespace(), ShouldResemble, ns) So(cpuTime.Data_, ShouldEqual, 144123232) }) }
func getCPUMetricTypes() ([]plugin.MetricType, error) { var mts []plugin.MetricType for _, metricType := range cpuMetrics { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "cpu", metricType)}) } return mts, nil }
// GetMetricTypes returns list of available metrics func (d *docker) GetMetricTypes(_ plugin.ConfigType) ([]plugin.MetricType, error) { var metricTypes []plugin.MetricType var err error // initialize containerData struct data := containerData{ Stats: wrapper.NewStatistics(), } // generate available namespace for data container structure dockerMetrics := []string{} utils.FromCompositeObject(data, "", &dockerMetrics) nscreator := nsCreator{dynamicElements: definedDynamicElements} for _, metricName := range dockerMetrics { ns := core.NewNamespace(NS_VENDOR, NS_PLUGIN). AddDynamicElement("docker_id", "an id of docker container") if ns, err = nscreator.createMetricNamespace(ns, metricName); err != nil { // skip this metric name which is not supported // fmt.Fprintf(os.Stderr, "Error in creating metric namespace: %v\n", err) continue } metricType := plugin.MetricType{ Namespace_: ns, Version_: VERSION, } metricTypes = append(metricTypes, metricType) } return metricTypes, nil }
// extractFromNamespace extracts element of index i from namespace string func extractFromNamespace(namespace string, i int) (string, error) { ns := core.NewNamespace(strings.Split(strings.TrimPrefix(namespace, "/"), "/")...) if len(ns) < i+1 { return "", fmt.Errorf("Cannot extract element from namespace, index out of range (i = %d)", i) } return ns[i].Value, nil }
func getCounterMetricTypes() ([]plugin.MetricType, error) { var mts []plugin.MetricType for _, counter := range virtioCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "virtio", counter)}) } for _, counter := range netCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "net", counter)}) } for _, counter := range memoryCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "memory", counter)}) } for _, counter := range calloutCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "callout", counter)}) } for _, counter := range waitCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "wait", counter)}) } for _, counter := range asyncCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "async", counter)}) } for _, counter := range vfsCounters { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(Vendor, Name, "trace", "vfs", counter)}) } return mts, nil }
// GetCephDaemonMetrics executes "ceph --admin-daemon perf dump" command for defined daemon-socket and returns its metrics func (ceph *Ceph) GetCephDaemonMetrics(mts []plugin.MetricType, daemon string) ([]plugin.MetricType, error) { out, err := cmd.perfDump(filepath.Join(ceph.path, "ceph"), "--admin-daemon", filepath.Join(ceph.socket.path, daemon), "perf", "dump") timestamp := time.Now() if err != nil { fmt.Fprintf(os.Stderr, "Ceph perf dump command execution failed for socket %+v, err=%+v\n", filepath.Join(ceph.socket.path, daemon), err) return nil, err } var jsonData map[string]interface{} if err := json.Unmarshal(out, &jsonData); err != nil { fmt.Fprintf(os.Stderr, "Cannot unmarshal JSON object from ceph-daemon socket, err=%+v\n", err) return nil, err } daemonNameSplit := strings.Split(trimPrefixAndSuffix(daemon, ceph.socket.prefix, "."+ceph.socket.ext), ".") daemonName := daemonNameSplit[0] daemonID := daemonNameSplit[1] metrics := []plugin.MetricType{} for _, m := range mts { // Get metrics defined in task for this daemon if matchSlice(m.Namespace().Strings()[daemonNameIndex:daemonIDIndex+1], daemonNameSplit) { daemonMetrics := make(map[string]interface{}) ceph.getJSONDataByNamespace(jsonData, m.Namespace().Strings()[daemonIDIndex+1:], []string{}, daemonMetrics) // No metrics found for desired namespace if len(daemonMetrics) == 0 { daemonMetrics[strings.Join(m.Namespace().Strings()[daemonIDIndex+1:], "/")] = nil } for ns, data := range daemonMetrics { metric := plugin.MetricType{ Namespace_: core.NewNamespace(m.Namespace().Strings()[:daemonIDIndex]...).AddStaticElement(daemonID).AddStaticElements(strings.Split(ns, "/")...), Data_: data, // get value of metric Tags_: map[string]string{"daemon_source": daemonName + "." + daemonID}, Timestamp_: timestamp, } assignMetricMeta(&metric, allMetrics) metrics = append(metrics, metric) } } } // No metrics fount at all if len(metrics) == 0 { return metrics, errors.New("No metrics found!") } return metrics, nil }
// GetMetricTypes returns the metric types exposed by pcm func (p *PCM) GetMetricTypes(_ plugin.ConfigType) ([]plugin.MetricType, error) { mts := make([]plugin.MetricType, len(p.keys)) p.mutex.RLock() defer p.mutex.RUnlock() for i, k := range p.keys { mts[i] = plugin.MetricType{Namespace_: core.NewNamespace(strings.Split(strings.TrimPrefix(k, "/"), "/")...)} } return mts, nil }
//GetMetricTypes returns metric types for testing func (p *Ping) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) { mts := []plugin.MetricType{} for _, metricName := range metricNames { mts = append(mts, plugin.MetricType{ Namespace_: core.NewNamespace("worldping", "*", "*", "ping", metricName), }) } return mts, nil }
// GetMetricTypes returns the metric types exposed by snap-plugin-collector-users func (users *Users) GetMetricTypes(_ plugin.ConfigType) ([]plugin.MetricType, error) { mts := []plugin.MetricType{} for m := range users.data { metric := plugin.MetricType{Namespace_: core.NewNamespace(createNamespace(m)...)} mts = append(mts, metric) } return mts, nil }
func get_supported_metrics(source string, cgroups []string, events []string) []plugin.MetricType { mts := []plugin.MetricType{} for _, e := range events { for _, c := range flatten_cg_name(cgroups) { mts = append(mts, plugin.MetricType{Namespace_: core.NewNamespace(ns_vendor, ns_class, ns_type, source, e, c)}) } } return mts }
// GetMetricTypes returns list of available metric types // It returns error in case retrieval was not successful func (p *Plugin) GetMetricTypes(cfg plugin.ConfigType) ([]plugin.MetricType, error) { if !p.initialized { if err := p.init(cfg.Table()); err != nil { return nil, err } } if err := getStats(p.proc_path, p.stats, p.prevMetricsSum, p.cpuMetricsNumber, p.snapMetricsNames, p.procStatMetricsNames); err != nil { return nil, err } metricTypes := []plugin.MetricType{} namespaces := []string{} prefix := filepath.Join(vendor, fs, pluginName) for cpu, stats := range p.stats { for metric, _ := range stats { namespaces = append(namespaces, prefix+"/"+cpu+"/"+metric) } } // List of terminal metric names mList := make(map[string]bool) for _, namespace := range namespaces { namespace = strings.TrimRight(namespace, string(os.PathSeparator)) metricType := plugin.MetricType{ Namespace_: core.NewNamespace(strings.Split(namespace, string(os.PathSeparator))...)} ns := metricType.Namespace() // CPU metric (aka last element in namespace) mItem := ns[len(ns)-1] // Keep it if not already seen before if !mList[mItem.Value] { mList[mItem.Value] = true metricTypes = append(metricTypes, plugin.MetricType{ Namespace_: core.NewNamespace(strings.Split(prefix, string(os.PathSeparator))...). AddDynamicElement("cpuID", "ID of CPU ('all' for aggregate)"). AddStaticElement(mItem.Value), Description_: "dynamic CPU metric: " + mItem.Value, }) } } return metricTypes, nil }
func TestCollectMetrics(t *testing.T) { Convey("RPC client errors", t, func() { proxy := ControlProxy{Client: mockClient{RpcErr: true}} _, errs := proxy.CollectMetrics([]core.Metric{}, time.Now(), "", map[string]map[string]string{}) Convey("So the error should be passed through", func() { So(errs[0].Error(), ShouldResemble, rpcErr.Error()) }) }) Convey("Control.CollectMetrics returns an error", t, func() { reply := &rpc.CollectMetricsResponse{ Metrics: nil, Errors: []string{"error in collect"}, } proxy := ControlProxy{Client: mockClient{CollectReply: reply}} _, errs := proxy.CollectMetrics([]core.Metric{}, time.Now(), "", map[string]map[string]string{}) Convey("So len of errs should be 1", func() { So(len(errs), ShouldEqual, 1) }) Convey("So error should contain the string 'error in collect'", func() { So(errs[0].Error(), ShouldResemble, "error in collect") }) }) Convey("Control.CollectMetrics returns sucessfully", t, func() { reply := &rpc.CollectMetricsResponse{ Metrics: []*common.Metric{&common.Metric{ Namespace: common.ToNamespace(core.NewNamespace("testing", "this")), Version: 6, Tags: map[string]string{}, Timestamp: &common.Time{Sec: time.Now().Unix(), Nsec: int64(time.Now().Nanosecond())}, LastAdvertisedTime: &common.Time{Sec: time.Now().Unix(), Nsec: int64(time.Now().Nanosecond())}, }}, Errors: nil, } proxy := ControlProxy{Client: mockClient{CollectReply: reply}} mts, errs := proxy.CollectMetrics([]core.Metric{}, time.Now(), "", map[string]map[string]string{}) Convey("So len of errs should be 0", func() { So(len(errs), ShouldEqual, 0) }) Convey("So mts should not be nil", func() { So(mts, ShouldNotBeNil) }) Convey("So len of metrics returned should be 1", func() { So(len(mts), ShouldEqual, 1) }) }) }
func TestMetricNamespaceValidation(t *testing.T) { Convey("validateMetricNamespace()", t, func() { Convey("validation passes", func() { ns := core.NewNamespace("mock", "foo", "bar") err := validateMetricNamespace(ns) So(err, ShouldBeNil) }) Convey("contains not allowed characters", func() { ns := core.NewNamespace("mock", "foo", "(bar)") err := validateMetricNamespace(ns) So(err, ShouldNotBeNil) }) Convey("contains unacceptable wildcardat at the end", func() { ns := core.NewNamespace("mock", "foo", "*") err := validateMetricNamespace(ns) So(err, ShouldNotBeNil) }) }) }
func makeMts(cfg *cdata.ConfigDataNode, ns ...string) []plugin.MetricType { res := make([]plugin.MetricType, len(ns)) for i, v := range ns { res[i].Config_ = cfg rns := []string{"intel", "openstack", "nova"} res[i].Namespace_ = core.NewNamespace(append(rns, strings.Split(v, "/")...)...) } return res }