cubefs

Форк
0
162 строки · 5.1 Кб
1
// Copyright 2015 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

14
package expfmt
15

16
import (
17
	"fmt"
18
	"io"
19
	"net/http"
20

21
	"github.com/golang/protobuf/proto" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
22
	"github.com/matttproud/golang_protobuf_extensions/pbutil"
23
	"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
24

25
	dto "github.com/prometheus/client_model/go"
26
)
27

28
// Encoder types encode metric families into an underlying wire protocol.
29
type Encoder interface {
30
	Encode(*dto.MetricFamily) error
31
}
32

33
// Closer is implemented by Encoders that need to be closed to finalize
34
// encoding. (For example, OpenMetrics needs a final `# EOF` line.)
35
//
36
// Note that all Encoder implementations returned from this package implement
37
// Closer, too, even if the Close call is a no-op. This happens in preparation
38
// for adding a Close method to the Encoder interface directly in a (mildly
39
// breaking) release in the future.
40
type Closer interface {
41
	Close() error
42
}
43

44
type encoderCloser struct {
45
	encode func(*dto.MetricFamily) error
46
	close  func() error
47
}
48

49
func (ec encoderCloser) Encode(v *dto.MetricFamily) error {
50
	return ec.encode(v)
51
}
52

53
func (ec encoderCloser) Close() error {
54
	return ec.close()
55
}
56

57
// Negotiate returns the Content-Type based on the given Accept header. If no
58
// appropriate accepted type is found, FmtText is returned (which is the
59
// Prometheus text format). This function will never negotiate FmtOpenMetrics,
60
// as the support is still experimental. To include the option to negotiate
61
// FmtOpenMetrics, use NegotiateOpenMetrics.
62
func Negotiate(h http.Header) Format {
63
	for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
64
		ver := ac.Params["version"]
65
		if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
66
			switch ac.Params["encoding"] {
67
			case "delimited":
68
				return FmtProtoDelim
69
			case "text":
70
				return FmtProtoText
71
			case "compact-text":
72
				return FmtProtoCompact
73
			}
74
		}
75
		if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
76
			return FmtText
77
		}
78
	}
79
	return FmtText
80
}
81

82
// NegotiateIncludingOpenMetrics works like Negotiate but includes
83
// FmtOpenMetrics as an option for the result. Note that this function is
84
// temporary and will disappear once FmtOpenMetrics is fully supported and as
85
// such may be negotiated by the normal Negotiate function.
86
func NegotiateIncludingOpenMetrics(h http.Header) Format {
87
	for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) {
88
		ver := ac.Params["version"]
89
		if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
90
			switch ac.Params["encoding"] {
91
			case "delimited":
92
				return FmtProtoDelim
93
			case "text":
94
				return FmtProtoText
95
			case "compact-text":
96
				return FmtProtoCompact
97
			}
98
		}
99
		if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
100
			return FmtText
101
		}
102
		if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion || ver == "") {
103
			return FmtOpenMetrics
104
		}
105
	}
106
	return FmtText
107
}
108

109
// NewEncoder returns a new encoder based on content type negotiation. All
110
// Encoder implementations returned by NewEncoder also implement Closer, and
111
// callers should always call the Close method. It is currently only required
112
// for FmtOpenMetrics, but a future (breaking) release will add the Close method
113
// to the Encoder interface directly. The current version of the Encoder
114
// interface is kept for backwards compatibility.
115
func NewEncoder(w io.Writer, format Format) Encoder {
116
	switch format {
117
	case FmtProtoDelim:
118
		return encoderCloser{
119
			encode: func(v *dto.MetricFamily) error {
120
				_, err := pbutil.WriteDelimited(w, v)
121
				return err
122
			},
123
			close: func() error { return nil },
124
		}
125
	case FmtProtoCompact:
126
		return encoderCloser{
127
			encode: func(v *dto.MetricFamily) error {
128
				_, err := fmt.Fprintln(w, v.String())
129
				return err
130
			},
131
			close: func() error { return nil },
132
		}
133
	case FmtProtoText:
134
		return encoderCloser{
135
			encode: func(v *dto.MetricFamily) error {
136
				_, err := fmt.Fprintln(w, proto.MarshalTextString(v))
137
				return err
138
			},
139
			close: func() error { return nil },
140
		}
141
	case FmtText:
142
		return encoderCloser{
143
			encode: func(v *dto.MetricFamily) error {
144
				_, err := MetricFamilyToText(w, v)
145
				return err
146
			},
147
			close: func() error { return nil },
148
		}
149
	case FmtOpenMetrics:
150
		return encoderCloser{
151
			encode: func(v *dto.MetricFamily) error {
152
				_, err := MetricFamilyToOpenMetrics(w, v)
153
				return err
154
			},
155
			close: func() error {
156
				_, err := FinalizeOpenMetrics(w)
157
				return err
158
			},
159
		}
160
	}
161
	panic(fmt.Errorf("expfmt.NewEncoder: unknown format %q", format))
162
}
163

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.