25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

217 satır
6.7 KiB

  1. // Copyright 2018 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package prometheus
  14. import (
  15. "fmt"
  16. "sort"
  17. //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
  18. "github.com/golang/protobuf/proto"
  19. dto "github.com/prometheus/client_model/go"
  20. "github.com/prometheus/client_golang/prometheus/internal"
  21. )
  22. // WrapRegistererWith returns a Registerer wrapping the provided
  23. // Registerer. Collectors registered with the returned Registerer will be
  24. // registered with the wrapped Registerer in a modified way. The modified
  25. // Collector adds the provided Labels to all Metrics it collects (as
  26. // ConstLabels). The Metrics collected by the unmodified Collector must not
  27. // duplicate any of those labels. Wrapping a nil value is valid, resulting
  28. // in a no-op Registerer.
  29. //
  30. // WrapRegistererWith provides a way to add fixed labels to a subset of
  31. // Collectors. It should not be used to add fixed labels to all metrics
  32. // exposed. See also
  33. // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
  34. //
  35. // Conflicts between Collectors registered through the original Registerer with
  36. // Collectors registered through the wrapping Registerer will still be
  37. // detected. Any AlreadyRegisteredError returned by the Register method of
  38. // either Registerer will contain the ExistingCollector in the form it was
  39. // provided to the respective registry.
  40. //
  41. // The Collector example demonstrates a use of WrapRegistererWith.
  42. func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
  43. return &wrappingRegisterer{
  44. wrappedRegisterer: reg,
  45. labels: labels,
  46. }
  47. }
  48. // WrapRegistererWithPrefix returns a Registerer wrapping the provided
  49. // Registerer. Collectors registered with the returned Registerer will be
  50. // registered with the wrapped Registerer in a modified way. The modified
  51. // Collector adds the provided prefix to the name of all Metrics it collects.
  52. // Wrapping a nil value is valid, resulting in a no-op Registerer.
  53. //
  54. // WrapRegistererWithPrefix is useful to have one place to prefix all metrics of
  55. // a sub-system. To make this work, register metrics of the sub-system with the
  56. // wrapping Registerer returned by WrapRegistererWithPrefix. It is rarely useful
  57. // to use the same prefix for all metrics exposed. In particular, do not prefix
  58. // metric names that are standardized across applications, as that would break
  59. // horizontal monitoring, for example the metrics provided by the Go collector
  60. // (see NewGoCollector) and the process collector (see NewProcessCollector). (In
  61. // fact, those metrics are already prefixed with “go_” or “process_”,
  62. // respectively.)
  63. //
  64. // Conflicts between Collectors registered through the original Registerer with
  65. // Collectors registered through the wrapping Registerer will still be
  66. // detected. Any AlreadyRegisteredError returned by the Register method of
  67. // either Registerer will contain the ExistingCollector in the form it was
  68. // provided to the respective registry.
  69. func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer {
  70. return &wrappingRegisterer{
  71. wrappedRegisterer: reg,
  72. prefix: prefix,
  73. }
  74. }
  75. type wrappingRegisterer struct {
  76. wrappedRegisterer Registerer
  77. prefix string
  78. labels Labels
  79. }
  80. func (r *wrappingRegisterer) Register(c Collector) error {
  81. if r.wrappedRegisterer == nil {
  82. return nil
  83. }
  84. return r.wrappedRegisterer.Register(&wrappingCollector{
  85. wrappedCollector: c,
  86. prefix: r.prefix,
  87. labels: r.labels,
  88. })
  89. }
  90. func (r *wrappingRegisterer) MustRegister(cs ...Collector) {
  91. if r.wrappedRegisterer == nil {
  92. return
  93. }
  94. for _, c := range cs {
  95. if err := r.Register(c); err != nil {
  96. panic(err)
  97. }
  98. }
  99. }
  100. func (r *wrappingRegisterer) Unregister(c Collector) bool {
  101. if r.wrappedRegisterer == nil {
  102. return false
  103. }
  104. return r.wrappedRegisterer.Unregister(&wrappingCollector{
  105. wrappedCollector: c,
  106. prefix: r.prefix,
  107. labels: r.labels,
  108. })
  109. }
  110. type wrappingCollector struct {
  111. wrappedCollector Collector
  112. prefix string
  113. labels Labels
  114. }
  115. func (c *wrappingCollector) Collect(ch chan<- Metric) {
  116. wrappedCh := make(chan Metric)
  117. go func() {
  118. c.wrappedCollector.Collect(wrappedCh)
  119. close(wrappedCh)
  120. }()
  121. for m := range wrappedCh {
  122. ch <- &wrappingMetric{
  123. wrappedMetric: m,
  124. prefix: c.prefix,
  125. labels: c.labels,
  126. }
  127. }
  128. }
  129. func (c *wrappingCollector) Describe(ch chan<- *Desc) {
  130. wrappedCh := make(chan *Desc)
  131. go func() {
  132. c.wrappedCollector.Describe(wrappedCh)
  133. close(wrappedCh)
  134. }()
  135. for desc := range wrappedCh {
  136. ch <- wrapDesc(desc, c.prefix, c.labels)
  137. }
  138. }
  139. func (c *wrappingCollector) unwrapRecursively() Collector {
  140. switch wc := c.wrappedCollector.(type) {
  141. case *wrappingCollector:
  142. return wc.unwrapRecursively()
  143. default:
  144. return wc
  145. }
  146. }
  147. type wrappingMetric struct {
  148. wrappedMetric Metric
  149. prefix string
  150. labels Labels
  151. }
  152. func (m *wrappingMetric) Desc() *Desc {
  153. return wrapDesc(m.wrappedMetric.Desc(), m.prefix, m.labels)
  154. }
  155. func (m *wrappingMetric) Write(out *dto.Metric) error {
  156. if err := m.wrappedMetric.Write(out); err != nil {
  157. return err
  158. }
  159. if len(m.labels) == 0 {
  160. // No wrapping labels.
  161. return nil
  162. }
  163. for ln, lv := range m.labels {
  164. out.Label = append(out.Label, &dto.LabelPair{
  165. Name: proto.String(ln),
  166. Value: proto.String(lv),
  167. })
  168. }
  169. sort.Sort(internal.LabelPairSorter(out.Label))
  170. return nil
  171. }
  172. func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc {
  173. constLabels := Labels{}
  174. for _, lp := range desc.constLabelPairs {
  175. constLabels[*lp.Name] = *lp.Value
  176. }
  177. for ln, lv := range labels {
  178. if _, alreadyUsed := constLabels[ln]; alreadyUsed {
  179. return &Desc{
  180. fqName: desc.fqName,
  181. help: desc.help,
  182. variableLabels: desc.variableLabels,
  183. constLabelPairs: desc.constLabelPairs,
  184. err: fmt.Errorf("attempted wrapping with already existing label name %q", ln),
  185. }
  186. }
  187. constLabels[ln] = lv
  188. }
  189. // NewDesc will do remaining validations.
  190. newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels)
  191. // Propagate errors if there was any. This will override any errer
  192. // created by NewDesc above, i.e. earlier errors get precedence.
  193. if desc.err != nil {
  194. newDesc.err = desc.err
  195. }
  196. return newDesc
  197. }