...

Source file src/sigs.k8s.io/controller-runtime/pkg/log/log.go

Documentation: sigs.k8s.io/controller-runtime/pkg/log

     1  /*
     2  Copyright 2018 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 log contains utilities for fetching a new logger
    18  // when one is not already available.
    19  //
    20  // # The Log Handle
    21  //
    22  // This package contains a root logr.Logger Log.  It may be used to
    23  // get a handle to whatever the root logging implementation is.  By
    24  // default, no implementation exists, and the handle returns "promises"
    25  // to loggers.  When the implementation is set using SetLogger, these
    26  // "promises" will be converted over to real loggers.
    27  //
    28  // # Logr
    29  //
    30  // All logging in controller-runtime is structured, using a set of interfaces
    31  // defined by a package called logr
    32  // (https://pkg.go.dev/github.com/go-logr/logr).  The sub-package zap provides
    33  // helpers for setting up logr backed by Zap (go.uber.org/zap).
    34  package log
    35  
    36  import (
    37  	"bytes"
    38  	"context"
    39  	"fmt"
    40  	"os"
    41  	"runtime/debug"
    42  	"sync/atomic"
    43  	"time"
    44  
    45  	"github.com/go-logr/logr"
    46  )
    47  
    48  // SetLogger sets a concrete logging implementation for all deferred Loggers.
    49  func SetLogger(l logr.Logger) {
    50  	logFullfilled.Store(true)
    51  	rootLog.Fulfill(l.GetSink())
    52  }
    53  
    54  func eventuallyFulfillRoot() {
    55  	if logFullfilled.Load() {
    56  		return
    57  	}
    58  	if time.Since(rootLogCreated).Seconds() >= 30 {
    59  		if logFullfilled.CompareAndSwap(false, true) {
    60  			stack := debug.Stack()
    61  			stackLines := bytes.Count(stack, []byte{'\n'})
    62  			sep := []byte{'\n', '\t', '>', ' ', ' '}
    63  
    64  			fmt.Fprintf(os.Stderr,
    65  				"[controller-runtime] log.SetLogger(...) was never called; logs will not be displayed.\nDetected at:%s%s", sep,
    66  				// prefix every line, so it's clear this is a stack trace related to the above message
    67  				bytes.Replace(stack, []byte{'\n'}, sep, stackLines-1),
    68  			)
    69  			SetLogger(logr.New(NullLogSink{}))
    70  		}
    71  	}
    72  }
    73  
    74  var (
    75  	logFullfilled atomic.Bool
    76  )
    77  
    78  // Log is the base logger used by kubebuilder.  It delegates
    79  // to another logr.Logger. You *must* call SetLogger to
    80  // get any actual logging. If SetLogger is not called within
    81  // the first 30 seconds of a binaries lifetime, it will get
    82  // set to a NullLogSink.
    83  var (
    84  	rootLog, rootLogCreated = func() (*delegatingLogSink, time.Time) {
    85  		return newDelegatingLogSink(NullLogSink{}), time.Now()
    86  	}()
    87  	Log = logr.New(rootLog)
    88  )
    89  
    90  // FromContext returns a logger with predefined values from a context.Context.
    91  func FromContext(ctx context.Context, keysAndValues ...interface{}) logr.Logger {
    92  	log := Log
    93  	if ctx != nil {
    94  		if logger, err := logr.FromContext(ctx); err == nil {
    95  			log = logger
    96  		}
    97  	}
    98  	return log.WithValues(keysAndValues...)
    99  }
   100  
   101  // IntoContext takes a context and sets the logger as one of its values.
   102  // Use FromContext function to retrieve the logger.
   103  func IntoContext(ctx context.Context, log logr.Logger) context.Context {
   104  	return logr.NewContext(ctx, log)
   105  }
   106  

View as plain text