mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
Merge pull request #118820 from logicalhan/processstart
Write process start time to prometheus options so that scraping clients can parse it first
This commit is contained in:
commit
421ca53be4
@ -19,19 +19,28 @@ package metrics
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
processStartedAt time.Time
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
processStartedAt = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
// These constants cause handlers serving metrics to behave as described if
|
// These constants cause handlers serving metrics to behave as described if
|
||||||
// errors are encountered.
|
// errors are encountered.
|
||||||
const (
|
const (
|
||||||
// Serve an HTTP status code 500 upon the first error
|
// HTTPErrorOnError serve an HTTP status code 500 upon the first error
|
||||||
// encountered. Report the error message in the body.
|
// encountered. Report the error message in the body.
|
||||||
HTTPErrorOnError promhttp.HandlerErrorHandling = iota
|
HTTPErrorOnError promhttp.HandlerErrorHandling = iota
|
||||||
|
|
||||||
// Ignore errors and try to serve as many metrics as possible. However,
|
// ContinueOnError ignore errors and try to serve as many metrics as possible.
|
||||||
// if no metrics can be served, serve an HTTP status code 500 and the
|
// However, if no metrics can be served, serve an HTTP status code 500 and the
|
||||||
// last error message in the body. Only use this in deliberate "best
|
// last error message in the body. Only use this in deliberate "best
|
||||||
// effort" metrics collection scenarios. In this case, it is highly
|
// effort" metrics collection scenarios. In this case, it is highly
|
||||||
// recommended to provide other means of detecting errors: By setting an
|
// recommended to provide other means of detecting errors: By setting an
|
||||||
@ -41,7 +50,7 @@ const (
|
|||||||
// alerts.
|
// alerts.
|
||||||
ContinueOnError
|
ContinueOnError
|
||||||
|
|
||||||
// Panic upon the first error encountered (useful for "crash only" apps).
|
// PanicOnError panics upon the first error encountered (useful for "crash only" apps).
|
||||||
PanicOnError
|
PanicOnError
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,6 +59,7 @@ const (
|
|||||||
type HandlerOpts promhttp.HandlerOpts
|
type HandlerOpts promhttp.HandlerOpts
|
||||||
|
|
||||||
func (ho *HandlerOpts) toPromhttpHandlerOpts() promhttp.HandlerOpts {
|
func (ho *HandlerOpts) toPromhttpHandlerOpts() promhttp.HandlerOpts {
|
||||||
|
ho.ProcessStartTime = processStartedAt
|
||||||
return promhttp.HandlerOpts(*ho)
|
return promhttp.HandlerOpts(*ho)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package legacyregistry
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/collectors"
|
"github.com/prometheus/client_golang/prometheus/collectors"
|
||||||
@ -45,19 +46,22 @@ var (
|
|||||||
|
|
||||||
// Registerer exposes the global registerer
|
// Registerer exposes the global registerer
|
||||||
Registerer = defaultRegistry.Registerer
|
Registerer = defaultRegistry.Registerer
|
||||||
|
|
||||||
|
processStart time.Time
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RawMustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
|
RawMustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
|
||||||
RawMustRegister(collectors.NewGoCollector(collectors.WithGoCollectorRuntimeMetrics(collectors.MetricsAll)))
|
RawMustRegister(collectors.NewGoCollector(collectors.WithGoCollectorRuntimeMetrics(collectors.MetricsAll)))
|
||||||
defaultRegistry.RegisterMetaMetrics()
|
defaultRegistry.RegisterMetaMetrics()
|
||||||
|
processStart = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler returns an HTTP handler for the DefaultGatherer. It is
|
// Handler returns an HTTP handler for the DefaultGatherer. It is
|
||||||
// already instrumented with InstrumentHandler (using "prometheus" as handler
|
// already instrumented with InstrumentHandler (using "prometheus" as handler
|
||||||
// name).
|
// name).
|
||||||
func Handler() http.Handler {
|
func Handler() http.Handler {
|
||||||
return promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(defaultRegistry, promhttp.HandlerOpts{}))
|
return promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(defaultRegistry, promhttp.HandlerOpts{ProcessStartTime: processStart}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandlerWithReset returns an HTTP handler for the DefaultGatherer but invokes
|
// HandlerWithReset returns an HTTP handler for the DefaultGatherer but invokes
|
||||||
@ -65,7 +69,7 @@ func Handler() http.Handler {
|
|||||||
func HandlerWithReset() http.Handler {
|
func HandlerWithReset() http.Handler {
|
||||||
return promhttp.InstrumentMetricHandler(
|
return promhttp.InstrumentMetricHandler(
|
||||||
prometheus.DefaultRegisterer,
|
prometheus.DefaultRegisterer,
|
||||||
metrics.HandlerWithReset(defaultRegistry, metrics.HandlerOpts{}))
|
metrics.HandlerWithReset(defaultRegistry, metrics.HandlerOpts{ProcessStartTime: processStart}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomRegister registers a custom collector but uses the global registry.
|
// CustomRegister registers a custom collector but uses the global registry.
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2023 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package legacyregistry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
processStartTimeHeader = "Process-Start-Time-Unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProcessStartTimeHeader(t *testing.T) {
|
||||||
|
now := time.Now()
|
||||||
|
handler := Handler()
|
||||||
|
|
||||||
|
request, _ := http.NewRequest("GET", "/", nil)
|
||||||
|
writer := httptest.NewRecorder()
|
||||||
|
handler.ServeHTTP(writer, request)
|
||||||
|
got := writer.Header().Get(processStartTimeHeader)
|
||||||
|
gotInt, _ := strconv.ParseInt(got, 10, 64)
|
||||||
|
if gotInt != now.Unix() {
|
||||||
|
t.Errorf("got %d, wanted %d", gotInt, now.Unix())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user