// 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
}
// Recursively traverse the Executor struct, building "/"-delimited strings that resemble snap metric types. If a given
// feature is not enabled on a Mesos agent (e.g. the network isolator), then those metrics will be removed from the
// metric types returned by this function.
func GetMonitoringStatisticsMetricTypes(host string) ([]string, error) {
	log.Debug("Getting monitoring statistics metrics type from host ", host)
	// TODO(roger): supporting NetTrafficControlStatistics means adding another dynamic metric to the plugin.
	// When we're ready to do this, remove ns.InspectEmptyContainers(ns.AlwaysFalse) so this defaults to true.
	namespaces := []string{}
	err := ns.FromCompositeObject(
		&mesos_pb2.ResourceStatistics{}, "", &namespaces, ns.InspectEmptyContainers(ns.AlwaysFalse))
	if err != nil {
		log.Error(err)
		return nil, err
	}

	// Avoid returning a metric type that is impossible to collect on this system
	flags, err := GetFlags(host)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	// Isolators are defined using a comma-separated string passed to the "--isolation" flag on the Mesos agent.
	// See https://github.com/apache/mesos/blob/0.28.1/src/slave/containerizer/mesos/containerizer.cpp#L196-L223
	isolators := strings.Split(flags["isolation"], ",")

	if str.Contains(isolators, "cgroups/perf_event") {
		log.Debug("Isolator cgroups/perf_event is enabled on host ", host)
		// Expects a perf event from the output of `perf list`. Mesos then normalizes the event name. See
		// https://github.com/apache/mesos/blob/0.28.1/src/linux/perf.cpp#L65-L71
		namespaces = deleteFromSlice(namespaces, "^perf/.*")
		var normalizedPerfEvents []string
		perfEvents := strings.Split(flags["perf_events"], ",")

		for _, event := range perfEvents {
			log.Debug("Adding perf event ", event, " to metrics catalog")
			event = fmt.Sprintf("perf/%s", normalizePerfEventName(event))
			normalizedPerfEvents = append(normalizedPerfEvents, event)
		}
		namespaces = append(namespaces, normalizedPerfEvents...)
	} else {
		log.Debug("Isolator cgroups/perf_event is not enabled on host ", host)
		namespaces = deleteFromSlice(namespaces, "^perf.*")
	}

	if !str.Contains(isolators, "posix/disk") {
		log.Debug("Isolator posix/disk is not enabled on host ", host)
		namespaces = deleteFromSlice(namespaces, "^disk_.*")
	}

	if !str.Contains(isolators, "network/port_mapping") {
		log.Debug("Isolator network/port_mapping is not enabled on host ", host)
		namespaces = deleteFromSlice(namespaces, "^net_.*")
	}

	return namespaces, nil
}
// Recursively traverse the Frameworks struct, building "/"-delimited strings that resemble snap metric types.
func GetFrameworksMetricTypes() ([]string, error) {
	log.Debug("Getting frameworks metric types from protobuf (mesos_pb2)")
	namespaces := []string{}
	if err := ns.FromCompositeObject(Framework{}, "", &namespaces); err != nil {
		log.Error(err)
		return nil, err
	}
	for i := 0; i < len(namespaces); i++ {
		if namespaces[i] == "id" {
			namespaces = append(namespaces[:i], namespaces[i+1:]...)
			break
		}
	}
	return namespaces, nil

}