Пример #1
0
// GetQueriedNamespaces returns all matched metrics namespaces for query 'ns' which can contain
// an asterisk or tuple (refer to query support)
func (mc *metricCatalog) GetQueriedNamespaces(ns core.Namespace) ([]core.Namespace, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	// get metric key (might contain wildcard(s))
	wkey := ns.Key()

	return mc.matchedNamespaces(wkey)
}
Пример #2
0
// Remove removes a metricType from the catalog and from matching map
func (mc *metricCatalog) Remove(ns core.Namespace) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	mc.tree.Remove(ns.Strings())

	// remove all items from map mKey mapped for this 'ns'
	key := ns.Key()
	mc.removeMatchedKey(key)
}
Пример #3
0
func traceStat(ns core.Namespace, swagURL string) (*plugin.MetricType, error) {
	trace := ns.Strings()[4]
	metric, err := getTrace(trace, swagURL)
	if err != nil {
		return nil, err
	}
	return &plugin.MetricType{
		Namespace_: ns,
		Data_:      metric,
		Timestamp_: time.Now(),
	}, nil
}
Пример #4
0
// MatchQuery matches given 'ns' which could contain an asterisk or a tuple and add them to matching map under key 'ns'
// The matched metrics namespaces are also returned (as a []core.Namespace)
func (mc *metricCatalog) MatchQuery(ns core.Namespace) ([]core.Namespace, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	// get metric key (might contain wildcard(s))
	wkey := ns.Key()

	// adding matched namespaces to map
	mc.addItemToMatchingMap(wkey)

	return mc.matchedNamespaces(wkey)
}
Пример #5
0
func getDynamicElements(ns core.Namespace, indexes []int) []rbody.DynamicElement {
	elements := make([]rbody.DynamicElement, 0, len(indexes))
	for _, v := range indexes {
		e := ns.Element(v)
		elements = append(elements, rbody.DynamicElement{
			Index:       v,
			Name:        e.Name,
			Description: e.Description,
		})
	}
	return elements
}
Пример #6
0
func (mc *metricCatalog) GetPlugin(mns core.Namespace, ver int) (*loadedPlugin, error) {
	mt, err := mc.tree.GetMetric(mns.Strings(), ver)
	if err != nil {
		log.WithFields(log.Fields{
			"_module": "control",
			"_file":   "metrics.go,",
			"_block":  "get-plugin",
			"error":   err,
		}).Error("error getting plugin")
		return nil, err
	}
	return mt.Plugin, nil
}
Пример #7
0
// validateMetricNamespace validates metric namespace in terms of containing not allowed characters and ending with an asterisk
func validateMetricNamespace(ns core.Namespace) error {
	value := ""
	for _, i := range ns {
		// A dynamic element requires the name while a static element does not.
		if i.Name != "" && i.Value != "*" {
			return errorMetricStaticElementHasName(i.Value, i.Name, ns.String())
		}
		if i.Name == "" && i.Value == "*" {
			return errorMetricDynamicElementHasNoName(i.Value, ns.String())
		}

		value += i.Value
	}

	for _, chars := range notAllowedChars {
		for _, ch := range chars {
			if strings.ContainsAny(value, ch) {
				return errorMetricContainsNotAllowedChars(ns.String())
			}
		}
	}
	// plugin should NOT advertise metrics ending with a wildcard
	if strings.HasSuffix(value, "*") {
		return errorMetricEndsWithAsterisk(ns.String())
	}

	return nil
}
Пример #8
0
// specifyInstanceOfDynamicMetric returns specified namespace of incoming cataloged metric's namespace
// based on requested metric namespace
func specifyInstanceOfDynamicMetric(catalogedNamespace core.Namespace, requestedNamespace core.Namespace) core.Namespace {
	specifiedNamespace := make(core.Namespace, len(catalogedNamespace))
	copy(specifiedNamespace, catalogedNamespace)

	_, indexes := catalogedNamespace.IsDynamic()

	for _, index := range indexes {
		if len(requestedNamespace) > index {
			// use namespace's element of requested metric declared in task manifest
			// to specify a dynamic instance of the cataloged metric
			specifiedNamespace[index].Value = requestedNamespace[index].Value
		}
	}
	return specifiedNamespace
}
Пример #9
0
// GetVersions retrieves all versions of a given metric namespace.
func (mc *metricCatalog) GetVersions(ns core.Namespace) ([]*metricType, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	mts, err := mc.tree.GetVersions(ns.Strings())
	if err != nil {
		log.WithFields(log.Fields{
			"_module": "control",
			"_file":   "metrics.go,",
			"_block":  "get-versions",
			"error":   err,
		}).Error("error getting plugin version")
		return nil, err
	}
	return mts, nil
}
Пример #10
0
// Fetch transactionally retrieves all metrics which fall under namespace ns
func (mc *metricCatalog) Fetch(ns core.Namespace) ([]*metricType, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	mtsi, err := mc.tree.Fetch(ns.Strings())
	if err != nil {
		log.WithFields(log.Fields{
			"_module": "control",
			"_file":   "metrics.go,",
			"_block":  "fetch",
			"error":   err,
		}).Error("error fetching metrics")
		return nil, err
	}
	return mtsi, nil
}
Пример #11
0
// findTuplesMatches returns all matched combination of queried tuples in incoming namespace,
// where a tuple is in the form of `(host0;host1;host3)`. If the incoming namespace:
// - does not contain any tuple, return the incoming namespace as the only item in output slice.
// - contains a tuple, return the copies of incoming namespace with appropriate values set to namespaces' elements
func findTuplesMatches(incomingNs core.Namespace) []core.Namespace {
	// How it works, exemplary incoming namespace:
	// 	"intel", "mock", "(host0;host1)", "(baz;bar)"
	//
	// the following 4 namespaces will be returned:
	// 	"intel", "mock", "host0", "baz"
	// 	"intel", "mock", "host1", "baz"
	// 	"intel", "mock", "host0", "bar"
	// 	"intel", "mock", "host1", "bar"

	matchedItems := make(map[int][]string)
	numOfPossibleCombinations := 1

	for index, element := range incomingNs.Strings() {
		match := []string{}
		if ok, tupleItems := containsTuple(element); ok {
			match = tupleItems
		} else {
			match = []string{element}
		}
		// store matched items under current index of incoming namespace element
		matchedItems[index] = append(matchedItems[index], match...)

		// number of possible combinations increases N=len(match) times
		numOfPossibleCombinations = numOfPossibleCombinations * len(match)
	}

	//prepare slice for returned namespaces (results of tuple find)
	returnedNss := make([]core.Namespace, numOfPossibleCombinations)

	// initialize each of returned namespaces as a copy of incoming namespace
	// (copied original value, name and description of their elements)
	for i := 0; i < numOfPossibleCombinations; i++ {
		returnedNs := make([]core.NamespaceElement, len(incomingNs.Strings()))
		copy(returnedNs, incomingNs)
		returnedNss[i] = returnedNs
	}
	// set appropriate value to namespace's elements
	for index, items := range matchedItems {
		for i := range returnedNss {
			// retrieve the matched item (when 'i' exceeds the number of matched items, start from beginning)
			item := items[i%len(items)]
			returnedNss[i][index].Value = item
		}
	}
	return returnedNss
}
Пример #12
0
// validateMetricNamespace validates metric namespace in terms of containing not allowed characters and ending with an asterisk
func validateMetricNamespace(ns core.Namespace) error {
	name := ""
	for _, i := range ns {
		name += i.Value
	}
	for _, chars := range notAllowedChars {
		for _, ch := range chars {
			if strings.ContainsAny(name, ch) {
				return errorMetricContainsNotAllowedChars(ns.String())
			}
		}
	}
	// plugin should NOT advertise metrics ending with a wildcard
	if strings.HasSuffix(name, "*") {
		return errorMetricEndsWithAsterisk(ns.String())
	}

	return nil
}
Пример #13
0
func memStat(ns core.Namespace, swagURL string) (*plugin.MetricType, error) {
	memType := ns.Strings()[3]
	switch {
	case regexp.MustCompile(`^/` + Vendor + `/` + Name + `/memory/free`).MatchString(ns.String()):
		metric, err := getMemStat(swagURL, memType)
		if err != nil {
			return nil, err
		}
		return &plugin.MetricType{
			Namespace_: ns,
			Data_:      metric,
			Timestamp_: time.Now(),
		}, nil

	case regexp.MustCompile(`^/` + Vendor + `/` + Name + `/memory/total`).MatchString(ns.String()):
		metric, err := getMemStat(swagURL, memType)
		if err != nil {
			return nil, err
		}
		return &plugin.MetricType{
			Namespace_: ns,
			Data_:      metric,
			Timestamp_: time.Now(),
		}, nil

	}

	return nil, fmt.Errorf("Unknown error processing %v", ns)
}
Пример #14
0
// GetMetric retrieves a metric for a given requested namespace and version.
// If provided a version of -1 the latest plugin will be returned.
func (mc *metricCatalog) GetMetric(requested core.Namespace, version int) (*metricType, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	var ns core.Namespace

	catalogedmt, err := mc.tree.GetMetric(requested.Strings(), version)
	if err != nil {
		log.WithFields(log.Fields{
			"_module": "control",
			"_file":   "metrics.go,",
			"_block":  "get-metric",
			"error":   err,
		}).Error("error getting metric")
		return nil, err
	}

	ns = catalogedmt.Namespace()

	if isDynamic, _ := ns.IsDynamic(); isDynamic {
		// when namespace is dynamic and the cataloged namespace (e.g. ns=/intel/mock/*/bar) is different than
		// the requested (e.g. requested=/intel/mock/host0/bar), than specify an instance of dynamic element,
		// so as a result the dynamic element will have set a value (e.g. ns[2].Value equals "host0")
		if ns.String() != requested.String() {
			ns = specifyInstanceOfDynamicMetric(ns, requested)
		}
	}

	returnedmt := &metricType{
		Plugin:             catalogedmt.Plugin,
		namespace:          ns,
		version:            catalogedmt.Version(),
		lastAdvertisedTime: catalogedmt.LastAdvertisedTime(),
		tags:               catalogedmt.Tags(),
		policy:             catalogedmt.Plugin.ConfigPolicy.Get(catalogedmt.Namespace().Strings()),
		config:             catalogedmt.Config(),
		unit:               catalogedmt.Unit(),
		description:        catalogedmt.Description(),
		subscriptions:      catalogedmt.SubscriptionCount(),
	}
	return returnedmt, nil
}
// createMetricNamespace returns metric namespace based on given `ns` which is used as a prefix; all dynamic elements
// in the `metricName` are defined based on content of map `dynamicElements`
func (creator *nsCreator) createMetricNamespace(ns core.Namespace, metricName string) (core.Namespace, error) {
	metricName = strings.TrimSpace(metricName)

	if len(metricName) == 0 {
		return nil, errors.New("Cannot create metric namespace: empty metric name")
	}

	elements := strings.Split(metricName, "/")

	// check if metricName contains only static elements
	if !strings.Contains(metricName, "*") {
		ns = ns.AddStaticElements(elements...)
		return ns, nil
	}

	// when metric name contains dynamic element iterate over elements
	for index, element := range elements {
		if element == "*" {
			// the following element is dynamic
			dynamicElement, ok := creator.dynamicElements[elements[index-1]]
			// check if this dynamic element is supported (name and description are available)
			if !ok {
				return nil, fmt.Errorf("Unknown dynamic element in metric `%s` under index %d", metricName, index)
			}
			// add recognize dynamic element (define its name and description)
			ns = ns.AddDynamicElement(dynamicElement.name, dynamicElement.description)

			if len(elements)-1 == index {
				// in case when an asterisk is the last element, add `value` at the end of ns
				ns = ns.AddStaticElement("value")
			}
		} else {
			// the following element is static
			ns = ns.AddStaticElement(element)
		}
	}
	if len(ns) == 0 {
		return nil, fmt.Errorf("Cannot create metric namespace for metric %s", metricName)
	}
	return ns, nil
}
Пример #16
0
// Get retrieves a metric given a namespace and version.
// If provided a version of -1 the latest plugin will be returned.
func (mc *metricCatalog) Get(ns core.Namespace, version int) (*metricType, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	return mc.get(ns.Strings(), version)
}
Пример #17
0
// Remove removes a metricType from the catalog and from matching map
func (mc *metricCatalog) Remove(ns core.Namespace) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()

	mc.tree.Remove(ns.Strings())
}
Пример #18
0
func parseName(namespace core.Namespace) string {
	return strings.Join(namespace.Strings()[len(namespacePrefix):], "/")
}
Пример #19
0
// GetVersions retrieves all versions of a given metric namespace.
func (mc *metricCatalog) GetVersions(ns core.Namespace) ([]*metricType, error) {
	mc.mutex.Lock()
	defer mc.mutex.Unlock()
	return mc.getVersions(ns.Strings())
}