|
|
@@ -7,6 +7,9 @@ import (
|
|
|
"k8s.io/klog"
|
|
|
)
|
|
|
|
|
|
+// TODO for deduped functions, if timeLogged > logTypeLimit, should we log once
|
|
|
+// every... 100 (?) times so we don't lose track entirely?
|
|
|
+
|
|
|
// concurrency-safe counter
|
|
|
var ctr = newCounter()
|
|
|
|
|
|
@@ -15,17 +18,17 @@ func Errorf(format string, a ...interface{}) {
|
|
|
}
|
|
|
|
|
|
func DedupedErrorf(logTypeLimit int, format string, a ...interface{}) {
|
|
|
- timesLogged := ctr.increment(format)
|
|
|
-
|
|
|
- if timesLogged < logTypeLimit {
|
|
|
- Errorf(format, a...)
|
|
|
- } else if timesLogged == logTypeLimit {
|
|
|
- Errorf(format, a...)
|
|
|
- Infof("%s logged %d times: suppressing future logs", format, logTypeLimit)
|
|
|
- }
|
|
|
-
|
|
|
- // TODO if timeLogged > logTypeLimit, log once every... 100 (?) times so we
|
|
|
- // don't lose track entirely?
|
|
|
+ // Run within a goroutine so that the original call does not block
|
|
|
+ go func(logTypeLimit int, format string, a ...interface{}) {
|
|
|
+ timesLogged := ctr.increment(format)
|
|
|
+
|
|
|
+ if timesLogged < logTypeLimit {
|
|
|
+ Errorf(format, a...)
|
|
|
+ } else if timesLogged == logTypeLimit {
|
|
|
+ Errorf(format, a...)
|
|
|
+ Infof("%s logged %d times: suppressing future logs", format, logTypeLimit)
|
|
|
+ }
|
|
|
+ }(logTypeLimit, format, a...)
|
|
|
}
|
|
|
|
|
|
func Warningf(format string, a ...interface{}) {
|
|
|
@@ -33,17 +36,17 @@ func Warningf(format string, a ...interface{}) {
|
|
|
}
|
|
|
|
|
|
func DedupedWarningf(logTypeLimit int, format string, a ...interface{}) {
|
|
|
- timesLogged := ctr.increment(format)
|
|
|
-
|
|
|
- if timesLogged < logTypeLimit {
|
|
|
- Warningf(format, a...)
|
|
|
- } else if timesLogged == logTypeLimit {
|
|
|
- Warningf(format, a...)
|
|
|
- Infof("%s logged %d times: suppressing future logs", format, logTypeLimit)
|
|
|
- }
|
|
|
-
|
|
|
- // TODO if timeLogged > logTypeLimit, log once every... 100 (?) times so we
|
|
|
- // don't lose track entirely?
|
|
|
+ // Run within a goroutine so that the original call does not block
|
|
|
+ go func(logTypeLimit int, format string, a ...interface{}) {
|
|
|
+ timesLogged := ctr.increment(format)
|
|
|
+
|
|
|
+ if timesLogged < logTypeLimit {
|
|
|
+ Warningf(format, a...)
|
|
|
+ } else if timesLogged == logTypeLimit {
|
|
|
+ Warningf(format, a...)
|
|
|
+ Infof("%s logged %d times: suppressing future logs", format, logTypeLimit)
|
|
|
+ }
|
|
|
+ }(logTypeLimit, format, a...)
|
|
|
}
|
|
|
|
|
|
func Infof(format string, a ...interface{}) {
|
|
|
@@ -51,17 +54,17 @@ func Infof(format string, a ...interface{}) {
|
|
|
}
|
|
|
|
|
|
func DedupedInfof(logTypeLimit int, format string, a ...interface{}) {
|
|
|
- timesLogged := ctr.increment(format)
|
|
|
-
|
|
|
- if timesLogged < logTypeLimit {
|
|
|
- Infof(format, a...)
|
|
|
- } else if timesLogged == logTypeLimit {
|
|
|
- Infof(format, a...)
|
|
|
- Infof("%s logged %d times: suppressing future logs", format, logTypeLimit)
|
|
|
- }
|
|
|
-
|
|
|
- // TODO if timeLogged > logTypeLimit, log once every... 100 (?) times so we
|
|
|
- // don't lose track entirely?
|
|
|
+ // Run within a goroutine so that the original call does not block
|
|
|
+ go func(logTypeLimit int, format string, a ...interface{}) {
|
|
|
+ timesLogged := ctr.increment(format)
|
|
|
+
|
|
|
+ if timesLogged < logTypeLimit {
|
|
|
+ Infof(format, a...)
|
|
|
+ } else if timesLogged == logTypeLimit {
|
|
|
+ Infof(format, a...)
|
|
|
+ Infof("%s logged %d times: suppressing future logs", format, logTypeLimit)
|
|
|
+ }
|
|
|
+ }(logTypeLimit, format, a...)
|
|
|
}
|
|
|
|
|
|
func Profilef(format string, a ...interface{}) {
|
|
|
@@ -83,63 +86,3 @@ func ProfileWithThreshold(start time.Time, threshold time.Duration, name string)
|
|
|
Profilef("%s: %s", elapsed, name)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-type Profiler struct {
|
|
|
- profiles map[string]time.Duration
|
|
|
- starts map[string]time.Time
|
|
|
-}
|
|
|
-
|
|
|
-func NewProfiler() *Profiler {
|
|
|
- return &Profiler{
|
|
|
- profiles: map[string]time.Duration{},
|
|
|
- starts: map[string]time.Time{},
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (p *Profiler) Start(name string) {
|
|
|
- if p == nil {
|
|
|
- return
|
|
|
- }
|
|
|
- p.starts[name] = time.Now()
|
|
|
-}
|
|
|
-
|
|
|
-func (p *Profiler) Stop(name string) time.Duration {
|
|
|
- if p == nil {
|
|
|
- return 0
|
|
|
- }
|
|
|
- if start, ok := p.starts[name]; ok {
|
|
|
- elapsed := time.Since(start)
|
|
|
- p.profiles[name] += elapsed
|
|
|
- return elapsed
|
|
|
- }
|
|
|
- return 0
|
|
|
-}
|
|
|
-
|
|
|
-func (p *Profiler) Log(name string) {
|
|
|
- if p == nil {
|
|
|
- return
|
|
|
- }
|
|
|
- Profilef("%s: %s", p.profiles[name], name)
|
|
|
-}
|
|
|
-
|
|
|
-func (p *Profiler) LogAll() {
|
|
|
- if p == nil {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // Print profiles, largest to smallest. (Inefficienct, but shouldn't matter.)
|
|
|
- print := map[string]time.Duration{}
|
|
|
- for name, value := range p.profiles {
|
|
|
- print[name] = value
|
|
|
- }
|
|
|
- for len(print) > 0 {
|
|
|
- largest := ""
|
|
|
- for name := range print {
|
|
|
- if print[name] > print[largest] {
|
|
|
- largest = name
|
|
|
- }
|
|
|
- }
|
|
|
- Profilef("%s: %s", print[largest], largest)
|
|
|
- delete(print, largest)
|
|
|
- }
|
|
|
-}
|