...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package expfmt
16
17 import (
18 "fmt"
19 "strings"
20
21 "github.com/prometheus/common/model"
22 )
23
24
25 type Format string
26
27
28
29
30
31
32
33
34 const (
35 TextVersion = "0.0.4"
36 ProtoType = `application/vnd.google.protobuf`
37 ProtoProtocol = `io.prometheus.client.MetricFamily`
38 protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
39 OpenMetricsType = `application/openmetrics-text`
40 OpenMetricsVersion_0_0_1 = "0.0.1"
41 OpenMetricsVersion_1_0_0 = "1.0.0"
42
43
44
45
46 fmtUnknown Format = `<unknown>`
47 fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
48 fmtProtoDelim Format = protoFmt + ` encoding=delimited`
49 fmtProtoText Format = protoFmt + ` encoding=text`
50 fmtProtoCompact Format = protoFmt + ` encoding=compact-text`
51 fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
52 fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
53 )
54
55 const (
56 hdrContentType = "Content-Type"
57 hdrAccept = "Accept"
58 )
59
60
61
62
63
64 type FormatType int
65
66 const (
67 TypeUnknown FormatType = iota
68 TypeProtoCompact
69 TypeProtoDelim
70 TypeProtoText
71 TypeTextPlain
72 TypeOpenMetrics
73 )
74
75
76
77
78
79 func NewFormat(t FormatType) Format {
80 switch t {
81 case TypeProtoCompact:
82 return fmtProtoCompact
83 case TypeProtoDelim:
84 return fmtProtoDelim
85 case TypeProtoText:
86 return fmtProtoText
87 case TypeTextPlain:
88 return fmtText
89 case TypeOpenMetrics:
90 return fmtOpenMetrics_1_0_0
91 default:
92 return fmtUnknown
93 }
94 }
95
96
97
98 func NewOpenMetricsFormat(version string) (Format, error) {
99 if version == OpenMetricsVersion_0_0_1 {
100 return fmtOpenMetrics_0_0_1, nil
101 }
102 if version == OpenMetricsVersion_1_0_0 {
103 return fmtOpenMetrics_1_0_0, nil
104 }
105 return fmtUnknown, fmt.Errorf("unknown open metrics version string")
106 }
107
108
109 func (f Format) FormatType() FormatType {
110 toks := strings.Split(string(f), ";")
111 params := make(map[string]string)
112 for i, t := range toks {
113 if i == 0 {
114 continue
115 }
116 args := strings.Split(t, "=")
117 if len(args) != 2 {
118 continue
119 }
120 params[strings.TrimSpace(args[0])] = strings.TrimSpace(args[1])
121 }
122
123 switch strings.TrimSpace(toks[0]) {
124 case ProtoType:
125 if params["proto"] != ProtoProtocol {
126 return TypeUnknown
127 }
128 switch params["encoding"] {
129 case "delimited":
130 return TypeProtoDelim
131 case "text":
132 return TypeProtoText
133 case "compact-text":
134 return TypeProtoCompact
135 default:
136 return TypeUnknown
137 }
138 case OpenMetricsType:
139 if params["charset"] != "utf-8" {
140 return TypeUnknown
141 }
142 return TypeOpenMetrics
143 case "text/plain":
144 v, ok := params["version"]
145 if !ok {
146 return TypeTextPlain
147 }
148 if v == TextVersion {
149 return TypeTextPlain
150 }
151 return TypeUnknown
152 default:
153 return TypeUnknown
154 }
155 }
156
157
158
159
160
161 func (format Format) ToEscapingScheme() model.EscapingScheme {
162 for _, p := range strings.Split(string(format), ";") {
163 toks := strings.Split(p, "=")
164 if len(toks) != 2 {
165 continue
166 }
167 key, value := strings.TrimSpace(toks[0]), strings.TrimSpace(toks[1])
168 if key == model.EscapingKey {
169 scheme, err := model.ToEscapingScheme(value)
170 if err != nil {
171 return model.NameEscapingScheme
172 }
173 return scheme
174 }
175 }
176 return model.NameEscapingScheme
177 }
178
View as plain text