| // Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ |
| // |
| // Copyright 2013 Google Inc. All Rights Reserved. |
| // Copyright 2022 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 klog |
| |
| import ( |
| "fmt" |
| "os" |
| "time" |
| ) |
| |
| var ( |
| |
| // ExitFlushTimeout is the timeout that klog has traditionally used during |
| // calls like Fatal or Exit when flushing log data right before exiting. |
| // Applications that replace those calls and do not have some specific |
| // requirements like "exit immediately" can use this value as parameter |
| // for FlushAndExit. |
| // |
| // Can be set for testing purpose or to change the application's |
| // default. |
| ExitFlushTimeout = 10 * time.Second |
| |
| // OsExit is the function called by FlushAndExit to terminate the program. |
| // |
| // Can be set for testing purpose or to change the application's |
| // default behavior. Note that the function should not simply return |
| // because callers of functions like Fatal will not expect that. |
| OsExit = os.Exit |
| ) |
| |
| // FlushAndExit flushes log data for a certain amount of time and then calls |
| // os.Exit. Combined with some logging call it provides a replacement for |
| // traditional calls like Fatal or Exit. |
| func FlushAndExit(flushTimeout time.Duration, exitCode int) { |
| timeoutFlush(flushTimeout) |
| OsExit(exitCode) |
| } |
| |
| // timeoutFlush calls Flush and returns when it completes or after timeout |
| // elapses, whichever happens first. This is needed because the hooks invoked |
| // by Flush may deadlock when klog.Fatal is called from a hook that holds |
| // a lock. Flushing also might take too long. |
| func timeoutFlush(timeout time.Duration) { |
| done := make(chan bool, 1) |
| go func() { |
| Flush() // calls logging.lockAndFlushAll() |
| done <- true |
| }() |
| select { |
| case <-done: |
| case <-time.After(timeout): |
| fmt.Fprintln(os.Stderr, "klog: Flush took longer than", timeout) |
| } |
| } |