github.com/openshift-online/ocm-sdk-go@v0.1.473/metrics/path_tree.go (about)

     1  /*
     2  Copyright (c) 2021 Red Hat, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8    http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // This file contains the type that describes trees of URL paths used to translate request paths
    18  // into labes suitalbe for use as Prometheus labels.
    19  
    20  package metrics
    21  
    22  import (
    23  	"strings"
    24  
    25  	jsoniter "github.com/json-iterator/go"
    26  )
    27  
    28  // pathTree defines a tree of URL paths that will be used to transform request paths into labels
    29  // suitable for use in Prometheus metrics. For example, a server that has these URL paths:
    30  //
    31  //	/api
    32  //	/api/clusters_mgmt
    33  //	/api/clusters_mgmt/v1
    34  //	/api/clusters_mgmt/v1/clusters
    35  //	/api/clusters_mgmt/v1/clusters/{cluster_id}
    36  //	/api/clusters_mgmt/v1/clusters/{cluster_id}/groups
    37  //	/api/clusters_mgmt/v1/clusters/{cluster_id}/groups/{group_id}
    38  //
    39  // Will be described with a tree like this:
    40  //
    41  //	var pathRoot = pathTree{
    42  //		"api": {
    43  //			"clusters_mgmt": {
    44  //				"v1": {
    45  //					"clusters": {
    46  //						"-": {
    47  //							"groups": {
    48  //								"-": nil,
    49  //							},
    50  //						},
    51  //					},
    52  //				},
    53  //			},
    54  //		},
    55  //	}
    56  //
    57  // Path variables are represented with a dash.
    58  type pathTree map[string]pathTree
    59  
    60  // copy creates a deep copy of this tree.
    61  func (t pathTree) copy() pathTree {
    62  	if t == nil {
    63  		return nil
    64  	}
    65  	tree := pathTree{}
    66  	for label, child := range t {
    67  		tree[label] = child.copy()
    68  	}
    69  	return tree
    70  }
    71  
    72  // add adds the given branch to this tree.
    73  func (t pathTree) add(path string) {
    74  	path = t.clean(path)
    75  	if len(path) == 0 {
    76  		return
    77  	}
    78  	segments := strings.Split(path, "/")
    79  	t.addSegments(segments)
    80  }
    81  
    82  func (t pathTree) addSegments(segments []string) {
    83  	if len(segments) == 0 {
    84  		return
    85  	}
    86  	head := segments[0]
    87  	tail := segments[1:]
    88  	next := t[head]
    89  	if next == nil {
    90  		if len(tail) > 0 {
    91  			next = pathTree{}
    92  		}
    93  		t[head] = next
    94  	}
    95  	next.addSegments(tail)
    96  }
    97  
    98  func (t pathTree) clean(path string) string {
    99  	for len(path) > 0 && strings.HasPrefix(path, "/") {
   100  		path = path[1:]
   101  	}
   102  	for len(path) > 0 && strings.HasSuffix(path, "/") {
   103  		path = path[0 : len(path)-1]
   104  	}
   105  	return path
   106  }
   107  
   108  // pathRoot is the root of the URL path tree.
   109  var pathRoot pathTree
   110  
   111  func init() {
   112  	err := jsoniter.Unmarshal([]byte(pathTreeData), &pathRoot)
   113  	if err != nil {
   114  		panic(err)
   115  	}
   116  }