...

Source file src/k8s.io/component-base/logs/api/v1/registry.go

Documentation: k8s.io/component-base/logs/api/v1

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1
    18  
    19  import (
    20  	"fmt"
    21  	"sort"
    22  	"strings"
    23  	"sync"
    24  
    25  	"github.com/go-logr/logr"
    26  
    27  	"k8s.io/component-base/featuregate"
    28  )
    29  
    30  var logRegistry = newLogFormatRegistry()
    31  
    32  // logFormatRegistry stores factories for all supported logging formats.
    33  type logFormatRegistry struct {
    34  	mutex    sync.Mutex
    35  	registry map[string]logFormat
    36  	frozen   bool
    37  }
    38  
    39  type logFormat struct {
    40  	factory LogFormatFactory
    41  	feature featuregate.Feature
    42  }
    43  
    44  // +k8s:deepcopy-gen=false
    45  
    46  // RuntimeControl provides operations that aren't available through the normal
    47  // Logger or LogSink API.
    48  type RuntimeControl struct {
    49  	// Flush ensures that all in-memory data is written.
    50  	// May be nil.
    51  	Flush func()
    52  
    53  	// SetVerbosityLevel changes the level for all Logger instances
    54  	// derived from the initial one. May be nil.
    55  	//
    56  	// The parameter is intentionally a plain uint32 instead of
    57  	// VerbosityLevel to enable implementations that don't need to import
    58  	// the API (helps avoid circular dependencies).
    59  	SetVerbosityLevel func(v uint32) error
    60  }
    61  
    62  // LogFormatFactory provides support for a certain additional,
    63  // non-default log format.
    64  type LogFormatFactory interface {
    65  	// Create returns a logger with the requested configuration.
    66  	Create(c LoggingConfiguration, o LoggingOptions) (logr.Logger, RuntimeControl)
    67  }
    68  
    69  // RegisterLogFormat registers support for a new logging format. This must be called
    70  // before using any of the methods in LoggingConfiguration. The feature must
    71  // be one of those defined in this package (typically LoggingAlphaOptions,
    72  // LoggingBetaOptions or LoggingStableOptions).
    73  func RegisterLogFormat(name string, factory LogFormatFactory, feature featuregate.Feature) error {
    74  	return logRegistry.register(name, logFormat{factory, feature})
    75  }
    76  
    77  func newLogFormatRegistry() *logFormatRegistry {
    78  	registry := &logFormatRegistry{
    79  		registry: make(map[string]logFormat),
    80  		frozen:   false,
    81  	}
    82  	_ = registry.register(DefaultLogFormat, logFormat{factory: textFactory{}, feature: LoggingStableOptions})
    83  	return registry
    84  }
    85  
    86  // register adds a new log format. It's an error to modify an existing one.
    87  func (lfr *logFormatRegistry) register(name string, format logFormat) error {
    88  	lfr.mutex.Lock()
    89  	defer lfr.mutex.Unlock()
    90  	if lfr.frozen {
    91  		return fmt.Errorf("log format registry is frozen, unable to register log format %s", name)
    92  	}
    93  	if _, ok := lfr.registry[name]; ok {
    94  		return fmt.Errorf("log format: %s already exists", name)
    95  	}
    96  	if _, ok := featureGates()[format.feature]; !ok && format.feature != LoggingStableOptions {
    97  		return fmt.Errorf("log format %s: unsupported feature gate %s", name, format.feature)
    98  	}
    99  	lfr.registry[name] = format
   100  	return nil
   101  }
   102  
   103  // get specified log format factory
   104  func (lfr *logFormatRegistry) get(name string) (*logFormat, error) {
   105  	lfr.mutex.Lock()
   106  	defer lfr.mutex.Unlock()
   107  	format, ok := lfr.registry[name]
   108  	if !ok {
   109  		return nil, fmt.Errorf("log format: %s does not exists", name)
   110  	}
   111  	return &format, nil
   112  }
   113  
   114  // list names of registered log formats, including feature gates (sorted)
   115  func (lfr *logFormatRegistry) list() string {
   116  	lfr.mutex.Lock()
   117  	defer lfr.mutex.Unlock()
   118  	formats := make([]string, 0, len(lfr.registry))
   119  	for name, format := range lfr.registry {
   120  		item := fmt.Sprintf(`"%s"`, name)
   121  		if format.feature != LoggingStableOptions {
   122  			item += fmt.Sprintf(" (gated by %s)", format.feature)
   123  		}
   124  		formats = append(formats, item)
   125  	}
   126  	sort.Strings(formats)
   127  	return strings.Join(formats, ", ")
   128  }
   129  
   130  // freeze prevents further modifications of the registered log formats.
   131  func (lfr *logFormatRegistry) freeze() {
   132  	lfr.mutex.Lock()
   133  	defer lfr.mutex.Unlock()
   134  	lfr.frozen = true
   135  }
   136  

View as plain text