Skip to content

Commit 9c96e30

Browse files
committed
update documentation for promsafe
1 parent 5efce43 commit 9c96e30

File tree

1 file changed

+92
-2
lines changed

1 file changed

+92
-2
lines changed

prometheus/promsafe/safe.go

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,96 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14-
// Package promsafe provides safe labeling - strongly typed labels in prometheus metrics.
15-
// Enjoy promsafe as you wish!
14+
// Package promsafe provides a layer of type-safety for label management in Prometheus metrics.
15+
//
16+
// Promsafe introduces type-safe labels, ensuring that the labels used with
17+
// Prometheus metrics are explicitly defined and validated at compile-time. This
18+
// eliminates common runtime errors caused by mislabeling, such as typos or
19+
// incorrect label orders.
20+
//
21+
// The following example demonstrates how to create and use a CounterVec with
22+
// type-safe labels (compared to how it's done in a regular way):
23+
//
24+
// package main
25+
//
26+
// import (
27+
// "strconv"
28+
//
29+
// "github.com/prometheus/client_golang/prometheus"
30+
// "github.com/prometheus/client_golang/prometheus/promsafe"
31+
// )
32+
//
33+
// // Original unsafe way (no type safety)
34+
// func originalUnsafeWay() {
35+
// counterVec := prometheus.NewCounterVec(
36+
// prometheus.CounterOpts{
37+
// Name: "http_requests_total",
38+
// Help: "Total number of HTTP requests by status code and method.",
39+
// },
40+
// []string{"code", "method"}, // Labels defined as raw strings
41+
// )
42+
//
43+
// // No compile-time checks; label order and types must be correct
44+
// // You have to know which and how many labels are expected (in proper order)
45+
// counterVec.WithLabelValues("200", "GET").Inc()
46+
//
47+
// // or you can use map, that is even more fragile
48+
// counterVect.WithLabels(prometheus.Labels{"code": "200", "method": "GET"}).Inc()
49+
// }
50+
//
51+
// // Safe way (Quick implementation, reflect-based under-the-hood)
52+
// type Labels1 struct {
53+
// promsafe.StructLabelProvider
54+
// Code int
55+
// Method string
56+
// }
57+
//
58+
// func safeReflectWay() {
59+
// counterVec := promsafe.NewCounterVec[Labels1](prometheus.CounterOpts{
60+
// Name: "http_requests_total_reflection",
61+
// Help: "Total number of HTTP requests by status code and method (reflection-based).",
62+
// })
63+
//
64+
// // Compile-time safe and readable; Will be converted into properly ordered list: "200", "GET"
65+
// counterVec.With(Labels1{Method: "GET", Code: 200}).Inc()
66+
// }
67+
//
68+
// // Safe way with manual implementation (no reflection overhead, as fast as original)
69+
// type Labels2 struct {
70+
// promsafe.StructLabelProvider
71+
// Code int
72+
// Method string
73+
// }
74+
//
75+
// func (c Labels2) ToPrometheusLabels() prometheus.Labels {
76+
// return prometheus.Labels{
77+
// "code": strconv.Itoa(c.Code), // Convert int to string
78+
// "method": c.Method,
79+
// }
80+
// }
81+
//
82+
// func (c Labels2) ToLabelNames() []string {
83+
// return []string{"code", "method"}
84+
// }
85+
//
86+
// func safeManualWay() {
87+
// counterVec := promsafe.NewCounterVec[Labels2](prometheus.CounterOpts{
88+
// Name: "http_requests_total_custom",
89+
// Help: "Total number of HTTP requests by status code and method (manual implementation).",
90+
// })
91+
// counterVec.With(Labels2{Code: 404, Method: "POST"}).Inc()
92+
// }
93+
//
94+
// Promsafe also provides compatibility adapter for integration with Prometheus's
95+
// `promauto` package, ensuring seamless adoption while preserving type-safety.
96+
// Methods that cannot guarantee type safety, such as those using raw `[]string`
97+
// label values, are explicitly deprecated and will raise runtime errors.
98+
//
99+
// A separate package allows conservative users to entirely ignore it. And
100+
// whoever wants to use it will do so explicitly, with an opportunity to read
101+
// this warning.
102+
//
103+
// Enjoy promsafe as it's safe!
16104
package promsafe
17105

18106
import (
@@ -91,3 +179,5 @@ func NewCounter(opts prometheus.CounterOpts) prometheus.Counter {
91179
func NewCounterFunc(opts prometheus.CounterOpts, function func() float64) prometheus.CounterFunc {
92180
return prometheus.NewCounterFunc(opts, function)
93181
}
182+
183+
// TODO: other methods (Gauge, Histogram, Summary, etc.)

0 commit comments

Comments
 (0)