{% import ( "sort" "strings" "github.com/VictoriaMetrics/VictoriaMetrics/lib/logger" ) %} {% stripspace %} MetricsFindResponse generates response for /metrics/find . See https://graphite-api.readthedocs.io/en/latest/api.html#metrics-find {% func MetricsFindResponse(paths []string, delimiter, format string, addWildcards bool, jsonp string) %} {% if jsonp != "" %}{%s= jsonp %}({% endif %} {% switch format %} {% case "completer" %} {%= metricsFindResponseCompleter(paths, delimiter, addWildcards) %} {% case "treejson" %} {%= metricsFindResponseTreeJSON(paths, delimiter, addWildcards) %} {% default %} {% code logger.Panicf("BUG: unexpected format=%q", format) %} {% endswitch %} {% if jsonp != "" %}){% endif %} {% endfunc %} {% func metricsFindResponseCompleter(paths []string, delimiter string, addWildcards bool) %} { "metrics":[ {% for i, path := range paths %} { "path": {%q= path %}, "name": {%= metricPathName(path, delimiter) %}, "is_leaf": {% if strings.HasSuffix(path, delimiter) %}0{% else %}1{% endif %} } {% if i+1 < len(paths) %},{% endif %} {% endfor %} {% if addWildcards && len(paths) > 1 %} ,{ "name": "*" } {% endif %} ] } {% endfunc %} {% func metricsFindResponseTreeJSON(paths []string, delimiter string, addWildcards bool) %} [ {% code if len(paths) > 1 { sort.Strings(paths) // Substitute `path` and `path` with `path`. // Such path is treated specially during rendering - see code below for details. dst := paths[:1] for _, path := range paths[1:] { prevPath := dst[len(dst)-1] if len(path) == len(prevPath)+1 && strings.HasSuffix(path, delimiter) && strings.HasPrefix(path, prevPath) { // The path is equivalent to + // Overwrite the prevPath with + as carbonapi does. // I.e. the resulting path ends with double delimiter. // Such path is treated specially during rendering - see metrics_find_response.qtpl for details. dst[len(dst)-1] = path + delimiter continue } dst = append(dst, path) } paths = dst } %} {% for i, path := range paths %} { {% code id := path allowChildren := "0" isLeaf := "1" if strings.HasSuffix(id, delimiter) { if strings.HasSuffix(id[:len(id)-1], delimiter) { // Special case when id ends with double delimiter. // See the code above for details. id = id[:len(id)-2] } allowChildren = "1" isLeaf = "0" } %} "id": {%q= id %}, "text": {%= metricPathName(path, delimiter) %}, "allowChildren": {%s= allowChildren %}, "expandable": {%s= allowChildren %}, "leaf": {%s= isLeaf %} } {% if i+1 < len(paths) %},{% endif %} {% endfor %} {% if addWildcards && len(paths) > 1 %} ,{ {% code path := paths[0] for strings.HasSuffix(path, delimiter) { path = path[:len(path)-1] } id := "" if n := strings.LastIndexByte(path, delimiter[0]); n >= 0 { id = path[:n+1] } id += "*" allowChildren := "0" isLeaf := "1" for _, path := range paths { if strings.HasSuffix(path, delimiter) { allowChildren = "1" isLeaf = "0" break } } %} "id": {%q= id %}, "text": "*", "allowChildren": {%s= allowChildren %}, "expandable": {%s= allowChildren %}, "leaf": {%s= isLeaf %} } {% endif %} ] {% endfunc %} {% func metricPathName(path, delimiter string) %} {% code name := path for strings.HasSuffix(name, delimiter) { name = name[:len(name)-1] } if n := strings.LastIndexByte(name, delimiter[0]); n >= 0 { name = name[n+1:] } %} {%q= name %} {% endfunc %} {% endstripspace %}