mirror of https://github.com/knative/pkg.git
Support fetching observability from ctx. (#2610)
* add option to load observability config from ctx Signed-off-by: Kenny Leung <kleung@chainguard.dev> * comments and tests Signed-off-by: Kenny Leung <kleung@chainguard.dev> * undo Signed-off-by: Kenny Leung <kleung@chainguard.dev> * move observability setup logic into function to match logger Signed-off-by: Kenny Leung <kleung@chainguard.dev> * fix arg Signed-off-by: Kenny Leung <kleung@chainguard.dev> Signed-off-by: Kenny Leung <kleung@chainguard.dev>
This commit is contained in:
parent
714b7630a8
commit
b812affa38
|
@ -104,6 +104,25 @@ func GetLeaderElectionConfig(ctx context.Context) (*leaderelection.Config, error
|
|||
return leaderelection.NewConfigFromConfigMap(leaderElectionConfigMap)
|
||||
}
|
||||
|
||||
// GetObservabilityConfig gets the observability config from the (in order):
|
||||
// 1. provided context,
|
||||
// 2. reading from the API server,
|
||||
// 3. defaults (if not found).
|
||||
func GetObservabilityConfig(ctx context.Context) (*metrics.ObservabilityConfig, error) {
|
||||
if cfg := metrics.GetObservabilityConfig(ctx); cfg != nil {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
observabilityConfigMap, err := kubeclient.Get(ctx).CoreV1().ConfigMaps(system.Namespace()).Get(ctx, metrics.ConfigMapName(), metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
return metrics.NewObservabilityConfigFromConfigMap(nil)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return metrics.NewObservabilityConfigFromConfigMap(observabilityConfigMap)
|
||||
}
|
||||
|
||||
// EnableInjectionOrDie enables Knative Injection and starts the informers.
|
||||
// Both Context and Config are optional.
|
||||
// Deprecated: use injection.EnableInjectionOrDie
|
||||
|
@ -249,6 +268,8 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
|
|||
leaderElectionConfig.GetComponentConfig(component))
|
||||
}
|
||||
|
||||
SetupObservabilityOrDie(ctx, component, logger, profilingHandler)
|
||||
|
||||
controllers, webhooks := ControllersAndWebhooksFromCtors(ctx, cmw, ctors...)
|
||||
WatchLoggingConfigOrDie(ctx, cmw, logger, atomicLevel, component)
|
||||
WatchObservabilityConfigOrDie(ctx, cmw, profilingHandler, logger, component)
|
||||
|
@ -327,6 +348,18 @@ func SetupLoggerOrDie(ctx context.Context, component string) (*zap.SugaredLogger
|
|||
return l, level
|
||||
}
|
||||
|
||||
// SetupObservabilityOrDie sets up the observability using the config from the given context
|
||||
// or dies by calling log.Fatalf.
|
||||
func SetupObservabilityOrDie(ctx context.Context, component string, logger *zap.SugaredLogger, profilingHandler *profiling.Handler) {
|
||||
observabilityConfig, err := GetObservabilityConfig(ctx)
|
||||
if err != nil {
|
||||
logger.Fatal("Error loading observability configuration: ", err)
|
||||
}
|
||||
observabilityConfigMap := observabilityConfig.GetConfigMap()
|
||||
metrics.ConfigMapWatcher(ctx, component, SecretFetcher(ctx), logger)(&observabilityConfigMap)
|
||||
profilingHandler.UpdateFromConfigMap(&observabilityConfigMap)
|
||||
}
|
||||
|
||||
// CheckK8sClientMinimumVersionOrDie checks that the hosting Kubernetes cluster
|
||||
// is at least the minimum allowable version or dies by calling log.Fatalw.
|
||||
func CheckK8sClientMinimumVersionOrDie(ctx context.Context, logger *zap.SugaredLogger) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"knative.dev/pkg/injection"
|
||||
"knative.dev/pkg/leaderelection"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/metrics"
|
||||
)
|
||||
|
||||
func TestEnabledControllers(t *testing.T) {
|
||||
|
@ -103,3 +104,25 @@ func TestWithLeaderElectionConfig(t *testing.T) {
|
|||
t.Errorf("(-got, +want) = %s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TextWithObservabilityConfig(t *testing.T) {
|
||||
want := &metrics.ObservabilityConfig{
|
||||
EnableVarLogCollection: false,
|
||||
LoggingURLTemplate: "url-template",
|
||||
RequestLogTemplate: "log-template",
|
||||
EnableProbeRequestLog: true,
|
||||
RequestMetricsBackend: "prometheus",
|
||||
EnableProfiling: true,
|
||||
EnableRequestLog: false,
|
||||
MetricsCollectorAddress: "localhost:9090",
|
||||
}
|
||||
ctx := metrics.WithConfig(context.Background(), want)
|
||||
|
||||
got, err := GetObservabilityConfig(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("GetObservabilityConfig() = %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("(-got, +want) = %s", diff)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@ limitations under the License.
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
texttemplate "text/template"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -81,6 +83,22 @@ type ObservabilityConfig struct {
|
|||
MetricsCollectorAddress string
|
||||
}
|
||||
|
||||
type ocfg struct{}
|
||||
|
||||
// WithConfig associates a observability configuration with the context.
|
||||
func WithConfig(ctx context.Context, cfg *ObservabilityConfig) context.Context {
|
||||
return context.WithValue(ctx, ocfg{}, cfg)
|
||||
}
|
||||
|
||||
// GetObservability gets the observability config from the provided context.
|
||||
func GetObservabilityConfig(ctx context.Context) *ObservabilityConfig {
|
||||
untyped := ctx.Value(ocfg{})
|
||||
if untyped == nil {
|
||||
return nil
|
||||
}
|
||||
return untyped.(*ObservabilityConfig)
|
||||
}
|
||||
|
||||
func defaultConfig() *ObservabilityConfig {
|
||||
return &ObservabilityConfig{
|
||||
LoggingURLTemplate: DefaultLogURLTemplate,
|
||||
|
@ -120,6 +138,21 @@ func NewObservabilityConfigFromConfigMap(configMap *corev1.ConfigMap) (*Observab
|
|||
return oc, nil
|
||||
}
|
||||
|
||||
func (oc *ObservabilityConfig) GetConfigMap() corev1.ConfigMap {
|
||||
return corev1.ConfigMap{
|
||||
Data: map[string]string{
|
||||
"logging.enable-var-log-collection": strconv.FormatBool(oc.EnableVarLogCollection),
|
||||
"logging.revision-url-template": oc.LoggingURLTemplate,
|
||||
ReqLogTemplateKey: oc.RequestLogTemplate,
|
||||
EnableReqLogKey: strconv.FormatBool(oc.EnableRequestLog),
|
||||
EnableProbeReqLogKey: strconv.FormatBool(oc.EnableProbeRequestLog),
|
||||
"metrics.request-metrics-backend-destination": oc.RequestMetricsBackend,
|
||||
"profiling.enable": strconv.FormatBool(oc.EnableProfiling),
|
||||
"metrics.opencensus-address": oc.MetricsCollectorAddress,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigMapName gets the name of the metrics ConfigMap
|
||||
func ConfigMapName() string {
|
||||
if cm := os.Getenv(configMapNameEnv); cm != "" {
|
||||
|
|
|
@ -154,3 +154,55 @@ func TestConfigMapName(t *testing.T) {
|
|||
t.Errorf("ConfigMapName = %q, want: %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservabilityConfigMap(t *testing.T) {
|
||||
observabilityConfigMapTests := []struct {
|
||||
name string
|
||||
config *ObservabilityConfig
|
||||
wantConfigMapData map[string]string
|
||||
}{{
|
||||
name: "observability configuration with all inputs",
|
||||
config: &ObservabilityConfig{
|
||||
EnableProbeRequestLog: true,
|
||||
EnableProfiling: true,
|
||||
EnableVarLogCollection: true,
|
||||
EnableRequestLog: true,
|
||||
LoggingURLTemplate: "https://logging.io",
|
||||
RequestLogTemplate: `{"requestMethod": "{{.Request.Method}}"}`,
|
||||
RequestMetricsBackend: "opencensus",
|
||||
},
|
||||
wantConfigMapData: map[string]string{
|
||||
EnableProbeReqLogKey: "true",
|
||||
"logging.enable-var-log-collection": "true",
|
||||
ReqLogTemplateKey: `{"requestMethod": "{{.Request.Method}}"}`,
|
||||
"logging.revision-url-template": "https://logging.io",
|
||||
EnableReqLogKey: "true",
|
||||
"metrics.request-metrics-backend-destination": "opencensus",
|
||||
"profiling.enable": "true",
|
||||
"metrics.opencensus-address": "",
|
||||
},
|
||||
}, {
|
||||
name: "observability configuration default config",
|
||||
config: defaultConfig(),
|
||||
wantConfigMapData: map[string]string{
|
||||
EnableProbeReqLogKey: "false",
|
||||
"logging.enable-var-log-collection": "false",
|
||||
ReqLogTemplateKey: `{"httpRequest": {"requestMethod": "{{.Request.Method}}", "requestUrl": "{{js .Request.RequestURI}}", "requestSize": "{{.Request.ContentLength}}", "status": {{.Response.Code}}, "responseSize": "{{.Response.Size}}", "userAgent": "{{js .Request.UserAgent}}", "remoteIp": "{{js .Request.RemoteAddr}}", "serverIp": "{{.Revision.PodIP}}", "referer": "{{js .Request.Referer}}", "latency": "{{.Response.Latency}}s", "protocol": "{{.Request.Proto}}"}, "traceId": "{{index .Request.Header "X-B3-Traceid"}}"}`,
|
||||
"logging.revision-url-template": "",
|
||||
EnableReqLogKey: "false",
|
||||
"metrics.request-metrics-backend-destination": "prometheus",
|
||||
"profiling.enable": "false",
|
||||
"metrics.opencensus-address": "",
|
||||
},
|
||||
}}
|
||||
|
||||
for _, tt := range observabilityConfigMapTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cm := tt.config.GetConfigMap()
|
||||
|
||||
if got, want := cm.Data, tt.wantConfigMapData; !cmp.Equal(got, want) {
|
||||
t.Errorf("Got = %v, want: %v, diff(-want,+got)\n%s", got, want, cmp.Diff(want, got))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue