tags/normalize.go
func normalizeOriginal(s string) (string, error) {
	arr := strings.Split(s, ";")

	if len(arr[0]) == 0 {
		return "", fmt.Errorf("cannot parse path %#v, no metric found", s)
	}

	tags := make(map[string]string)

	for i := 1; i < len(arr); i++ {
		kv := strings.SplitN(arr[i], "=", 2)

		if len(kv) != 2 || len(kv[0]) == 0 {
			return "", fmt.Errorf("cannot parse path %#v, invalid segment %#v", s, arr[i])
		}

		tags[kv[0]] = kv[1]
	}

	tmp := make([]string, len(tags))
	i := 0
	for k, v := range tags {
		tmp[i] = fmt.Sprintf(";%s=%s", k, v)
		i++
	}

	sort.Strings(tmp)

	result := arr[0] + strings.Join(tmp, "")

	return result, nil
}
func normalizeOriginal(s string) (string, error) {
	arr := strings.Split(s, ";")

	if len(arr[0]) == 0 {
		return "", fmt.Errorf("cannot parse path %#v, no metric found", s)
	}

	tags := make(map[string]string)

	for i := 1; i < len(arr); i++ {
		kv := strings.SplitN(arr[i], "=", 2)

		if len(kv) != 2 || len(kv[0]) == 0 {
			return "", fmt.Errorf("cannot parse path %#v, invalid segment %#v", s, arr[i])
		}

		tags[kv[0]] = kv[1]
	}

	tmp := make([]string, len(tags))
	i := 0
	for k, v := range tags {
		tmp[i] = fmt.Sprintf(";%s=%s", k, v)
		i++
	}

	sort.Strings(tmp)

	result := arr[0] + strings.Join(tmp, "")

	return result, nil
}
// as in https://github.com/graphite-project/carbon/blob/master/lib/carbon/util.py