Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

198 lignes
4.3 KiB

  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. package tag
  16. import (
  17. "bytes"
  18. "context"
  19. "fmt"
  20. "sort"
  21. )
  22. // Tag is a key value pair that can be propagated on wire.
  23. type Tag struct {
  24. Key Key
  25. Value string
  26. }
  27. // Map is a map of tags. Use New to create a context containing
  28. // a new Map.
  29. type Map struct {
  30. m map[Key]string
  31. }
  32. // Value returns the value for the key if a value for the key exists.
  33. func (m *Map) Value(k Key) (string, bool) {
  34. if m == nil {
  35. return "", false
  36. }
  37. v, ok := m.m[k]
  38. return v, ok
  39. }
  40. func (m *Map) String() string {
  41. if m == nil {
  42. return "nil"
  43. }
  44. keys := make([]Key, 0, len(m.m))
  45. for k := range m.m {
  46. keys = append(keys, k)
  47. }
  48. sort.Slice(keys, func(i, j int) bool { return keys[i].Name() < keys[j].Name() })
  49. var buffer bytes.Buffer
  50. buffer.WriteString("{ ")
  51. for _, k := range keys {
  52. buffer.WriteString(fmt.Sprintf("{%v %v}", k.name, m.m[k]))
  53. }
  54. buffer.WriteString(" }")
  55. return buffer.String()
  56. }
  57. func (m *Map) insert(k Key, v string) {
  58. if _, ok := m.m[k]; ok {
  59. return
  60. }
  61. m.m[k] = v
  62. }
  63. func (m *Map) update(k Key, v string) {
  64. if _, ok := m.m[k]; ok {
  65. m.m[k] = v
  66. }
  67. }
  68. func (m *Map) upsert(k Key, v string) {
  69. m.m[k] = v
  70. }
  71. func (m *Map) delete(k Key) {
  72. delete(m.m, k)
  73. }
  74. func newMap() *Map {
  75. return &Map{m: make(map[Key]string)}
  76. }
  77. // Mutator modifies a tag map.
  78. type Mutator interface {
  79. Mutate(t *Map) (*Map, error)
  80. }
  81. // Insert returns a mutator that inserts a
  82. // value associated with k. If k already exists in the tag map,
  83. // mutator doesn't update the value.
  84. func Insert(k Key, v string) Mutator {
  85. return &mutator{
  86. fn: func(m *Map) (*Map, error) {
  87. if !checkValue(v) {
  88. return nil, errInvalidValue
  89. }
  90. m.insert(k, v)
  91. return m, nil
  92. },
  93. }
  94. }
  95. // Update returns a mutator that updates the
  96. // value of the tag associated with k with v. If k doesn't
  97. // exists in the tag map, the mutator doesn't insert the value.
  98. func Update(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.update(k, v)
  105. return m, nil
  106. },
  107. }
  108. }
  109. // Upsert returns a mutator that upserts the
  110. // value of the tag associated with k with v. It inserts the
  111. // value if k doesn't exist already. It mutates the value
  112. // if k already exists.
  113. func Upsert(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.upsert(k, v)
  120. return m, nil
  121. },
  122. }
  123. }
  124. // Delete returns a mutator that deletes
  125. // the value associated with k.
  126. func Delete(k Key) Mutator {
  127. return &mutator{
  128. fn: func(m *Map) (*Map, error) {
  129. m.delete(k)
  130. return m, nil
  131. },
  132. }
  133. }
  134. // New returns a new context that contains a tag map
  135. // originated from the incoming context and modified
  136. // with the provided mutators.
  137. func New(ctx context.Context, mutator ...Mutator) (context.Context, error) {
  138. m := newMap()
  139. orig := FromContext(ctx)
  140. if orig != nil {
  141. for k, v := range orig.m {
  142. if !checkKeyName(k.Name()) {
  143. return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName)
  144. }
  145. if !checkValue(v) {
  146. return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue)
  147. }
  148. m.insert(k, v)
  149. }
  150. }
  151. var err error
  152. for _, mod := range mutator {
  153. m, err = mod.Mutate(m)
  154. if err != nil {
  155. return ctx, err
  156. }
  157. }
  158. return NewContext(ctx, m), nil
  159. }
  160. // Do is similar to pprof.Do: a convenience for installing the tags
  161. // from the context as Go profiler labels. This allows you to
  162. // correlated runtime profiling with stats.
  163. //
  164. // It converts the key/values from the given map to Go profiler labels
  165. // and calls pprof.Do.
  166. //
  167. // Do is going to do nothing if your Go version is below 1.9.
  168. func Do(ctx context.Context, f func(ctx context.Context)) {
  169. do(ctx, f)
  170. }
  171. type mutator struct {
  172. fn func(t *Map) (*Map, error)
  173. }
  174. func (m *mutator) Mutate(t *Map) (*Map, error) {
  175. return m.fn(t)
  176. }