Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / go.opencensus.io / tag / map.go
1 // Copyright 2017, OpenCensus Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15
16 package tag
17
18 import (
19         "bytes"
20         "context"
21         "fmt"
22         "sort"
23 )
24
25 // Tag is a key value pair that can be propagated on wire.
26 type Tag struct {
27         Key   Key
28         Value string
29 }
30
31 // Map is a map of tags. Use New to create a context containing
32 // a new Map.
33 type Map struct {
34         m map[Key]string
35 }
36
37 // Value returns the value for the key if a value for the key exists.
38 func (m *Map) Value(k Key) (string, bool) {
39         if m == nil {
40                 return "", false
41         }
42         v, ok := m.m[k]
43         return v, ok
44 }
45
46 func (m *Map) String() string {
47         if m == nil {
48                 return "nil"
49         }
50         keys := make([]Key, 0, len(m.m))
51         for k := range m.m {
52                 keys = append(keys, k)
53         }
54         sort.Slice(keys, func(i, j int) bool { return keys[i].Name() < keys[j].Name() })
55
56         var buffer bytes.Buffer
57         buffer.WriteString("{ ")
58         for _, k := range keys {
59                 buffer.WriteString(fmt.Sprintf("{%v %v}", k.name, m.m[k]))
60         }
61         buffer.WriteString(" }")
62         return buffer.String()
63 }
64
65 func (m *Map) insert(k Key, v string) {
66         if _, ok := m.m[k]; ok {
67                 return
68         }
69         m.m[k] = v
70 }
71
72 func (m *Map) update(k Key, v string) {
73         if _, ok := m.m[k]; ok {
74                 m.m[k] = v
75         }
76 }
77
78 func (m *Map) upsert(k Key, v string) {
79         m.m[k] = v
80 }
81
82 func (m *Map) delete(k Key) {
83         delete(m.m, k)
84 }
85
86 func newMap() *Map {
87         return &Map{m: make(map[Key]string)}
88 }
89
90 // Mutator modifies a tag map.
91 type Mutator interface {
92         Mutate(t *Map) (*Map, error)
93 }
94
95 // Insert returns a mutator that inserts a
96 // value associated with k. If k already exists in the tag map,
97 // mutator doesn't update the value.
98 func Insert(k Key, v string) Mutator {
99         return &mutator{
100                 fn: func(m *Map) (*Map, error) {
101                         if !checkValue(v) {
102                                 return nil, errInvalidValue
103                         }
104                         m.insert(k, v)
105                         return m, nil
106                 },
107         }
108 }
109
110 // Update returns a mutator that updates the
111 // value of the tag associated with k with v. If k doesn't
112 // exists in the tag map, the mutator doesn't insert the value.
113 func Update(k Key, v string) Mutator {
114         return &mutator{
115                 fn: func(m *Map) (*Map, error) {
116                         if !checkValue(v) {
117                                 return nil, errInvalidValue
118                         }
119                         m.update(k, v)
120                         return m, nil
121                 },
122         }
123 }
124
125 // Upsert returns a mutator that upserts the
126 // value of the tag associated with k with v. It inserts the
127 // value if k doesn't exist already. It mutates the value
128 // if k already exists.
129 func Upsert(k Key, v string) Mutator {
130         return &mutator{
131                 fn: func(m *Map) (*Map, error) {
132                         if !checkValue(v) {
133                                 return nil, errInvalidValue
134                         }
135                         m.upsert(k, v)
136                         return m, nil
137                 },
138         }
139 }
140
141 // Delete returns a mutator that deletes
142 // the value associated with k.
143 func Delete(k Key) Mutator {
144         return &mutator{
145                 fn: func(m *Map) (*Map, error) {
146                         m.delete(k)
147                         return m, nil
148                 },
149         }
150 }
151
152 // New returns a new context that contains a tag map
153 // originated from the incoming context and modified
154 // with the provided mutators.
155 func New(ctx context.Context, mutator ...Mutator) (context.Context, error) {
156         m := newMap()
157         orig := FromContext(ctx)
158         if orig != nil {
159                 for k, v := range orig.m {
160                         if !checkKeyName(k.Name()) {
161                                 return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName)
162                         }
163                         if !checkValue(v) {
164                                 return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue)
165                         }
166                         m.insert(k, v)
167                 }
168         }
169         var err error
170         for _, mod := range mutator {
171                 m, err = mod.Mutate(m)
172                 if err != nil {
173                         return ctx, err
174                 }
175         }
176         return NewContext(ctx, m), nil
177 }
178
179 // Do is similar to pprof.Do: a convenience for installing the tags
180 // from the context as Go profiler labels. This allows you to
181 // correlated runtime profiling with stats.
182 //
183 // It converts the key/values from the given map to Go profiler labels
184 // and calls pprof.Do.
185 //
186 // Do is going to do nothing if your Go version is below 1.9.
187 func Do(ctx context.Context, f func(ctx context.Context)) {
188         do(ctx, f)
189 }
190
191 type mutator struct {
192         fn func(t *Map) (*Map, error)
193 }
194
195 func (m *mutator) Mutate(t *Map) (*Map, error) {
196         return m.fn(t)
197 }