@@ -84,6 +84,16 @@ func Handler() http.Handler {
8484// instrumentation. Use the InstrumentMetricHandler function to apply the same
8585// kind of instrumentation as it is used by the Handler function.
8686func HandlerFor (reg prometheus.Gatherer , opts HandlerOpts ) http.Handler {
87+ return HandlerForIteratable (prometheus .ToIteratableGatherer (reg ), opts )
88+ }
89+
90+ // HandlerForIteratable returns an uninstrumented http.Handler for the provided
91+ // IteratableGatherer. The behavior of the Handler is defined by the provided
92+ // HandlerOpts. Thus, HandlerFor is useful to create http.Handlers for custom
93+ // Gatherers, with non-default HandlerOpts, and/or with custom (or no)
94+ // instrumentation. Use the InstrumentMetricHandler function to apply the same
95+ // kind of instrumentation as it is used by the Handler function.
96+ func HandlerForIteratable (reg prometheus.IteratableGatherer , opts HandlerOpts ) http.Handler {
8797 var (
8898 inFlightSem chan struct {}
8999 errCnt = prometheus .NewCounterVec (
@@ -123,7 +133,8 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
123133 return
124134 }
125135 }
126- mfs , err := reg .Gather ()
136+
137+ iter , err := reg .GatherIterate ()
127138 if err != nil {
128139 if opts .ErrorLog != nil {
129140 opts .ErrorLog .Println ("error gathering metrics:" , err )
@@ -133,7 +144,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
133144 case PanicOnError :
134145 panic (err )
135146 case ContinueOnError :
136- if len ( mfs ) == 0 {
147+ if iter == nil {
137148 // Still report the error if no metrics have been gathered.
138149 httpError (rsp , err )
139150 return
@@ -169,14 +180,22 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
169180
170181 // handleError handles the error according to opts.ErrorHandling
171182 // and returns true if we have to abort after the handling.
172- handleError := func (err error ) bool {
183+ handleError := func (encoding bool , err error ) bool {
173184 if err == nil {
174185 return false
175186 }
176- if opts .ErrorLog != nil {
177- opts .ErrorLog .Println ("error encoding and sending metric family:" , err )
187+ if encoding {
188+ if opts .ErrorLog != nil {
189+ opts .ErrorLog .Println ("error encoding and sending metric family:" , err )
190+ }
191+ errCnt .WithLabelValues ("encoding" ).Inc ()
192+ } else {
193+ if opts .ErrorLog != nil {
194+ opts .ErrorLog .Println ("error gathering metrics:" , err )
195+ }
196+ errCnt .WithLabelValues ("gathering" ).Inc ()
178197 }
179- errCnt . WithLabelValues ( "encoding" ). Inc ()
198+
180199 switch opts .ErrorHandling {
181200 case PanicOnError :
182201 panic (err )
@@ -191,14 +210,16 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
191210 return false
192211 }
193212
194- for _ , mf := range mfs {
195- if handleError (enc .Encode (mf )) {
213+ for iter . Next () {
214+ if handleError (true , enc .Encode (iter . At () )) {
196215 return
197216 }
198217 }
218+ handleError (false , iter .Err ())
219+
199220 if closer , ok := enc .(expfmt.Closer ); ok {
200221 // This in particular takes care of the final "# EOF\n" line for OpenMetrics.
201- if handleError (closer .Close ()) {
222+ if handleError (true , closer .Close ()) {
202223 return
203224 }
204225 }
0 commit comments